def add_combo(self, data=None): """Add a combo for selecting an option""" combo = ProxyComboBox() self.pack_start(combo, False, False, 0) if data: combo.prefill(data) return combo
class ComboSearchFilter(SearchFilter): """ - a label - a combo with a set of predefined item to select from """ __gtype_name__ = 'ComboSearchFilter' def __init__(self, label='', values=None): """ Create a new ComboSearchFilter object. @param name: name of the search filter @param values: items to put in the combo, see L{kiwi.ui.widgets.combo.ProxyComboBox.prefill} """ SearchFilter.__init__(self, label=label) label = gtk.Label(label) self.pack_start(label, False, False) label.show() self.title_label = label self.combo = ProxyComboBox() if values: self.combo.prefill(values) self.combo.connect('content-changed', self._on_combo__content_changed) self.pack_start(self.combo, False, False, 6) self.combo.show() # # SearchFilter # def get_state(self): return NumberQueryState(filter=self, value=self.combo.get_selected_data()) def get_title_label(self): return self.title_label def get_mode_combo(self): return self.combo # # Public API # def select(self, data): """ selects an item in the combo @param data: what to select """ self.combo.select(data) # # Callbacks # def _on_combo__content_changed(self, mode): self.emit('changed')
def _setup_options_combo_slave(self): widget = ProxyComboBox() widget.props.sensitive = self.sensitive widget.model_attribute = "field_value" widget.data_type = unicode data = [(value, unicode(key)) for key, value in self.detail.options.items()] widget.prefill(data) self.proxy.add_widget("field_value", widget) self.container.add(widget) widget.show()
def test_prefill_attr_none(self): model = Settable(attr=None) proxy = Proxy(FakeView(), model) combo = ProxyComboBox() combo.data_type = int combo.model_attribute = 'attr' combo.prefill([('foo', 10), ('bar', 20)]) proxy.add_widget('attr', combo) # Even though attr is None, the combo doesn't allow something # not prefilled in it to be selected. In this case, it will select # the first item (prefill actually does that) instead. self.assertEqual(model.attr, 10)
class ComboSearchFilter(SearchFilter): """ - a label - a combo with a set of predefined item to select from """ __gtype_name__ = 'ComboSearchFilter' def __init__(self, label='', values=None): """ Create a new ComboSearchFilter object. @param name: name of the search filter @param values: items to put in the combo, see L{kiwi.ui.widgets.combo.ProxyComboBox.prefill} """ SearchFilter.__init__(self, label=label) label = gtk.Label(label) self.pack_start(label, False, False) label.show() self.title_label = label self.combo = ProxyComboBox() if values: self.combo.prefill(values) self.combo.connect('content-changed', self._on_combo__content_changed) self.pack_start(self.combo, False, False, 6) self.combo.show() # # SearchFilter # def get_state(self): return NumberQueryState(filter=self, value=self.combo.get_selected_data()) def get_title_label(self): return self.title_label def get_mode_combo(self): return self.combo def get_description(self): desc = '' data = self.combo.get_selected_data() if data is not None: desc += self.combo.get_selected_label() return '%s %s' % (self.title_label.get_text(), desc,) # # Public API # def select(self, data): """ selects an item in the combo @param data: what to select """ self.combo.select(data) # # Callbacks # def _on_combo__content_changed(self, mode): self.emit('changed')
class WorkOrderQuoteItemStep(SaleQuoteItemStep): """Third step for work order pre-sales Just like :class:`stoqlib.gui.wizards.salequotewizard.SaleQuoteItemStep`, but each item added here will be added to a workorder too (selected on a combo). """ # # Public API # def get_extra_columns(self): """Get some extra columns for the items list Subclasses can override this and add some extra columns. Those columns will be added just after the 'description' and before the 'quantity' columns. """ return [Column('_equipment', title=_(u'Equipment'), data_type=str, ellipsize=pango.ELLIPSIZE_END)] def setup_work_order(self, work_order): """Do some extra setup for the work order This is called at the initialization of this step. Subclasses can override this to do any extra setup they need on the work order. :param work_order: the |workorder| we are describing """ # # SaleQuoteItemStep # def setup_proxies(self): self._radio_group = None self._setup_work_orders_widgets() super(WorkOrderQuoteItemStep, self).setup_proxies() def get_order_item(self, sellable, price, quantity, batch=None): item = super(WorkOrderQuoteItemStep, self).get_order_item( sellable, price, quantity, batch=batch) work_order = self._selected_workorder wo_item = work_order.add_sellable( sellable, price=price, batch=batch, quantity=quantity) wo_item.sale_item = item item._equipment = work_order.description return item def get_saved_items(self): for item in super(WorkOrderQuoteItemStep, self).get_saved_items(): wo_item = WorkOrderItem.get_from_sale_item(self.store, item) item._equipment = wo_item.order.description yield item def remove_items(self, items): # Remove the workorder items first to avoid reference problems for item in items: wo_item = WorkOrderItem.get_from_sale_item(self.store, item) wo_item.order.remove_item(wo_item) super(WorkOrderQuoteItemStep, self).remove_items(items) def get_columns(self): columns = [ Column('sellable.code', title=_(u'Code'), data_type=str, visible=False), Column('sellable.barcode', title=_(u'Barcode'), data_type=str, visible=False), Column('sellable.description', title=_('Description'), data_type=str, expand=True, format_func=self._format_description, format_func_data=True), ] columns.extend(self.get_extra_columns()) columns.extend([ Column('quantity', title=_(u'Quantity'), data_type=decimal.Decimal, format_func=format_quantity), Column('base_price', title=_('Original Price'), data_type=currency), Column('price', title=_('Sale Price'), data_type=currency), Column('sale_discount', title=_('Discount'), data_type=decimal.Decimal, format_func=get_formatted_percentage), Column('total', title=_(u'Total'), data_type=currency), ]) return columns def validate_step(self): # When finishing the wizard, make sure that all modifications on # sale items on this step are propagated to their work order items for sale_item in self.model.get_items(): wo_item = WorkOrderItem.get_from_sale_item(self.store, sale_item) wo_item.quantity = sale_item.quantity wo_item.quantity_decreased = sale_item.quantity_decreased wo_item.price = sale_item.price return super(WorkOrderQuoteItemStep, self).validate_step() # # Private # def _format_description(self, item, data): return format_sellable_description(item.sellable, item.batch) def _setup_work_orders_widgets(self): self._work_orders_hbox = gtk.HBox(spacing=6) self.item_vbox.pack_start(self._work_orders_hbox, False, True, 6) self.item_vbox.reorder_child(self._work_orders_hbox, 0) self._work_orders_hbox.show() label = gtk.Label(_("Work order:")) self._work_orders_hbox.pack_start(label, False, True) data = [] for wo in self.wizard.workorders: # The work order might be already approved if we are editing a sale if wo.can_approve(): wo.approve() self.setup_work_order(wo) data.append([wo.description, wo]) if len(data) <= _MAX_WORK_ORDERS_FOR_RADIO: self.work_orders_combo = None for desc, wo in data: self._add_work_order_radio(desc, wo) else: self.work_orders_combo = ProxyComboBox() self.work_orders_combo.prefill(data) self._selected_workorder = self.work_orders_combo.get_selected() self._work_orders_hbox.pack_start(self.work_orders_combo, False, False) self._work_orders_hbox.show_all() def _add_work_order_radio(self, desc, workorder): radio = gtk.RadioButton(group=self._radio_group, label=desc) radio.set_data('workorder', workorder) radio.connect('toggled', self._on_work_order_radio__toggled) if self._radio_group is None: self._radio_group = radio self._selected_workorder = workorder self._work_orders_hbox.pack_start(radio, False, False, 6) radio.show_all() # # Callbacks # def on_work_orders_combo__content_changed(self, combo): self._selected_workorder = combo.get_selected() def _on_work_order_radio__toggled(self, radio): if not radio.get_active(): return self._selected_workorder = radio.get_data('workorder')
class ComboSearchFilter(SearchFilter): """ - a label - a combo with a set of predefined item to select from """ __gtype_name__ = 'ComboSearchFilter' def __init__(self, label='', values=None): """ Create a new ComboSearchFilter object. :param label: label of the search filter :param values: items to put in the combo, see :class:`kiwi.ui.widgets.combo.ProxyComboBox.prefill` """ self._block_updates = False SearchFilter.__init__(self, label=label) label = Gtk.Label(label=label) self.pack_start(label, False, False, 0) label.show() self.title_label = label # We create the mode, but it will only be added to this box when # enable_advanced is called self.mode = ProxyComboBox() self.mode.connect('content-changed', self._on_mode__content_changed) for option in (ComboEquals, ComboDifferent): self.add_option(option) self.mode.select_item_by_position(0) self.combo = ProxyComboBox() if values: self.update_values(values) self.combo.connect('content-changed', self._on_combo__content_changed) self.pack_start(self.combo, False, False, 6) self.combo.show() # # SearchFilter # def get_state(self): value = self.combo.get_selected_data() mode = self.mode.get_selected_data() state = NumberQueryState(filter=self, value=value, mode=mode.mode) if hasattr(value, 'id'): state.value_id = value.id return state def set_state(self, value, value_id=None, mode=None): if mode is None: mode = NumberQueryState.EQUALS if value_id is not None: for item in self.combo.get_model_items().values(): if item is None: continue # Filter can come as a string or as a FilterItem object item_id = item if isinstance(item, str) else item.id if item_id == value_id: value = item break self.select(value) def update_values(self, values): self._block_updates = True self.combo.prefill(values) self._block_updates = False def get_title_label(self): return self.title_label def get_mode_combo(self): return self.combo def get_description(self): desc = '' data = self.combo.get_selected_data() if data is not None: desc += self.combo.get_selected_label() return '%s %s' % ( self.title_label.get_text(), desc, ) # # Public API # def add_option(self, option_type, position=0): """ Adds an option :param option_type: option to add :type option_type: a :class:`ComboSearchOption` subclass """ option = option_type() num = len(self.mode) + position self.mode.insert_item(num, option.name, option_type) def select(self, data): """ selects an item in the combo :param data: what to select """ self.combo.select(data) def enable_advanced(self): self.pack_start(self.mode, False, False, 6) self.reorder_child(self.mode, 1) self.mode.show() # # Callbacks # def _on_mode__content_changed(self, combo): if not self._block_updates: self.emit('changed') def _on_combo__content_changed(self, mode): if not self._block_updates: self.emit('changed')
class ChartDialog(gtk.Window): def __init__(self): self._js_data = None self._js_options = None self._current = None gtk.Window.__init__(self) self.set_size_request(800, 480) self.vbox = gtk.VBox() self.add(self.vbox) self.vbox.show() hbox = gtk.HBox() self.vbox.pack_start(hbox, False, False, 6) hbox.show() label = gtk.Label('Period:') hbox.pack_start(label, False, False, 6) label.show() self.chart_type = ProxyComboBox() self.chart_type.connect( 'content-changed', self._on_chart_type__content_changed) hbox.pack_start(self.chart_type, False, False, 6) self.chart_type.show() self.period_values = ProxyComboBox() self.period_values.connect( 'content-changed', self._on_period_values__content_changed) hbox.pack_start(self.period_values, False, False, 6) self.period_values.show() self._view = WebView() self._view.get_view().connect( 'load-finished', self._on_view__document_load_finished) self.vbox.pack_start(self._view, True, True) self.results = ObjectList() self.results.connect( 'row-activated', self._on_results__row_activated) self.vbox.pack_start(self.results, True, True) self._setup_daemon() @api.async def _setup_daemon(self): daemon = yield start_daemon() self._daemon_uri = daemon.base_uri proxy = daemon.get_client() yield proxy.callRemote('start_webservice') self.chart_type.prefill([ ('Year', 'YearlyPayments'), ('Month', 'MonthlyPayments'), ('Day', 'DailyPayments'), ]) @api.async def _invoke_chart(self, chart_type_name, **report_kwargs): def _get_chart_url(**kwargs): params = [] for key, value in kwargs.items(): params.append(key + '=' + str(value)) return '%s/web/chart.json?%s' % ( self._daemon_uri, '&'.join(params)) url = _get_chart_url(type=chart_type_name, **report_kwargs) page = yield getPage(url) data = json.loads(page) api.asyncReturn(data) def _render_chart(self, chart_class, response): self._render_javascript(chart_class, response) self._render_objectlist(chart_class, response) def _render_javascript(self, chart_class, response): ticks = [item['short_title'] for item in response['items']] self._js_data = response['data'] options = {} options['description'] = response['description'] options['series'] = [dict(label=c['title']) for c in chart_class.columns][1:] options['xaxis_ticks'] = ticks self._js_options = options self._view.load_uri('%s/web/static/chart.html' % ( self._daemon_uri,)) def _render_objectlist(self, chart_class, response): columns = [] for kwargs in chart_class.columns: kwargs = kwargs.copy() name = kwargs.pop('name') columns.append(Column(name, **kwargs)) self.results.set_columns(columns) items = [] for item in response['items']: settable = Settable(**item) settable.chart_class = chart_class items.append(settable) self.results.add_list(items, clear=True) self.results.show() def _load_finished(self): self._view.js_function_call( "plot", self._js_data, self._js_options) @api.async def _show_one(self, chart_type_name, start, end): chart_class = get_chart_class(chart_type_name) report_kwargs = dict(start=start.strftime('%Y-%m-%d'), end=end.strftime('%Y-%m-%d')) # Get chart datab response = yield self._invoke_chart(chart_type_name, **report_kwargs) self._render_chart(chart_class, response) def _update_period_values(self): chart_type_name = self.chart_type.get_selected() chart_class = get_chart_class(chart_type_name) values = chart_class.get_combo_labels() self.period_values.prefill(values) # # Callbacks # def _on_view__document_load_finished(self, view, frame): self._load_finished() def _on_chart_type__content_changed(self, combo): self._update_period_values() def _on_period_values__content_changed(self, combo): kind = self.chart_type.get_selected() value = self.period_values.get_selected() if not value: return start, end = value if self._current == (kind, start, end): return self._show_one(kind, start, end) self._current = kind, start, end def _on_results__row_activated(self, results, item): chart_type_name = item.chart_class.__name__ if chart_type_name == 'YearlyPayments': start = localdate(item.year, 1, 1).date() end = localdate(item.year, 12, 31).date() chart_type_name = 'MonthlyPayments' elif chart_type_name == 'MonthlyPayments': start = localdate(item.year, item.month, 1).date() end = start + relativedelta(days=31) chart_type_name = 'DailyPayments' else: return self._show_one(chart_type_name, start, end)
class AccountEditor(BaseEditor): """ Account Editor """ gladefile = "AccountEditor" proxy_widgets = ['description', 'code'] model_type = Account model_name = _('Account') def __init__(self, store, model=None, parent_account=None): self._last_account_type = None self._bank_number = -1 self._bank_widgets = [] self._bank_option_widgets = [] self._option_fields = {} self._test_button = None self.existing = model is not None self.parent_account = parent_account self.bank_model = _TemporaryBankAccount() BaseEditor.__init__(self, store, model) action_area = self.main_dialog.action_area action_area.set_layout(Gtk.ButtonBoxStyle.END) action_area.pack_start(self._test_button, False, False, 0) action_area.set_child_secondary(self._test_button, True) self._test_button.show() # # BaseEditor hooks # def create_model(self, store): return Account(description=u"", account_type=Account.TYPE_CASH, store=store) def _setup_widgets(self): self._test_button = Gtk.Button(_("Print a test bill")) self._test_button.connect('clicked', self._on_test_button__clicked) self.parent_accounts = AccountTree(with_code=False, create_mode=True) self.parent_accounts.connect( 'selection-changed', self._on_parent_accounts__selection_changed) self.tree_box.pack_start(self.parent_accounts, True, True, 0) self.tree_box.reorder_child(self.parent_accounts, 0) if sysparam.compare_object('IMBALANCE_ACCOUNT', self.model): self.account_type.set_sensitive(False) self.account_type.prefill(Account.account_type_descriptions) account_type = self.model.account_type self.parent_accounts.insert_initial(self.store, edited_account=self.model) if self.parent_account: account = self.parent_accounts.get_account_by_id( self.parent_account.id) self.parent_accounts.select(account) if not self.existing: account_type = account.account_type self.account_type.select(account_type) self.parent_accounts.show() def setup_proxies(self): self._setup_widgets() self.add_proxy(self.model, AccountEditor.proxy_widgets) def validate_confirm(self): if not self.model.description: return False account = self.parent_accounts.get_selected() if not account: return True return account.selectable def on_confirm(self): new_parent = self.parent_accounts.get_selected() if new_parent: new_parent = new_parent.account if new_parent != self.model: self.model.parent = new_parent self.model.account_type = self.account_type.get_selected() self._save_bank() def refresh_ok(self, value): BaseEditor.refresh_ok(self, value) account_type = self.account_type.get_selected() if account_type != Account.TYPE_BANK: value = False self._test_button.set_sensitive(value) # Private def _save_bank(self): bank_account = self.model.bank if not bank_account: bank_account = BankAccount(account=self.model, store=self.store) # FIXME: Who sets this to a str? bank_account.bank_account = unicode(self.bank_model.bank_account) bank_account.bank_branch = unicode(self.bank_model.bank_branch) if self._bank_number is not None: bank_account.bank_number = self.bank_model.bank_number self._save_bank_bill_options(bank_account) def _save_bank_bill_options(self, bank_account): for option, entry in self._option_fields.items(): value = unicode(entry.get_text()) bill_option = self.store.find(BillOption, bank_account=bank_account, option=option).one() if bill_option is None: bill_option = BillOption(store=self.store, bank_account=bank_account, option=option, value=value) bill_option.value = value def _add_widget(self, label, widget, options=False): n_rows = self.table.props.n_rows l = Gtk.Label() l.set_markup(label) l.props.xalign = 1.0 self.table.resize(n_rows + 1, 2) self.table.attach(l, 0, 1, n_rows, n_rows + 1, Gtk.AttachOptions.FILL, 0, 0, 0) self.table.attach(widget, 1, 2, n_rows, n_rows + 1, Gtk.AttachOptions.EXPAND | Gtk.AttachOptions.FILL, 0, 0, 0) if options: self._bank_option_widgets.extend([l, widget]) else: self._bank_widgets.extend([l, widget]) l.show() return l def _update_bank_type(self): self._remove_bank_option_widgets() bank_number = self.bank_type.get_selected() bank_info = None if bank_number: bank_info = get_bank_info_by_number(bank_number) self.bank_number = ProxyEntry() self.bank_number.props.data_type = int self.bank_number.set_sensitive(False) bank_number_lbl = self._add_widget(api.escape(_("Number:")), self.bank_number, options=True) self.bank_branch = ProxyEntry() self.bank_branch.connect('validate', self._on_bank_branch__validate, bank_info) self.bank_branch.props.data_type = 'str' self.bank_branch.props.mandatory = True self.bank_branch.model_attribute = "bank_branch" bank_branch_lbl = self._add_widget(api.escape(_("Agency:")), self.bank_branch, options=True) if bank_number is not None: bank_branch_lbl.show() self.bank_branch.show() else: bank_branch_lbl.hide() self.bank_account = ProxyEntry() self.bank_account.connect('validate', self._on_bank_account__validate, bank_info) self._add_widget(api.escape(_("Account:")), self.bank_account, options=True) self.bank_account.model_attribute = "bank_account" self.bank_account.props.data_type = 'str' if bank_number is not None: self.bank_account.props.mandatory = True self.bank_account.show() attributes = ['bank_account', 'bank_branch', 'bank_number'] if bank_number is not None: bank_number_lbl.show() self.bank_number.show() self.bank_model.bank_number = bank_number for i, option in enumerate(bank_info.get_extra_options()): name = 'option' + str(i) entry = ProxyEntry() entry.model_attribute = name setattr(self, name, entry) # Set the model attr too so it can be validated setattr(self.bank_model, name, u'') entry.props.data_type = 'str' entry.connect('validate', self._on_bank_option__validate, bank_info, option) name = option.replace('_', ' ').capitalize() self._add_widget("<i>%s</i>:" % api.escape(name), entry, options=True) entry.show() self._option_fields[option] = entry attributes.append(entry.model_attribute) else: bank_number_lbl.hide() self.bank_proxy = self.add_proxy(self.bank_model, attributes) self._fill_bank_account() def _fill_bank_account(self): if not self.model.bank: return self.bank_model.bank_branch = self.model.bank.bank_branch.encode( 'utf-8') self.bank_model.bank_account = self.model.bank.bank_account.encode( 'utf-8') self.bank_proxy.update('bank_branch') self.bank_proxy.update('bank_account') bill_options = list( self.store.find(BillOption, bank_account=self.model.bank)) for bill_option in bill_options: if bill_option.option is None: continue field_entry = self._option_fields.get(bill_option.option) if field_entry: field_entry.set_text(bill_option.value) def _update_account_type(self, account_type): if not self.account_type.get_sensitive(): return if account_type != Account.TYPE_BANK: self._remove_bank_widgets() self._remove_bank_option_widgets() self.code.set_sensitive(True) return self.code.set_sensitive(False) self.bank_type = ProxyComboBox() self._add_widget(api.escape(_("Bank:")), self.bank_type) self.bank_type.connect('content-changed', self._on_bank_type__content_changed) self.bank_type.show() banks = [(_('Generic'), None)] banks.extend([(b.description, b.bank_number) for b in get_all_banks()]) self.bank_type.prefill(banks) if self.model.bank: try: self.bank_type.select(self.model.bank.bank_number) except KeyError: self.bank_type.select(None) self._update_bank_type() def _remove_bank_widgets(self): for widget in self._bank_widgets: widget.get_parent().remove(widget) widget.destroy() self.table.resize(5, 2) self._bank_widgets = [] def _remove_bank_option_widgets(self): for widget in self._bank_option_widgets: widget.get_parent().remove(widget) widget.destroy() self.table.resize(5 + len(self._bank_widgets) / 2, 2) self._bank_option_widgets = [] self._option_fields = {} def _print_test_bill(self): try: bank_info = get_bank_info_by_number(self.bank_model.bank_number) except NotImplementedError: info(_("This bank does not support printing of bills")) return kwargs = dict( valor_documento=12345.67, data_vencimento=datetime.date.today(), data_documento=datetime.date.today(), data_processamento=datetime.date.today(), nosso_numero=u'24533', numero_documento=u'1138', sacado=[_(u"Drawee"), _(u"Address"), _(u"Details")], cedente=[_(u"Supplier"), _(u"Address"), _(u"Details"), ("CNPJ")], demonstrativo=[_(u"Demonstration")], instrucoes=[_(u"Instructions")], agencia=self.bank_model.bank_branch, conta=self.bank_model.bank_account, ) for opt in self.bank_model.options: kwargs[opt.option] = opt.value data = bank_info(**kwargs) print_report(BillTestReport, data) # Callbacks def _on_parent_accounts__selection_changed(self, objectlist, account): self.force_validation() def on_description__activate(self, entry): if self.validate_confirm(): self.confirm() def on_description__validate(self, entry, text): if not text: return ValidationError(_("Account description cannot be empty")) def on_account_type__content_changed(self, account_type): account_type = account_type.get_selected() if self._last_account_type == account_type: return self._update_account_type(account_type) self._last_account_type = account_type def _on_bank_type__content_changed(self, bank_type): bank_number = bank_type.get_selected() if self._bank_number == bank_number: return self._update_bank_type() self._bank_number = bank_number def _on_bank_branch__validate(self, entry, value, bank_info): if bank_info: try: bank_info.validate_field(value) except BoletoException as e: return ValidationError(str(e)) def _on_bank_account__validate(self, entry, value, bank_info): if bank_info: try: bank_info.validate_field(value) except BoletoException as e: return ValidationError(str(e)) def _on_bank_option__validate(self, entry, value, bank_info, option): try: bank_info.validate_option(option, value) except BoletoException as e: return ValidationError(str(e)) self.bank_model.set_option(option, value) def _on_test_button__clicked(self, button): self._print_test_bill()
class ComboSearchFilter(SearchFilter): """ - a label - a combo with a set of predefined item to select from """ __gtype_name__ = 'ComboSearchFilter' def __init__(self, label='', values=None): """ Create a new ComboSearchFilter object. :param label: label of the search filter :param values: items to put in the combo, see :class:`kiwi.ui.widgets.combo.ProxyComboBox.prefill` """ self._block_updates = False SearchFilter.__init__(self, label=label) label = gtk.Label(label) self.pack_start(label, False, False) label.show() self.title_label = label self.combo = ProxyComboBox() if values: self.update_values(values) self.combo.connect('content-changed', self._on_combo__content_changed) self.pack_start(self.combo, False, False, 6) self.combo.show() # # SearchFilter # def get_state(self): value = self.combo.get_selected_data() state = NumberQueryState(filter=self, value=value) if hasattr(value, 'id'): state.value_id = value.id return state def set_state(self, value, value_id=None): if value_id is not None: for item in self.combo.get_model_items().values(): if item is None: continue if item.id == value_id: value = item break self.select(value) def update_values(self, values): self._block_updates = True self.combo.prefill(values) self._block_updates = False def get_title_label(self): return self.title_label def get_mode_combo(self): return self.combo def get_description(self): desc = '' data = self.combo.get_selected_data() if data is not None: desc += self.combo.get_selected_label() return '%s %s' % ( self.title_label.get_text(), desc, ) # # Public API # def select(self, data): """ selects an item in the combo :param data: what to select """ self.combo.select(data) # # Callbacks # def _on_combo__content_changed(self, mode): if not self._block_updates: self.emit('changed')
class ComboSearchFilter(SearchFilter): """ - a label - a combo with a set of predefined item to select from """ __gtype_name__ = 'ComboSearchFilter' def __init__(self, label='', values=None): """ Create a new ComboSearchFilter object. :param label: label of the search filter :param values: items to put in the combo, see :class:`kiwi.ui.widgets.combo.ProxyComboBox.prefill` """ self._block_updates = False SearchFilter.__init__(self, label=label) label = gtk.Label(label) self.pack_start(label, False, False) label.show() self.title_label = label self.combo = ProxyComboBox() if values: self.update_values(values) self.combo.connect('content-changed', self._on_combo__content_changed) self.pack_start(self.combo, False, False, 6) self.combo.show() # # SearchFilter # def get_state(self): value = self.combo.get_selected_data() state = NumberQueryState(filter=self, value=value) if hasattr(value, 'id'): state.value_id = value.id return state def set_state(self, value, value_id=None): if value_id is not None: for item in self.combo.get_model_items().values(): if item is None: continue if item.id == value_id: value = item break self.select(value) def update_values(self, values): self._block_updates = True self.combo.prefill(values) self._block_updates = False def get_title_label(self): return self.title_label def get_mode_combo(self): return self.combo def get_description(self): desc = '' data = self.combo.get_selected_data() if data is not None: desc += self.combo.get_selected_label() return '%s %s' % (self.title_label.get_text(), desc,) # # Public API # def select(self, data): """ selects an item in the combo :param data: what to select """ self.combo.select(data) # # Callbacks # def _on_combo__content_changed(self, mode): if not self._block_updates: self.emit('changed')
class WorkOrderQuoteItemStep(SaleQuoteItemStep): """Third step for work order pre-sales Just like :class:`stoqlib.gui.wizards.salequotewizard.SaleQuoteItemStep`, but each item added here will be added to a workorder too (selected on a combo). """ # # Public API # def get_extra_columns(self): """Get some extra columns for the items list Subclasses can override this and add some extra columns. Those columns will be added just after the 'description' and before the 'quantity' columns. """ return [ Column('_equipment', title=_(u'Equipment'), data_type=str, ellipsize=Pango.EllipsizeMode.END) ] def setup_work_order(self, work_order): """Do some extra setup for the work order This is called at the initialization of this step. Subclasses can override this to do any extra setup they need on the work order. :param work_order: the |workorder| we are describing """ # # SaleQuoteItemStep # def setup_proxies(self): self._radio_group = None self._setup_work_orders_widgets() super(WorkOrderQuoteItemStep, self).setup_proxies() def get_order_item(self, sellable, price, quantity, batch=None, parent=None): item = super(WorkOrderQuoteItemStep, self).get_order_item(sellable, price, quantity, batch=batch, parent=parent) work_order = self._selected_workorder wo_item = work_order.add_sellable(sellable, price=price, batch=batch, quantity=quantity) wo_item.sale_item = item item._equipment = work_order.description return item def get_saved_items(self): for item in super(WorkOrderQuoteItemStep, self).get_saved_items(): wo_item = WorkOrderItem.get_from_sale_item(self.store, item) item._equipment = wo_item.order.description yield item def remove_items(self, items): # Remove the workorder items first to avoid reference problems for item in items: wo_item = WorkOrderItem.get_from_sale_item(self.store, item) # If the item's quantity_decreased changed in this step, the # synchronization between the 2 that happens on self.validate_step # would not have happened yet, meaning that order.remove_item # would try to return a wrong quantity to the stock. Force the # synchronization to avoid any problems like that wo_item.quantity_decreased = item.quantity_decreased wo_item.order.remove_item(wo_item) super(WorkOrderQuoteItemStep, self).remove_items(items) def get_columns(self): columns = [ Column('sellable.code', title=_(u'Code'), data_type=str, visible=False), Column('sellable.barcode', title=_(u'Barcode'), data_type=str, visible=False), Column('sellable.description', title=_('Description'), data_type=str, expand=True, format_func=self._format_description, format_func_data=True), ] columns.extend(self.get_extra_columns()) columns.extend([ Column('quantity', title=_(u'Quantity'), data_type=decimal.Decimal, format_func=format_quantity), Column('base_price', title=_('Original Price'), data_type=currency), Column('price', title=_('Sale Price'), data_type=currency), Column('sale_discount', title=_('Discount'), data_type=decimal.Decimal, format_func=get_formatted_percentage), Column('total', title=_(u'Total'), data_type=currency), ]) return columns def validate_step(self): # When finishing the wizard, make sure that all modifications on # sale items on this step are propagated to their work order items for sale_item in self.model.get_items(): wo_item = WorkOrderItem.get_from_sale_item(self.store, sale_item) wo_item.quantity = sale_item.quantity wo_item.quantity_decreased = sale_item.quantity_decreased wo_item.price = sale_item.price return super(WorkOrderQuoteItemStep, self).validate_step() # # Private # def _format_description(self, item, data): return format_sellable_description(item.sellable, item.batch) def _setup_work_orders_widgets(self): self._work_orders_hbox = Gtk.HBox(spacing=6) self.item_vbox.pack_start(self._work_orders_hbox, False, True, 6) self.item_vbox.reorder_child(self._work_orders_hbox, 0) self._work_orders_hbox.show() label = Gtk.Label(label=_("Work order:")) self._work_orders_hbox.pack_start(label, False, True, 0) data = [] for wo in self.wizard.workorders: # The work order might be already approved if we are editing a sale if wo.can_approve(): wo.approve() self.setup_work_order(wo) data.append([wo.description, wo]) if len(data) <= _MAX_WORK_ORDERS_FOR_RADIO: self.work_orders_combo = None for desc, wo in data: self._add_work_order_radio(desc, wo) else: self.work_orders_combo = ProxyComboBox() self.work_orders_combo.prefill(data) self._selected_workorder = self.work_orders_combo.get_selected() self._work_orders_hbox.pack_start(self.work_orders_combo, False, False, 0) self._work_orders_hbox.show_all() def _add_work_order_radio(self, desc, workorder): radio = Gtk.RadioButton(group=self._radio_group, label=desc) radio._workorder = workorder radio.connect('toggled', self._on_work_order_radio__toggled) if self._radio_group is None: self._radio_group = radio self._selected_workorder = workorder self._work_orders_hbox.pack_start(radio, False, False, 6) radio.show_all() # # Callbacks # def on_work_orders_combo__content_changed(self, combo): self._selected_workorder = combo.get_selected() def _on_work_order_radio__toggled(self, radio): if not radio.get_active(): return self._selected_workorder = radio._workorder
class ComboSearchFilter(SearchFilter): """ - a label - a combo with a set of predefined item to select from """ __gtype_name__ = 'ComboSearchFilter' def __init__(self, label='', values=None): """ Create a new ComboSearchFilter object. :param label: label of the search filter :param values: items to put in the combo, see :class:`kiwi.ui.widgets.combo.ProxyComboBox.prefill` """ self._block_updates = False SearchFilter.__init__(self, label=label) label = gtk.Label(label) self.pack_start(label, False, False) label.show() self.title_label = label # We create the mode, but it will only be added to this box when # enable_advanced is called self.mode = ProxyComboBox() self.mode.connect('content-changed', self._on_mode__content_changed) for option in (ComboEquals, ComboDifferent): self.add_option(option) self.mode.select_item_by_position(0) self.combo = ProxyComboBox() if values: self.update_values(values) self.combo.connect('content-changed', self._on_combo__content_changed) self.pack_start(self.combo, False, False, 6) self.combo.show() # # SearchFilter # def get_state(self): value = self.combo.get_selected_data() mode = self.mode.get_selected_data() state = NumberQueryState(filter=self, value=value, mode=mode.mode) if hasattr(value, 'id'): state.value_id = value.id return state def set_state(self, value, value_id=None, mode=None): if mode is None: mode = NumberQueryState.EQUALS if value_id is not None: for item in self.combo.get_model_items().values(): if item is None: continue if item.id == value_id: value = item break self.select(value) def update_values(self, values): self._block_updates = True self.combo.prefill(values) self._block_updates = False def get_title_label(self): return self.title_label def get_mode_combo(self): return self.combo def get_description(self): desc = '' data = self.combo.get_selected_data() if data is not None: desc += self.combo.get_selected_label() return '%s %s' % (self.title_label.get_text(), desc,) # # Public API # def add_option(self, option_type, position=0): """ Adds an option :param option_type: option to add :type option_type: a :class:`ComboSearchOption` subclass """ option = option_type() num = len(self.mode) + position self.mode.insert_item(num, option.name, option_type) def select(self, data): """ selects an item in the combo :param data: what to select """ self.combo.select(data) def enable_advanced(self): self.pack_start(self.mode, False, False, 6) self.reorder_child(self.mode, 1) self.mode.show() # # Callbacks # def _on_mode__content_changed(self, combo): if not self._block_updates: self.emit('changed') def _on_combo__content_changed(self, mode): if not self._block_updates: self.emit('changed')
class AccountEditor(BaseEditor): """ Account Editor """ gladefile = "AccountEditor" proxy_widgets = ['description', 'code'] model_type = Account model_name = _('Account') def __init__(self, store, model=None, parent_account=None): self._last_account_type = None self._bank_number = -1 self._bank_widgets = [] self._bank_option_widgets = [] self._option_fields = {} self._test_button = None self.existing = model is not None self.parent_account = parent_account self.bank_model = _TemporaryBankAccount() BaseEditor.__init__(self, store, model) action_area = self.main_dialog.action_area action_area.set_layout(gtk.BUTTONBOX_END) action_area.pack_start(self._test_button, expand=False, fill=False) action_area.set_child_secondary(self._test_button, True) self._test_button.show() # # BaseEditor hooks # def create_model(self, store): return Account(description=u"", account_type=Account.TYPE_CASH, store=store) def _setup_widgets(self): self._test_button = gtk.Button(_("Print a test bill")) self._test_button.connect('clicked', self._on_test_button__clicked) self.parent_accounts = AccountTree(with_code=False, create_mode=True) self.parent_accounts.connect('selection-changed', self._on_parent_accounts__selection_changed) self.tree_box.pack_start(self.parent_accounts) self.tree_box.reorder_child(self.parent_accounts, 0) if self.model == sysparam(self.store).IMBALANCE_ACCOUNT: self.account_type.set_sensitive(False) self.account_type.prefill(Account.account_type_descriptions) account_type = self.model.account_type self.parent_accounts.insert_initial(self.store, edited_account=self.model) if self.parent_account: account = self.parent_accounts.get_account_by_id( self.parent_account.id) self.parent_accounts.select(account) if not self.existing: account_type = account.account_type self.account_type.select(account_type) self.parent_accounts.show() def setup_proxies(self): self._setup_widgets() self.add_proxy(self.model, AccountEditor.proxy_widgets) def validate_confirm(self): if not self.model.description: return False account = self.parent_accounts.get_selected() if not account: return True return account.selectable def on_confirm(self): new_parent = self.parent_accounts.get_selected() if new_parent: new_parent = new_parent.account if new_parent != self.model: self.model.parent = new_parent self.model.account_type = self.account_type.get_selected() self._save_bank() def refresh_ok(self, value): BaseEditor.refresh_ok(self, value) account_type = self.account_type.get_selected() if account_type != Account.TYPE_BANK: value = False self._test_button.set_sensitive(value) # Private def _save_bank(self): bank_account = self.model.bank if not bank_account: bank_account = BankAccount(account=self.model, store=self.store) # FIXME: Who sets this to a str? bank_account.bank_account = unicode(self.bank_model.bank_account) bank_account.bank_branch = unicode(self.bank_model.bank_branch) if self._bank_number is not None: bank_account.bank_number = self.bank_model.bank_number self._save_bank_bill_options(bank_account) def _save_bank_bill_options(self, bank_account): for option, entry in self._option_fields.items(): value = unicode(entry.get_text()) bill_option = self.store.find(BillOption, bank_account=bank_account, option=option).one() if bill_option is None: bill_option = BillOption(store=self.store, bank_account=bank_account, option=option, value=value) bill_option.value = value def _add_widget(self, label, widget, options=False): n_rows = self.table.props.n_rows l = gtk.Label() l.set_markup(label) l.props.xalign = 1.0 self.table.resize(n_rows + 1, 2) self.table.attach( l, 0, 1, n_rows, n_rows + 1, gtk.FILL, 0, 0, 0) self.table.attach( widget, 1, 2, n_rows, n_rows + 1, gtk.EXPAND | gtk.FILL, 0, 0, 0) if options: self._bank_option_widgets.extend([l, widget]) else: self._bank_widgets.extend([l, widget]) l.show() return l def _update_bank_type(self): self._remove_bank_option_widgets() bank_number = self.bank_type.get_selected() bank_info = None if bank_number: bank_info = get_bank_info_by_number(bank_number) self.bank_number = ProxyEntry() self.bank_number.props.data_type = int self.bank_number.set_sensitive(False) bank_number_lbl = self._add_widget(api.escape(_("Number:")), self.bank_number, options=True) self.bank_branch = ProxyEntry() self.bank_branch.connect('validate', self._on_bank_branch__validate, bank_info) self.bank_branch.props.data_type = 'str' self.bank_branch.props.mandatory = True self.bank_branch.model_attribute = "bank_branch" bank_branch_lbl = self._add_widget(api.escape(_("Agency:")), self.bank_branch, options=True) if bank_number is not None: bank_branch_lbl.show() self.bank_branch.show() else: bank_branch_lbl.hide() self.bank_account = ProxyEntry() self.bank_account.connect('validate', self._on_bank_account__validate, bank_info) self._add_widget(api.escape(_("Account:")), self.bank_account, options=True) self.bank_account.model_attribute = "bank_account" self.bank_account.props.data_type = 'str' if bank_number is not None: self.bank_account.props.mandatory = True self.bank_account.show() attributes = ['bank_account', 'bank_branch', 'bank_number'] if bank_number is not None: bank_number_lbl.show() self.bank_number.show() self.bank_model.bank_number = bank_number for i, option in enumerate(bank_info.get_extra_options()): name = 'option' + str(i) entry = ProxyEntry() entry.model_attribute = name setattr(self, name, entry) # Set the model attr too so it can be validated setattr(self.bank_model, name, u'') entry.props.data_type = 'str' entry.connect('validate', self._on_bank_option__validate, bank_info, option) self._add_widget("<i>%s</i>:" % (api.escape(option.capitalize()), ), entry, options=True) entry.show() self._option_fields[option] = entry attributes.append(entry.model_attribute) else: bank_number_lbl.hide() self.bank_proxy = self.add_proxy( self.bank_model, attributes) self._fill_bank_account() def _fill_bank_account(self): if not self.model.bank: return self.bank_model.bank_branch = self.model.bank.bank_branch.encode('utf-8') self.bank_model.bank_account = self.model.bank.bank_account.encode('utf-8') self.bank_proxy.update('bank_branch') self.bank_proxy.update('bank_account') bill_options = list(self.store.find(BillOption, bank_account=self.model.bank)) for bill_option in bill_options: if bill_option.option is None: continue field_entry = self._option_fields.get(bill_option.option) if field_entry: field_entry.set_text(bill_option.value) def _update_account_type(self, account_type): if not self.account_type.get_sensitive(): return if account_type != Account.TYPE_BANK: self._remove_bank_widgets() self._remove_bank_option_widgets() self.code.set_sensitive(True) return self.code.set_sensitive(False) self.bank_type = ProxyComboBox() self._add_widget(api.escape(_("Bank:")), self.bank_type) self.bank_type.connect('content-changed', self._on_bank_type__content_changed) self.bank_type.show() banks = [(_('Generic'), None)] banks.extend([(b.description, b.bank_number) for b in get_all_banks()]) self.bank_type.prefill(banks) if self.model.bank: try: self.bank_type.select(self.model.bank.bank_number) except KeyError: self.bank_type.select(None) self._update_bank_type() def _remove_bank_widgets(self): for widget in self._bank_widgets: widget.get_parent().remove(widget) widget.destroy() self.table.resize(5, 2) self._bank_widgets = [] def _remove_bank_option_widgets(self): for widget in self._bank_option_widgets: widget.get_parent().remove(widget) widget.destroy() self.table.resize(5 + len(self._bank_widgets) / 2, 2) self._bank_option_widgets = [] self._option_fields = {} def _print_test_bill(self): try: bank_info = get_bank_info_by_number(self.bank_model.bank_number) except NotImplementedError: info(_("This bank does not support printing of bills")) return kwargs = dict( valor_documento=12345.67, data_vencimento=datetime.date.today(), data_documento=datetime.date.today(), data_processamento=datetime.date.today(), nosso_numero=u'624533', numero_documento=u'1138', sacado=[_(u"Drawee"), _(u"Address"), _(u"Details")], cedente=_(u"Supplier"), demonstrativo=[_(u"Demonstration")], instrucoes=[_(u"Instructions")], agencia=self.bank_model.bank_branch, conta=self.bank_model.bank_account, ) for opt in self.bank_model.options: kwargs[opt.option] = opt.value data = bank_info(**kwargs) print_report(BillTestReport, data) # Callbacks def _on_parent_accounts__selection_changed(self, objectlist, account): self.force_validation() def on_description__activate(self, entry): if self.validate_confirm(): self.confirm() def on_description__validate(self, entry, text): if not text: return ValidationError(_("Account description cannot be empty")) def on_account_type__content_changed(self, account_type): account_type = account_type.get_selected() if self._last_account_type == account_type: return self._update_account_type(account_type) self._last_account_type = account_type def _on_bank_type__content_changed(self, bank_type): bank_number = bank_type.get_selected() if self._bank_number == bank_number: return self._update_bank_type() self._bank_number = bank_number def _on_bank_branch__validate(self, entry, value, bank_info): if bank_info: try: bank_info.validate_field(value) except BoletoException, e: return ValidationError(str(e))
class TestComboBox(unittest.TestCase): def setUp(self): self.combo = ProxyComboBox() def _prefill(self): self.combo.prefill((('Johan', 1981), ('Lorenzo', 1979), ('Christian', 1976))) def testPrefill(self): self.combo.prefill(('foo', 'bar')) model = self.combo.get_model() self.assertEqual(tuple(model[0]), ('foo', None)) self.assertEqual(tuple(model[1]), ('bar', None)) def testPrefillWithData(self): self.combo.prefill((('foo', 42), ('bar', 138))) model = self.combo.get_model() self.assertEqual(tuple(model[0]), ('foo', 42)) self.assertEqual(tuple(model[1]), ('bar', 138)) self.combo.prefill([]) self.assertEqual(len(self.combo.get_model()), 0) self.assertEqual(len(model), 0) self.assertEqual(len(self.combo), 0) def testSelectItemByPosition(self): self._prefill() self.combo.select_item_by_position(1) model = self.combo.get_model() iter = self.combo.get_active_iter() self.assertEqual(model.get_value(iter, 0), 'Lorenzo') self.assertEqual(model.get_value(iter, 1), 1979) self.assertRaises(KeyError, self.combo.select_item_by_label, 4) def testSelectItemByLabel(self): self._prefill() self.combo.select_item_by_label('Christian') model = self.combo.get_model() iter = self.combo.get_active_iter() rowNo = model.get_path(iter)[0] self.assertEqual(rowNo, 2) self.assertRaises(KeyError, self.combo.select_item_by_label, 'Salgado') def testSelectByData(self): self._prefill() self.combo.select_item_by_data(1976) model = self.combo.get_model() iter = self.combo.get_active_iter() rowNo = model.get_path(iter)[0] self.assertEqual(rowNo, 2) self.assertEqual(model.get_value(iter, 0), 'Christian') self.assertEqual(model.get_value(iter, 1), 1976) self.assertRaises(KeyError, self.combo.select_item_by_data, 1980) def testGetSelectedData(self): self._prefill() self.combo.select_item_by_position(0) self.assertEqual(self.combo.get_selected_data(), 1981) self.assertRaises(TypeError, self.combo.select_item_by_position, 'foobar') def testGetSelectedLabel(self): self._prefill() def testClear(self): self._prefill() self.combo.clear() self.assertEqual(map(list, self.combo.get_model()), [])
class ChartDialog(gtk.Window): def __init__(self): self._js_data = None self._js_options = None self._current = None gtk.Window.__init__(self) self.set_size_request(800, 480) self.vbox = gtk.VBox() self.add(self.vbox) self.vbox.show() hbox = gtk.HBox() self.vbox.pack_start(hbox, False, False, 6) hbox.show() label = gtk.Label('Period:') hbox.pack_start(label, False, False, 6) label.show() self.chart_type = ProxyComboBox() self.chart_type.connect('content-changed', self._on_chart_type__content_changed) hbox.pack_start(self.chart_type, False, False, 6) self.chart_type.show() self.period_values = ProxyComboBox() self.period_values.connect('content-changed', self._on_period_values__content_changed) hbox.pack_start(self.period_values, False, False, 6) self.period_values.show() self._view = WebView() self._view.get_view().connect('load-finished', self._on_view__document_load_finished) self.vbox.pack_start(self._view, True, True) self.results = ObjectList() self.results.connect('row-activated', self._on_results__row_activated) self.vbox.pack_start(self.results, True, True) self._setup_daemon() @api. async def _setup_daemon(self): daemon = yield start_daemon() self._daemon_uri = daemon.base_uri proxy = daemon.get_client() yield proxy.callRemote('start_webservice') self.chart_type.prefill([ ('Year', 'YearlyPayments'), ('Month', 'MonthlyPayments'), ('Day', 'DailyPayments'), ]) @api. async def _invoke_chart(self, chart_type_name, **report_kwargs): def _get_chart_url(**kwargs): params = [] for key, value in kwargs.items(): params.append(key + '=' + str(value)) return '%s/web/chart.json?%s' % (self._daemon_uri, '&'.join(params)) url = _get_chart_url(type=chart_type_name, **report_kwargs) page = yield getPage(url) data = json.loads(page) api.asyncReturn(data) def _render_chart(self, chart_class, response): self._render_javascript(chart_class, response) self._render_objectlist(chart_class, response) def _render_javascript(self, chart_class, response): ticks = [item['short_title'] for item in response['items']] self._js_data = response['data'] options = {} options['description'] = response['description'] options['series'] = [ dict(label=c['title']) for c in chart_class.columns ][1:] options['xaxis_ticks'] = ticks self._js_options = options self._view.load_uri('%s/web/static/chart.html' % (self._daemon_uri, )) def _render_objectlist(self, chart_class, response): columns = [] for kwargs in chart_class.columns: kwargs = kwargs.copy() name = kwargs.pop('name') columns.append(Column(name, **kwargs)) self.results.set_columns(columns) items = [] for item in response['items']: settable = Settable(**item) settable.chart_class = chart_class items.append(settable) self.results.add_list(items, clear=True) self.results.show() def _load_finished(self): self._view.js_function_call("plot", self._js_data, self._js_options) @api. async def _show_one(self, chart_type_name, start, end): chart_class = get_chart_class(chart_type_name) report_kwargs = dict(start=start.strftime('%Y-%m-%d'), end=end.strftime('%Y-%m-%d')) # Get chart datab response = yield self._invoke_chart(chart_type_name, **report_kwargs) self._render_chart(chart_class, response) def _update_period_values(self): chart_type_name = self.chart_type.get_selected() chart_class = get_chart_class(chart_type_name) values = chart_class.get_combo_labels() self.period_values.prefill(values) # # Callbacks # def _on_view__document_load_finished(self, view, frame): self._load_finished() def _on_chart_type__content_changed(self, combo): self._update_period_values() def _on_period_values__content_changed(self, combo): kind = self.chart_type.get_selected() value = self.period_values.get_selected() if not value: return start, end = value if self._current == (kind, start, end): return self._show_one(kind, start, end) self._current = kind, start, end def _on_results__row_activated(self, results, item): chart_type_name = item.chart_class.__name__ if chart_type_name == 'YearlyPayments': start = localdate(item.year, 1, 1).date() end = localdate(item.year, 12, 31).date() chart_type_name = 'MonthlyPayments' elif chart_type_name == 'MonthlyPayments': start = localdate(item.year, item.month, 1).date() end = start + relativedelta(days=31) chart_type_name = 'DailyPayments' else: return self._show_one(chart_type_name, start, end)
class TestComboBox(unittest.TestCase): def setUp(self): self.combo = ProxyComboBox() def _prefill(self): self.combo.prefill( (('Johan', 1981), ('Lorenzo', 1979), ('Christian', 1976))) def testPrefill(self): self.combo.prefill(('foo', 'bar')) model = self.combo.get_model() self.assertEqual(tuple(model[0]), ('foo', None)) self.assertEqual(tuple(model[1]), ('bar', None)) def testPrefillWithData(self): self.combo.prefill((('foo', 42), ('bar', 138))) model = self.combo.get_model() self.assertEqual(tuple(model[0]), ('foo', 42)) self.assertEqual(tuple(model[1]), ('bar', 138)) self.combo.prefill([]) self.assertEqual(len(self.combo.get_model()), 0) self.assertEqual(len(model), 0) self.assertEqual(len(self.combo), 0) def testSelectItemByPosition(self): self._prefill() self.combo.select_item_by_position(1) model = self.combo.get_model() iter = self.combo.get_active_iter() self.assertEqual(model.get_value(iter, 0), 'Lorenzo') self.assertEqual(model.get_value(iter, 1), 1979) self.assertRaises(KeyError, self.combo.select_item_by_label, 4) def testSelectItemByLabel(self): self._prefill() self.combo.select_item_by_label('Christian') model = self.combo.get_model() iter = self.combo.get_active_iter() rowNo = model.get_path(iter)[0] self.assertEqual(rowNo, 2) self.assertRaises(KeyError, self.combo.select_item_by_label, 'Salgado') def testSelectByData(self): self._prefill() self.combo.select_item_by_data(1976) model = self.combo.get_model() iter = self.combo.get_active_iter() rowNo = model.get_path(iter)[0] self.assertEqual(rowNo, 2) self.assertEqual(model.get_value(iter, 0), 'Christian') self.assertEqual(model.get_value(iter, 1), 1976) self.assertRaises(KeyError, self.combo.select_item_by_data, 1980) def testGetSelectedData(self): self._prefill() self.combo.select_item_by_position(0) self.assertEqual(self.combo.get_selected_data(), 1981) self.assertRaises(TypeError, self.combo.select_item_by_position, 'foobar') def testGetSelectedLabel(self): self._prefill() def testClear(self): self._prefill() self.combo.clear() self.assertEqual(list(map(list, self.combo.get_model())), [])