class 商業選址App(MDApp): dialog = None def build(self): inspector.create_inspector(Window, Test()) return Test() def on_start(self): if not self.dialog: self.dialog = MDDialog( #text="Discard draft?", buttons=[ MDFlatButton(text=" ", text_color=self.theme_cls.primary_color), MDRectangleFlatIconButton( text="I know!", text_color=self.theme_cls.primary_color, font_name='msjhbd.ttc', on_release=self.dialog_vanish) ]) self.dialog.add_widget(Image(source='tutorial.png')) self.dialog.auto_dismiss = False self.dialog.size_hint = [0.74, 0.74] self.dialog.children[1].size_hint = [1, 1] self.dialog.md_bg_color = [1, 1, 1, 1] self.dialog.open() def dialog_vanish(self, obj): self.dialog.dismiss()
class MyApp(MDApp): title = "Black Hole" __version__ = "0.7" status = True play_status = 'stop' last_screen = [] win_size = min(Window.size) # def on_start(self): # self.root.ids.tabs.add_widget(Tab(text='Local')) # self.root.ids.tabs.add_widget(Tab(text='Global')) #def on_start(self): # self.trend_list = self.root.ids.trend_list # self.trend_list.clear_widgets() # add_trend_thread=threading.Thread(target=self.add_songs) # add_trend_thread.start() def build(self): if self.user_data.exists('theme'): self.theme_cls.theme_style = self.user_data.get('theme')['mode'] else: self.user_data.put('theme', mode='Light') if self.user_data.exists('accent'): self.theme_cls.primary_palette = self.user_data.get( 'accent')['color'] if self.theme_cls.theme_style == "Dark": self.root.ids.dark_mode_switch.active = True #self.theme_cls.primary_hue = "A400" self.theme_cls.accent_palette = self.theme_cls.primary_palette Loader.loading_image = 'cover.jpg' #return Builder.load_string(main) # if self.user_data.exists('sync'): # if int(time.time()) - int(self.user_data.get('sync')['time']) > 21600: # sync_thread = threading.Thread(target=self.get_chart) # sync_thread.start() # self.user_data.put('sync', time=time.time()) # else: # print('already synced') # else: # sync_thread = threading.Thread(target=self.get_chart) # sync_thread.start() def notify(self, title='', message='', app_name='', app_icon='', timeout=10, ticker='', toast=False): AndroidString = autoclass('java.lang.String') PythonActivity = autoclass('org.kivy.android.PythonActivity') NotificationBuilder = autoclass('android.app.Notification$Builder') Context = autoclass('android.content.Context') Drawable = autoclass('org.test.notify.R$drawable') app_icon = Drawable.icon notification_builder = NotificationBuilder(PythonActivity.mActivity) notification_builder.setContentTitle( AndroidString(title.encode('utf-8'))) notification_builder.setContentText( AndroidString(message.encode('utf-8'))) notification_builder.setSmallIcon(app_icon) notification_builder.setAutoCancel(True) notification_service = notification_service = PythonActivity.mActivity.getSystemService( Context.NOTIFICATION_SERVICE) notification_service.notify(0, notification_builder.build()) def tap_target_start(self): if self.tap_target_view.state == "close": self.tap_target_view.start() else: self.tap_target_view.stop() def __init__(self, **kwargs): super().__init__(**kwargs) self.user_data_path = os.path.join(self.user_data_dir, 'data.json') self.user_data = JsonStore(self.user_data_path) Window.bind(on_keyboard=self.events) if self.user_data.exists('download_path'): self.path = self.user_data.get('download_path')['path'] else: self.path = os.path.join(os.getenv('EXTERNAL_STORAGE'), 'Songs') self.data_path = os.path.join(self.user_data_dir, 'cache') #self.user_data.put('accent', color='Blue') self.manager_open = False self.file_manager = MDFileManager( exit_manager=self.exit_manager, select_path=self.select_path, ) self.file_manager.ext = [".m4a", ".mp3"] if os.path.exists(self.path): pass else: os.mkdir(self.path) if os.path.exists(self.data_path): pass else: os.mkdir(self.data_path) if not os.path.exists(self.user_data_path): self.user_data.put('theme', mode='Light') self.user_data.put('accent', color='Blue') def change_theme(self): if self.root.ids.dark_mode_switch.active == True: self.theme_cls.theme_style = "Dark" self.user_data.put('theme', mode='Dark') else: self.theme_cls.theme_style = "Light" self.user_data.put('theme', mode='Light') def on_tab_switch(self, instance_tabs, instance_tab, instance_tab_label, tab_text): instance_tab.ids.label.text = tab_text def check_update(self): webbrowser.open_new( 'https://github.com/Sangwan5688/Black_Hole-music_downloader') def get_chart(self): with open('top_local_chart.csv', 'wb') as f: f.write( requests.get( 'https://spotifycharts.com/regional/in/daily/latest/download' ).content) # with open('top_global_chart.csv', 'wb') as f: # f.write(requests.get("https://spotifycharts.com/regional/global/daily/latest/download").content) self.user_data.put('sync', time=time.time()) def add_top(self): self.top_list = self.root.ids.top_list # self.top_global_list = self.root.ids.top_global_list if self.top_list.children == []: Clock.schedule_once(self.thread_top) self.dia = MDDialog(text="Loading spotify top 200 chart", size_hint=(0.7, 1)) self.dia.open() def thread_top(self, *args): self.add_top_thread = threading.Thread(target=self.add_songs) self.add_top_thread.start() def add_trend(self): Clock.schedule_once(self.add_trend2) self.dia = MDDialog(text="Loading trending songs", size_hint=(0.7, 1)) self.dia.open() def add_trend2(self, *args): if self.root.ids.trend_grid.children == []: for key, values in playlist_ids.items(): self.get_playlist(key, values) self.dia.dismiss() #for i in ["znKA,YavndBuOxiEGmm6lQ__", "8MT-LQlP35c_", "LdbVc1Z5i9E_", "xXiMISqMjsrfemJ68FuXsA__"]: # executor.submit(self.get_playlist, i) #executor.shutdown() def add_songs(self): url = 'https://spotifycharts.com/regional/in/daily/latest/download' with closing(requests.get(url, stream=True)) as r: f = (line.decode('utf-8') for line in r.iter_lines()) reader = csv.reader(f, delimiter=',', quotechar='"') for row in reader: try: pos = int(row[0]) song_name = row[1] art_name = row[2] lst = TwoLineAvatarListItem( text="{}. {}".format(pos, song_name), secondary_text=art_name, on_press=lambda x, y=song_name: self.select_spotify(y)) lst.add_widget(IconLeftWidget(icon='music-note-outline')) self.top_list.add_widget(lst) except: continue try: self.dia.dismiss() except: pass def select_spotify(self, song_name): self.dia = MDDialog(text="Loading..", size_hint=(0.7, 1)) self.dia.open() spoti = threading.Thread(target=self.spoti_thread, args=(song_name, )) spoti.start() def spoti_thread(self, song_name): response = requests.get(search_base_url + song_name) result = response.content.decode() self.search_data = json.loads( result.replace(""", "'").replace("&", "&").replace("'", "'"))['songs']['data'] self.song_details(0) def push_notify(self, head): notification.notify(head, "Download complete") def download_list(self): self.down_list = self.root.ids.downloadlist self.down_list.clear_widgets() td = threading.Thread(target=self.add_songs_downlist) td.start() def add_songs_downlist(self): self.down_path_list = [] for root, dirs, files in os.walk(os.getenv('EXTERNAL_STORAGE')): for filename in files: if os.path.splitext(filename)[1] in [ ".mp3", ".m4a", ".ogg", ".wav" ]: self.down_path_list.append( (os.path.join(root, filename), filename)) for i in range(len(self.down_path_list)): lst = OneLineAvatarListItem( text=self.down_path_list[i][1], on_press=lambda x, y=i: self.play_song(y)) lst.add_widget(IconLeftWidget(icon='music-note-outline')) self.down_list.add_widget(lst) def show_data(self, query): close_btn = MDFlatButton(text="Close", on_release=self.close_dialog) if query == '': self.dia = MDDialog(title="Invalid Name", text="Please enter a song name", size_hint=(0.7, 1), buttons=[close_btn]) self.dia.open() else: self.change_screen('SongListScreen') self.dia = MDDialog(text="Searching for songs ...", size_hint=(0.7, 1)) self.list_view = self.root.ids.container self.list_view.clear_widgets() self.dia.open() req = UrlRequest(search_base_url + query.replace(' ', '+'), self.show_list) def show_list(self, req, result): self.search_data = json.loads( result.replace(""", "'").replace("&", "&").replace("'", "'"))['songs']['data'] for i in range(len(self.search_data)): lst = TwoLineAvatarListItem( text=self.search_data[i]['title'].replace( """, "'").replace("&", "&").replace("'", "'"), secondary_text=self.search_data[i]['more_info'] ['primary_artists'].replace(""", "'").replace( "&", "&").replace("'", "'"), on_press=lambda x, y=i: self.song_details(y)) lst.add_widget(IconLeftWidget(icon='music-note-outline')) self.list_view.add_widget(lst) self.dia.dismiss() def fetch_details(self): print('started fetching details') self.song_data = json.loads( requests.get(song_details_base_url + self.song_id).text.replace( """, "'").replace("&", "&").replace("'", "'"))[self.song_id] try: url = self.song_data['media_preview_url'] url = url.replace("preview", "aac") if self.song_data['320kbps'] == "true": url = url.replace("_96_p.mp4", "_320.mp4") else: url = url.replace("_96_p.mp4", "_160.mp4") self.song_dwn_url = url except KeyError or TypeError: self.song_data['media_url'] = self.decrypt_url( self.song_data['encrypted_media_url']) if self.song_data['320kbps'] != "true": self.song_dwn_url = self.song_data['media_url'].replace( "_320.mp4", "_160.mp4") self.song_name = self.song_data['song'] self.album = self.song_data['album'] self.artist_name = self.song_data["primary_artists"] self.featured_artist = self.song_data["featured_artists"] self.year = self.song_data["year"] self.genre = (self.song_data["language"]).capitalize() self.prepare(self.song_dwn_url) self.root.ids.SongDetailsScreen.add_widget( MDLabel(text=self.convert_sec(self.sound.getDuration()), halign='right', theme_text_color='Secondary', padding_x='20dp', pos_hint={"top": 0.725})) self.play_stamp = (MDLabel(text=self.convert_sec( self.sound.getCurrentPosition()), halign='left', theme_text_color='Secondary', padding_x='20dp', pos_hint={"top": 0.725})) self.root.ids.SongDetailsScreen.add_widget(self.play_stamp) print('finished fetching details') def get_playlist(self, title, listId): image = AsyncImage(source=playlist_images[listId], size_hint=(1, 1), pos_hint={'top': 0.9}, allow_stretch=True) card = MDCard(orientation='vertical', border_radius=15, radius=[0, 0, 15, 15], pos_hint={ "center_x": 0.5, "center_y": 0.5 }, size_hint=(None, None), size=(self.win_size * 0.3, self.win_size * 0.3)) card.add_widget(image) self.root.ids.trend_grid.add_widget( MDTextButton(text=title, pos_hint={'center_x': 0.5}, on_press=lambda x: self.show_top(title, listId))) self.root.ids.trend_grid.add_widget(card) self.root.ids.trend_grid.add_widget(MDLabel(text='')) self.root.ids.trend_grid.add_widget(MDLabel(text='')) self.root.ids.trend_grid.add_widget(MDLabel(text='')) self.root.ids.trend_grid.add_widget(MDLabel(text='')) def show_top(self, ttl, Id): self.dia = MDDialog(text="Loading {}".format(ttl), size_hint=(0.7, 1)) self.dia.open() t3 = threading.Thread(target=self.show_top2, args=(ttl, Id)) t3.start() def show_top2(self, ttl, Id): self.tlist = self.root.ids.trend_list self.root.ids.trend_toolbar.title = ttl self.tlist.clear_widgets() try: response = requests.get(playlist_details_base_url.format(Id)) if response.status_code == 200: songs_json = response.text.encode().decode() songs_json = json.loads(songs_json) self.search_data = songs_json['list'] for i in range(int(len(songs_json['list']))): #print(items['id']) #print(i) #print(songs_json['list'][i]['title']) lst = TwoLineAvatarListItem( text=songs_json['list'][i]['title'].replace( """, "'").replace("&", "&").replace("'", "'"), secondary_text=songs_json['list'][i] ['subtitle'].replace(""", "'").replace( "&", "&").replace("'", "'"), on_press=lambda x, y=i: self.song_details(y)) lst.add_widget(IconLeftWidget(icon='music-note-outline')) self.tlist.add_widget(lst) self.change_screen('TrendListScreen') except Exception as e: print(e) self.dia.dismiss() def decrypt_url(url): des_cipher = des(b"38346591", ECB, b"\0\0\0\0\0\0\0\0", pad=None, padmode=PAD_PKCS5) enc_url = base64.b64decode(url.strip()) dec_url = des_cipher.decrypt(enc_url, padmode=PAD_PKCS5).decode('utf-8') dec_url = dec_url.replace("_96.mp4", "_320.mp4") return dec_url def song_details(self, i): self.s_manager = self.root.ids.screen_manager self.change_screen('SongDetailsScreen') self.details_screen = self.root.ids.SongDetailsScreen self.details_screen.clear_widgets() self.song_name = self.search_data[i]['title'].replace( """, "'").replace("&", "&").replace("'", "'") self.song_id = self.search_data[i]['id'] try: self.artist_name = self.search_data[i]['more_info'][ 'primary_artists'].replace(""", "'").replace( "&", "&").replace("'", "'") self.album = self.search_data[i]['album'].replace( """, "'").replace("&", "&").replace("'", "'") except: self.artist_name = self.search_data[i]['subtitle'] self.image_url = self.search_data[i]['image'].replace( '50x50', '500x500').replace('150x150', '500x500') self.image_path = os.path.join(self.data_path, self.song_id + '.jpg') self.fetch_thread = threading.Thread(target=self.fetch_details) self.fetch_thread.start() self.details_screen.add_widget( MDIconButton(icon='chevron-left', pos_hint={ "center_x": 0.05, "center_y": 0.95 }, on_press=lambda x: self.back_screen())) song_image = AsyncImage(source=self.image_url, pos_hint={ "center_x": 0.5, "center_y": 0.5 }, allow_stretch=True) card = MDCard(orientation='vertical', pos_hint={ "center_x": 0.5, "center_y": 0.65 }, size_hint=(None, None), size=(self.win_size * 0.9, self.win_size * 0.9)) card.add_widget(song_image) self.details_screen.add_widget(card) self.details_screen.add_widget( MDLabel(text=self.song_name, halign='center', theme_text_color='Custom', text_color=self.theme_cls.primary_color, font_style='H4', bold=True, pos_hint={"top": 0.84})) self.details_screen.add_widget( MDLabel(text=self.artist_name, halign='center', theme_text_color='Secondary', font_style='H6', pos_hint={"top": 0.8})) self.spinner = MDSpinner(size_hint=(None, None), size=("50", "50"), pos_hint={ 'center_x': 0.5, "center_y": 0.15 }, active=True) #self.details_screen.add_widget(MDLabel(text=self.album, halign='center', theme_text_color='Hint', font_style='H6', pos_hint={"top":0.9})) self.heart_icon = MDIconButton(icon='heart-outline', user_font_size="30sp", theme_text_color='Secondary', pos_hint={ "center_x": 0.1, "center_y": 0.15 }, on_press=lambda x: self.add_fav()) self.details_screen.add_widget(self.heart_icon) self.play_progress = MDProgressBar(pos_hint={ 'center_x': 0.5, 'center_y': 0.25 }, size_hint_x=0.9, value=0, color=self.theme_cls.primary_color) self.details_screen.add_widget(self.play_progress) self.tap_target_view = MDTapTargetView( widget=self.heart_icon, title_text="Add to Favorites", description_text="Feature currently under development", widget_position="left_bottom", ) self.details_screen.add_widget( MDIconButton(icon="chevron-double-left", pos_hint={ "center_x": .3, "center_y": .15 }, user_font_size="50sp", on_release=lambda x: self.rewind())) self.details_screen.add_widget( MDIconButton(icon="chevron-double-right", pos_hint={ "center_x": .7, "center_y": .15 }, user_font_size="50sp", on_release=lambda x: self.forward())) self.play_btn = MDFloatingActionButton( icon='play', pos_hint={ 'center_x': 0.5, "center_y": 0.15 }, user_font_size="50sp", md_bg_color=(1, 1, 1, 1), elevation_normal=10, on_press=lambda x: self.play_song_online()) self.details_screen.add_widget(self.play_btn) self.details_screen.add_widget( MDIconButton(icon='arrow-collapse-down', user_font_size="30sp", theme_text_color='Secondary', pos_hint={ 'center_x': 0.9, "center_y": 0.15 }, on_press=lambda x: self.download_bar())) try: self.dia.dismiss() except: pass def add_fav(self): if self.heart_icon.icon == 'heart-outline': self.heart_icon.icon = 'heart' self.heart_icon.theme_text_color = "Custom" self.heart_icon.text_color = (1, 0, 0, 1) self.tap_target_view.start() #toast("Feature under development") elif self.heart_icon.icon == 'heart': #self.heart_icon.icon = 'heart-broken' self.heart_icon.icon = 'heart-outline' self.heart_icon.theme_text_color = 'Secondary' #self.heart_icon.text_color = self.theme_cls.text_color toast("Removed from Favorites") def change_screen(self, screen, *args): if self.root.ids.screen_manager.current == 'SongDetailsScreen' or self.root.ids.screen_manager.current == 'PlayScreen': try: self.stop() except: pass if args: self.root.ids.screen_manager.transition.direction = args[0] if args[0] != 'right': self.last_screen.append(self.root.ids.screen_manager.current) else: self.root.ids.screen_manager.transition.direction = 'left' self.last_screen.append(self.root.ids.screen_manager.current) self.root.ids.screen_manager.current = screen def back_screen(self): if self.root.ids.screen_manager.current != 'MainScreen': self.change_screen(self.last_screen[-1], 'right') self.last_screen.pop(-1) def cancel(self): self.download_progress.color = 1, 0, 0, 1 self.status = False t3 = threading.Thread(target=self.cancel2) t3.start() def cancel2(self): time.sleep(0.5) try: os.remove("{}/{} - {}.m4a".format(self.data_path, self.song_name, self.artist_name)) print('removed') except: print('failed to remove') pass self.dia.dismiss() self.status = True def download_bar(self): self.download_progress = MDProgressBar( pos_hint={ 'center_x': 0.5, 'center_y': 0.5 }, size_hint_x=0.8, value=0, color=self.theme_cls.primary_color) self.dia = MDDialog(text='Downloading', buttons=[ MDFlatButton( text="CANCEL", text_color=self.theme_cls.primary_color, on_press=lambda x: self.cancel()) ]) #self.dia.add_widget(IconLeftWidget(icon='download', pos_hint={'center_x': .1, 'center_y': .1})) self.dia.add_widget(self.download_progress) self.dia.open() t2 = threading.Thread(target=self.download_song) t2.start() def play_song_online(self): self.fetch_thread.join() if self.sound: #print("Sound found at %s" % self.sound.source) #print("Sound is %.3f seconds" % self.sound.length) if self.play_status == 'pause' or self.play_status == 'stop': self.play_btn.icon = 'pause' self.play() lnth = self.sound.getDuration() t2 = threading.Thread(target=self.online_play_bar, args=(lnth, )) t2.start() elif self.play_status == 'play': self.play_btn.icon = 'play' self.pause() else: time.sleep(0.5) self.play_song_online def online_play_bar(self, length, *args): while True: if length != 0: self.play_progress.value = 100 * ( self.sound.getCurrentPosition()) / length #print(self.progress.value) time.sleep(1) self.play_stamp.text = self.convert_sec( self.sound.getCurrentPosition()) if self.play_status == 'stop': break if self.play_stamp.text == self.length_stamp.text: self.play_song(args[0] + 1) def play_song(self, i): try: self.stop() except: pass link = self.down_path_list[i][0] if self.root.ids.screen_manager.current != 'PlayScreen': self.change_screen("PlayScreen") self.prepare(link) if link.endswith('.m4a'): self.audio = MP4(link) self.play_song_name = self.audio.get('\xa9nam', ['Unknown'])[0] #print(audio['\xa9alb']) self.play_art_name = self.audio.get('\xa9ART', ['Unknown'])[0] #print(audio['\xa9day']) #print(audio['\xa9gen']) try: self.img_data = self.audio["covr"][0] except: with open('cover.jpg', 'rb') as f: self.img_data = f.read() elif link.endswith('.mp3'): self.audio = MP3(link, ID3=EasyID3) self.audio_tags = ID3(link) self.play_song_name = self.audio.get('title', ['Unknown'])[0] self.play_art_name = self.audio.get('artist', ['Unknown'])[0] try: self.img_data = self.audio_tags.get("APIC:").data except: with open('cover.jpg', 'rb') as f: self.img_data = f.read() else: with open('cover.jpg', 'rb') as f: self.img_data = f.read() self.play_song_name = 'Unknown' self.play_art_name = 'Unknown' play_image_data = io.BytesIO(self.img_data) img = CoreImage(play_image_data, ext="jpg").texture song_image = Image(allow_stretch=True) song_image.texture = img self.root.ids.PlayScreen.clear_widgets() self.root.ids.PlayScreen.add_widget( MDIconButton(icon='chevron-left', pos_hint={ "center_x": 0.05, "center_y": 0.95 }, on_press=lambda x: self.back_screen())) card = MDCard(orientation='vertical', pos_hint={ "center_x": 0.5, "center_y": 0.65 }, size_hint=(None, None), size=(self.win_size * 0.9, self.win_size * 0.9)) card.add_widget(song_image) self.root.ids.PlayScreen.add_widget(card) self.root.ids.PlayScreen.add_widget( MDLabel(text=self.play_song_name, halign='center', theme_text_color='Custom', text_color=self.theme_cls.primary_color, font_style='H4', bold=True, pos_hint={"top": 0.84})) self.root.ids.PlayScreen.add_widget( MDLabel(text=self.play_art_name, halign='center', theme_text_color='Secondary', font_style='H6', pos_hint={"top": 0.8})) self.play_progress = MDProgressBar(pos_hint={ 'center_x': 0.5, 'center_y': 0.25 }, size_hint_x=0.9, value=0, color=self.theme_cls.primary_color) self.root.ids.PlayScreen.add_widget(self.play_progress) self.root.ids.PlayScreen.add_widget( MDIconButton(icon="chevron-double-left", pos_hint={ "center_x": .15, "center_y": .15 }, user_font_size="40sp", on_release=lambda x: self.rewind())) self.root.ids.PlayScreen.add_widget( MDIconButton(icon="chevron-double-right", pos_hint={ "center_x": .85, "center_y": .15 }, user_font_size="40sp", on_release=lambda x: self.forward())) self.next_button = MDIconButton( icon="skip-next", pos_hint={ "center_x": .65, "center_y": .15 }, user_font_size="55sp", on_release=lambda x: self.play_song(i + 1)) self.root.ids.PlayScreen.add_widget(self.next_button) self.previous_button = (MDIconButton( icon="skip-previous", pos_hint={ "center_x": .35, "center_y": .15 }, user_font_size="55sp", on_release=lambda x: self.play_song(i - 1))) self.root.ids.PlayScreen.add_widget(self.previous_button) self.play_btn = MDFloatingActionButton( icon='play', pos_hint={ 'center_x': 0.5, "center_y": 0.15 }, user_font_size="50sp", md_bg_color=(1, 1, 1, 1), elevation_normal=10, on_press=lambda x: self.play_song_offline(i)) self.root.ids.PlayScreen.add_widget(self.play_btn) self.length_stamp = MDLabel(text=self.convert_sec( self.sound.getDuration()), halign='right', theme_text_color='Secondary', padding_x='20dp', pos_hint={"top": 0.725}) self.root.ids.PlayScreen.add_widget(self.length_stamp) self.play_stamp = (MDLabel(text=self.convert_sec( self.sound.getCurrentPosition()), halign='left', theme_text_color='Secondary', padding_x='20dp', pos_hint={"top": 0.725})) self.root.ids.PlayScreen.add_widget(self.play_stamp) self.play_song_offline(i) def play_song_offline(self, i): if True: if self.play_status == 'pause' or self.play_status == 'stop': self.play_btn.icon = 'pause' self.play() lnth = self.sound.getDuration() t2 = threading.Thread(target=self.online_play_bar, args=(lnth, i)) t2.start() elif self.play_status == 'play': self.play_btn.icon = 'play' self.pause() else: time.sleep(0.5) self.play_song_offline def convert_sec(self, lnth): lnth = lnth / 1000 try: if int(lnth - (60 * (lnth // 60))) < 10: return ("{}:0{}".format(int(lnth // 60), int(lnth - (60 * (lnth // 60))))) else: return ("{}:{}".format(int(lnth // 60), int(lnth - (60 * (lnth // 60))))) except: print('Error: Length is {}'.format(lnth)) def prepare(self, link): print('preparing') try: self.sound = MediaPlayer() self.sound.setDataSource(link) self.sound.prepare() self.sound.setLooping(False) except Exception as e: print(e) time.sleep(0.25) self.prepare(link) print('prepared') def play(self): self.sound.start() self.play_status = 'play' def pause(self): self.sound.pause() self.play_status = 'pause' def stop(self): self.sound.stop() self.sound.release() self.play_status = 'stop' def forward(self): self.sound.seekTo(self.sound.getCurrentPosition() + 5000) def rewind(self): self.sound.seekTo(self.sound.getCurrentPosition() - 5000) def callback_for_about(self, *args): toast('Opening ' + args[0]) webbrowser.open_new(args[0]) def contact_us(self): bottom_sheet_menu = MDGridBottomSheet(radius=15, radius_from='top') data = [ { "name": "Telegram", "icon": "telegram", "link": "https://t.me/sangwan5688" }, { "name": "Instagram", "icon": "instagram", "link": "https://www.instagram.com/sangwan5688/" }, { "name": "Twitter", "icon": "twitter", "link": "https://twitter.com/sangwan5688" }, { "name": "Mail", "icon": "gmail", "link": "https://mail.google.com/mail/?view=cm&fs=1&[email protected]&su=Regarding+Mobile+App" }, { "name": "Facebook", "icon": "facebook", "link": "https://www.facebook.com/ankit.sangwan.5688" }, ] for item in data: bottom_sheet_menu.add_item( item["name"], lambda x, y=item["link"]: self.callback_for_about(y), icon_src=item["icon"], ) bottom_sheet_menu.open() def download_song(self): if self.status: print('started downloading song') fname = "{}/{} - {}.m4a".format(self.data_path, self.song_name, self.artist_name) #self.download_bar() with requests.get(self.song_dwn_url, stream=True) as r, open(fname, "wb") as f: file_size = int(r.headers['Content-Length']) total = int(file_size / 1024) self.dia.add_widget( MDLabel(text='{:.2f} MB'.format(file_size / (1024 * 1024)), halign='right')) for chunk in r.iter_content(chunk_size=1024): if self.status: f.write(chunk) self.download_progress.value += 100 / total else: #print('Download cancelled') break print('finished downloading song') if self.status: self.save_metadata() def save_metadata(self): with open(self.image_path, 'wb') as f: f.write(requests.get(self.image_url).content) print('getting metadata') audio_path = os.path.join( self.data_path, "{} - {}.m4a".format(self.song_name, self.artist_name)) audio = MP4(audio_path) audio['\xa9nam'] = self.song_name audio['\xa9alb'] = self.album audio['aART'] = self.artist_name if self.featured_artist != '': audio['\xa9ART'] = self.artist_name + ", " + self.featured_artist else: audio['\xa9ART'] = self.artist_name audio['\xa9day'] = self.year audio['\xa9gen'] = self.genre with open(os.path.join(self.data_path, self.song_id + '.jpg'), "rb") as f: audio["covr"] = [ MP4Cover(f.read(), imageformat=MP4Cover.FORMAT_JPEG) ] audio.save() shutil.move(audio_path, audio_path.replace(self.data_path, self.path)) print('finished getting metadata') #close_btn = MDFlatButton(text="OK", on_release=self.close_dialog) self.dia.dismiss() os.remove(os.path.join(self.data_path, self.song_id + '.jpg')) close_btn = MDIconButton(icon='checkbox-marked-circle-outline', theme_text_color="Custom", text_color=self.theme_cls.primary_color, on_release=self.close_dialog) self.dia = MDDialog(title="Download Complete", text="Song Downloaded Successfully!", size_hint=(0.7, 1), buttons=[close_btn]) self.dia.open() #notification.notify(self.song_name +' by '+ self.artist_name, "Download complete") #toast("Song Downloaded Successfully!") def set_nav_color(self, item): for child in self.root.ids.nav_list.children: #if child.text_color == self.theme_cls.primary_color: # child.text_color = self.theme_cls.text_color # break if child.text == item: child.text_color = self.theme_cls.primary_color break def file_manager_open(self): self.file_manager.show(self.path) # output manager to the screen self.manager_open = True def select_path(self, path): self.exit_manager() if os.path.isdir(path): self.path = path toast("Songs will be downloaded to: " + path) self.user_data.put('download_path', path=self.path) else: toast("No directory selected") def exit_manager(self, *args): self.manager_open = False self.file_manager.close() def events(self, instance, keyboard, keycode, text, modifiers): #print(keyboard) if keyboard in (1001, 27): if self.manager_open: self.file_manager.back() else: self.back_screen() if keyboard == 13: if self.root.ids.screen_manager.current == 'MainScreen': self.show_data(self.root.ids.song_name.text) else: pass return True def close_dialog(self, obj): self.dia.dismiss()
class Library(Screen): def __init__(self, **kwargs): super(Library, self).__init__(**kwargs) self.deckname = None self.skeleton_frame() def skeleton_frame(self): #Displays all decks on the app self.box = MDBoxLayout(orientation="vertical") self.scrollview = ScrollView() self.list = MDList() self.scrollview.add_widget(self.list) #calls the activate_for_loop method self.display_deck() # Buttons on the bottom of the screen # Buttons are places on bottom of screen self.box.add_widget( MDLabel(size_hint=(0.2, 0.15))) # Push down the list of buttons self.box.add_widget(self.scrollview) self.bottom_bar = MDToolbar() self.delete_deck_button = MDIconButton(icon="trash-can-outline", pos_hint={ 'center_x': .5, 'center_y': .5 }) self.delete_deck_button.bind(on_press=self.delete_deck) self.build_deck_button = MDIconButton(icon="plus-thick", pos_hint={ 'center_x': 0.5, 'center_y': 0.5 }) self.build_deck_button.bind(on_press=self.build_new_deck) #add method to make a new deck self.bottom_bar.add_widget(self.delete_deck_button) self.bottom_bar.add_widget(MDLabel()) self.bottom_bar.add_widget(self.build_deck_button) self.bottom_bar.add_widget(MDLabel()) self.box.add_widget(self.bottom_bar) self.add_widget(self.box) def skeleton_frame2(self, instance): # method must be used to make the on_press method work self.scrollview.remove_widget(self.list) self.box.remove_widget(self.bottom_bar) self.list = MDList() self.scrollview.add_widget(self.list) #Displays all decks on the app self.box = MDBoxLayout(orientation="vertical") self.scrollview = ScrollView() self.list = MDList() self.scrollview.add_widget(self.list) #calls the activate_for_loop method self.display_deck() # Buttons on the bottom of the screen # Buttons are places on bottom of screen self.box.add_widget( MDLabel(size_hint=(0.2, 0.15))) # Push down the list of buttons self.box.add_widget(self.scrollview) self.bottom_bar = MDToolbar() self.delete_deck_button = MDIconButton(icon="trash-can-outline", pos_hint={ 'center_x': .5, 'center_y': .5 }) self.delete_deck_button.bind(on_press=self.delete_deck) self.build_deck_button = MDIconButton(icon="plus-thick", pos_hint={ 'center_x': 0.5, 'center_y': 0.5 }) self.build_deck_button.bind(on_press=self.build_new_deck) #add method to make a new deck self.bottom_bar.add_widget(self.delete_deck_button) self.bottom_bar.add_widget(MDLabel()) self.bottom_bar.add_widget(self.build_deck_button) self.bottom_bar.add_widget(MDLabel()) self.box.add_widget(self.bottom_bar) self.add_widget(self.box) # Creates a section that will list out the decks def display_deck(self): conn = sqlite3.connect("flashcard_app.db") cur = conn.cursor() cur.execute(""" SELECT DeckName FROM Decks """) names = cur.fetchall() for name in names: # the nested for loop will remove (),' from the string name = str(name) for char in name: if char == "(" or char == ")" or char == "," or char == "'": name = name.replace(char, "") self.items = OneLineListItem(text=name) self.items.bind(on_press=self.display_cards) self.list.add_widget(self.items) conn.commit() conn.close() # working code to switch screens with python code def display_cards(self, instance): self.scrollview.remove_widget(self.list) self.box.remove_widget(self.bottom_bar) self.list = MDList() self.scrollview.add_widget(self.list) self.deckname = instance.text print(self.deckname) conn = sqlite3.connect("flashcard_app.db") cur = conn.cursor() cur.execute( """ SELECT CardName FROM Cards WHERE DeckName = ? """, (instance.text, )) names = cur.fetchall() for name in names: # the nested for loop will remove (),' from the string name = str(name) for char in name: if char == "(" or char == ")" or char == "," or char == "'": name = name.replace(char, "") self.items = OneLineListItem(text=name) self.items.bind(on_press=self.display_name_def) self.list.add_widget(self.items) conn.commit() conn.close() self.get_bottom_bar() def display_cards2(self): self.scrollview.remove_widget(self.list) self.box.remove_widget(self.bottom_bar) self.list = MDList() self.scrollview.add_widget(self.list) conn = sqlite3.connect("flashcard_app.db") cur = conn.cursor() cur.execute( """ SELECT CardName FROM Cards WHERE DeckName = ? """, (self.deckname, )) names = cur.fetchall() for name in names: # the nested for loop will remove (),' from the string name = str(name) for char in name: if char == "(" or char == ")" or char == "," or char == "'": name = name.replace(char, "") self.items = OneLineListItem(text=name) self.items.bind(on_press=self.display_name_def) self.list.add_widget(self.items) conn.commit() conn.close() self.get_bottom_bar() #displays the bottom nav bar when display_cards is called def get_bottom_bar(self): self.bottom_bar = MDToolbar() self.add_card_button = MDIconButton(icon="plus-thick", pos_hint={ 'center_x': 0.5, 'center_y': 0.5 }) self.trash_button = MDIconButton(icon="trash-can-outline", pos_hint={ 'center_x': 0.5, 'center_y': 0.5 }) self.back_button = MDIconButton(icon="arrow-left-bold", pos_hint={ 'center_x': 0.5, 'center_y': 0.5 }) self.trash_button.bind(on_press=self.delete_card) self.back_button.bind(on_press=self.skeleton_frame2) self.add_card_button.bind(on_press=self.add_cards) #self.build_deck_button.bind(on_press=self.to_build_card) # jargon of code to space out the buttons on bottom nav bar self.bottom_bar.add_widget(MDLabel()) self.bottom_bar.add_widget(self.back_button) self.bottom_bar.add_widget(MDLabel()) self.bottom_bar.add_widget(MDLabel()) self.bottom_bar.add_widget(self.add_card_button) self.bottom_bar.add_widget(MDLabel()) self.bottom_bar.add_widget(MDLabel()) self.bottom_bar.add_widget(self.trash_button) self.bottom_bar.add_widget(MDLabel()) self.bottom_bar.add_widget(MDLabel()) self.box.add_widget(self.bottom_bar) def add_cards(self, instance): close_button = MDFlatButton(text="Close", on_release=self.close_dialog) enter_button = MDFlatButton(text="Enter", on_release=self.add_cardname_to_db) self.grid = MDGridLayout(rows=4, size_hint_y=None, height=int(Window.height) / 8.9) self.front_input = MDTextField(size_hint=(.9, 1)) self.back_input = MDTextField(size_hint=(.9, 1)) self.dialog = MDDialog(title="Card Creation", pos_hint={ 'center_x': .5, 'center_y': .5 }, type="custom", content_cls=Content(), size_hint=(.9, 1), buttons=[close_button, enter_button]) self.grid.add_widget(MDLabel(text=" Front")) self.grid.add_widget(self.front_input) self.grid.add_widget(MDLabel(text=" Back")) self.grid.add_widget(self.back_input) self.dialog.add_widget(self.grid) self.dialog.open() def add_cardname_to_db(self, instance): front_input = self.front_input.text back_input = self.back_input.text print(self.deckname) print(front_input) print(back_input) con = sqlite3.connect("flashcard_app.db") cur = con.cursor() cur.execute( """ INSERT INTO Cards (CardName, Definition, DeckName) VALUES(?, ?, ?) """, (front_input, back_input, self.deckname)) names = cur.fetchall() for name in names: # the nested for loop will remove (),' from the string name = str(name) for char in name: if char == "(" or char == ")" or char == "," or char == "'": name = name.replace(char, "") self.items = OneLineListItem(text=name) #self.items.bind(on_press=self.display_name_def) self.list.add_widget(self.items) con.commit() con.close() self.display_cards2() # displays the front and back of a single card def display_name_def(self, instance): self.predicate = True self.scrollview.remove_widget(self.list) self.box.remove_widget(self.bottom_bar) print(instance.text) con = sqlite3.connect("flashcard_app.db") cur = con.cursor() cur.execute( """ SELECT CardName, Definition FROM Cards WHERE CardName = ? """, (instance.text, )) row = cur.fetchall() for cardname, definition in row: self.front = cardname self.back = definition print(self.front, self.back) con.commit() con.close() # will display the front-side of selected card self.click_action() # the screen will act as a button to display the front or back after clicking the screen def click_action(self): if self.predicate == True: self.button = Button(text=self.front, color=(1, 0, 1, 1), background_color=(0, 0, 0, 0), font_size='20sp', on_release=self.click_action2) self.predicate = False else: self.button = Button(text=self.back, color=(1, 0, 1, 1), background_color=(0, 0, 0, 0), font_size='20sp', on_release=self.click_action2) self.predicate = True self.scrollview.add_widget(self.button) self.bottom_bar_name_def() def click_action2(self, instance): self.box.remove_widget(self.scrollview) self.remove_widget(self.bottom_bar) self.scrollview = ScrollView() if self.predicate == True: self.button = Button(text=self.front, color=(1, 0, 1, 1), background_color=(0, 0, 0, 0), font_size='20sp', on_release=self.click_action2) self.predicate = False else: self.button = Button(text=self.back, color=(1, 0, 1, 1), background_color=(0, 0, 0, 0), font_size='20sp', on_release=self.click_action2) self.predicate = True self.scrollview.add_widget(self.button) self.box.add_widget(self.scrollview) self.bottom_bar_name_def() # displays bottom bar that will return user to displaying the list of decks def bottom_bar_name_def(self): self.bottom_bar = MDToolbar() #self.box = MDBoxLayout(orientation="horizontal") self.back_button = MDFlatButton(text="Return to Decks", pos_hint={ 'center_x': 0.5, 'center_y': 0.5 }) self.back_button.bind(on_press=self.back_display_cards) #self.box.add_widget(self.back_button) #self.box.add_widget(MDLabel()) self.bottom_bar.add_widget(self.back_button) self.add_widget(self.bottom_bar) def back_display_cards(self, instance): self.box.remove_widget(self.scrollview) self.remove_widget(self.bottom_bar) self.skeleton_frame() # method to build a new deck using a dialog box def build_new_deck(self, instance): close_button = MDFlatButton(text="Close", on_release=self.close_dialog) # *** This button will put name into db, then refresh the page enter_button = MDFlatButton(text="Enter", on_release=self.add_name_to_db) self.input = MDTextField(pos_hint={ 'center_x': 0.5, 'center_y': 0.5 }, size_hint=(.9, 1)) self.dialog = MDDialog(title="Enter Deck Name", size_hint=(0.7, 1), buttons=[close_button, enter_button]) self.dialog.add_widget(self.input) self.dialog.open() # method to close the dialog box def close_dialog(self, instance): self.dialog.dismiss() #method that inserts the deck name into db def add_name_to_db(self, instance): input = self.input.text # this will have an if else statement if an error was typed in #self.error = MDDialog() #self.error.open() conn = sqlite3.connect("flashcard_app.db") cur = conn.cursor() cur.execute( """ INSERT INTO Decks (deckname) VALUES(?)""", (input, )) conn.commit() conn.close() self.remove_widget(self.box) self.skeleton_frame() print("boo") def delete_deck(self, instance): close_button = MDFlatButton(text="Close", on_release=self.close_dialog) delete_dialog_button = MDFlatButton(text="Delete", on_release=self.delete_deck_input) self.dialog = MDDialog(title="Delete Deck", size_hint=(0.7, 1), buttons=[close_button, delete_dialog_button]) self.input = MDTextField() self.dialog.add_widget(self.input) self.dialog.open() def delete_deck_input(self, instance): input = self.input.text con = sqlite3.connect("flashcard_app.db") cur = con.cursor() cur.execute( """ DELETE FROM Decks WHERE DeckName = ?; """, (input, )) cur.execute( """ DELETE FROM Cards WHERE DeckName = ?; """, (input, )) con.commit() con.close() self.remove_widget(self.box) self.skeleton_frame() def delete_card(self, instance): close_button = MDFlatButton(text="Close", on_release=self.close_dialog) delete_dialog_button = MDFlatButton(text="Delete", on_release=self.delete_card_input) self.dialog = MDDialog(title="Delete Card", size_hint=(0.7, 1), buttons=[close_button, delete_dialog_button]) self.input = MDTextField() self.dialog.add_widget(self.input) self.dialog.open() def delete_card_input(self, instance): input = self.input.text con = sqlite3.connect("flashcard_app.db") cur = con.cursor() cur.execute( """ DELETE FROM Cards WHERE CardName = ? """, (input, )) con.commit() con.close() self.display_cards2()
class Test(MDGridLayout, MDApp, Widget): '''這是螢幕主畫面(不包含一開始進去tutorial,tutorial在650多行那邊的on_start()''' '''這邊到300行出頭是一開始進去後會難到的配置,300多行後會是按完Run之後會秀出來的畫面''' progress_bar = ObjectProperty() def __init__(self, **kwargs): super(Test, self).__init__(**kwargs) self.click = 0 # ---以下定義點擊前三名按鈕時的次數--- self.add1 = 0 self.add1_shop_list = [] self.add1_temp_list = [] self.add1_rent_list = [] self.add1_bound = [] self.bound1 = GeoJsonMapLayer() self.add2 = 0 self.add2_shop_list = [] self.add2_temp_list = [] self.add2_rent_list = [] self.add2_bound = [] self.bound2 = GeoJsonMapLayer() self.add3 = 0 self.add3_shop_list = [] self.add3_temp_list = [] self.add3_rent_list = [] self.add3_bound = [] self.bound3 = GeoJsonMapLayer() # from geopy.geocoders import Nominatim # self.geolocator = Nominatim(user_agent="Brian_map") # self.wid = Widget() self.progress_bar = MDProgressBar() self.popup = MDDialog(title='數據加載中,請稍後!', #content = self.progress_bar ) self.popup.auto_dismiss = False self.popup.add_widget(self.progress_bar) self.popup.children[1].size_hint = [1, 1] self.popup.children[1].children[5].font_size = 40 self.popup.children[1].children[5].font_name = 'msjhbd.ttc' self.popup.size_hint = [0.5, 0.5] self.popup.background_color = [0.5, 0.5, 0.5, 0.75] self.progress_bar.value = 1 self.popup.bind(on_open=self.puopen) # 主畫面切成左右兩欄 self.cols = 3 # 左欄是一個Gridlayout,有四列 self.left = MDGridLayout(rows=6, size_hint=[0.4, 1], spacing=[0, 3]) # 創建地圖 self.map = FarmersMapView() # 左欄最上方要來做店租範圍 self.left.one = MDGridLayout(size=[590, 657], rows=2, size_hint=[1, 0.2], md_bg_color=[0.39, 0.4, 0.72, 1], padding=[35, -20, 35, -20], spacing=[0, -30]) # 把標籤裝進去最上層 self.left.one.add_widget( Label(text='選擇月租範圍', font_size='20sp', font_name='msjhbd.ttc', size_hint_y=0.18)) # 新增一層容器準備裝三個東西 self.left.one.box = BoxLayout(spacing=8, size_hint_y=0.15) # 盒子裝進一個下限input、一上限input、一個'-'tag self.lower_bound = MDTextFieldRect(x=275, hint_text="$下限", font_name='msjhbd.ttc', pos_hint={'y': 0.45}, size_hint=[1.5, 0.5], use_bubble=True, use_handles=True) self.upper_bound = MDTextFieldRect(hint_text="$上限", font_name='msjhbd.ttc', pos_hint={'y': 0.45}, center_x=275.76, center_y=508.20, size_hint=[1.5, 0.5], use_bubble=True, use_handles=True) self.dash_sign = MDFlatButton(text='-', font_size=30, size_hint=[1, 0.49], pos_hint={'y': 0.45}) self.dash_sign.md_bg_color = [1, 1, 1, 1] self.left.one.box.add_widget(self.lower_bound) self.left.one.box.add_widget(self.dash_sign) self.left.one.box.add_widget(self.upper_bound) # 盒子裝回上層 self.left.one.add_widget(self.left.one.box) # 新增行政區選單 self.left.six = MDGridLayout(size=[590, 657], rows=2, size_hint=[1, 0.25], md_bg_color=[0.39, 0.4, 0.72, 1], padding=[35, -5, 35, 5], spacing=[0, -10]) self.left.six.add_widget( Label(text='行政區選擇', font_size='20sp', font_name='msjhbd.ttc', height=32, size_hint=[1, 0.1])) self.left.six.box = BoxLayout(size_hint_y=0.15, center_y=390) from kivy.uix.spinner import Spinner district = [ "中區", "東區", "西區", "南區", "北區", "西屯區", "南屯區", "北屯區", "豐原區", "大里區", "太平區", "清水區", "沙鹿區", "大甲區", "東勢區", "梧棲區", "烏日區", "神岡區", "大肚區", "大雅區", "后里區", "霧峰區", "潭子區", "龍井區", "外埔區", "和平區", "石岡區", "大安區", "新社區" ] self.spinner = Spinner( text='行政區', values=[n for n in district], size_hint=(None, None), size=(95, 44), #pos_hint = {'right':0.2}, font_name='msjhbd.ttc', background_color=[1, 0, 0, 1]) self.spinner.option_cls.font_name = 'msjhbd.ttc' self.spinner.option_cls.background_color = [1, 0, 0, 1] #self.spinner.values[0].font_name = 'msjhbd.ttc' self.spinner.dropdown_cls.max_height = self.spinner.height * 7 + 7 * 4 #self.spinner.center_x = 160 #self.left.six.box.add_widget(BoxLayout(size_hint_y=0.5, size_hint_x=0.5, width=100)) self.left.six.box.add_widget( MDGridLayout(md_bg_color=[0.39, 0.4, 0.72, 1], size_hint=[None, 0.5])) self.left.six.box.add_widget(self.spinner) self.left.six.add_widget(self.left.six.box) #self.left.six.box.children[0].center = (160, 522.1339285) #self.spinner.pos_hint = {'right':0.9} #self.spinner.center_x = 150 # 這裡是畫面左欄第二格 self.left.two = MDGridLayout(rows=2, size_hint=[1, None], size=[365, 170], md_bg_color=[0.39, 0.4, 0.72, 1]) #self.left.two.center_y = 400 # 把"指標排序"標籤裝進第二格子的上方 self.left.two.add_widget( Label(text='指標排序', font_size='20sp', font_name='msjhbd.ttc', height=32, size_hint=[1, 0.1])) # 左欄第二格下方增加一個grid容器 self.left.two.grid = MDGridLayout(rows=3, size_hint=[1, 0.26], padding=[30, 0, 20, 0]) self.left.two.grid.size_hint = [1, 0.26] self.left.two.add_widget(self.left.two.grid) # 準備三個box放入此grid self.left.two.box1 = BoxLayout(size_hint=[1, None], size=[365, 40], spacing=13) self.left.two.box2 = BoxLayout(size_hint=[1, None], size=[365, 40], spacing=13) self.left.two.box3 = BoxLayout(size_hint=[1, None], size=[365, 40], spacing=13) self.left.two.grid.add_widget(self.left.two.box1) self.left.two.grid.add_widget(self.left.two.box2) self.left.two.grid.add_widget(self.left.two.box3) # 處理第一個box的標籤(全用按鈕取代)、輸入 self.left.two.btn1 = MDRaisedButton(text=' 人口特性 ', font_name='msjhbd.ttc', font_size='16sp') self.left.two.btn1.md_bg_color = [0.55, 0.63, 0.99, 1] self.left.two.input1 = MDTextFieldRect(hint_text='請輸入1、2、3:', size_hint=[1, None], size=[94, 37], font_name='msjhbd.ttc') self.left.two.input1.size_hint_x = None self.left.two.input1.width = 120 self.left.two.box1.add_widget(self.left.two.btn1) self.left.two.box1.add_widget(self.left.two.input1) self.left.two.btn3 = MDRaisedButton(text=' 薪資所得 ', font_name='msjhbd.ttc', font_size='16sp') self.left.two.btn3.md_bg_color = [0.68, 0.82, 0.96, 1] self.left.two.input3 = MDTextFieldRect(hint_text='請輸入1、2、3:', size_hint=[1, None], size=[94, 37], font_name='msjhbd.ttc') self.left.two.input3.size_hint_x = None self.left.two.input3.width = 120 self.left.two.box2.add_widget(self.left.two.btn3) self.left.two.box2.add_widget(self.left.two.input3) self.left.two.btn5 = MDRaisedButton(text=' 人口消長 ', font_name='msjhbd.ttc', font_size='16sp') self.left.two.btn5.md_bg_color = [0.5, 0.87, 0.98, 1] self.left.two.input5 = MDTextFieldRect(hint_text='請輸入1、2、3:', size_hint=[1, None], size=[94, 37], font_name='msjhbd.ttc') self.left.two.input5.size_hint_x = None self.left.two.input5.width = 120 self.left.two.box3.add_widget(self.left.two.btn5) self.left.two.box3.add_widget(self.left.two.input5) # 這裡是畫面左欄第三格 self.left.three = MDGridLayout(rows=2, md_bg_color=[0.39, 0.4, 0.72, 1], size_hint=[1, 0.57]) # 把"指標排序"標籤裝進第二格子的上方 self.left.three.add_widget( Label(text='選擇競爭對手', font_size='20sp', font_name='msjhbd.ttc', height=32, size_hint=[1, 0.06])) # 左欄第三格下方增加一個grid容器 self.left.three.grid = MDGridLayout(rows=5, size_hint=[1, 0.26], spacing=3, padding=[30, 0, 40, 0]) self.left.three.add_widget(self.left.three.grid) # 準備五個box放入此grid self.left.three.box1 = BoxLayout(size_hint=[1, 0.05]) self.left.three.box2 = BoxLayout(size_hint=[1, 0.05]) self.left.three.box3 = BoxLayout(size_hint=[1, 0.05]) self.left.three.box4 = BoxLayout(size_hint=[1, 0.05]) #self.left.three.box5 = BoxLayout(size_hint=[1, 0.4]) self.left.three.box6 = BoxLayout() self.left.three.grid.add_widget(self.left.three.box1) self.left.three.grid.add_widget(self.left.three.box2) self.left.three.grid.add_widget(self.left.three.box3) self.left.three.grid.add_widget(self.left.three.box4) # 處理第一個box的標籤(全用按鈕取代)、勾選 self.left.three.btn1 = MDRaisedButton(text=' 早餐店 ', font_name='msjhbd.ttc', size_hint=[None, 0.9], font_size='16sp') self.left.three.btn1.md_bg_color = [0.55, 0.63, 0.99, 1] self.left.three.input1 = MDCheckbox() self.left.three.input1.x = 140 self.left.three.input1.selected_color = (1, 1, 1, 1) self.left.three.input1.unselected_color = (1, 1, 1, 1) self.left.three.box1.add_widget(self.left.three.btn1) self.left.three.box1.add_widget(self.left.three.input1) # 處理第二個box的標籤(全用按鈕取代)、勾選 self.left.three.btn2 = MDRaisedButton(text='便當、自助餐店', font_name='msjhbd.ttc', size_hint=[None, 0.9], font_size='16sp') self.left.three.btn2.md_bg_color = [0.48, 0.81, 0.78, 1] self.left.three.input2 = MDCheckbox() self.left.three.input2.x = 140 self.left.three.input2.selected_color = (1, 1, 1, 1) self.left.three.input2.unselected_color = (1, 1, 1, 1) self.left.three.box2.add_widget(self.left.three.btn2) self.left.three.box2.add_widget(self.left.three.input2) # 處理第三個box的標籤(全用按鈕取代)、勾選 self.left.three.btn3 = MDRaisedButton(text='麵店、小吃店 ', font_name='msjhbd.ttc', size_hint=[None, 0.9], font_size='16sp') self.left.three.btn3.md_bg_color = [0.68, 0.82, 0.96, 1] self.left.three.input3 = MDCheckbox() self.left.three.input3.x = 140 self.left.three.input3.selected_color = (1, 1, 1, 1) self.left.three.input3.unselected_color = (1, 1, 1, 1) self.left.three.box3.add_widget(self.left.three.btn3) self.left.three.box3.add_widget(self.left.three.input3) # 處理第四個box的標籤(全用按鈕取代)、勾選 self.left.three.btn4 = MDRaisedButton(text=' 餐館餐廳 ', font_name='msjhbd.ttc', size_hint=[None, 0.9], font_size='16sp') self.left.three.btn4.md_bg_color = [0.62, 0.84, 0.51, 1] self.left.three.input4 = MDCheckbox() self.left.three.input4.x = 140 #self.left.three.input4.color = [1,1,1,2] self.left.three.input4.selected_color = (1, 1, 1, 1) self.left.three.input4.unselected_color = (1, 1, 1, 1) self.left.three.box4.add_widget(self.left.three.btn4) self.left.three.box4.add_widget(self.left.three.input4) self.run_button = MDRaisedButton(text='Run') # 製作廟宇按鈕 self.left.four = MDGridLayout(rows=2, size_hint=[1, None], size=[365, 90], md_bg_color=[0.39, 0.4, 0.72, 1]) self.left.four.add_widget( Label(text='廟宇出現與否', font_size='20sp', font_name='msjhbd.ttc', height=32, size_hint=[1, 0.025])) self.left.four.box = BoxLayout(size_hint=[1, 0.025], padding=[30, -20, 40, 5]) self.left.four.add_widget(self.left.four.box) self.left.four.btn = MDRaisedButton(text=' 廟宇 ', font_name='msjhbd.ttc', size_hint=[None, 0.8], font_size='16sp') self.left.four.input = MDCheckbox() self.left.four.input.selected_color = (1, 1, 1, 1) self.left.four.input.unselected_color = (1, 1, 1, 1) self.left.four.box.add_widget(self.left.four.btn) self.left.four.box.add_widget(self.left.four.input) # 把每一層加回去 self.left.add_widget(self.left.one) self.left.add_widget(self.left.six) self.left.add_widget(self.left.two) self.left.add_widget(self.left.three) self.left.add_widget(self.left.four) self.add_widget(self.left) self.add_widget(self.map) # 測試用的按鈕 #self.run_button = MDRaisedButton(text='Run') self.left.five = MDGridLayout(size_hint=[1, 0.1], md_bg_color=[0.39, 0.4, 0.72, 1]) self.left.five.add_widget(self.run_button) self.run_button.bind(on_release=self.popup.open) self.left.add_widget(self.left.five) self.run_button.right = 270 self.run_button.ripple_alpha = 0.7 self.run_button.radius = [10, 10, 10, 10] self.run_button.md_bg_color = [1, 1, 1, 1] self.run_button.text_color = [0, 0, 0, 1] #self.left.six.box.children[0].right = 150 #self.left.six.box.right = 390 #self.left.six.box.children[0].pos_hint = {'right':0.001, 'left':0.9} #self.left.four.box.pos_hint = {'top':0.5} def add_shop(self, neigh, clist, password): shop_list = gd.get_shop_codata(neigh, clist) # print(shop_list) #self.add1 += 1 #print(self.add1) print('###add_shop_func###') if shop_list == ['no data']: print('') else: for shop in shop_list: lon = float(shop['coor'][1]) lat = float(shop['coor'][0]) marker = MapMarkerPopup(lat=lat, lon=lon, source="競爭對手_標點.png") marker.add_widget( Button(text=neigh + '\n' + shop['name'] + '\n' + shop['class'], font_name='msjhbd.ttc', font_size=15, size_hint=[None, None], size=[150, 150])) self.map.add_marker(marker) if (password == 1): self.add1_shop_list.append(marker) elif (password == 2): self.add2_shop_list.append(marker) elif (password == 3): self.add3_shop_list.append(marker) #print(self.add1) # else: # for marker in self.add1_shop_list: # self.map.remove_marker(marker) #print('sucess') def clear_shop(self, password): print('###clear_shop_func###') if (password == 1): print("clear1!") for marker in self.add1_shop_list: self.map.remove_marker(marker) self.add1_shop_list.clear() elif (password == 2): print("clear2!") for marker in self.add2_shop_list: self.map.remove_marker(marker) self.add2_shop_list.clear() elif (password == 3): for marker in self.add3_shop_list: self.map.remove_marker(marker) self.add3_shop_list.clear() def add_temp(self, neigh, boolt, password): print('###add_temp_func###') temp_list = gd.get_temp_codata(neigh) # print(temp_list) if boolt == True: if temp_list == ['no data']: print('') else: for temp in temp_list: lon = float(temp['coor'][1]) lat = float(temp['coor'][0]) marker = MapMarkerPopup(lat=lat, lon=lon, source="廟_標點.png") marker.add_widget( Button(text=neigh + '\n' + temp['name'], font_name='msjhbd.ttc', font_size=15, size_hint=[None, None], size=[100, 100])) self.map.add_widget(marker) if (password == 1): self.add1_temp_list.append(marker) elif (password == 2): self.add2_temp_list.append(marker) print('hoooooo') elif (password == 3): self.add3_temp_list.append(marker) else: print("") def clear_temp(self, password): print('###clear_temp_func###') if (password == 1): print("clear1!") for marker in self.add1_temp_list: print(marker) self.map.remove_marker(marker) self.add1_temp_list.clear() elif (password == 2): print("clear2!") for marker in self.add2_temp_list: print(marker) self.map.remove_marker(marker) self.add2_temp_list.clear() elif (password == 3): for marker in self.add3_temp_list: print(marker) self.map.remove_marker(marker) self.add3_temp_list.clear() def add_rent(self, password, neigh, Min_price=0, Max_price=100000000): print('###add_rent_func###') # print(Min_price, Max_price) rent_list = gd.get_rent_codata(neigh) # print(rent_list) if rent_list == ['no data']: print('') else: cou = 1 for rent in rent_list: if (int(rent['price']) >= Min_price) & (int(rent['price']) <= Max_price): lon = float(rent['coor'][1]) lat = float(rent['coor'][0]) marker = MapMarkerPopup(lat=lat, lon=lon, source="店面_標點.png") rent_button = Button(text=neigh + '\n' + '店面' + str(cou) + '\n' + rent['size'] + '\n' + '$' + rent['price'] + '/月', font_name='msjhbd.ttc', font_size=15, size_hint=[None, None], size=[100, 100]) rent_button.bind( on_press=partial(webbrowser.open, rent['web'])) marker.add_widget(rent_button) self.map.add_widget(marker) cou += 1 if (password == 1): self.add1_rent_list.append(marker) elif (password == 2): self.add2_rent_list.append(marker) elif (password == 3): self.add3_rent_list.append(marker) def clear_rent(self, password): print('###clear_rent_func###') if (password == 1): print("clear1!") for marker in self.add1_rent_list: self.map.remove_marker(marker) self.add1_rent_list.clear() elif (password == 2): print("clear2!") for marker in self.add2_rent_list: self.map.remove_marker(marker) self.add2_rent_list.clear() elif (password == 3): for marker in self.add3_rent_list: self.map.remove_marker(marker) self.add3_rent_list.clear() # def add_border(self, filename): # import os, sys # import json # with open(os.path.realpath(sys.argv[0]).strip(sys.argv[0])+"data\\"+"鄰里邊界\\"+filename, 'r', encoding = 'utf-8') as f: # data = json.load(f) # for i in data['features'][0]['geometry']['coordinates'][0]: # lon = i[0] # lat = i[1] # marker = MapMarkerPopup(lon=lon, lat=lat, source='邊界.png') # self.map.add_widget(marker) def add_boundary(self, password): print('###add_boundary_func###') print('我要密碼') print(password) # if(self.add1 == 1 and password == 1): # self.bound1 = GeoJsonMapLayer() # elif(self.add2 == 1 and password == 2): # self.bound2 = GeoJsonMapLayer() # if(self.add3 == 1 and password == 3): # self.bound3 = GeoJsonMapLayer() #self.bound3 = GeoJsonMapLayer() # if(password == 1): # print('1號邊界成功') # #print("梧棲區\\" + self.rank1.text + ".json") # self.bound1.source = os.path.realpath(sys.argv[0]).strip(sys.argv[0]) + "梧棲區\\" + self.rank1.text + ".json" # self.add1_bound.append(self.bound1) # self.map.add_layer(self.bound1) if (password == 1): self.bound1.source = os.path.realpath(sys.argv[0]).strip( sys.argv[0] ) + "data\\" + "鄰里邊界\\" + self.spinner.text + "\\" + self.rank1.text + ".json" self.add1_bound.append(self.bound1) self.map.add_layer(self.bound1) elif (password == 2): self.bound2.source = os.path.realpath(sys.argv[0]).strip( sys.argv[0] ) + "data\\" + "鄰里邊界\\" + self.spinner.text + "\\" + self.rank2.text + ".json" self.add2_bound.append(self.bound2) self.map.add_layer(self.bound2) elif (password == 3): self.bound3.source = os.path.realpath(sys.argv[0]).strip( sys.argv[0] ) + "data\\" + "鄰里邊界\\" + self.spinner.text + "\\" + self.rank3.text + ".json" self.add3_bound.append(self.bound3) self.map.add_layer(self.bound3) # elif(password == 3): # print(password) # self.bound3.source = os.path.realpath(sys.argv[0]).strip(sys.argv[0]) + "梧棲區\\" + self.rank3.text + ".json" # self.add3_bound.append(self.bound3) # self.map.add_layer(self.bound3) # if(password == 1): # self.bound1.source = os.path.realpath(sys.argv[0]).strip(sys.argv[0]) + "梧棲區\\" + self.rank1.text + ".json" # #print(bound1.source) # self.add1_bound.append(self.bound1) # print("我是密碼" + str(password)) # print(self.rank1.text) # elif(password == 2): # self.bound2.source = os.path.realpath(sys.argv[0]).strip(sys.argv[0]) + "梧棲區\\" + self.rank2.text + ".json" # #print(self.bound2.source) # self.add2_bound.append(self.bound2) # print("我是密碼" + str(password)) # print(self.rank2.text) # elif(password == 3): # self.bound3.source = os.path.realpath(sys.argv[0]).strip(sys.argv[0]) + "梧棲區\\" + self.rank3.text + ".json" # self.add3_bound.append(self.bound3) # print("我是密碼" + str(password)) # if(password == 1): # self.map.add_layer(self.bound1) # elif(password == 2): # self.map.add_layer(self.bound2) # elif(password == 3): # self.map.add_layer(self.bound3) def remove_boundary(self, password): print('###remove_boundary_func###') #target = None # if(password == 1): # for a in self.add1_bound: # self.map.remove_layer(a) # self.add1_bound.clear() if (password == 1): for b in self.add1_bound: self.map.remove_layer(b) self.add1_bound.clear() elif (password == 2): for b in self.add2_bound: self.map.remove_layer(b) self.add2_bound.clear() elif (password == 3): for b in self.add3_bound: self.map.remove_layer(b) self.add3_bound.clear() # elif(password == 3): # for c in self.add3_bound: # self.map.remove_layer(c) # self.add3_bound.clear() #print(target, end=',,') #self.map.remove_layer(target[0]) #target.clear() #print(target, end=',,') '''pressed定義Run之後處理數據並放到資訊卡上的事件''' acard = None def pressed(self, instance): print(self.spinner.text) #print(self.spinner.text) top3_rank = final_combiner.final_rank([ int(self.left.two.input1.text), int(self.left.two.input3.text), int(self.left.two.input5.text) ]) if not self.acard: self.rank1 = ThreeLineIconListItem( text=top3_rank[0][0], secondary_text='人口特性:' + str(top3_rank[0][1]), tertiary_text='新資所得:' + str(top3_rank[0][2]), text_color=[1, 1, 1, 1]) self.rank1.add_widget(IconLeftWidget(icon='numeric-1-box')) self.rank1.bg_color = [0, 0, 0, 0] self.rank1.children[1].children[2].font_name = 'msjhbd.ttc' self.rank1.children[1].children[1].font_name = 'msjhbd.ttc' self.rank1.children[1].children[0].font_name = 'msjhbd.ttc' self.rank1.children[1].children[2].font_size = '18' more_rank1 = MDLabel(text='人口消長:' + str(top3_rank[0][3])) more_rank1.font_name = 'msjhbd.ttc' more_rank1.font_style = 'Body1' more_rank1.font_size = 16 more_rank1.color = [0, 0, 0, 0.7] self.rank1.children[1].add_widget(more_rank1) self.rank1.children[1].size_hint = [1, None] self.rank1.children[1].children[3].pos = [56, 280] self.rank1.children[0].children[0].children[0].color = [1, 1, 1, 1] self.rank1.children[0].children[0].children[0].pos_hint = { 'left': 0.1 } self.rank1.children[0].padding = [-10, 0, 0, 0] self.rank1.children[1].children[3].theme_text_color = 'Custom' self.rank1.children[1].children[3].text_color = [1, 1, 1, 1] self.rank1.children[1].children[2].theme_text_color = 'Custom' self.rank1.children[1].children[2].text_color = [1, 1, 1, 1] self.rank1.children[1].children[1].theme_text_color = 'Custom' self.rank1.children[1].children[1].text_color = [1, 1, 1, 1] self.rank1.children[1].children[0].theme_text_color = 'Custom' self.rank1.children[1].children[0].text_color = [1, 1, 1, 1] # 從另一個預先寫好、計算各里指標分數的模組final_combiner引進final_rank函數,取得前三名的區域及其各項指標分數後用top3_rank變數紀錄起來 # 接著改寫、擴充kivy套件內的工具(ThreeLineIconListItem),做成資訊卡,同時使其擁有按鈕的特性讓使用者做點選 self.rank2 = ThreeLineIconListItem( text=top3_rank[1][0], secondary_text='人口特性:' + str(top3_rank[1][1]), tertiary_text='新資所得:' + str(top3_rank[1][2])) self.rank2.add_widget(IconLeftWidget(icon='numeric-2-box')) self.rank2.bg_color = [0, 0, 0, 0] self.rank2.children[1].children[2].font_size = '18' self.rank2.children[1].children[2].font_name = 'msjhbd.ttc' self.rank2.children[1].children[1].font_name = 'msjhbd.ttc' self.rank2.children[1].children[0].font_name = 'msjhbd.ttc' more_rank2 = MDLabel(text='人口消長:' + str(top3_rank[1][3])) more_rank2.font_name = 'msjhbd.ttc' more_rank2.font_style = 'Body1' more_rank2.font_size = 16 more_rank2.color = [0, 0, 0, 0.54] self.rank2.children[1].add_widget(more_rank2) self.rank2.children[1].size_hint = [1, None] self.rank2.children[0].children[0].children[0].color = [1, 1, 1, 1] self.rank2.children[0].children[0].children[0].pos_hint = { 'left': 0.1 } self.rank2.children[0].padding = [-10, 0, 0, 0] self.rank2.children[1].children[3].theme_text_color = 'Custom' self.rank2.children[1].children[3].text_color = [1, 1, 1, 1] self.rank2.children[1].children[2].theme_text_color = 'Custom' self.rank2.children[1].children[2].text_color = [1, 1, 1, 1] self.rank2.children[1].children[1].theme_text_color = 'Custom' self.rank2.children[1].children[1].text_color = [1, 1, 1, 1] self.rank2.children[1].children[0].theme_text_color = 'Custom' self.rank2.children[1].children[0].text_color = [1, 1, 1, 1] self.rank3 = ThreeLineIconListItem( text=top3_rank[2][0], secondary_text='人口特性:' + str(top3_rank[2][1]), tertiary_text='新資所得:' + str(top3_rank[2][2])) self.rank3.add_widget(IconLeftWidget(icon='numeric-3-box')) self.rank3.bg_color = [0, 0, 0, 0] self.rank3.children[1].children[2].font_size = '18' self.rank3.children[1].children[2].font_name = 'msjhbd.ttc' self.rank3.children[1].children[1].font_name = 'msjhbd.ttc' self.rank3.children[1].children[0].font_name = 'msjhbd.ttc' more_rank3 = MDLabel(text='人口消長:' + str(top3_rank[2][3])) more_rank3.font_name = 'msjhbd.ttc' more_rank3.font_style = 'Body1' more_rank3.font_size = 16 more_rank3.color = [0, 0, 0, 0.54] self.rank3.children[1].add_widget(more_rank3) self.rank3.children[1].size_hint = [1, None] self.rank3.children[0].children[0].children[0].color = [1, 1, 1, 1] self.rank3.children[0].children[0].children[0].pos_hint = { 'left': 0.1 } self.rank3.children[0].padding = [-10, 0, 0, 0] self.rank3.children[1].children[3].theme_text_color = 'Custom' self.rank3.children[1].children[3].text_color = [1, 1, 1, 1] self.rank3.children[1].children[2].theme_text_color = 'Custom' self.rank3.children[1].children[2].text_color = [1, 1, 1, 1] self.rank3.children[1].children[1].theme_text_color = 'Custom' self.rank3.children[1].children[1].text_color = [1, 1, 1, 1] self.rank3.children[1].children[0].theme_text_color = 'Custom' self.rank3.children[1].children[0].text_color = [1, 1, 1, 1] self.rank1.size = [352, 100] self.rank2.size = [352, 100] self.rank3.size = [352, 100] self.click += 1 self.rank1.children[1].padding = [56, 16, 24, 7] self.rank2.children[1].padding = [56, 4, 24, 7] self.rank3.children[1].padding = [56, 4, 24, 7] self.rank1.children[1].children[0].adaptive_height = True self.rank1.children[1].pos = [0, 180] self.rank2.children[1].children[1].adaptive_height = True self.rank2.children[1].pos = [0, 130] self.rank3.children[1].children[1].adaptive_height = True self.add_widget( MDGridLayout(cols=1, size_hint=[0.285, 1], md_bg_color=[0.39, 0.4, 0.72, 1])) self.children[0].add_widget(self.rank1) self.children[0].add_widget(self.rank2) self.children[0].add_widget(self.rank3) self.rank1.bind(on_release=self.add_renk1_marker) self.rank2.bind(on_release=self.add_renk2_marker) self.rank3.bind(on_release=self.add_renk3_marker) ''' 當初設計沒有想好架構,導致要再次定義pressed事件(第二次之後的Run),如果是如果是第二次點擊Run之後要重新更新資訊卡的內容''' def second_pressed(self, instance): for i in range(1, 4): self.clear_shop(i) self.clear_temp(i) self.clear_rent(i) self.remove_boundary(i) self.add1 = 0 self.add2 = 0 self.add3 = 0 #self.map.children[0].unload() top3_rank = final_combiner.final_rank([ int(self.left.two.input1.text), int(self.left.two.input3.text), int(self.left.two.input5.text) ]) self.rank1.children[1].children[3].text = top3_rank[0][0] self.rank1.children[1].children[2].text = "人口特性:" + str( top3_rank[0][1]) self.rank1.children[1].children[1].text = "新資所得:" + str( top3_rank[0][2]) self.rank1.children[1].children[0].text = "人口消長:" + str( top3_rank[0][3]) self.rank2.children[1].children[3].text = top3_rank[1][0] self.rank2.children[1].children[2].text = "人口特性:" + str( top3_rank[1][1]) self.rank2.children[1].children[1].text = "新資所得:" + str( top3_rank[1][2]) self.rank2.children[1].children[0].text = "人口消長:" + str( top3_rank[1][3]) self.rank3.children[1].children[3].text = top3_rank[2][0] self.rank3.children[1].children[2].text = "人口特性:" + str( top3_rank[2][1]) self.rank3.children[1].children[1].text = "新資所得:" + str( top3_rank[2][2]) self.rank3.children[1].children[0].text = "人口消長:" + str( top3_rank[2][3]) self.rank1.bind(on_release=self.add_renk1_marker) self.rank2.bind(on_release=self.add_renk2_marker) self.rank3.bind(on_release=self.add_renk3_marker) def add_renk1_marker(self, instance): # print(len(self.map.children[2])) cla_list = [ self.left.three.btn1.text.strip(), self.left.three.btn2.text.strip(), self.left.three.btn3.text.strip(), self.left.three.btn4.text.strip() ] ch_list = [ self.left.three.input1.active, self.left.three.input2.active, self.left.three.input3.active, self.left.three.input4.active ] #print(cla_list, ch_list) act_list = [] for cont in range(4): if ch_list[cont] == True: act_list.append(cla_list[cont]) #print(self.rank1.text) self.add1 += 1 if (self.add1 % 2 == 1): self.add_boundary(1) self.add_shop(self.rank1.text, act_list, 1) self.add_temp(self.rank1.text, self.left.four.input.active, 1) self.add_rent(1, self.rank1.text, int(self.lower_bound.text), int(self.upper_bound.text)) # location = self.geolocator.geocode("梧棲區大庄里") # self.map.center_on(location.latitude , location.longitude) self.map.center_on(24.2454073, 120.54976945174974) elif (self.add1 % 2 == 0): self.remove_boundary(1) self.clear_shop(1) self.clear_temp(1) self.clear_rent(1) # filename = self.rank1.text + ".json" # self.add_border(filename) self.map.zoom = 13 # from geopy.geocoders import Nominatim # geolocator = Nominatim(user_agent="Brian_map") def add_renk2_marker(self, instance): cla_list = [ self.left.three.btn1.text.strip(), self.left.three.btn2.text.strip(), self.left.three.btn3.text.strip(), self.left.three.btn4.text.strip() ] ch_list = [ self.left.three.input1.active, self.left.three.input2.active, self.left.three.input3.active, self.left.three.input4.active ] act_list = [] for cont in range(4): if ch_list[cont] == True: act_list.append(cla_list[cont]) self.add2 += 1 if (self.add2 % 2 == 1): self.add_boundary(2) self.add_shop(self.rank2.text, act_list, 2) self.add_temp(self.rank2.text, self.left.four.input.active, 2) self.add_rent(2, self.rank2.text, int(self.lower_bound.text), int(self.upper_bound.text)) # location = self.geolocator.geocode("梧棲區大村里") # self.map.center_on(location.latitude , location.longitude) self.map.center_on(24.2549239, 120.5316259) elif (self.add2 % 2 == 0): self.remove_boundary(2) self.clear_shop(2) self.clear_temp(2) self.clear_rent(2) def add_renk3_marker(self, instance): cla_list = [ self.left.three.btn1.text.strip(), self.left.three.btn2.text.strip(), self.left.three.btn3.text.strip(), self.left.three.btn4.text.strip() ] ch_list = [ self.left.three.input1.active, self.left.three.input2.active, self.left.three.input3.active, self.left.three.input4.active ] act_list = [] for cont in range(4): if ch_list[cont] == True: act_list.append(cla_list[cont]) self.add3 += 1 if (self.add3 % 2 == 1): self.add_boundary(3) self.add_shop(self.rank3.text, act_list, 3) self.add_temp(self.rank3.text, self.left.four.input.active, 3) self.add_rent(3, self.rank3.text, int(self.lower_bound.text), int(self.upper_bound.text)) # location = self.geolocator.geocode("梧棲區大村里") # self.map.center_on(location.latitude , location.longitude) self.map.center_on(24.2570033, 120.53346300048884) elif (self.add3 % 2 == 0): self.remove_boundary(3) self.clear_shop(3) self.clear_temp(3) self.clear_rent(3) '''進度條跑到滿格時,要讓他reset變1''' def progress_reset(self, run): self.progress_bar.value = 1 '''讓進度條要一直往右跑,如果滿了就要關掉進度條畫面''' def next(self, dt): self.progress_bar.value += 6 if self.progress_bar.value >= 100: Clock.schedule_once(self.popup.dismiss, 0.5) if self.click == 0: Clock.schedule_once(self.pressed, 0.6) else: Clock.schedule_once(self.second_pressed, 0.6) #else: Clock.unschedule(self.new) Clock.schedule_once(self.progress_reset, 0.6) '''定義進度條跑的速率''' def puopen(self, instance): self.new = Clock.schedule_interval(self.next, 1 / 20)
class StartPage(FloatLayout): def __init__(self, **kwargs): super().__init__(**kwargs) from android.activity import bind self.app = MDApp.get_running_app() self.age_dialog = None self.genres_dialog = None self.get_genres_trigger = None self.get_preferences_trigger = None bind(on_activity_result=activity_data) self.age_dialog = MDDialog( title="Enter age", text="Enter your age and I'll guess your favorite genres.", type="custom", content_cls=AgeDialogContent(), buttons=[ MDFlatButton( text="CANCEL", text_color=self.app.theme_cls.primary_color, on_release=lambda *args: self.age_dialog.dismiss() ), MDFlatButton( text="OK", text_color=self.app.theme_cls.primary_color, on_release=lambda *args: self.submit_age( self.age_dialog.content_cls.ids.age_textfield.text) ), ], ) self.loading = loading_spinner(pos_hint={'center_x': .5, 'center_y': .2}) self.age_dialog.add_widget(self.loading) def get_preferences(self, code, platform): page = OAuthInfoPage() page_name = 'oauth_page' switch_screen(page, page_name) def retry(*args): self.snackbar.dismiss() self.retry_event.cancel() self.get_preferences(code, platform) return def get_and_save_preferences(*args): if req.status_code == 200: self.app.genres = req.response['genres'] self.app.artists = req.response['artists'] Logger.debug(self.app.genres) if self.app.genres: OAuthCompletePage(self.app.genres, self.app.artists) else: msg = (f"Sorry, couldn't guess " f"preferences from {platform.capitalize()}") for button in self.ids.choices_layout.children[0].children: if platform in button.text.lower(): button.disabled = True break self.snackbar = create_snackbar(msg, callback=None) self.app.screen_manager.switch_to(self.parent) self.snackbar.open() else: msg = "Failed to get preferences. Retrying in 3 seconds." self.snackbar = create_snackbar(msg, retry) self.retry_event = Clock.schedule_once(retry, 3) self.snackbar.open() if self.get_preferences_trigger is None: self.get_preferences_trigger = Clock.create_trigger( get_and_save_preferences ) req = self.app.api.get_preferences( code=code, platform=platform, trigger=self.get_preferences_trigger ) def select_choice(self, button): import random self.request_code = random.randint(1, 9999) if 'Genius' in button.text: self.platform = "genius" start_genius_auth() else: self.platform = "spotify" start_spotify_auth() def enter_age(self): self.age_dialog.open() def submit_age(self, age): try: age = int(age) except ValueError: toast('Invalid age. Try again.') return def retry(*args): self.snackbar.dismiss() self.retry_event.cancel() self.submit_age(age) return def get_and_save_genres(*args): self.loading.active = False if req.status_code == 200: self.app.genres = req.response['genres'] Logger.debug(self.app.genres) self.age_dialog.dismiss() switch_screen(ArtistsPage(), 'artists_page') else: msg = "Failed to get genrs. Retrying in 3 seconds." self.snackbar = create_snackbar(msg, retry) self.retry_event = Clock.schedule_once(retry, 3) self.snackbar.open() self.loading.active = True if self.get_genres_trigger is None: self.get_genres_trigger = Clock.create_trigger(get_and_save_genres) req = self.app.api.get_genres(age=age, trigger=self.get_genres_trigger) def select_genres(self, *args): if self.genres_dialog is None: self.genres_dialog = GenresDialog(root=self, callback=self.submit_genres) self.genres_dialog.select_genres() def submit_genres(self, genres): Logger.info('GENRES: %s', genres) if len(genres) >= 1: self.genres_dialog.genres_dialog.dismiss() self.app.genres = genres switch_screen(ArtistsPage(), 'artists_page') else: toast('You must at least choose one genre.')
class Recipes(Screen): # Recipe Window #class variable definitions data = { # 'database-plus': 'Add all checked to Pantry', 'delete': 'Delete all checked recipes', 'plus': 'Add recipe to Pantry', } bufferDate = None container = ObjectProperty() quantity = ObjectProperty() alreadyCheck = False alreadyCheckNav = False RecipeList = [ #to be filled by database "", #empty item because the positioning puts it under the nav bar ] def on_enter(self): icons_item = { #This needs extra items at the bottom to fill out the nav bar - mid priority bug to be fixed later "food-apple": "Food", "pasta": "Recipes", "database": "Pantry", "brush": "Theme", #completely unesccesary but would be cool to customize colors of the app #see MDThemePicker https://kivymd.readthedocs.io/en/latest/components/pickers/index.html "logout": "log out", "a":"", "b":"", "c":"", "d":"", } #pull items owned by a user from the database RecipeItems = App.db.exec(f"SELECT name FROM Recipe;") #fill the list with them for item in RecipeItems: self.RecipeList.append(item[0]) print(RecipeItems) #debug if self.alreadyCheckNav == False: #If the navbar is already full, don't fill it again for icon_name in icons_item.keys(): self.ids.content_drawer.add_widget( ItemDrawer(icon=icon_name, text=icons_item[icon_name])) self.alreadyCheckNav = True if self.alreadyCheck == False: for i in self.RecipeList: #prints all the items in user local list self.ids.container.add_widget(SwipeItem_Pantry(text=i)) self.alreadyCheck = True def remove_item( self, instance ): #callback function to remove widgets, used for deleting items from the list self.ids.container.remove_widget(instance) def JSON_maker(self, food, date, quant): #debug print( food ) #returns the food name, will need to change the variable name of this #debug print("date in JSON maker: " + str(date)) if date != None: print(date) #debug if date != None: #if the date is not empty then set the expires boolean to true exp_bool = 1 else: exp_bool = 0 #otherwise set it to false if date != None: #2 different queries have to be called based on whether a date was given or not App.db.exec( f"INSERT INTO Food(owner,name,expired,exp_date) VALUES('{App.user.username}', '{food}', '{exp_bool}', '{date}')" ) else: App.db.exec( f"INSERT INTO Food(owner,name,expired) VALUES('{App.user.username}', '{food}', '{exp_bool}')" ) JSON = { #debug "Owner": App.user.username, "Name": food, "Expires": exp_bool, "Exp_date": date, "Quantity": quant, "Type": None } print(JSON) #debug def got_date(self, the_date): #gets date from the calender self.bufferDate = the_date return (self.bufferDate) def show_date_picker(self): #opens up the calender date_dialog = MDDatePicker(callback=self.got_date) date_dialog.open() def add_pantry_item( self, instance ): #Opens dialog box and prompts for additional information needed for the add to pantry functionality self.bufferDate = None #reset bufferdate back to null when dialog box opens self.food_name = instance.text #this gets the title of the item clicked self.pantry_item_instance = instance #So looks like variables need to use self. to be able to use elsewhere close_button = MDRectangleFlatButton(text='Close', on_release=self.close_dialog) submit_button = MDRectangleFlatButton(text='Submit', on_release=self.submit_dialog) self.dialog = MDDialog( title="Add item to Pantry?", size_hint=(0.8, 1), type="custom", content_cls=dialog_content(), buttons=[submit_button, close_button], ) self.dialog.open() # open thingy that prompts for more info and then creates a food object which is then sent to the food handler def close_dialog(self, instance): #closes the dialog box self.dialog.dismiss() def submit_dialog(self, instance): #quant = self.dialog.content_cls.ids.quantity.text if App.sm.get_screen( "window2" ).bufferDate: #if a date was selected assign it to a nicer variable name date = App.sm.get_screen("window2").bufferDate else: #else let it be empty date = None if self.dialog.content_cls.ids.quantity.text: #If quantity was chosen assign it to a nicer variable name quant = self.dialog.content_cls.ids.quantity.text else: #else it defaults to 1 quant = 1 self.JSON_maker(self.food_name, date, quant) #send collected info to be sent to the database #after submitting, remove the item and close the box self.remove_item( self.pantry_item_instance ) #removes the item from the list when button is pressed self.dialog.dismiss() def call_back(self, instance): #debug if (instance.icon == 'delete'): self.deletion() else: self.show_data(self) def deletion(self): for delete in CheckedItemsList: self.alreadyCheck = False self.RecipeList.remove(delete) self.ids.container.clear_widgets() if self.alreadyCheck == False: for i in self.RecipeList: #prints all the items in user local list self.ids.container.add_widget(SwipeItem(text=i)) self.alreadyCheck = True CheckedItemsList.clear() print(*self.RecipeList, sep='\n') def show_data(self, obj): close_button = MDRectangleFlatButton(text="Add", pos_hint={ "center_x": 0.5, "center_y": 0.4 }, on_press=self.close_dialog, on_release=self.add_to_list) self.alreadyCheck = False x_button = MDFlatButton(text="X", pos_hint={ "center_x": 1.0, "center_y": 3.5 }, on_press=self.close_dialog) self.foodItem = MDTextField( hint_text="Enter an item", helper_text="e.g. apples, bananas, orange, etc.", helper_text_mode="on_focus", # icon_right_color = app.theme_cls.primary_color, pos_hint={ "center_x": 0.5, "center_y": 0.5 }, size_hint_x=None, width=250) self.dialog = MDDialog(title="Enter an item:", size_hint=(0.7, 1), buttons=[close_button, x_button]) self.dialog.add_widget(self.foodItem) self.dialog.open() self.alreadyCheck = True def add_to_list(self, obj): self.RecipeList.append(self.foodItem.text) self.ids.container.add_widget(SwipeItem(text=self.foodItem.text))
class Window2(Screen): #Main List Window -- CHANGE NAME LATER #class variable definitions data = { 'emoticon-angry': "WILL, I'LL END YOUR BLOODLINE", 'database-plus': 'Add all checked to Pantry', 'delete': 'Delete all checked', 'plus': 'Add item to list', } bufferDate = None container = ObjectProperty() quantity = ObjectProperty() alreadyCheck = False alreadyCheckNav = False localList = [ "", #empty item because the positioning puts it under the nav bar "pizza", "Banana", "Lamb", "Chicky nuggies", "Gogurt", "Cheeze stick", "Cold pasta sauce", "Spam", "Paimon", "Shallot", "Carrot", "Way too many green onions", "Chili", "Paprika", "Flour", "Sugar", "Apples", "Sour patch kids" ] def on_enter(self): icons_item = { #This needs extra items at the bottom to fill out the nav bar "food-apple": "Food", "pasta": "Recipes", "database": "Pantry", "brush": "Theme", #completely unesccesary but would be cool to customize colors of the app #see MDThemePicker https://kivymd.readthedocs.io/en/latest/components/pickers/index.html "logout": "log out", "a":"", "b":"", "c":"", "d":"", } if self.alreadyCheckNav == False: for icon_name in icons_item.keys(): self.ids.content_drawer.add_widget( ItemDrawer(icon=icon_name, text=icons_item[icon_name])) self.alreadyCheckNav = True if self.alreadyCheck == False: for i in self.localList: #prints all the items in user local list self.ids.container.add_widget(SwipeItem(text=i)) self.alreadyCheck = True def remove_item(self, instance): self.ids.container.remove_widget(instance) def JSON_maker(self, food, date, quant): print( food ) #returns the food name, will need to change the variable name of this print("date in JSON maker: " + str(date)) if date != None: print(date) if date != None: exp_bool = True else: exp_bool = False JSON = { "Owner": App.user.username, "Name": food, "Expires": exp_bool, "Exp_date": date, "Quantity": quant, "Type": None } print(JSON) def got_date(self, the_date): self.bufferDate = the_date return (self.bufferDate) def show_date_picker(self): date_dialog = MDDatePicker(callback=self.got_date) date_dialog.open() def add_pantry_item(self, instance): self.bufferDate = None #reset bufferdate back to null when dialog box opens self.food_name = instance.text #this gets the title of the item clicked self.pantry_item_instance = instance #So looks like variables need to use self. to be able to use elsewhere close_button = MDRectangleFlatButton(text='Close', on_release=self.close_dialog) submit_button = MDRectangleFlatButton(text='Submit', on_release=self.submit_dialog) self.dialog = MDDialog( title="Add item to Pantry?", size_hint=(0.8, 1), type="custom", content_cls=dialog_content(), buttons=[submit_button, close_button], ) self.dialog.open() # open thingy that prompts for more info and then creates a food object which is then sent to the food handler def close_dialog(self, instance): self.dialog.dismiss() def submit_dialog(self, instance): #quant = self.dialog.content_cls.ids.quantity.text if App.sm.get_screen("window2").bufferDate: date = App.sm.get_screen("window2").bufferDate else: date = None if self.dialog.content_cls.ids.quantity.text: quant = self.dialog.content_cls.ids.quantity.text else: quant = 1 self.JSON_maker( self.food_name, date, quant) #send collected info to be made into JSON type beat #after submitting, remove the item and close the box self.remove_item( self.pantry_item_instance ) #removes the item from the list when button is pressed self.dialog.dismiss() def call_back(self, instance): self.show_data(self) def show_data(self, obj): close_button = MDRectangleFlatButton(text="Add", pos_hint={ "center_x": 0.5, "center_y": 0.4 }, on_press=self.close_dialog, on_release=self.print_something) self.alreadyCheck = False self.foodItem = MDTextField( hint_text="Enter an item", helper_text="e.g. apples, bananas, orange, etc.", helper_text_mode="on_focus", # icon_right_color = app.theme_cls.primary_color, pos_hint={ "center_x": 0.5, "center_y": 0.5 }, size_hint_x=None, width=500) self.dialog = MDDialog(title="Enter an item:", size_hint=(0.7, 1), buttons=[close_button]) self.dialog.add_widget(self.foodItem) self.dialog.open() def close_dialog(self, obj): self.dialog.dismiss() def print_something(self, obj): self.localList.append(self.foodItem.text) self.ids.container.add_widget(SwipeItem(text=self.foodItem.text))