electrum-bitcoinprivate/gui/kivy/uix/screens.py

623 lines
20 KiB
Python
Raw Normal View History

2015-10-07 04:06:28 -07:00
from weakref import ref
from decimal import Decimal
import re
import datetime
2015-10-13 10:09:12 -07:00
import traceback, sys
2015-10-07 04:06:28 -07:00
from kivy.app import App
from kivy.cache import Cache
from kivy.clock import Clock
from kivy.compat import string_types
from kivy.properties import (ObjectProperty, DictProperty, NumericProperty,
2015-12-04 02:47:46 -08:00
ListProperty, StringProperty)
2016-01-16 07:47:48 -08:00
from kivy.uix.label import Label
2015-12-04 02:47:46 -08:00
from kivy.lang import Builder
from kivy.factory import Factory
2016-02-06 07:58:31 -08:00
from kivy.utils import platform
2016-02-18 02:24:38 -08:00
from electrum.util import profiler, parse_URI, format_time, InvalidPassword, NotEnoughFunds
2015-10-07 04:06:28 -07:00
from electrum import bitcoin
2015-10-13 03:12:49 -07:00
from electrum.util import timestamp_to_datetime
2016-02-04 01:57:09 -08:00
from electrum.paymentrequest import PR_UNPAID, PR_PAID, PR_UNKNOWN, PR_EXPIRED
2015-12-12 07:54:32 -08:00
from context_menu import ContextMenu
2016-02-04 01:57:09 -08:00
from electrum_gui.kivy.i18n import _
2016-01-19 03:57:18 -08:00
class EmptyLabel(Factory.Label):
pass
2016-01-19 03:57:18 -08:00
class CScreen(Factory.Screen):
__events__ = ('on_activate', 'on_deactivate', 'on_enter', 'on_leave')
action_view = ObjectProperty(None)
loaded = False
kvname = None
2015-12-12 07:54:32 -08:00
context_menu = None
menu_actions = []
app = App.get_running_app()
def _change_action_view(self):
app = App.get_running_app()
action_bar = app.root.manager.current_screen.ids.action_bar
_action_view = self.action_view
if (not _action_view) or _action_view.parent:
return
action_bar.clear_widgets()
action_bar.add_widget(_action_view)
def on_enter(self):
# FIXME: use a proper event don't use animation time of screen
Clock.schedule_once(lambda dt: self.dispatch('on_activate'), .25)
pass
def update(self):
pass
2015-10-06 05:30:44 -07:00
@profiler
def load_screen(self):
self.screen = Builder.load_file('gui/kivy/uix/ui_screens/' + self.kvname + '.kv')
self.add_widget(self.screen)
self.loaded = True
self.update()
setattr(self.app, self.kvname + '_screen', self)
def on_activate(self):
if self.kvname and not self.loaded:
2015-10-06 05:30:44 -07:00
self.load_screen()
#Clock.schedule_once(lambda dt: self._change_action_view())
def on_leave(self):
self.dispatch('on_deactivate')
def on_deactivate(self):
2015-12-12 07:54:32 -08:00
self.hide_menu()
def hide_menu(self):
if self.context_menu is not None:
self.remove_widget(self.context_menu)
2015-12-12 07:54:32 -08:00
self.context_menu = None
def show_menu(self, obj):
self.hide_menu()
self.context_menu = ContextMenu(obj, self.menu_actions)
self.add_widget(self.context_menu)
2015-12-12 07:54:32 -08:00
TX_ICONS = [
"close",
"close",
"close",
"unconfirmed",
"close",
"clock1",
"clock2",
"clock3",
"clock4",
"clock5",
"confirmed",
]
class HistoryScreen(CScreen):
tab = ObjectProperty(None)
kvname = 'history'
2016-06-01 10:21:37 -07:00
cards = {}
def __init__(self, **kwargs):
self.ra_dialog = None
super(HistoryScreen, self).__init__(**kwargs)
2016-02-12 07:09:16 -08:00
self.menu_actions = [ ('Label', self.label_dialog), ('Details', self.show_tx)]
def show_tx(self, obj):
tx_hash = obj.tx_hash
tx = self.app.wallet.transactions.get(tx_hash)
if not tx:
return
self.app.tx_dialog(tx)
2015-12-14 03:08:11 -08:00
def label_dialog(self, obj):
from dialogs.label_dialog import LabelDialog
key = obj.tx_hash
2015-12-15 03:52:30 -08:00
text = self.app.wallet.get_label(key)
2015-12-14 03:08:11 -08:00
def callback(text):
self.app.wallet.set_label(key, text)
self.update()
d = LabelDialog(_('Enter Transaction Label'), text, callback)
d.open()
2016-06-01 10:21:37 -07:00
def get_card(self, tx_hash, height, conf, timestamp, value, balance):
status, status_str = self.app.wallet.get_tx_status(tx_hash, height, conf, timestamp)
icon = "atlas://gui/kivy/theming/light/" + TX_ICONS[status]
label = self.app.wallet.get_label(tx_hash) if tx_hash else _('Pruned transaction outputs')
date = timestamp_to_datetime(timestamp)
ri = self.cards.get(tx_hash)
if ri is None:
ri = Factory.HistoryItem()
ri.screen = self
ri.tx_hash = tx_hash
self.cards[tx_hash] = ri
ri.icon = icon
ri.date = status_str
ri.message = label
ri.value = value or 0
2017-03-09 07:55:32 -08:00
ri.amount = self.app.format_amount(value, True) if value is not None else '--'
2016-06-01 10:21:37 -07:00
ri.confirmations = conf
if self.app.fiat_unit and date:
rate = self.app.fx.history_rate(date)
2016-06-01 10:21:37 -07:00
if rate:
s = self.app.fx.value_str(value, rate)
2016-06-01 10:21:37 -07:00
ri.quote_text = '' if s is None else s + ' ' + self.app.fiat_unit
return ri
def update(self, see_all=False):
2015-10-13 06:58:34 -07:00
if self.app.wallet is None:
return
2016-08-30 02:19:30 -07:00
history = reversed(self.app.wallet.get_history())
2016-01-16 07:47:48 -08:00
history_card = self.screen.ids.history_container
2015-12-12 07:54:32 -08:00
history_card.clear_widgets()
count = 0
2015-10-07 04:06:28 -07:00
for item in history:
2016-06-01 10:21:37 -07:00
ri = self.get_card(*item)
count += 1
2016-01-16 07:47:48 -08:00
history_card.add_widget(ri)
2016-01-16 07:47:48 -08:00
if count == 0:
msg = _('This screen shows your list of transactions. It is currently empty.')
history_card.add_widget(EmptyLabel(text=msg))
class SendScreen(CScreen):
2015-12-02 06:27:23 -08:00
kvname = 'send'
2015-12-11 06:21:21 -08:00
payment_request = None
2015-12-02 06:27:23 -08:00
def set_URI(self, text):
import electrum
try:
uri = electrum.util.parse_URI(text, self.app.on_pr)
except:
2016-02-26 01:48:43 -08:00
self.app.show_info(_("Not a Bitcoin URI"))
return
2016-02-18 06:53:52 -08:00
amount = uri.get('amount')
2015-12-04 02:47:46 -08:00
self.screen.address = uri.get('address', '')
self.screen.message = uri.get('message', '')
self.screen.amount = self.app.format_amount_and_units(amount) if amount else ''
2016-02-18 06:53:52 -08:00
self.payment_request = None
self.screen.is_pr = False
2015-12-12 14:23:58 -08:00
def update(self):
2016-02-12 13:20:20 -08:00
pass
2015-12-12 14:23:58 -08:00
2015-10-14 05:18:15 -07:00
def do_clear(self):
2015-12-04 02:47:46 -08:00
self.screen.amount = ''
self.screen.message = ''
self.screen.address = ''
2015-12-11 06:21:21 -08:00
self.payment_request = None
self.screen.is_pr = False
2015-12-11 06:21:21 -08:00
def set_request(self, pr):
self.screen.address = pr.get_requestor()
2015-12-13 08:49:51 -08:00
amount = pr.get_amount()
self.screen.amount = self.app.format_amount_and_units(amount) if amount else ''
2015-12-11 06:21:21 -08:00
self.screen.message = pr.get_memo()
if pr.is_pr():
self.screen.is_pr = True
self.payment_request = pr
2016-02-18 06:45:34 -08:00
else:
self.screen.is_pr = False
self.payment_request = None
2015-10-14 05:18:15 -07:00
2016-02-09 03:48:25 -08:00
def do_save(self):
if not self.screen.address:
return
2016-02-18 06:45:34 -08:00
if self.screen.is_pr:
2016-02-09 03:48:25 -08:00
# it sould be already saved
return
# save address as invoice
from electrum.paymentrequest import make_unsigned_request, PaymentRequest
req = {'address':self.screen.address, 'memo':self.screen.message}
amount = self.app.get_amount(self.screen.amount) if self.screen.amount else 0
req['amount'] = amount
pr = make_unsigned_request(req).SerializeToString()
pr = PaymentRequest(pr)
self.app.wallet.invoices.add(pr)
2016-02-09 03:48:25 -08:00
self.app.update_tab('invoices')
self.app.show_info(_("Invoice saved"))
2016-02-19 04:53:01 -08:00
if pr.is_pr():
self.screen.is_pr = True
self.payment_request = pr
else:
self.screen.is_pr = False
self.payment_request = None
2016-02-09 03:48:25 -08:00
2015-12-04 02:47:46 -08:00
def do_paste(self):
contents = unicode(self.app._clipboard.paste())
2016-02-09 03:48:25 -08:00
if not contents:
self.app.show_info(_("Clipboard is empty"))
return
self.set_URI(contents)
2015-10-06 05:30:44 -07:00
2015-12-04 02:47:46 -08:00
def do_send(self):
2016-02-18 06:45:34 -08:00
if self.screen.is_pr:
2015-12-11 06:21:21 -08:00
if self.payment_request.has_expired():
self.app.show_error(_('Payment request has expired'))
return
outputs = self.payment_request.get_outputs()
else:
address = str(self.screen.address)
2016-02-26 01:25:37 -08:00
if not address:
2016-02-26 01:29:16 -08:00
self.app.show_error(_('Recipient not specified.') + ' ' + _('Please scan a Bitcoin address or a payment request'))
2016-02-26 01:25:37 -08:00
return
2015-12-11 06:21:21 -08:00
if not bitcoin.is_address(address):
self.app.show_error(_('Invalid Bitcoin Address') + ':\n' + address)
return
try:
amount = self.app.get_amount(self.screen.amount)
except:
self.app.show_error(_('Invalid amount') + ':\n' + self.screen.amount)
return
2016-01-14 08:15:50 -08:00
outputs = [(bitcoin.TYPE_ADDRESS, address, amount)]
2015-12-04 03:01:13 -08:00
message = unicode(self.screen.message)
2016-02-13 01:00:20 -08:00
amount = sum(map(lambda x:x[2], outputs))
2016-07-29 06:47:13 -07:00
if self.app.electrum_config.get('use_rbf'):
from dialogs.question import Question
d = Question(_('Should this transaction be replaceable?'), lambda b: self._do_send(amount, message, outputs, b))
d.open()
else:
self._do_send(amount, message, outputs, False)
def _do_send(self, amount, message, outputs, rbf):
2015-10-06 05:30:44 -07:00
# make unsigned transaction
coins = self.app.wallet.get_spendable_coins()
2016-02-13 01:00:20 -08:00
config = self.app.electrum_config
2015-10-06 05:30:44 -07:00
try:
2016-02-13 01:00:20 -08:00
tx = self.app.wallet.make_unsigned_transaction(coins, outputs, config, None)
2016-02-18 02:24:38 -08:00
except NotEnoughFunds:
self.app.show_error(_("Not enough funds"))
return
2015-10-06 05:30:44 -07:00
except Exception as e:
traceback.print_exc(file=sys.stdout)
self.app.show_error(str(e))
2015-10-06 05:30:44 -07:00
return
2016-07-29 06:47:13 -07:00
if rbf:
2016-06-09 20:49:22 -07:00
tx.set_sequence(0)
2016-02-13 01:00:20 -08:00
fee = tx.get_fee()
msg = [
_("Amount to be sent") + ": " + self.app.format_amount_and_units(amount),
_("Mining fee") + ": " + self.app.format_amount_and_units(fee),
]
if fee >= config.get('confirm_fee', 100000):
msg.append(_('Warning')+ ': ' + _("The fee for this transaction seems unusually high."))
msg.append(_("Enter your PIN code to proceed"))
2016-02-19 05:25:01 -08:00
self.app.protected('\n'.join(msg), self.send_tx, (tx, message))
2016-02-13 01:00:20 -08:00
2016-02-19 05:25:01 -08:00
def send_tx(self, tx, message, password):
def on_success(tx):
if tx.is_complete():
2016-02-19 04:53:01 -08:00
self.app.broadcast(tx, self.payment_request)
2016-02-19 05:25:01 -08:00
self.app.wallet.set_label(tx.hash(), message)
else:
self.app.tx_dialog(tx)
def on_failure(error):
self.app.show_error(error)
2016-02-13 01:33:49 -08:00
if self.app.wallet.can_sign(tx):
self.app.show_info("Signing...")
self.app.sign_tx(tx, password, on_success, on_failure)
else:
2016-02-12 23:15:06 -08:00
self.app.tx_dialog(tx)
2015-10-06 05:30:44 -07:00
class ReceiveScreen(CScreen):
2015-10-14 02:44:01 -07:00
2015-12-04 02:47:46 -08:00
kvname = 'receive'
2016-02-08 10:01:34 -08:00
2015-10-06 05:30:44 -07:00
def update(self):
2016-02-08 10:01:34 -08:00
if not self.screen.address:
self.get_new_address()
2016-02-14 19:18:58 -08:00
else:
status = self.app.wallet.get_request_status(self.screen.address)
2016-02-15 02:33:48 -08:00
self.screen.status = _('Payment received') if status == PR_PAID else ''
2016-02-08 10:01:34 -08:00
2016-03-05 00:44:28 -08:00
def clear(self):
self.screen.address = ''
self.screen.amount = ''
self.screen.message = ''
2016-02-08 10:01:34 -08:00
def get_new_address(self):
2016-03-10 07:22:19 -08:00
if not self.app.wallet:
return False
self.clear()
addr = self.app.wallet.get_unused_address()
2016-02-08 10:01:34 -08:00
if addr is None:
2017-03-08 09:41:47 -08:00
addr = self.app.wallet.get_receiving_address() or ''
b = False
else:
b = True
2015-12-12 14:23:58 -08:00
self.screen.address = addr
return b
2016-02-08 10:01:34 -08:00
def on_address(self, addr):
2016-02-14 03:24:31 -08:00
req = self.app.wallet.get_payment_request(addr, self.app.electrum_config)
self.screen.status = ''
2015-12-12 14:23:58 -08:00
if req:
2015-12-13 06:26:08 -08:00
self.screen.message = unicode(req.get('memo', ''))
2015-12-13 08:49:51 -08:00
amount = req.get('amount')
2016-02-14 19:18:58 -08:00
self.screen.amount = self.app.format_amount_and_units(amount) if amount else ''
status = req.get('status', PR_UNKNOWN)
2016-02-15 02:33:48 -08:00
self.screen.status = _('Payment received') if status == PR_PAID else ''
2016-02-08 10:01:34 -08:00
Clock.schedule_once(lambda dt: self.update_qr())
2015-10-14 02:44:01 -07:00
2015-12-04 02:47:46 -08:00
def get_URI(self):
2015-10-14 09:03:02 -07:00
from electrum.util import create_URI
2015-12-04 02:47:46 -08:00
amount = self.screen.amount
if amount:
a, u = self.screen.amount.split()
2015-10-16 02:18:24 -07:00
assert u == self.app.base_unit
amount = Decimal(a) * pow(10, self.app.decimal_point())
2015-12-04 02:47:46 -08:00
return create_URI(self.screen.address, amount, self.screen.message)
@profiler
def update_qr(self):
uri = self.get_URI()
qr = self.screen.ids.qr
2015-10-14 02:44:01 -07:00
qr.set_data(uri)
2016-02-06 07:58:31 -08:00
def do_share(self):
uri = self.get_URI()
2016-06-16 00:47:31 -07:00
self.app.do_share(uri, _("Share Bitcoin Request"))
2016-02-06 07:35:21 -08:00
2016-02-06 07:58:31 -08:00
def do_copy(self):
uri = self.get_URI()
self.app._clipboard.copy(uri)
2016-01-29 03:46:28 -08:00
self.app.show_info(_('Request copied to clipboard'))
2015-10-14 09:45:26 -07:00
def save_request(self):
2015-12-11 06:48:56 -08:00
addr = str(self.screen.address)
amount = str(self.screen.amount)
2016-03-13 00:25:48 -08:00
message = unicode(self.screen.message)
2016-02-08 10:01:34 -08:00
amount = self.app.get_amount(amount) if amount else 0
2015-12-11 06:48:56 -08:00
req = self.app.wallet.make_payment_request(addr, amount, message, None)
self.app.wallet.add_payment_request(req, self.app.electrum_config)
2015-12-18 06:03:38 -08:00
self.app.update_tab('requests')
def on_amount_or_message(self):
self.save_request()
2016-02-08 10:01:34 -08:00
Clock.schedule_once(lambda dt: self.update_qr())
2015-12-11 06:48:56 -08:00
2015-12-13 06:26:08 -08:00
def do_new(self):
addr = self.get_new_address()
if not addr:
2016-02-08 10:01:34 -08:00
self.app.show_info(_('Please use the existing requests first.'))
else:
self.save_request()
2016-02-15 02:33:48 -08:00
self.app.show_info(_('New request added to your list.'))
2015-10-06 05:30:44 -07:00
2016-02-15 02:33:48 -08:00
invoice_text = {
PR_UNPAID:_('Pending'),
PR_UNKNOWN:_('Unknown'),
PR_PAID:_('Paid'),
PR_EXPIRED:_('Expired')
}
2016-02-15 02:33:48 -08:00
request_text = {
PR_UNPAID: _('Pending'),
PR_UNKNOWN: _('Unknown'),
PR_PAID: _('Received'),
PR_EXPIRED: _('Expired')
2016-02-14 19:18:58 -08:00
}
pr_icon = {
PR_UNPAID: 'atlas://gui/kivy/theming/light/important',
PR_UNKNOWN: 'atlas://gui/kivy/theming/light/important',
PR_PAID: 'atlas://gui/kivy/theming/light/confirmed',
PR_EXPIRED: 'atlas://gui/kivy/theming/light/close'
}
class InvoicesScreen(CScreen):
kvname = 'invoices'
2016-06-01 10:21:37 -07:00
cards = {}
def get_card(self, pr):
key = pr.get_id()
ci = self.cards.get(key)
if ci is None:
ci = Factory.InvoiceItem()
ci.key = key
ci.screen = self
self.cards[key] = ci
ci.requestor = pr.get_requestor()
ci.memo = pr.get_memo()
amount = pr.get_amount()
if amount:
ci.amount = self.app.format_amount_and_units(amount)
2017-03-08 11:05:26 -08:00
status = self.app.wallet.invoices.get_status(ci.key)
2016-06-01 10:21:37 -07:00
ci.status = invoice_text[status]
ci.icon = pr_icon[status]
else:
ci.amount = _('No Amount')
ci.status = ''
exp = pr.get_expiration_date()
ci.date = format_time(exp) if exp else _('Never')
return ci
def update(self):
2016-02-11 02:40:23 -08:00
self.menu_actions = [('Pay', self.do_pay), ('Details', self.do_view), ('Delete', self.do_delete)]
invoices_list = self.screen.ids.invoices_container
invoices_list.clear_widgets()
_list = self.app.wallet.invoices.sorted_list()
2016-01-16 07:47:48 -08:00
for pr in _list:
2016-06-01 10:21:37 -07:00
ci = self.get_card(pr)
invoices_list.add_widget(ci)
2016-01-16 07:47:48 -08:00
if not _list:
2016-02-09 04:46:42 -08:00
msg = _('This screen shows the list of payment requests that have been sent to you. You may also use it to store contact addresses.')
2016-01-16 07:47:48 -08:00
invoices_list.add_widget(EmptyLabel(text=msg))
2015-12-12 14:23:58 -08:00
def do_pay(self, obj):
pr = self.app.wallet.invoices.get(obj.key)
self.app.on_pr(pr)
2015-12-12 07:54:32 -08:00
2016-02-11 02:40:23 -08:00
def do_view(self, obj):
pr = self.app.wallet.invoices.get(obj.key)
pr.verify(self.app.wallet.contacts)
self.app.show_pr_details(pr.get_dict(), obj.status, True)
2016-02-11 02:40:23 -08:00
2015-12-12 14:23:58 -08:00
def do_delete(self, obj):
2016-02-08 10:01:34 -08:00
from dialogs.question import Question
2016-07-29 06:47:13 -07:00
def cb(result):
if result:
self.app.wallet.invoices.remove(obj.key)
2016-07-29 06:47:13 -07:00
self.app.update_tab('invoices')
2016-02-08 10:01:34 -08:00
d = Question(_('Delete invoice?'), cb)
d.open()
2015-12-12 07:54:32 -08:00
class RequestsScreen(CScreen):
kvname = 'requests'
2016-06-01 10:21:37 -07:00
cards = {}
def get_card(self, req):
address = req['address']
timestamp = req.get('time', 0)
amount = req.get('amount')
expiration = req.get('exp', None)
status = req.get('status')
signature = req.get('sig')
ci = self.cards.get(address)
if ci is None:
ci = Factory.RequestItem()
ci.screen = self
ci.address = address
self.cards[address] = ci
ci.memo = self.app.wallet.get_label(address)
if amount:
status = req.get('status')
ci.status = request_text[status]
else:
received = self.app.wallet.get_addr_received(address)
ci.status = self.app.format_amount_and_units(amount)
ci.icon = pr_icon[status]
ci.amount = self.app.format_amount_and_units(amount) if amount else _('No Amount')
ci.date = format_time(timestamp)
return ci
def update(self):
2016-02-15 04:49:33 -08:00
self.menu_actions = [('Show', self.do_show), ('Details', self.do_view), ('Delete', self.do_delete)]
requests_list = self.screen.ids.requests_container
requests_list.clear_widgets()
2016-03-10 07:22:19 -08:00
_list = self.app.wallet.get_sorted_requests(self.app.electrum_config) if self.app.wallet else []
2016-01-16 07:47:48 -08:00
for req in _list:
2016-06-01 10:21:37 -07:00
ci = self.get_card(req)
requests_list.add_widget(ci)
2016-01-16 07:47:48 -08:00
if not _list:
2016-01-21 03:20:45 -08:00
msg = _('This screen shows the list of payment requests you made.')
2016-01-16 07:47:48 -08:00
requests_list.add_widget(EmptyLabel(text=msg))
2015-12-12 14:23:58 -08:00
def do_show(self, obj):
self.app.show_request(obj.address)
2016-02-15 04:49:33 -08:00
def do_view(self, obj):
req = self.app.wallet.get_payment_request(obj.address, self.app.electrum_config)
status = req.get('status')
amount = req.get('amount')
address = req['address']
if amount:
status = req.get('status')
status = request_text[status]
2016-02-15 04:49:33 -08:00
else:
2016-02-17 21:58:46 -08:00
received_amount = self.app.wallet.get_addr_received(address)
status = self.app.format_amount_and_units(received_amount)
2016-02-15 04:49:33 -08:00
self.app.show_pr_details(req, status, False)
2015-12-12 14:23:58 -08:00
def do_delete(self, obj):
2016-02-08 10:01:34 -08:00
from dialogs.question import Question
2016-07-29 06:47:13 -07:00
def cb(result):
if result:
self.app.wallet.remove_payment_request(obj.address, self.app.electrum_config)
self.update()
2016-02-08 10:01:34 -08:00
d = Question(_('Delete request?'), cb)
d.open()
2015-12-12 07:54:32 -08:00
class TabbedCarousel(Factory.TabbedPanel):
'''Custom TabbedPanel using a carousel used in the Main Screen
'''
carousel = ObjectProperty(None)
def animate_tab_to_center(self, value):
scrlv = self._tab_strip.parent
if not scrlv:
return
idx = self.tab_list.index(value)
2015-12-10 06:26:38 -08:00
n = len(self.tab_list)
if idx in [0, 1]:
scroll_x = 1
elif idx in [n-1, n-2]:
scroll_x = 0
else:
scroll_x = 1. * (n - idx - 1) / (n - 1)
mation = Factory.Animation(scroll_x=scroll_x, d=.25)
mation.cancel_all(scrlv)
mation.start(scrlv)
def on_current_tab(self, instance, value):
self.animate_tab_to_center(value)
def on_index(self, instance, value):
current_slide = instance.current_slide
if not hasattr(current_slide, 'tab'):
return
tab = current_slide.tab
ct = self.current_tab
try:
if ct.text != tab.text:
carousel = self.carousel
carousel.slides[ct.slide].dispatch('on_leave')
self.switch_to(tab)
carousel.slides[tab.slide].dispatch('on_enter')
except AttributeError:
current_slide.dispatch('on_enter')
def switch_to(self, header):
# we have to replace the functionality of the original switch_to
if not header:
return
if not hasattr(header, 'slide'):
header.content = self.carousel
super(TabbedCarousel, self).switch_to(header)
try:
tab = self.tab_list[-1]
except IndexError:
return
self._current_tab = tab
tab.state = 'down'
return
carousel = self.carousel
self.current_tab.state = "normal"
header.state = 'down'
self._current_tab = header
# set the carousel to load the appropriate slide
# saved in the screen attribute of the tab head
slide = carousel.slides[header.slide]
if carousel.current_slide != slide:
carousel.current_slide.dispatch('on_leave')
carousel.load_slide(slide)
slide.dispatch('on_enter')
def add_widget(self, widget, index=0):
if isinstance(widget, Factory.CScreen):
self.carousel.add_widget(widget)
return
super(TabbedCarousel, self).add_widget(widget, index=index)