From efc35c5f6919f479ea7a3379a46b98dd0eeed964 Mon Sep 17 00:00:00 2001 From: navjot Date: Tue, 14 Jul 2020 17:30:01 +0530 Subject: [PATCH] Updated all popup's with new UI and made all static path dynamic --- .gitignore | 2 +- src/bitmessagekivy/kv/addressbook.kv | 2 + src/bitmessagekivy/kv/allmails.kv | 1 + src/bitmessagekivy/kv/common_widgets.kv | 2 +- src/bitmessagekivy/kv/draft.kv | 1 + src/bitmessagekivy/kv/inbox.kv | 2 + src/bitmessagekivy/kv/login.kv | 154 +++--- src/bitmessagekivy/kv/myaddress.kv | 3 + src/bitmessagekivy/kv/popup.kv | 384 +++++-------- src/bitmessagekivy/kv/sent.kv | 2 + src/bitmessagekivy/kv/settings.kv | 18 +- src/bitmessagekivy/kv/trash.kv | 1 + src/bitmessagekivy/main.kv | 1 + src/bitmessagekivy/mpybit.py | 515 ++++++++++-------- src/buildozer.spec | 2 +- .../BM-2cVBL4cpxW5p1EuK78huuRFj3nhbP9QdfL.png | Bin 1142 -> 27162 bytes 16 files changed, 536 insertions(+), 554 deletions(-) diff --git a/.gitignore b/.gitignore index 85b62965..aff00e76 100644 --- a/.gitignore +++ b/.gitignore @@ -21,4 +21,4 @@ build pyan/ .buildozer/ bin/ -src/images/kivy/default_identicon/*png \ No newline at end of file +src/images/kivy/default_identicon/*.png \ No newline at end of file diff --git a/src/bitmessagekivy/kv/addressbook.kv b/src/bitmessagekivy/kv/addressbook.kv index e789afa0..73b4c1ef 100644 --- a/src/bitmessagekivy/kv/addressbook.kv +++ b/src/bitmessagekivy/kv/addressbook.kv @@ -4,6 +4,7 @@ orientation: 'vertical' spacing: dp(5) SearchBar: + id: address_search GridLayout: id: identi_tag padding: [20, 0, 0, 5] @@ -11,6 +12,7 @@ size_hint_y: None height: self.minimum_height MDLabel: + id: tag_label text: '' font_style: 'Subtitle2' BoxLayout: diff --git a/src/bitmessagekivy/kv/allmails.kv b/src/bitmessagekivy/kv/allmails.kv index a0514a48..f1b9387e 100644 --- a/src/bitmessagekivy/kv/allmails.kv +++ b/src/bitmessagekivy/kv/allmails.kv @@ -11,6 +11,7 @@ size_hint_y: None height: self.minimum_height MDLabel: + id: tag_label text: '' font_style: 'Subtitle2' BoxLayout: diff --git a/src/bitmessagekivy/kv/common_widgets.kv b/src/bitmessagekivy/kv/common_widgets.kv index bc10222c..d69e648c 100644 --- a/src/bitmessagekivy/kv/common_widgets.kv +++ b/src/bitmessagekivy/kv/common_widgets.kv @@ -5,7 +5,7 @@ y: self.parent.y + self.parent.height/2 - self.height + 5 : - id: search_bar + # id: search_bar size_hint_y: None height: self.minimum_height diff --git a/src/bitmessagekivy/kv/draft.kv b/src/bitmessagekivy/kv/draft.kv index 8182d91e..56682d2b 100644 --- a/src/bitmessagekivy/kv/draft.kv +++ b/src/bitmessagekivy/kv/draft.kv @@ -10,6 +10,7 @@ size_hint_y: None height: self.minimum_height MDLabel: + id: tag_label text: '' font_style: 'Subtitle2' BoxLayout: diff --git a/src/bitmessagekivy/kv/inbox.kv b/src/bitmessagekivy/kv/inbox.kv index 4aadf21f..b9cc8566 100644 --- a/src/bitmessagekivy/kv/inbox.kv +++ b/src/bitmessagekivy/kv/inbox.kv @@ -5,6 +5,7 @@ orientation: 'vertical' spacing: dp(5) SearchBar: + id:inbox_search GridLayout: id: identi_tag padding: [20, 0, 0, 5] @@ -12,6 +13,7 @@ size_hint_y: None height: self.minimum_height MDLabel: + id: tag_label text: '' font_style: 'Subtitle2' #FloatLayout: diff --git a/src/bitmessagekivy/kv/login.kv b/src/bitmessagekivy/kv/login.kv index d09cb4f6..2b923b90 100644 --- a/src/bitmessagekivy/kv/login.kv +++ b/src/bitmessagekivy/kv/login.kv @@ -137,90 +137,96 @@ : name:"random" + ScrollView: + id:add_random_bx + +: + orientation: "vertical" + #buttons-area-outer BoxLayout: orientation: "vertical" - id:add_random_bx - #buttons-area-outer - BoxLayout: - orientation: "vertical" - # padding: 0, dp(5), 0, dp(5) - # spacing: dp(5) - size_hint_y: .53 + # padding: 0, dp(5), 0, dp(5) + # spacing: dp(5) + size_hint_y: .53 + canvas: + Color: + rgba: 1,1,1,1 + Rectangle: + pos: self.pos + size: self.size + + #label area + AnchorLayout: + size_hint_y: None + height: dp(50) + MDLabel: + text: "Enter a label to generate address for:" + bold: True + halign: "center" + theme_text_color: "Custom" + text_color: .4,.4,.4,1 + + AnchorLayout: + size_hint_y: None + height: dp(40) + MDTextField: + id:lab + hint_text: "Label" + required: True + size_hint_x: None + width: dp(190) + helper_text_mode: "on_error" + # helper_text: "Please enter your label name" + on_text: app.root.ids.sc7.add_validation(self) + canvas.before: + Color: + rgba: (0,0,0,1) + + AnchorLayout: + MDFillRoundFlatIconButton: + icon: "chevron-double-right" + text: "Proceed Next" + on_release: app.root.ids.sc7.generateaddress(app) + + Widget: + + #info-area-outer + BoxLayout: + size_hint_y: .47 + padding: dp(7) + InfoLayout: + orientation:"vertical" + padding: 0, dp(5), 0, dp(5) canvas: Color: - rgba: 1,1,1,1 + rgba:1,1,1,1 Rectangle: pos: self.pos size: self.size + Color: + rgba: app.theme_cls.primary_color + Line: + rounded_rectangle: (self.pos[0]+4, self.pos[1]+4, self.width-8,self.height-8, 10, 10, 10, 10, 50) + width: dp(1) + ScreenManager: + id: info_screenmgr - #label area - AnchorLayout: - size_hint_y: None - height: dp(50) - MDLabel: - text: "Enter a label to generate address for:" - bold: True - halign: "center" - theme_text_color: "Custom" - text_color: .4,.4,.4,1 + Screen: + name: "info2" + ScrollView: + bar_width:0 + do_scroll_x: False - AnchorLayout: - size_hint_y: None - height: dp(40) - MDTextField: - id:lab - hint_text: "Label" - required: True - size_hint_x: None - width: dp(190) - helper_text_mode: "on_error" - helper_text: "Please enter your label name" + BoxLayout: + orientation: "vertical" + size_hint_y: None + height: self.minimum_height - AnchorLayout: - MDFillRoundFlatIconButton: - icon: "chevron-double-right" - text: "Proceed Next" - on_release: app.root.ids.sc7.generateaddress(app) - - Widget: - - #info-area-outer - BoxLayout: - size_hint_y: .47 - padding: dp(7) - InfoLayout: - orientation:"vertical" - padding: 0, dp(5), 0, dp(5) - canvas: - Color: - rgba:1,1,1,1 - Rectangle: - pos: self.pos - size: self.size - Color: - rgba: app.theme_cls.primary_color - Line: - rounded_rectangle: (self.pos[0]+4, self.pos[1]+4, self.width-8,self.height-8, 10, 10, 10, 10, 50) - width: dp(1) - ScreenManager: - id: info_screenmgr - - Screen: - name: "info2" - ScrollView: - bar_width:0 - do_scroll_x: False - - BoxLayout: - orientation: "vertical" - size_hint_y: None - height: self.minimum_height - - #note area - ContentHead: - section_name: "NOTE:" - ContentBody: - section_text: ("Here you may generate as many addresses as you like..Indeed creating and abandoning addresses is not encouraged.") + #note area + ContentHead: + section_name: "NOTE:" + ContentBody: + section_text: ("Here you may generate as many addresses as you like..Indeed creating and abandoning addresses is not encouraged.") : group: 'group' diff --git a/src/bitmessagekivy/kv/myaddress.kv b/src/bitmessagekivy/kv/myaddress.kv index a150d59f..39027b1c 100644 --- a/src/bitmessagekivy/kv/myaddress.kv +++ b/src/bitmessagekivy/kv/myaddress.kv @@ -1,9 +1,11 @@ : name: 'myaddress' BoxLayout: + id: main_box orientation: 'vertical' spacing: dp(5) SearchBar: + id: search_bar GridLayout: id: identi_tag padding: [20, 0, 0, 5] @@ -11,6 +13,7 @@ size_hint_y: None height: self.minimum_height MDLabel: + id: tag_label text: 'My Addresses' font_style: 'Subtitle2' FloatLayout: diff --git a/src/bitmessagekivy/kv/popup.kv b/src/bitmessagekivy/kv/popup.kv index 8d2ddd04..2feaf27d 100644 --- a/src/bitmessagekivy/kv/popup.kv +++ b/src/bitmessagekivy/kv/popup.kv @@ -13,263 +13,160 @@ : - id: popup - size_hint : (None,None) - height: 2*(label.height + address.height) + 10 - width :app.window_size[0] - (app.window_size[0]/10 if app.app_platform == 'android' else app.window_size[0]/4) - title: 'add contact\'s' - background: app.image_path + '/popup.jpeg' - title_size: sp(20) - title_color: 0.4, 0.3765, 0.3451, 1 - auto_dismiss: False - separator_color: 0.3529, 0.3922, 0.102, 0.7 + id: popup_box + orientation: 'vertical' + # spacing:dp(20) + # spacing: "12dp" + size_hint_y: None + # height: "120dp" + height: 1.5*label.height+address.height BoxLayout: - size_hint_y: 0.5 orientation: 'vertical' - spacing:dp(20) - id: popup_box - BoxLayout: - orientation: 'vertical' - MDTextField: - id: label - multiline: False - hint_text: "Label" - required: True - helper_text_mode: "on_error" - on_text: root.checkLabel_valid(self) - canvas.before: - Color: - rgba: (0,0,0,1) - MDTextField: - id: address - hint_text: "Address" - required: True - helper_text_mode: "on_error" - multiline: False - on_text: root.checkAddress_valid(self) - canvas.before: - Color: - rgba: (0,0,0,1) - BoxLayout: - spacing:5 - orientation: 'horizontal' - MDRaisedButton: - id: save_addr - size_hint: 1.5, None - height: dp(40) - on_release: - root.savecontact() - MDLabel: - font_style: 'H6' - text: 'Save' - font_size: '13sp' - color: (1,1,1,1) - halign: 'center' - MDRaisedButton: - size_hint: 1.5, None - height: dp(40) - on_press: root.dismiss() - on_press: root.close_pop() - MDLabel: - font_style: 'H6' - text: 'Cancel' - font_size: '13sp' - color: (1,1,1,1) - halign: 'center' - MDRaisedButton: - size_hint: 2, None - height: dp(40) - on_press: root.dismiss() - on_release: - app.root.ids.scr_mngr.current = 'scanscreen' - MDLabel: - font_style: 'H6' - text: 'Scan QR code' - font_size: '13sp' - color: (1,1,1,1) - halign: 'center' + MDTextField: + id: label + multiline: False + hint_text: "Label" + required: True + helper_text_mode: "on_error" + on_text: root.checkLabel_valid(self) + canvas.before: + Color: + rgba: (0,0,0,1) + MDTextField: + id: address + hint_text: "Address" + required: True + helper_text_mode: "on_error" + multiline: False + on_text: root.checkAddress_valid(self) + canvas.before: + Color: + rgba: (0,0,0,1) : - id: addbook_popup - size_hint : (None,None) - height: 4*(add_label.height) - width :app.window_size[0] - (app.window_size[0]/10 if app.app_platform == 'android' else app.window_size[0]/4) - background: app.image_path + '/popup.jpeg' - separator_height: 0 - auto_dismiss: False - BoxLayout: + id: addbook_popup_box + size_hint_y: None + height: 2.5*(add_label.height) + orientation: 'vertical' + spacing:dp(5) + MDLabel + font_style: 'Subtitle2' + theme_text_color: 'Primary' + text: "Label" + font_size: '17sp' + halign: 'left' + MDTextField: + id: add_label + font_style: 'Body1' + font_size: '15sp' + halign: 'left' + text: root.address_label + theme_text_color: 'Primary' + required: True + helper_text_mode: "on_error" + on_text: root.checkLabel_valid(self) + canvas.before: + Color: + rgba: (0,0,0,1) + MDLabel: + font_style: 'Subtitle2' + theme_text_color: 'Primary' + text: "Address" + font_size: '17sp' + halign: 'left' + Widget: size_hint_y: None - spacing:dp(70) - id: addbook_popup_box - orientation: 'vertical' - BoxLayout: - size_hint_y: None - orientation: 'vertical' - spacing:dp(15) - MDLabel: - font_style: 'Subtitle2' - theme_text_color: 'Primary' - text: "Label" - font_size: '17sp' - halign: 'left' - MDTextField: - id: add_label - font_style: 'Body1' - font_size: '15sp' - halign: 'left' - text: root.address_label - theme_text_color: 'Primary' - required: True - helper_text_mode: "on_error" - on_text: root.checkLabel_valid(self) - canvas.before: - Color: - rgba: (0,0,0,1) - MDLabel: - font_style: 'Subtitle2' - theme_text_color: 'Primary' - text: "Address" - font_size: '17sp' - halign: 'left' - Widget: - size_hint_y: None - height: dp(1) - BoxLayout: - orientation: 'horizontal' - MDLabel: - id: address - font_style: 'Body1' - theme_text_color: 'Primary' - text: root.address - font_size: '15sp' - halign: 'left' - IconRightSampleWidget: - pos_hint: {'center_x': 0, 'center_y': 1} - icon: 'content-copy' - on_press: app.copy_composer_text(root.address) - BoxLayout: - id: addbook_btn - spacing:5 - orientation: 'horizontal' - MDRaisedButton: - size_hint: 2, None - height: dp(40) - on_press: root.send_message_to() - MDLabel: - font_style: 'H6' - text: 'Send message to' - font_size: '13sp' - color: (1,1,1,1) - halign: 'center' - MDRaisedButton: - size_hint: 1.5, None - height: dp(40) - font_size: '10sp' - on_press: root.update_addbook_label(root.address) - MDLabel: - font_style: 'H6' - text: 'Save' - font_size: '13sp' - color: (1,1,1,1) - halign: 'center' - MDRaisedButton: - size_hint: 1.5, None - height: dp(40) - on_press: root.dismiss() - on_press: root.close_pop() - MDLabel: - font_style: 'H6' - text: 'Cancel' - font_size: '13sp' - color: (1,1,1,1) - halign: 'center' + height: dp(1) + BoxLayout: + orientation: 'horizontal' + MDLabel: + id: address + font_style: 'Body1' + theme_text_color: 'Primary' + text: root.address + font_size: '15sp' + halign: 'left' + IconRightSampleWidget: + pos_hint: {'center_x': 0, 'center_y': 1} + icon: 'content-copy' + on_press: app.copy_composer_text(root.address) : id: myadd_popup - size_hint : (None,None) - height: 4.5*(myaddr_label.height+ my_add_btn.children[0].height) - width :app.window_size[0] - (app.window_size[0]/10 if app.app_platform == 'android' else app.window_size[0]/4) - background: app.image_path + '/popup.jpeg' - auto_dismiss: False - separator_height: 0 + size_hint_y: None + spacing:dp(25) + height: dp(1.2*(myaddr_label.height)) + orientation: 'vertical' + MDLabel: + id: myaddr_label + font_style: 'Subtitle2' + theme_text_color: 'Primary' + text: "Label" + font_size: '17sp' + halign: 'left' + MDLabel: + font_style: 'Body1' + theme_text_color: 'Primary' + text: root.address_label + font_size: '15sp' + halign: 'left' + MDLabel: + font_style: 'Subtitle2' + theme_text_color: 'Primary' + text: "Address" + font_size: '17sp' + halign: 'left' BoxLayout: - id: myadd_popup_box + orientation: 'horizontal' + MDLabel: + id: label_address + font_style: 'Body1' + theme_text_color: 'Primary' + text: root.address + font_size: '15sp' + halign: 'left' + IconRightSampleWidget: + pos_hint: {'center_x': 0, 'center_y': 1} + icon: 'content-copy' + on_press: app.copy_composer_text(root.address) + BoxLayout: + id: my_add_btn + spacing:5 + orientation: 'horizontal' size_hint_y: None - spacing:dp(70) - orientation: 'vertical' - BoxLayout: - size_hint_y: None - orientation: 'vertical' - spacing:dp(25) + height: self.minimum_height + MDRaisedButton: + size_hint: 2, None + height: dp(40) + on_press: root.send_message_from() MDLabel: - id: myaddr_label - font_style: 'Subtitle2' - theme_text_color: 'Primary' - text: "Label" - font_size: '17sp' - halign: 'left' + font_style: 'H6' + text: 'Send message from' + font_size: '13sp' + color: (1,1,1,1) + halign: 'center' + MDRaisedButton: + size_hint: 1.5, None + height: dp(40) + on_press: app.root.ids.scr_mngr.current = 'showqrcode' + on_press: app.root.ids.sc15.qrdisplay(root, root.address) MDLabel: - font_style: 'Body1' - theme_text_color: 'Primary' - text: root.address_label - font_size: '15sp' - halign: 'left' + font_style: 'H6' + text: 'Show QR code' + font_size: '13sp' + color: (1,1,1,1) + halign: 'center' + MDRaisedButton: + size_hint: 1.5, None + height: dp(40) + on_press: root.close_pop() MDLabel: - font_style: 'Subtitle2' - theme_text_color: 'Primary' - text: "Address" - font_size: '17sp' - halign: 'left' - BoxLayout: - orientation: 'horizontal' - MDLabel: - font_style: 'Body1' - theme_text_color: 'Primary' - text: root.address - font_size: '15sp' - halign: 'left' - IconRightSampleWidget: - pos_hint: {'center_x': 0, 'center_y': 1} - icon: 'content-copy' - on_press: app.copy_composer_text(root.address) - BoxLayout: - id: my_add_btn - spacing:5 - orientation: 'horizontal' - MDRaisedButton: - size_hint: 2, None - height: dp(40) - on_press: root.send_message_from() - MDLabel: - font_style: 'H6' - text: 'Send message from' - font_size: '13sp' - color: (1,1,1,1) - halign: 'center' - MDRaisedButton: - size_hint: 1.5, None - height: dp(40) - on_press: root.dismiss() - on_press: app.root.ids.scr_mngr.current = 'showqrcode' - on_press: app.root.ids.sc15.qrdisplay() - MDLabel: - font_style: 'H6' - text: 'Show QR code' - font_size: '13sp' - color: (1,1,1,1) - halign: 'center' - MDRaisedButton: - size_hint: 1.5, None - height: dp(40) - on_press: root.dismiss() - on_press: root.close_pop() - MDLabel: - font_style: 'H6' - text: 'Cancel' - font_size: '13sp' - color: (1,1,1,1) - halign: 'center' + font_style: 'H6' + text: 'Cancel' + font_size: '13sp' + color: (1,1,1,1) + halign: 'center' : id: closing_popup @@ -398,6 +295,7 @@ id: sd_btn orientation: 'vertical' MDRaisedButton: + id: dismiss_btn on_press: root.dismiss() size_hint: .2, 0 pos_hint: {'x': 0.8, 'y': 0} diff --git a/src/bitmessagekivy/kv/sent.kv b/src/bitmessagekivy/kv/sent.kv index 17fa0e2f..11477ed6 100644 --- a/src/bitmessagekivy/kv/sent.kv +++ b/src/bitmessagekivy/kv/sent.kv @@ -4,6 +4,7 @@ orientation: 'vertical' spacing: dp(5) SearchBar: + id: sent_search GridLayout: id: identi_tag padding: [20, 0, 0, 5] @@ -11,6 +12,7 @@ size_hint_y: None height: self.minimum_height MDLabel: + id: tag_label text: '' font_style: 'Subtitle2' BoxLayout: diff --git a/src/bitmessagekivy/kv/settings.kv b/src/bitmessagekivy/kv/settings.kv index 05d3486b..98307c93 100644 --- a/src/bitmessagekivy/kv/settings.kv +++ b/src/bitmessagekivy/kv/settings.kv @@ -204,12 +204,18 @@ # halign: 'right' bold: True MDDropDownItem: - id: dropdown_item + id: drop_item + # pos_hint: {'center_x': .5, 'center_y': .5} text: 'italiano' - dropdown_max_height: 150 - dropdown_bg: [1, 1, 1, 1] - # pos_hint: {'center_x': 0.5, 'center_y': 0} - items: [f"{i}" for i in ['System Setting','U.S. English','italiano','Esperanto','dansk','Deutsch','Pirate English','francais','Nederlands','norsk bokmal','polski','portugues europeu']] + on_release: root.menu.open() + on_press: root.set_caller() + # MDDropDownItem: + # id: dropdown_item + # text: 'italiano' + # dropdown_max_height: 150 + # dropdown_bg: [1, 1, 1, 1] + # # pos_hint: {'center_x': 0.5, 'center_y': 0} + # items: [f"{i}" for i in ['System Setting','U.S. English','italiano','Esperanto','dansk','Deutsch','Pirate English','francais','Nederlands','norsk bokmal','polski','portugues europeu']] BoxLayout: spacing:5 orientation: 'horizontal' @@ -292,7 +298,7 @@ text: "Type:" halign: 'left' MDDropDownItem: - id: dropdown_item + id: dropdown_item2 dropdown_bg: [1, 1, 1, 1] text: 'none' pos_hint: {'x': 0.9, 'y': 0} diff --git a/src/bitmessagekivy/kv/trash.kv b/src/bitmessagekivy/kv/trash.kv index 7475c334..71708e6d 100644 --- a/src/bitmessagekivy/kv/trash.kv +++ b/src/bitmessagekivy/kv/trash.kv @@ -11,6 +11,7 @@ size_hint_y: None height: self.minimum_height MDLabel: + id: tag_label text: '' font_style: 'Subtitle2' BoxLayout: diff --git a/src/bitmessagekivy/main.kv b/src/bitmessagekivy/main.kv index a924d04e..70bd9fe8 100644 --- a/src/bitmessagekivy/main.kv +++ b/src/bitmessagekivy/main.kv @@ -43,6 +43,7 @@ text_color: root.active_color BadgeText: + id: badge_txt text: f"{root.badge_text}" theme_text_color: "Custom" #text_color: root.active_color diff --git a/src/bitmessagekivy/mpybit.py b/src/bitmessagekivy/mpybit.py index 58da3082..afd5c0b1 100644 --- a/src/bitmessagekivy/mpybit.py +++ b/src/bitmessagekivy/mpybit.py @@ -110,7 +110,7 @@ from kivy.utils import platform from kivymd.uix.button import MDIconButton from kivymd.uix.dialog import MDDialog from kivymd.uix.label import MDLabel -from kivymd.uix.button import MDFlatButton +from kivymd.uix.button import MDFlatButton, MDRaisedButton from kivymd.uix.list import ( ILeftBody, ILeftBodyTouch, @@ -138,6 +138,7 @@ from datetime import datetime from kivymd.uix.behaviors.elevation import RectangularElevationBehavior from kivymd.uix.bottomsheet import MDCustomBottomSheet from kivy.effects.dampedscroll import DampedScrollEffect +from kivymd.uix.menu import MDDropdownMenu if platform != "android": @@ -254,16 +255,17 @@ class Inbox(Screen): self.set_defaultAddress() self.account = state.association if state.searcing_text: - self.children[2].children[0].children[0].scroll_y = 1.0 + # self.children[2].children[0].children[0].scroll_y = 1.0 + self.ids.scroll_y.scroll_y = 1.0 where = ["subject", "message"] what = state.searcing_text xAddress = "toaddress" data = [] - self.ids.identi_tag.children[0].text = "" + self.ids.tag_label.text = "" self.inboxDataQuery(xAddress, where, what) - self.ids.identi_tag.children[0].text = "" + self.ids.tag_label.text = "" if self.queryreturn: - self.ids.identi_tag.children[0].text = "Inbox" + self.ids.tag_label.text = "Inbox" state.kivyapp.get_inbox_count() self.set_inboxCount(state.inbox_count) for mail in self.queryreturn: @@ -287,7 +289,7 @@ class Inbox(Screen): self.has_refreshed = True self.set_mdList(data) - self.children[2].children[0].children[0].bind(scroll_y=self.check_scroll_y) + self.ids.scroll_y.bind(scroll_y=self.check_scroll_y) else: self.set_inboxCount("0") content = MDLabel( @@ -305,7 +307,7 @@ class Inbox(Screen): def set_inboxCount(self, msgCnt): # pylint: disable=no-self-use """This method is used to sent inbox message count""" src_mng_obj = state.kivyapp.root.ids.content_drawer.ids.inbox_cnt - src_mng_obj.children[0].children[0].text = showLimitedCnt(int(msgCnt)) + src_mng_obj.ids.badge_txt.text = showLimitedCnt(int(msgCnt)) def inboxDataQuery(self, xAddress, where, what, start_indx=0, end_indx=20): """This method is used for retrieving inbox data""" @@ -326,7 +328,7 @@ class Inbox(Screen): meny._txt_right_pad = dp(70) meny.add_widget( AvatarSampleWidget( - source="./images/text_images/{}.png".format( + source=state.imageDir + "/text_images/{}.png".format( avatarImageFirstLetter(item["secondary_text"].strip()) ) ) @@ -356,10 +358,8 @@ class Inbox(Screen): def check_scroll_y(self, instance, somethingelse): """Loads data on scroll""" - if ( - self.children[2].children[0].children[0].scroll_y <= -0.0 and self.has_refreshed - ): - self.children[2].children[0].children[0].scroll_y = 0.06 + if self.ids.scroll_y.scroll_y <= -0.0 and self.has_refreshed: + self.ids.scroll_y.scroll_y = 0.06 total_message = len(self.ids.ml.children) self.update_inbox_screen_on_scroll(total_message) else: @@ -382,7 +382,8 @@ class Inbox(Screen): "secondary_text": body[:50] + "........" if len(body) >= 50 else (body + "," + subject.replace("\n", ""))[0:50] + "........", - "msgid": mail[1] + "msgid": mail[1], + "received": mail[6] } ) self.set_mdList(data) @@ -404,22 +405,24 @@ class Inbox(Screen): sqlExecute("UPDATE inbox SET folder = 'trash' WHERE msgid = ?;", data_index) msg_count_objs = self.parent.parent.ids.content_drawer.ids if int(state.inbox_count) > 0: - msg_count_objs.inbox_cnt.children[0].children[0].text = showLimitedCnt( + msg_count_objs.inbox_cnt.ids.badge_txt.text = showLimitedCnt( int(state.inbox_count) - 1 ) - msg_count_objs.trash_cnt.children[0].children[0].text = showLimitedCnt( + msg_count_objs.trash_cnt.ids.badge_txt.text = showLimitedCnt( int(state.trash_count) + 1 ) - msg_count_objs.allmail_cnt.children[0].children[0].text = showLimitedCnt( + msg_count_objs.allmail_cnt.ids.badge_txt.text = showLimitedCnt( int(state.all_count) - 1 ) state.inbox_count = str(int(state.inbox_count) - 1) state.trash_count = str(int(state.trash_count) + 1) state.all_count = str(int(state.all_count) - 1) if int(state.inbox_count) <= 0: - self.ids.identi_tag.children[0].text = "" - self.ids.ml.remove_widget(instance.parent.parent) - toast("Deleted") + # self.ids.identi_tag.children[0].text = '' + self.ids.tag_label.text = '' + self.ids.ml.remove_widget( + instance.parent.parent) + toast('Deleted') self.update_trash() def archive(self, data_index, instance, *args): @@ -463,6 +466,8 @@ class CustomTwoLineAvatarIconListItem(TwoLineAvatarIconListItem): class MyAddress(Screen): """MyAddress screen uses screen to show widgets of screens""" + address_label = StringProperty() + text_address = StringProperty() addresses_list = ListProperty() has_refreshed = True is_add_created = False @@ -485,9 +490,9 @@ class MyAddress(Screen): ] self.addresses_list = filtered_list self.addresses_list = [obj for obj in reversed(self.addresses_list)] - self.ids.identi_tag.children[0].text = '' + self.ids.tag_label.text = '' if self.addresses_list: - self.ids.identi_tag.children[0].text = 'My Addresses' + self.ids.tag_label.text = 'My Addresses' self.has_refreshed = True self.set_mdList(0, 15) self.ids.refresh_layout.bind(scroll_y=self.check_scroll_y) @@ -564,10 +569,20 @@ class MyAddress(Screen): # @staticmethod def myadd_detail(self, fromaddress, label, *args): """Load myaddresses details""" - if BMConfigParser().get(fromaddress, "enabled") == "true": - p = MyaddDetailPopup() - p.open() - p.set_address(fromaddress, label) + if BMConfigParser().get(fromaddress, 'enabled') == 'true': + obj = MyaddDetailPopup() + self.address_label = obj.address_label = label + self.text_address = obj.address =fromaddress + width = .9 if platform == 'android' else .8 + self.myadddetail_popup = MDDialog( + type="custom", + size_hint=(width, .25), + content_cls=obj, + ) + self.myadddetail_popup.set_normal_height() + self.myadddetail_popup.auto_dismiss = False + self.myadddetail_popup.open() + # p.set_address(fromaddress, label) else: width = .8 if platform == 'android' else .55 dialog_box=MDDialog( @@ -597,7 +612,7 @@ class MyAddress(Screen): """Method used for loading the myaddress screen data""" state.searcing_text = '' # state.kivyapp.root.ids.sc10.children[2].active = False - self.children[2].children[2].ids.search_field.text = '' + self.ids.search_bar.ids.search_field.text = '' self.has_refreshed = True self.ids.ml.clear_widgets() self.init_ui() @@ -663,6 +678,8 @@ class AddressBook(Screen): queryreturn = ListProperty() has_refreshed = True + address_label = StringProperty() + address = StringProperty() def __init__(self, *args, **kwargs): """Getting AddressBook Details""" @@ -681,12 +698,12 @@ class AddressBook(Screen): where = ['label', 'address'] what = state.searcing_text xAddress = '' - self.ids.identi_tag.children[0].text = '' + self.ids.tag_label.text = '' self.queryreturn = kivy_helper_search.search_sql( xAddress, account, "addressbook", where, what, False) self.queryreturn = [obj for obj in reversed(self.queryreturn)] if self.queryreturn: - self.ids.identi_tag.children[0].text = 'Address Book' + self.ids.tag_label.text = 'Address Book' self.has_refreshed = True self.set_mdList(0, 20) self.ids.scroll_y.bind(scroll_y=self.check_scroll_y) @@ -751,20 +768,80 @@ class AddressBook(Screen): # state.navinstance.ids.sc11.loadAddresslist(None, 'All', '') pass - @staticmethod - def addBook_detail(address, label, *args): + # @staticmethod + def addBook_detail(self, address, label, *args): """Addressbook details""" - p = AddbookDetailPopup() - p.open() - p.set_addbook_data(address, label) + obj = AddbookDetailPopup() + self.address_label = obj.address_label = label + self.address = obj.address = address + width = .9 if platform == 'android' else .8 + self.addbook_popup = MDDialog( + type="custom", + size_hint=(width, .25), + content_cls=obj, + buttons=[ + MDRaisedButton( + text="Send message to", + text_color=state.kivyapp.theme_cls.primary_color, + on_release=self.send_message_to, + ), + MDRaisedButton( + text="Save", text_color=state.kivyapp.theme_cls.primary_color, + on_release=self.update_addbook_label, + ), + MDRaisedButton( + text="Cancel", text_color=state.kivyapp.theme_cls.primary_color, + on_release=self.close_pop, + ), + ], + ) + self.addbook_popup.set_normal_height() + self.addbook_popup.auto_dismiss = False + self.addbook_popup.open() def delete_address(self, address, instance, *args): """Delete inbox mail from inbox listing""" self.ids.ml.remove_widget(instance.parent.parent) # if len(self.ids.ml.children) == 0: if self.ids.ml.children is not None: - self.ids.identi_tag.children[0].text = "" - sqlExecute("DELETE FROM addressbook WHERE address = '{}';".format(address)) + self.ids.tag_label.text = '' + sqlExecute( + "DELETE FROM addressbook WHERE address = '{}';".format(address)) + + def close_pop(self, instance): + """Pop is Canceled""" + self.addbook_popup.dismiss() + toast('Canceled') + + def update_addbook_label(self, instance): + """Updating the label of address book address""" + address_list = kivy_helper_search.search_sql(folder="addressbook") + stored_labels = [labels[0] for labels in address_list] + add_dict = dict(address_list) + label = str(self.addbook_popup.content_cls.ids.add_label.text) + if label in stored_labels and self.address == add_dict[label]: + stored_labels.remove(label) + if label and label not in stored_labels: + sqlExecute( + "UPDATE addressbook SET label = '{}' WHERE" + " address = '{}';".format( + label, self.addbook_popup.content_cls.address)) + state.kivyapp.root.ids.sc11.ids.ml.clear_widgets() + state.kivyapp.root.ids.sc11.loadAddresslist(None, 'All', '') + self.addbook_popup.dismiss() + toast('Saved') + + def send_message_to(self, instance): + """Method used to fill to_address of composer autofield""" + state.kivyapp.set_navbar_for_composer() + window_obj = state.kivyapp.root.ids + window_obj.sc3.children[1].ids.txt_input.text = self.address + window_obj.sc3.children[1].ids.ti.text = '' + window_obj.sc3.children[1].ids.btn.text = 'Select' + window_obj.sc3.children[1].ids.subject.text = '' + window_obj.sc3.children[1].ids.body.text = '' + window_obj.scr_mngr.current = 'create' + self.addbook_popup.dismiss() class SelectableRecycleBoxLayout( @@ -1200,9 +1277,10 @@ class Random(Screen): def generateaddress(self, navApp): """Method for Address Generator""" - entered_label = str(self.ids.lab.text).strip() + # entered_label = str(self.ids.lab.text).strip() + entered_label = str(self.ids.add_random_bx.children[0].ids.lab.text).strip() if not entered_label: - self.ids.lab.focus = True + self.ids.add_random_bx.children[0].ids.lab.focus = True #self.ids.lab.error = True #self.ids.lab.helper_text = 'This field is required' streamNumberForAddress = 1 @@ -1249,7 +1327,7 @@ class Random(Screen): for obj in BMConfigParser().addresses()] if entered_label in lables: instance.error = True - instance.helper_text = 'Label name is already exist you'\ + instance.helper_text = 'it is already exist you'\ ' can try this Ex. ( {0}_1, {0}_2 )'.format( entered_label) elif entered_label: @@ -1293,10 +1371,10 @@ class Sent(Screen): what = state.searcing_text xAddress = 'fromaddress' data = [] - self.ids.identi_tag.children[0].text = '' + self.ids.tag_label.text = '' self.sentDataQuery(xAddress, where, what) if self.queryreturn: - self.ids.identi_tag.children[0].text = 'Sent' + self.ids.tag_label.text = 'Sent' self.set_sentCount(state.sent_count) for mail in self.queryreturn: data.append({ @@ -1424,18 +1502,18 @@ class Sent(Screen): 'secondary_text': mail[2][:50] + '........' if len( mail[2]) >= 50 else (mail[2] + ',' + mail[3].replace( '\n', ''))[0:50] + '........', - 'ackdata': mail[5]}) + 'ackdata': mail[5], 'senttime': mail[6]}) self.set_mdlist(data, 0) @staticmethod def set_sentCount(total_sent): """Set the total no. of sent message count""" src_mng_obj = state.kivyapp.root.ids.content_drawer.ids.send_cnt + state.kivyapp.root.ids.content_drawer.ids.send_cnt.ids.badge_txt.text if state.association: - src_mng_obj.children[0].children[0].text = showLimitedCnt(int(total_sent)) - # state.kivyapp.get_sent_count() + src_mng_obj.ids.badge_txt.text = showLimitedCnt(int(total_sent)) else: - src_mng_obj.children[0].children[0].text = '0' + src_mng_obj.ids.badge_txt.text = '0' def sent_detail(self, ackdata, *args): """Load sent mail details""" @@ -1453,14 +1531,14 @@ class Sent(Screen): """Delete sent mail from sent mail listing""" msg_count_objs = self.parent.parent.ids.content_drawer.ids if int(state.sent_count) > 0: - msg_count_objs.send_cnt.children[0].children[0].text = showLimitedCnt(int(state.sent_count) - 1) - msg_count_objs.trash_cnt.children[0].children[0].text = showLimitedCnt(int(state.trash_count) + 1) - msg_count_objs.allmail_cnt.children[0].children[0].text = showLimitedCnt(int(state.all_count) - 1) + msg_count_objs.send_cnt.ids.badge_txt.text = showLimitedCnt(int(state.sent_count) - 1) + msg_count_objs.trash_cnt.ids.badge_txt.text = showLimitedCnt(int(state.trash_count) + 1) + msg_count_objs.allmail_cnt.ids.badge_txt.text = showLimitedCnt(int(state.all_count) - 1) state.sent_count = str(int(state.sent_count) - 1) state.trash_count = str(int(state.trash_count) + 1) state.all_count = str(int(state.all_count) - 1) if int(state.sent_count) <= 0: - self.ids.identi_tag.children[0].text = '' + self.ids.tag_label.text = '' sqlExecute( "UPDATE sent SET folder = 'trash'" " WHERE ackdata = ?;", data_index) @@ -1508,10 +1586,10 @@ class Trash(Screen): if state.association == '': if BMConfigParser().addresses(): state.association = BMConfigParser().addresses()[0] - self.ids.identi_tag.children[0].text = '' + self.ids.tag_label.text = '' self.trashDataQuery(0, 20) if self.trash_messages: - self.ids.identi_tag.children[0].text = 'Trash' + self.ids.tag_label.text = 'Trash' # src_mng_obj = state.kivyapp.root.children[2].children[0].ids # src_mng_obj.trash_cnt.badge_text = state.trash_count self.set_TrashCnt(state.trash_count) @@ -1545,7 +1623,7 @@ class Trash(Screen): def set_TrashCnt(self, Count): # pylint: disable=no-self-use """This method is used to set trash message count""" trashCnt_obj = state.kivyapp.root.ids.content_drawer.ids.trash_cnt - trashCnt_obj.children[0].children[0].text = showLimitedCnt(int(Count)) + trashCnt_obj.ids.badge_txt.text = showLimitedCnt(int(Count)) def set_mdList(self): """This method is used to create the mdlist""" @@ -1693,6 +1771,33 @@ class Setting(Screen): Here you may change that behavior by having Bitmessage give up after a certain number of days \ or months." + def __init__(self, *args, **kwargs): + """Trash method, delete sent message and add in Trash""" + super(Setting, self).__init__(*args, **kwargs) + Clock.schedule_once(self.init_ui, 0) + + def init_ui(self, dt=0): + menu_items = [{"text": f"{i}"} for i in ['System Setting','U.S. English','italiano', + 'Esperanto','dansk','Deutsch','Pirate English','francais', + 'Nederlands','norsk bokmal','polski','portugues europeu']] + self.menu = MDDropdownMenu( + caller=self, + items=menu_items, + position="auto", + callback=self.set_item, + width_mult=3, + use_icon_item=False, + ) + + def set_caller(self): + self.menu.caller= self.ids.drop_item + # self.menu.use_icon_item = False + self.menu.target_height = 150 + + def set_item(self, instance): + self.ids.drop_item.set_item(instance.text) + self.menu.dismiss() + class NavigateApp(MDApp): """Navigation Layout of class""" @@ -1712,7 +1817,7 @@ class NavigateApp(MDApp): count = 0 manager_open = False file_manager = None - # state.imageDir = os.path.join(os.path.abspath(os.path.join(__file__ ,"../../..")),'images', 'kivy') + #state.imageDir = os.path.join(os.path.abspath(os.path.join(__file__ ,"../../..")),'images', 'kivy') state.imageDir = os.path.join('./images', 'kivy') image_path = state.imageDir @@ -1802,11 +1907,68 @@ class NavigateApp(MDApp): return state.association return "Bitmessage Login" - @staticmethod - def addingtoaddressbook(): + # @staticmethod + def addingtoaddressbook(self): """Adding to address Book""" - p = GrashofPopup() - p.open() + width = .85 if platform == 'android' else .8 + self.add_popup = MDDialog( + title='add contact\'s', + type="custom", + size_hint=(width, .25), + content_cls=GrashofPopup(), + buttons=[ + MDRaisedButton( + text="Save", + text_color=self.theme_cls.primary_color, + on_release=self.savecontact, + ), + MDRaisedButton( + text="Cancel", text_color=self.theme_cls.primary_color, + on_release=self.close_pop, + ), + MDRaisedButton( + text="Scan QR code", text_color=self.theme_cls.primary_color + ), + ], + ) + self.add_popup.set_normal_height() + self.add_popup.auto_dismiss = False + self.add_popup.open() + # p = GrashofPopup() + # p.open() + + def savecontact(self, instance): + """Method is used for saving contacts""" + pupup_obj = self.add_popup.content_cls + label = pupup_obj.ids.label.text.strip() + address = pupup_obj.ids.address.text.strip() + if label == '' and address == '': + pupup_obj.ids.label.focus = True + pupup_obj.ids.address.focus = True + elif address == '': + pupup_obj.ids.address.focus = True + elif label == '': + pupup_obj.ids.label.focus = True + + stored_address = [addr[1] for addr in kivy_helper_search.search_sql( + folder="addressbook")] + stored_labels = [labels[0] for labels in kivy_helper_search.search_sql( + folder="addressbook")] + if label and address and address not in stored_address \ + and label not in stored_labels and pupup_obj.valid: + # state.navinstance = self.parent.children[1] + queues.UISignalQueue.put(('rerenderAddressBook', '')) + self.add_popup.dismiss() + sqlExecute("INSERT INTO addressbook VALUES(?,?)", label, address) + self.root.ids.sc11.ids.ml.clear_widgets() + self.root.ids.sc11.loadAddresslist(None, 'All', '') + self.root.ids.scr_mngr.current = 'addressbook' + toast('Saved') + + def close_pop(self, instance): + """Pop is Canceled""" + self.add_popup.dismiss() + toast('Canceled') def getDefaultAccData(self): """Getting Default Account Data""" @@ -2142,32 +2304,36 @@ class NavigateApp(MDApp): # pylint: disable=unused-variable state.searcing_text = '' if state.search_screen == 'inbox': - try: - self.root.ids.sc1.children[ - 3].children[2].ids.search_field.text = '' - except Exception: - self.root.ids.sc1.children[ - 2].children[2].ids.search_field.text = '' + self.root.ids.sc1.ids.inbox_search.ids.search_field.text = '' + # try: + # self.root.ids.sc1.children[ + # 3].children[2].ids.search_field.text = '' + # except Exception: + # self.root.ids.sc1.children[ + # 2].children[2].ids.search_field.text = '' self.root.ids.sc1.children[1].active = True Clock.schedule_once(self.search_callback, 0.5) elif state.search_screen == 'addressbook': - self.root.ids.sc11.children[ - 2].children[2].ids.search_field.text = '' + self.root.ids.sc11.ids.address_search.ids.search_field.text = '' + # self.root.ids.sc11.children[ + # 2].children[2].ids.search_field.text = '' self.root.ids.sc11.children[ 1].active = True Clock.schedule_once(self.search_callback, 0.5) elif state.search_screen == 'myaddress': - try: - self.root.ids.sc10.children[ - 1].children[2].ids.search_field.text = '' - except Exception: - self.root.ids.sc10.children[ - 2].children[2].ids.search_field.text = '' + self.root.ids.sc10.ids.search_bar.ids.search_field.text = '' + # try: + # self.root.ids.sc10.children[ + # 1].children[2].ids.search_field.text = '' + # except Exception: + # self.root.ids.sc10.children[ + # 2].children[2].ids.search_field.text = '' self.loadMyAddressScreen(True) Clock.schedule_once(self.search_callback, 0.5) else: - self.root.ids.sc4.children[ - 2].children[2].ids.search_field.text = '' + self.root.ids.sc4.ids.sent_search.ids.search_field.text = '' + # self.root.ids.sc4.children[ + # 2].children[2].ids.search_field.text = '' self.root.ids.sc4.children[1].active = True Clock.schedule_once(self.search_callback, 0.5) return @@ -2307,8 +2473,8 @@ class NavigateApp(MDApp): def reset_login_screen(self): """This method is used for clearing random screen""" - # if self.root.ids.sc7.ids.add_random_bx.children: - # self.root.ids.sc7.ids.add_random_bx.clear_widgets() + if self.root.ids.sc7.ids.add_random_bx.children: + self.root.ids.sc7.ids.add_random_bx.clear_widgets() def open_payment_layout(self, sku): pml = PaymentMethodLayout() @@ -2329,7 +2495,7 @@ class NavigateApp(MDApp): self.root.ids.scr_mngr.current = 'create' -class GrashofPopup(Popup): +class GrashofPopup(BoxLayout): """Moule for save contacts and error messages""" valid = False @@ -2338,44 +2504,10 @@ class GrashofPopup(Popup): """Grash of pop screen settings""" super(GrashofPopup, self).__init__(**kwargs) - def savecontact(self): - """Method is used for saving contacts""" - label = self.ids.label.text.strip() - address = self.ids.address.text.strip() - if label == '' and address == '': - self.ids.label.focus = True - self.ids.address.focus = True - elif address == '': - self.ids.address.focus = True - elif label == '': - self.ids.label.focus = True - - stored_address = [addr[1] for addr in kivy_helper_search.search_sql( - folder="addressbook")] - stored_labels = [labels[0] for labels in kivy_helper_search.search_sql( - folder="addressbook")] - if label and address and address not in stored_address \ - and label not in stored_labels and self.valid: - # state.navinstance = self.parent.children[1] - queues.UISignalQueue.put(('rerenderAddressBook', '')) - self.dismiss() - sqlExecute("INSERT INTO addressbook VALUES(?,?)", label, address) - self.parent.children[1].ids.sc11.ids.ml.clear_widgets() - self.parent.children[1].ids.sc11.loadAddresslist(None, 'All', '') - self.parent.children[1].ids.scr_mngr.current = 'addressbook' - toast('Saved') - - @staticmethod - def close_pop(): - """Pop is Canceled""" - toast('Canceled') - def checkAddress_valid(self, instance): """Checking address is valid or not""" - # my_addresses = ( - # self.parent.children[1].children[0].children[0].ids.btn.values) my_addresses = ( - state.kivyapp.root.children[0].children[0].ids.btn.values) + state.kivyapp.root.ids.content_drawer.ids.btn.values) add_book = [addr[1] for addr in kivy_helper_search.search_sql( folder="addressbook")] entered_text = str(instance.text).strip() @@ -2428,7 +2560,8 @@ class GrashofPopup(Popup): elif status == 'checksumfailed': text = ( "The address is not typed or copied correctly" - " (the checksum failed).") + # " (the checksum failed)." + ) elif status == 'versiontoohigh': text = ( "The version number of this address is higher than this" @@ -2541,24 +2674,20 @@ class MailDetail(Screen): # pylint: disable=too-many-instance-attributes state.searcing_text = '' self.children[0].children[0].active = True if state.detailPageType == 'sent': - state.kivyapp.root.ids.sc4.children[ - 2].children[2].ids.search_field.text = '' + state.kivyapp.root.ids.sc4.ids.sent_search.ids.search_field.text = '' sqlExecute( "UPDATE sent SET folder = 'trash' WHERE" " ackdata = ?;", state.mail_id) - msg_count_objs.send_cnt.children[0].children[0].text = str(int(state.sent_count) - 1) + msg_count_objs.send_cnt.ids.badge_txt.text = str(int(state.sent_count) - 1) state.sent_count = str(int(state.sent_count) - 1) self.parent.screens[3].ids.ml.clear_widgets() self.parent.screens[3].loadSent(state.association) elif state.detailPageType == 'inbox': - state.kivyapp.root.ids.sc1.children[ - 2].children[2].ids.search_field.text = '' - self.parent.screens[0].children[2].children[ - 2].ids.search_field.text = '' + state.kivyapp.root.ids.sc1.ids.inbox_search.ids.search_field.text = '' sqlExecute( "UPDATE inbox SET folder = 'trash' WHERE" " msgid = ?;", state.mail_id) - msg_count_objs.inbox_cnt.children[0].children[0].text = str( + msg_count_objs.inbox_cnt.ids.badge_txt.text = str( int(state.inbox_count) - 1) state.inbox_count = str(int(state.inbox_count) - 1) self.parent.screens[0].ids.ml.clear_widgets() @@ -2566,16 +2695,16 @@ class MailDetail(Screen): # pylint: disable=too-many-instance-attributes elif state.detailPageType == 'draft': sqlExecute("DELETE FROM sent WHERE ackdata = ?;", state.mail_id) - msg_count_objs.draft_cnt.children[0].children[0].text = str( + msg_count_objs.draft_cnt.ids.badge_txt.text = str( int(state.draft_count) - 1) state.draft_count = str(int(state.draft_count) - 1) self.parent.screens[15].clear_widgets() self.parent.screens[15].add_widget(Draft()) if state.detailPageType != 'draft': - msg_count_objs.trash_cnt.children[0].children[0].text = str( + msg_count_objs.trash_cnt.ids.badge_txt.text = str( int(state.trash_count) + 1) - msg_count_objs.allmail_cnt.children[0].children[0].text = str( + msg_count_objs.allmail_cnt.ids.badge_txt.text = str( int(state.all_count) - 1) state.trash_count = str(int(state.trash_count) + 1) state.all_count = str(int(state.all_count) - 1) if int(state.all_count) else '0' @@ -2648,7 +2777,7 @@ class MailDetail(Screen): # pylint: disable=too-many-instance-attributes toast(text_item) -class MyaddDetailPopup(Popup): +class MyaddDetailPopup(BoxLayout): """MyaddDetailPopup pop is used for showing my address detail""" address_label = StringProperty() @@ -2658,33 +2787,26 @@ class MyaddDetailPopup(Popup): """My Address Details screen setting""" super(MyaddDetailPopup, self).__init__(**kwargs) - def set_address(self, address, label): - """Getting address for displaying details on popup""" - self.address_label = label - self.address = address - def send_message_from(self): """Method used to fill from address of composer autofield""" state.kivyapp.set_navbar_for_composer() - try: - window_obj = self.parent.children[2].ids - except Exception: - window_obj = self.parent.children[1].ids + window_obj = state.kivyapp.root.ids window_obj.sc3.children[1].ids.ti.text = self.address window_obj.sc3.children[1].ids.btn.text = self.address window_obj.sc3.children[1].ids.txt_input.text = '' window_obj.sc3.children[1].ids.subject.text = '' window_obj.sc3.children[1].ids.body.text = '' window_obj.scr_mngr.current = 'create' - self.dismiss() + self.parent.parent.parent.dismiss() - @staticmethod - def close_pop(): + # @staticmethod + def close_pop(self): """Pop is Canceled""" + self.parent.parent.parent.dismiss() toast('Canceled') -class AddbookDetailPopup(Popup): +class AddbookDetailPopup(BoxLayout): """AddbookDetailPopup pop is used for showing my address detail""" address_label = StringProperty() @@ -2694,49 +2816,6 @@ class AddbookDetailPopup(Popup): """Set screen of address detail page""" super(AddbookDetailPopup, self).__init__(**kwargs) - def set_addbook_data(self, address, label): - """Getting address book data for detial dipaly""" - self.address_label = label - self.address = address - - def update_addbook_label(self, address): - """Updating the label of address book address""" - address_list = kivy_helper_search.search_sql(folder="addressbook") - stored_labels = [labels[0] for labels in address_list] - add_dict = dict(address_list) - label = str(self.ids.add_label.text) - if label in stored_labels and self.address == add_dict[label]: - stored_labels.remove(label) - if label and label not in stored_labels: - sqlExecute( - "UPDATE addressbook SET label = '{}' WHERE" - " address = '{}';".format( - str(self.ids.add_label.text), address)) - state.kivyapp.root.ids.sc11.ids.ml.clear_widgets() - state.kivyapp.root.ids.sc11.loadAddresslist(None, 'All', '') - self.dismiss() - toast('Saved') - - def send_message_to(self): - """Method used to fill to_address of composer autofield""" - state.kivyapp.set_navbar_for_composer() - try: - window_obj = self.parent.children[2].ids - except Exception: - window_obj = self.parent.children[1].ids - window_obj.sc3.children[1].ids.txt_input.text = self.address - window_obj.sc3.children[1].ids.ti.text = '' - window_obj.sc3.children[1].ids.btn.text = 'Select' - window_obj.sc3.children[1].ids.subject.text = '' - window_obj.sc3.children[1].ids.body.text = '' - window_obj.scr_mngr.current = 'create' - self.dismiss() - - @staticmethod - def close_pop(): - """Pop is Canceled""" - toast('Canceled') - def checkLabel_valid(self, instance): """Checking address label is unique of not""" entered_label = str(instance.text.strip()) @@ -2758,7 +2837,7 @@ class ShowQRCode(Screen): """ShowQRCode Screen uses to show the detail of mails""" address = StringProperty() - def qrdisplay(self): + def qrdisplay(self, instasnce, address): """Method used for showing QR Code""" self.ids.qr.clear_widgets() state.kivyapp.set_toolbar_for_QrCode() @@ -2766,13 +2845,10 @@ class ShowQRCode(Screen): from kivy.garden.qrcode import QRCodeWidget except Exception as e: from kivy_garden.qrcode import QRCodeWidget - try: - address = self.manager.get_parent_window().children[0].address - except Exception: - address = self.manager.get_parent_window().children[1].address self.address = address self.ids.qr.add_widget(QRCodeWidget(data=address)) self.ids.qr.children[0].show_border = False + instasnce.parent.parent.parent.dismiss() toast('Show QR code') @@ -2805,12 +2881,12 @@ class Draft(Screen): def loadDraft(self, where="", what=""): """Load draft list for Draft messages""" xAddress = 'fromaddress' - self.ids.identi_tag.children[0].text = '' + self.ids.tag_label.text = '' self.draftDataQuery(xAddress, where, what) # if state.msg_counter_objs: # state.msg_counter_objs.draft_cnt.children[0].children[0].text = showLimitedCnt(len(self.queryreturn)) if self.queryreturn: - self.ids.identi_tag.children[0].text = 'Draft' + self.ids.tag_label.text = 'Draft' self.set_draftCnt(state.draft_count) self.set_mdList() self.ids.scroll_y.bind(scroll_y=self.check_scroll_y) @@ -2834,7 +2910,7 @@ class Draft(Screen): def set_draftCnt(self, Count): # pylint: disable=no-self-use """This method set the count of draft mails""" draftCnt_obj = state.kivyapp.root.ids.content_drawer.ids.draft_cnt - draftCnt_obj.children[0].children[0].text = showLimitedCnt(int(Count)) + draftCnt_obj.ids.badge_txt.text = showLimitedCnt(int(Count)) def set_mdList(self): """This method is used to create mdlist""" @@ -2906,23 +2982,12 @@ class Draft(Screen): def delete_draft(self, data_index, instance, *args): """Delete draft message permanently""" sqlExecute("DELETE FROM sent WHERE ackdata = ?;", data_index) - # try: - # msg_count_objs = ( - # self.parent.parent.parent.parent.parent.children[ - # 2].children[0].ids) - # except Exception: - # msg_count_objs = ( - # self.parent.parent.parent.parent.parent.parent.children[ - # 2].children[0].ids) - # msg_count_objs = self.parent.parent.parent.parent.parent.children[ - # 2].children[0].ids if int(state.draft_count) > 0: - # msg_count_objs.draft_cnt.badge_text = str( - # int(state.draft_count) - 1) state.draft_count = str(int(state.draft_count) - 1) self.set_draftCnt(state.draft_count) if int(state.draft_count) <= 0: - self.ids.identi_tag.children[0].text = '' + # self.ids.identi_tag.children[0].text = '' + self.ids.tag_label.text = '' self.ids.ml.remove_widget(instance.parent.parent) toast('Deleted') @@ -3004,10 +3069,10 @@ class Allmails(Screen): def loadMessagelist(self): """Load Inbox, Sent anf Draft list of messages""" self.account = state.association - self.ids.identi_tag.children[0].text = '' + self.ids.tag_label.text = '' self.allMessageQuery(0, 20) if self.all_mails: - self.ids.identi_tag.children[0].text = 'All Mails' + self.ids.tag_label.text = 'All Mails' state.kivyapp.get_inbox_count() state.kivyapp.get_sent_count() state.all_count = str( @@ -3042,7 +3107,7 @@ class Allmails(Screen): def set_AllmailCnt(self, Count): # pylint: disable=no-self-use """This method is used to set allmails message count""" allmailCnt_obj = state.kivyapp.root.ids.content_drawer.ids.allmail_cnt - allmailCnt_obj.children[0].children[0].text = showLimitedCnt(int(Count)) + allmailCnt_obj.ids.badge_txt.text = showLimitedCnt(int(Count)) def set_mdlist(self): """This method is used to create mdList for allmaills""" @@ -3129,21 +3194,21 @@ class Allmails(Screen): msg_count_objs = self.parent.parent.parent.ids.content_drawer.ids nav_lay_obj = self.parent.parent.parent.ids if folder == 'inbox': - msg_count_objs.inbox_cnt.children[0].children[0].text = showLimitedCnt(int(state.inbox_count) - 1) + msg_count_objs.inbox_cnt.ids.badge_txt.text = showLimitedCnt(int(state.inbox_count) - 1) state.inbox_count = str(int(state.inbox_count) - 1) nav_lay_obj.sc1.ids.ml.clear_widgets() nav_lay_obj.sc1.loadMessagelist(state.association) else: - msg_count_objs.send_cnt.children[0].children[0].text = showLimitedCnt(int(state.sent_count) - 1) + msg_count_objs.send_cnt.ids.badge_txt.text = showLimitedCnt(int(state.sent_count) - 1) state.sent_count = str(int(state.sent_count) - 1) nav_lay_obj.sc4.ids.ml.clear_widgets() nav_lay_obj.sc4.loadSent(state.association) - msg_count_objs.trash_cnt.children[0].children[0].text = showLimitedCnt(int(state.trash_count) + 1) - msg_count_objs.allmail_cnt.children[0].children[0].text = showLimitedCnt(int(state.all_count) - 1) + msg_count_objs.trash_cnt.ids.badge_txt.text = showLimitedCnt(int(state.trash_count) + 1) + msg_count_objs.allmail_cnt.ids.badge_txt.text = showLimitedCnt(int(state.all_count) - 1) state.trash_count = str(int(state.trash_count) + 1) state.all_count = str(int(state.all_count) - 1) if int(state.all_count) <= 0: - self.ids.identi_tag.children[0].text = '' + self.ids.tag_label.text = '' nav_lay_obj.sc5.clear_widgets() nav_lay_obj.sc5.add_widget(Trash()) nav_lay_obj.sc17.remove_widget(instance.parent.parent) @@ -3296,7 +3361,7 @@ class SenderDetailPopup(Popup): time_obj = datetime.fromtimestamp(int(timeinseconds)) self.time_tag = time_obj.strftime("%d %b %Y, %I:%M %p") device_type = 2 if platform == 'android' else 1.5 - pop_height = device_type * (self.ids.sd_label.height + self.ids.sd_btn.children[0].height) + pop_height = device_type * (self.ids.sd_label.height + self.ids.dismiss_btn.height) if len(to_addr) > 3: self.height = 0 self.height = pop_height @@ -3335,35 +3400,29 @@ class OneLineListTitle(OneLineListItem): """On long press""" self.copymessageTitle(self.text) - def copymessageTitle(self, text): + def copymessageTitle(self, title_text): """this method is for displaying dialog box""" + self.title_text = title_text width = .8 if platform == 'android' else .55 - dialog_box=MDDialog( - text=text, + self.dialog_box=MDDialog( + text=title_text, size_hint=(width, .25), buttons=[ MDFlatButton( - text="Copy", on_release=lambda x: callback_for_copy_title(text) + text="Copy", on_release=self.callback_for_copy_title ), MDFlatButton( - text="Cancel",on_release=lambda x: callback_for_copy_title(text), + text="Cancel",on_release=self.callback_for_copy_title, ), ],) - dialog_box.open() + self.dialog_box.open() - def callback_for_copy_title(text_item, *arg): - """Callback of alert box""" - if text_item == 'Copy': - Clipboard.copy() - dialog_box.dismiss() - toast(text_item) - - # @staticmethod - # def callback_for_copy_title(text_item, *arg): - # """Callback of alert box""" - # if text_item == 'Copy': - # Clipboard.copy(str(arg[0].text)) - # toast(text_item) + def callback_for_copy_title(self, instance): + """Callback of alert box""" + if instance.text == 'Copy': + Clipboard.copy(self.title_text) + self.dialog_box.dismiss() + toast(instance.text) class ToAddrBoxlayout(BoxLayout): diff --git a/src/buildozer.spec b/src/buildozer.spec index f8a1684e..810d2183 100644 --- a/src/buildozer.spec +++ b/src/buildozer.spec @@ -16,7 +16,7 @@ source.dir = . source.include_exts = py,png,jpg,kv,atlas,gif,zip, json, css, ttf,java # (list) List of inclusions using pattern matching -#source.include_patterns = assets/*,images/*.png +#source.include_patterns = assets/*,images/*.png, ../images1/*/*.png # (list) Source files to exclude (let empty to not exclude anything) #source.exclude_exts = spec diff --git a/src/images/kivy/default_identicon/BM-2cVBL4cpxW5p1EuK78huuRFj3nhbP9QdfL.png b/src/images/kivy/default_identicon/BM-2cVBL4cpxW5p1EuK78huuRFj3nhbP9QdfL.png index 8ddf4e6ff40a006f0f0bf55528b6b40e018ba103..3b007a97711a8e7d02098ecc1fa5829958c3357c 100644 GIT binary patch literal 27162 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 Bh0g#0 literal 1142 zcmeAS@N?(olHy`uVBq!ia0y~yVAKI&4mO}jWo=(60|Se#r;B4q#hka-47*l12)JH+ zfBeXSzxr1WxV*U8bdcxh)Z(xY6TSuAj>`Va%<;qCmf?Z!K_(*>?h^t!3eFoEcm|5| z?Iq)x-RqATTbxU;VmcfX;n0@ADA~lC!XY+6aR52MaPsZ1c)jo2OU@6L$A9|xSDbAf za7RIcWurg;k5!LrmZ=-O*!L%@{@|c+*PF}C`(Ev