Skip to content

Commit 4f48bfb

Browse files
committed
Add Kivy myaddress screen
1 parent 09cc100 commit 4f48bfb

File tree

6 files changed

+305
-2
lines changed

6 files changed

+305
-2
lines changed
Lines changed: 232 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,232 @@
1+
# pylint: disable=unused-argument, import-error, no-member, attribute-defined-outside-init
2+
# pylint: disable=no-name-in-module, too-few-public-methods, too-many-instance-attributes
3+
4+
"""
5+
myaddress.py
6+
==============
7+
All generated addresses are managed in MyAddress
8+
"""
9+
10+
import os
11+
from functools import partial
12+
13+
from kivy.clock import Clock
14+
from kivy.properties import (
15+
ListProperty,
16+
StringProperty
17+
)
18+
from kivy.uix.screenmanager import Screen, ScreenManagerException
19+
from kivy.app import App
20+
21+
from kivymd.uix.list import (
22+
IRightBodyTouch,
23+
TwoLineAvatarIconListItem,
24+
)
25+
from kivymd.uix.selectioncontrol import MDSwitch
26+
27+
from pybitmessage.bmconfigparser import config
28+
29+
from pybitmessage.bitmessagekivy.get_platform import platform
30+
from pybitmessage.bitmessagekivy.baseclass.common import (
31+
avatar_image_first_letter, AvatarSampleWidget, ThemeClsColor,
32+
toast, empty_screen_label, load_image_path
33+
)
34+
35+
from pybitmessage.bitmessagekivy.baseclass.popup import MyaddDetailPopup
36+
from pybitmessage.bitmessagekivy.baseclass.myaddress_widgets import HelperMyAddress
37+
38+
39+
class ToggleBtn(IRightBodyTouch, MDSwitch):
40+
"""ToggleBtn class for kivy UI"""
41+
42+
43+
class CustomTwoLineAvatarIconListItem(TwoLineAvatarIconListItem):
44+
"""CustomTwoLineAvatarIconListItem class for kivy Ui"""
45+
46+
47+
class MyAddress(Screen, HelperMyAddress):
48+
"""MyAddress screen class for kivy Ui"""
49+
50+
address_label = StringProperty()
51+
text_address = StringProperty()
52+
addresses_list = ListProperty()
53+
has_refreshed = True
54+
is_add_created = False
55+
label_str = "Yet no address is created by user!!!!!!!!!!!!!"
56+
no_search_res_found = "No search result found"
57+
min_scroll_y_limit = -0.0
58+
scroll_y_step = 0.06
59+
number_of_addresses = 20
60+
addresses_at_a_time = 15
61+
canvas_color_black = [0, 0, 0, 0]
62+
canvas_color_gray = [0.5, 0.5, 0.5, 0.5]
63+
is_android_width = .9
64+
other_platform_width = .6
65+
disabled_addr_width = .8
66+
other_platform_disabled_addr_width = .55
67+
max_scroll_limit = 1.0
68+
69+
def __init__(self, *args, **kwargs):
70+
"""Clock schdule for method Myaddress accounts"""
71+
super(MyAddress, self).__init__(*args, **kwargs)
72+
self.image_dir = load_image_path()
73+
self.kivy_running_app = App.get_running_app()
74+
self.kivy_state = self.kivy_running_app.kivy_state_obj
75+
76+
Clock.schedule_once(self.init_ui, 0)
77+
78+
def init_ui(self, dt=0):
79+
"""Clock schdule for method Myaddress accounts"""
80+
self.addresses_list = config.addresses()
81+
if self.kivy_state.searching_text:
82+
self.ids.refresh_layout.scroll_y = self.max_scroll_limit
83+
filtered_list = [
84+
x for x in config.addresses()
85+
if self.filter_address(x)
86+
]
87+
self.addresses_list = filtered_list
88+
self.addresses_list = [obj for obj in reversed(self.addresses_list)]
89+
self.ids.tag_label.text = ''
90+
if self.addresses_list:
91+
self.ids.tag_label.text = 'My Addresses'
92+
self.has_refreshed = True
93+
self.set_mdList(0, self.addresses_at_a_time)
94+
self.ids.refresh_layout.bind(scroll_y=self.check_scroll_y)
95+
else:
96+
self.ids.ml.add_widget(empty_screen_label(self.label_str, self.no_search_res_found))
97+
if not self.kivy_state.searching_text and not self.is_add_created:
98+
try:
99+
self.manager.current = 'login'
100+
except ScreenManagerException:
101+
pass
102+
103+
def get_address_list(self, first_index, last_index, data):
104+
"""Getting address and append to the list"""
105+
for address in self.addresses_list[first_index:last_index]:
106+
data.append({
107+
'text': config.get(address, 'label'),
108+
'secondary_text': address}
109+
)
110+
return data
111+
112+
def set_address_to_widget(self, item):
113+
"""Setting address to the widget"""
114+
is_enable = config.getboolean(item['secondary_text'], 'enabled')
115+
meny = CustomTwoLineAvatarIconListItem(
116+
text=item['text'], secondary_text=item['secondary_text'],
117+
theme_text_color='Custom' if is_enable else 'Primary',
118+
text_color=ThemeClsColor,)
119+
try:
120+
meny.canvas.children[3].rgba = self.canvas_color_black if is_enable else self.canvas_color
121+
except Exception:
122+
pass
123+
meny.add_widget(AvatarSampleWidget(
124+
source=os.path.join(
125+
self.image_dir, "text_images", "{}.png".format(avatar_image_first_letter(
126+
item["text"].strip())))
127+
))
128+
meny.bind(on_press=partial(
129+
self.myadd_detail, item['secondary_text'], item['text']))
130+
self.set_address_status(item, meny, is_enable)
131+
132+
def set_address_status(self, item, meny, is_enable):
133+
"""Setting the identity status enable/disable on UI"""
134+
if self.kivy_state.association == item['secondary_text'] and is_enable:
135+
meny.add_widget(self.is_active_badge())
136+
else:
137+
meny.add_widget(ToggleBtn(active=True if is_enable else False))
138+
self.ids.ml.add_widget(meny)
139+
140+
def set_mdList(self, first_index, last_index):
141+
"""Creating the mdlist"""
142+
data = []
143+
self.get_address_list(first_index, last_index, data)
144+
for item in data:
145+
self.set_address_to_widget(item)
146+
147+
def check_scroll_y(self, instance, somethingelse):
148+
"""Load data on Scroll down"""
149+
if self.ids.refresh_layout.scroll_y <= self.min_scroll_y_limit and self.has_refreshed:
150+
self.ids.refresh_layout.scroll_y = self.scroll_y_step
151+
my_addresses = len(self.ids.ml.children)
152+
if my_addresses != len(self.addresses_list):
153+
self.update_addressBook_on_scroll(my_addresses)
154+
self.has_refreshed = (
155+
True if my_addresses != len(self.addresses_list) else False
156+
)
157+
158+
def update_addressBook_on_scroll(self, my_addresses):
159+
"""Loads more data on scroll down"""
160+
self.set_mdList(my_addresses, my_addresses + self.number_of_addresses)
161+
162+
def myadd_detail(self, fromaddress, label, *args):
163+
"""Load myaddresses details"""
164+
if config.get(fromaddress, 'enabled'):
165+
obj = MyaddDetailPopup()
166+
self.address_label = obj.address_label = label
167+
self.text_address = obj.address = fromaddress
168+
width = self.is_android_width if platform == 'android' else self.other_platform_width
169+
self.myadddetail_popup = self.myaddress_detail_popup(obj, width)
170+
self.myadddetail_popup.auto_dismiss = False
171+
self.myadddetail_popup.open()
172+
else:
173+
width = self.disabled_addr_width if platform == 'android' else self.other_platform_disabled_addr_width
174+
self.dialog_box = self.inactive_address_popup(width, self.callback_for_menu_items)
175+
self.dialog_box.open()
176+
177+
def callback_for_menu_items(self, text_item, *arg):
178+
"""Callback of inactive address alert box"""
179+
self.dialog_box.dismiss()
180+
toast(text_item)
181+
182+
def refresh_callback(self, *args):
183+
"""Method updates the state of application,
184+
While the spinner remains on the screen"""
185+
def refresh_callback(interval):
186+
"""Method used for loading the myaddress screen data"""
187+
self.kivy_state.searching_text = ''
188+
self.ids.search_bar.ids.search_field.text = ''
189+
self.has_refreshed = True
190+
self.ids.ml.clear_widgets()
191+
self.init_ui()
192+
self.ids.refresh_layout.refresh_done()
193+
Clock.schedule_once(self.address_permision_callback, 0)
194+
Clock.schedule_once(refresh_callback, 1)
195+
196+
@staticmethod
197+
def filter_address(address):
198+
"""It will return True if search is matched"""
199+
searched_text = App.get_running_app().kivy_state_obj.searching_text.lower()
200+
return bool(config.search_addresses(address, searched_text))
201+
202+
def disable_address_ui(self, address, instance):
203+
"""This method is used to disable addresses from UI"""
204+
config.disable_address(address)
205+
instance.parent.parent.theme_text_color = 'Primary'
206+
instance.parent.parent.canvas.children[3].rgba = MyAddress.canvas_color_gray
207+
toast('Address disabled')
208+
Clock.schedule_once(self.address_permision_callback, 0)
209+
210+
def enable_address_ui(self, address, instance):
211+
"""This method is used to enable addresses from UI"""
212+
config.enable_address(address)
213+
instance.parent.parent.theme_text_color = 'Custom'
214+
instance.parent.parent.canvas.children[3].rgba = MyAddress.canvas_color_black
215+
toast('Address Enabled')
216+
Clock.schedule_once(self.address_permision_callback, 0)
217+
218+
def address_permision_callback(self, dt=0):
219+
"""callback for enable or disable addresses"""
220+
addresses = [addr for addr in config.addresses()
221+
if config.getboolean(str(addr), 'enabled')]
222+
self.parent.parent.ids.content_drawer.ids.identity_dropdown.values = addresses
223+
# self.parent.parent.ids.sc3.children[1].ids.btn.values = addresses
224+
self.kivy_running_app.identity_list = addresses
225+
226+
def toggleAction(self, instance):
227+
"""This method is used for enable or disable address"""
228+
addr = instance.parent.parent.secondary_text
229+
if instance.active:
230+
self.enable_address_ui(addr, instance)
231+
else:
232+
self.disable_address_ui(addr, instance)
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
# pylint: disable=too-many-arguments, no-name-in-module, import-error
2+
# pylint: disable=too-few-public-methods, no-member, too-many-ancestors
3+
4+
"""
5+
MyAddress widgets are here.
6+
"""
7+
8+
from kivymd.uix.button import MDFlatButton
9+
from kivymd.uix.dialog import MDDialog
10+
from kivymd.uix.label import MDLabel
11+
from kivymd.uix.list import IRightBodyTouch
12+
13+
from pybitmessage.bitmessagekivy.get_platform import platform
14+
from pybitmessage.bitmessagekivy.baseclass.common import ThemeClsColor
15+
16+
17+
class BadgeText(IRightBodyTouch, MDLabel):
18+
"""BadgeText class for kivy UI"""
19+
20+
21+
class HelperMyAddress(object):
22+
"""Widget used in MyAddress are here"""
23+
dialog_height = .25
24+
25+
@staticmethod
26+
def is_active_badge():
27+
"""This function show the 'active' label of active Address."""
28+
active_status = 'Active'
29+
is_android_width = 90
30+
width = 50
31+
height = 60
32+
badge_obj = BadgeText(
33+
size_hint=(None, None),
34+
size=[is_android_width if platform == 'android' else width, height],
35+
text=active_status, halign='center',
36+
font_style='Body1', theme_text_color='Custom',
37+
text_color=ThemeClsColor, font_size='13sp'
38+
)
39+
return badge_obj
40+
41+
@staticmethod
42+
def myaddress_detail_popup(obj, width):
43+
"""This method show the details of address as popup opens."""
44+
show_myaddress_dialogue = MDDialog(
45+
type="custom",
46+
size_hint=(width, HelperMyAddress.dialog_height),
47+
content_cls=obj,
48+
)
49+
return show_myaddress_dialogue
50+
51+
@staticmethod
52+
def inactive_address_popup(width, callback_for_menu_items):
53+
"""This method shows the warning popup if the address is inactive"""
54+
dialog_text = 'Address is not currently active. Please click on Toggle button to active it.'
55+
dialog_box = MDDialog(
56+
text=dialog_text,
57+
size_hint=(width, HelperMyAddress.dialog_height),
58+
buttons=[
59+
MDFlatButton(
60+
text="Ok", on_release=lambda x: callback_for_menu_items("Ok")
61+
),
62+
],
63+
)
64+
return dialog_box

src/bitmessagekivy/kv/common_widgets.kv

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@
4949
size_hint: None, None
5050
size: dp(36), dp(48)
5151
pos_hint: {'center_x': .95, 'center_y': .4}
52-
on_active: app.root.ids.sc10.toggleAction(self)
52+
on_active: app.root.ids.id_myaddress.toggleAction(self)
5353

5454
<CustomTwoLineAvatarIconListItem>:
5555
canvas:

src/bitmessagekivy/kv/myaddress.kv

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,4 +30,4 @@
3030
size_hint: None, None
3131
size: dp(36), dp(48)
3232
pos_hint: {'center_x': .95, 'center_y': .4}
33-
on_active: app.root.ids.sc10.toggleAction(self)
33+
on_active: app.root.ids.id_myaddress.toggleAction(self)

src/bitmessagekivy/main.kv

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -212,6 +212,8 @@ MDNavigationLayout:
212212
id:sc6
213213
Random:
214214
id:id_newidentity
215+
MyAddress:
216+
id:id_myaddress
215217

216218
MDNavigationDrawer:
217219
id: nav_drawer

src/bitmessagekivy/screens_data.json

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,5 +2,10 @@
22
"Login": {
33
"kv_string": "login",
44
"Import": "from pybitmessage.bitmessagekivy.baseclass.login import *"
5+
},
6+
"My addresses": {
7+
"kv_string": "myaddress",
8+
"name_screen": "myaddress",
9+
"Import": "from pybitmessage.bitmessagekivy.baseclass.myaddress import MyAddress"
510
}
611
}

0 commit comments

Comments
 (0)