class ScrollableButtonStack(BoxLayout): def __init__(self, *args, **kwargs): data = kwargs.get("data", []) if data: del(kwargs["data"]) kwargs["orientation"] = "horizontal" super(ScrollableButtonStack, self).__init__(*args, **kwargs) self.sv = ScrollView(size_hint=(0.9,1)) self.buttonstack = BoxLayout(orientation="vertical", size_hint=(1,None), spacing=2) self.sv.add_widget(self.buttonstack) self.add_widget(self.sv) self.alphaidx = {} self.alphabet = BoxLayout(orientation="vertical", size_hint=(0.1,1), spacing=0) for i in string.uppercase: btn = Button(text=i, size_hint=(1,1.0/len(string.uppercase)), background_color=(0,0,0,1)) self.alphabet.add_widget(btn) btn.bind(on_touch_move=self.alphatouch) btn.bind(on_touch_down=self.alphatouch) self.add_widget(self.alphabet) self.UNIQUIFIER = 0 self.set_data(data) def alphatouch(self, btn, pos): if btn.collide_point(*pos.pos): uni = self.alphaidx.get(btn.text) if uni: Clock.schedule_once(lambda x: self._scroll_to_uniquifier(uni), 0.01) def set_data(self, data): self.sv.remove_widget(self.buttonstack) self.buttonstack.clear_widgets() self.buttonstack.height = BUTTONHEIGHT * len(data) self.alphaidx = {} for i in data: nd = i.copy() nd["unique"] = self.UNIQUIFIER self.UNIQUIFIER += 1 nd["open"] = False first = i["text"][0].upper() if first not in self.alphaidx: self.alphaidx[first] = nd["unique"] b = ButtonWithData(text=i["text"], size_hint_x=0.8, size_y=BUTTONHEIGHT, data=nd) self.buttonstack.add_widget(b) b.bind(on_press=self.toggle_open) self.sv.add_widget(self.buttonstack) def _get_button_at_top_uniquifier(self): print "gbatu" if not self.buttonstack.children: return None scrollable_height = self.buttonstack.height - self.height if scrollable_height < 0: return self.buttonstack.children[0].data["unique"] scrolled_px = scrollable_height * (1-self.sv.scroll_y) widget_idx_at_top = int(round(float(scrolled_px) / BUTTONHEIGHT)) # but buttonstack.children is in reverse order, so widget_idx_at_top = len(self.buttonstack.children) - widget_idx_at_top - 1 print "saving uniq", self.buttonstack.children[widget_idx_at_top].data["unique"] return self.buttonstack.children[widget_idx_at_top].data["unique"] def _scroll_to_uniquifier(self, uni): print "stu" if uni is None: return scrollable_height = self.buttonstack.height - self.height idx = None counter = 0 for c in self.buttonstack.children: if c.data["unique"] == uni: idx = counter break counter += 1 if idx is None: return # but buttonstack.children is in reverse order, so idx = len(self.buttonstack.children) - idx - 1 scroll_position = (idx * BUTTONHEIGHT) / scrollable_height print "scroll to widget uni", uni, "which is idx", idx, " posn", scroll_position Clock.schedule_once(lambda x: self.scroll_now_to(scroll_position), 2) def scroll_now_to(self, scroll_position): print "scroll now to" self.sv.scroll_y = 1-scroll_position def toggle_open(self, button): print "toggling open", button, button.data uni = self._get_button_at_top_uniquifier() if button.data["open"]: # remove all children of this button print "Removing children" to_remove = [x for x in self.buttonstack.children if x.owner_button and x.owner_button.data["unique"] == button.data["unique"]] self.buttonstack.height -= len(to_remove) * BUTTONHEIGHT for w in to_remove: self.buttonstack.remove_widget(w) button.data["open"] = False else: print "Collapsing all others" to_remove = [x for x in self.buttonstack.children if x.owner_button] self.buttonstack.height -= len(to_remove) * BUTTONHEIGHT for w in to_remove: self.buttonstack.remove_widget(w) print "Expanding" insert_idx = 0 count = 0 for w in self.buttonstack.children: if w.data["unique"] == button.data["unique"]: insert_idx = count break count += 1 self.buttonstack.height += 1 * BUTTONHEIGHT nd = { "unique": "load tracks", } self.UNIQUIFIER += 1 nbtn = ButtonWithData(text="loading...", size_hint_x=1, size_y=BUTTONHEIGHT, data=nd, owner_button=button) self.buttonstack.add_widget(nbtn, index=insert_idx) self.owner_app.mpc.send(("list_tracks", button.data["unique"]), 'find artist "%s"\n' % button.data["text"]) button.data["open"] = True self._scroll_to_uniquifier(uni) def load_tracks(self, tracks): # remove the loading button, if present, and get its index loading_button = None counter = 0 insert_idx = None for b in self.buttonstack.children: if b.data["unique"] == "load tracks": insert_idx = counter loading_button = b break counter += 1 if not loading_button: return print "removing loading button at idx", insert_idx owner = loading_button.owner_button self.buttonstack.remove_widget(loading_button) for t in tracks: nd = { "unique": self.UNIQUIFIER, } nd.update(t) self.UNIQUIFIER += 1 nbtn = ButtonWithData(text=t.get("Title", t.get("file")), size_hint_x=0.8, pos_hint={'right':1.0}, size_y=BUTTONHEIGHT, data=nd, owner_button=owner) nbtn.bind(on_press=self.queue_song) self.buttonstack.add_widget(nbtn, index=insert_idx) def queue_song(self, button): print "queueing song", button.data self.owner_app.mpc.send("add", 'add "%s"\n' % button.data["file"]) self.owner_app.mpc.send("play", "play\n")
class DisguiseLayout(GridLayout): def __init__(self, **kwargs): super(DisguiseLayout, self).__init__(**kwargs) self.disguise_size={'hair':(200,100),'eyes':(200,67),'nose':(200,44),'mouth':(200,44),'body':(200,200)} self.left_panel = GridLayout(cols=1, pos_hint=({'center_x':0.5, 'center_y':0.5})) self.right_panel = ScrollView(effect_cls=ScrollEffect) for id, typ in enumerate(self.disguise_size.keys()): but=DisguiseTypeButton(typ=typ, source=os.path.join('data','but_{}.png'.format(typ)))#, size_hint=(1,0.3))#, size=(50,50), pos_hint={'x':0, 'center_y':0.3+0.1*id}) but.bind(on_release=self.show_hide_list) self.left_panel.add_widget(but) self.add_widget(self.left_panel) self.add_widget(self.right_panel) #self.disguise_size={'hair':(200,100),'eyes':(200,67),'nose':(200,44),'mouth':(200,44),'body':(200,200)} self.disguise_size={'hair':(300,150),'eyes':(300,100),'nose':(300,67),'mouth':(300,67),'body':(300,300)} self.scroll_views={} self.max_texture_size=0 for typ,siz in self.disguise_size.items(): gridlayout = GridLayout(cols=1, spacing=10, padding=10, size_hint=(1,None)) gridlayout.bind(minimum_height=gridlayout.setter('height')) for filename in os.listdir('data'): if filename.startswith('id_{}'.format(typ)): id_trash, type_trash, name = filename.split('_') name=name.replace('.png','') btn = DisguiseButton(typ=typ, name=name, size_hint=(None, None), size=siz, background_normal=os.path.join('data',filename)) btn.bind(on_release=self.pick_from_list) gridlayout.add_widget(btn) img_size = Image(source=os.path.join('data',filename)).texture_size if img_size > self.max_texture_size: self.max_texture_size = img_size self.scroll_views[typ] = ScrollView(effect_cls=ScrollEffect) self.scroll_views[typ].add_widget(gridlayout) gridlayout.bind(minimum_width=self.scroll_views[typ].setter('width')) def show_hide_list(self, button): if self.scroll_views[button.typ] in self.right_panel.children: self.right_panel.remove_widget(self.scroll_views[button.typ]) else: for child in self.right_panel.children: if child.__class__.__name__ == 'ScrollView': self.right_panel.remove_widget(child) self.right_panel.add_widget(self.scroll_views[button.typ]) def pick_from_list(self, button): if button.typ and button.name != None: self.parent.driver.disguises[button.typ].source = button.background_normal self.right_panel.remove_widget(self.scroll_views[button.typ])
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 DisguiseLayout(GridLayout): def __init__(self, **kwargs): super(DisguiseLayout, self).__init__(**kwargs) self.disguise_size = { 'hair': (200, 100), 'eyes': (200, 67), 'nose': (200, 44), 'mouth': (200, 44), 'body': (200, 200) } self.left_panel = GridLayout(cols=1, pos_hint=({ 'center_x': 0.5, 'center_y': 0.5 })) self.right_panel = ScrollView(effect_cls=ScrollEffect) for id, typ in enumerate(self.disguise_size.keys()): but = DisguiseTypeButton( typ=typ, source=os.path.join('data', 'but_{}.png'.format(typ)) ) #, size_hint=(1,0.3))#, size=(50,50), pos_hint={'x':0, 'center_y':0.3+0.1*id}) but.bind(on_release=self.show_hide_list) self.left_panel.add_widget(but) self.add_widget(self.left_panel) self.add_widget(self.right_panel) #self.disguise_size={'hair':(200,100),'eyes':(200,67),'nose':(200,44),'mouth':(200,44),'body':(200,200)} self.disguise_size = { 'hair': (300, 150), 'eyes': (300, 100), 'nose': (300, 67), 'mouth': (300, 67), 'body': (300, 300) } self.scroll_views = {} self.max_texture_size = 0 for typ, siz in self.disguise_size.items(): gridlayout = GridLayout(cols=1, spacing=10, padding=10, size_hint=(1, None)) gridlayout.bind(minimum_height=gridlayout.setter('height')) for filename in os.listdir('data'): if filename.startswith('id_{}'.format(typ)): id_trash, type_trash, name = filename.split('_') name = name.replace('.png', '') btn = DisguiseButton(typ=typ, name=name, size_hint=(None, None), size=siz, background_normal=os.path.join( 'data', filename)) btn.bind(on_release=self.pick_from_list) gridlayout.add_widget(btn) img_size = Image( source=os.path.join('data', filename)).texture_size if img_size > self.max_texture_size: self.max_texture_size = img_size self.scroll_views[typ] = ScrollView(effect_cls=ScrollEffect) self.scroll_views[typ].add_widget(gridlayout) gridlayout.bind( minimum_width=self.scroll_views[typ].setter('width')) def show_hide_list(self, button): if self.scroll_views[button.typ] in self.right_panel.children: self.right_panel.remove_widget(self.scroll_views[button.typ]) else: for child in self.right_panel.children: if child.__class__.__name__ == 'ScrollView': self.right_panel.remove_widget(child) self.right_panel.add_widget(self.scroll_views[button.typ]) def pick_from_list(self, button): if button.typ and button.name != None: self.parent.driver.disguises[ button.typ].source = button.background_normal self.right_panel.remove_widget(self.scroll_views[button.typ])
class LectureTree(BoxLayout): def __init__(self, **kwargs): super(LectureTree, self).__init__(**kwargs) ########## AKTUALIZUJE DRZEWO CO 45 SEKUND Clock.schedule_interval(self.scheduled_update, 45) self.sv = ScrollView(do_scroll_x=False, pos = (0, 0)) self.tv = self.populate() self.sv.add_widget(self.tv) self.add_widget(self.sv) def scheduled_update(self, dt): self.update() def populate(self): self.cli = KNAPIclient() self.server = self.cli.getServer() global gserver gserver = self.cli.getServer() tv = CustomTV(root_options=dict(text='Tree One'), hide_root=True, indent_level=10, size_hint_y=None) tv.bind(minimum_height=tv.setter('height')) ################## TUTAJ DODAWANE SA LISCIE DO DRZEWA Z WYKLADAMI, MOZNA ZWIEKSZYC ICH ROZMIARY, OGARNALEM SCROLLOWANIE TEJ LISTY WIEC POWINNO BYC SPOKO for each in self.cli.retrieveAll(): lecture = tv.add_node(TreeViewLabel(text=each["title"], font_size=Window.size[1]/25, is_open = False)) info_node = tv.add_node(TreeViewLabel(text="Info", is_open = False, font_size=Window.size[1]/30, no_selection = True), lecture) description_node = tv.add_node(TreeViewLabel(text="Description", is_open = False, font_size=Window.size[1]/30, no_selection = True), lecture) resources_node = tv.add_node(TreeViewLabel(text="Resources", is_open = False, font_size=Window.size[1]/30, no_selection = True), lecture) moje_id = each['id'] for key in each: if key == "id" or key == "title": pass elif key == "description": key_node = tv.add_node(TreeViewLabel(text=str(each[key]), is_open = False, font_size=Window.size[1]/35, no_selection = True), description_node) elif key == "resources": for file in self.cli.returnFiles(moje_id): key_node = tv.add_node(TreeViewResource(resource_name=file["name"], filename=file["filename"], server=self.server, no_selection=True), resources_node) else: key_node = tv.add_node(TreeViewLabel(text=str(key)+": "+str(each[key]), is_open = False, font_size=Window.size[1]/35, no_selection = True), info_node) return tv def update(self): self.sv.remove_widget(self.tv) self.tv = self.populate() self.sv.add_widget(self.tv) ########### PONIZSZE DWIE METODY CHYBA DO WYWALENIA, TO JEST SPRAWDZANE W USLUDZE W TLE def check_if_starting_soon(self, dt): for lecture in self.cli.retrieveAll(): self.notify_starting_soon(lecture["startDate"], lecture["startTime"], lecture["title"], 5) def notify_starting_soon(self, date, time, title, timeout): datetime_object = datetime.datetime.strptime(date+" "+time, "%Y-%m-%d %H:%M:%S") if datetime.timedelta(minutes = int(timeout)) - datetime.timedelta(seconds = 15) < datetime_object - datetime.datetime.now() <= datetime.timedelta(minutes = int(timeout)): notification.notify(title="Oooo, startin soon", message="Lecture "+title+" is starting soon", app_name='ConferencePi', timeout=1) return True else: return False
class Review(Screen): def __init__(self, **kwargs): super(Review, self).__init__(**kwargs) self.predicate = True 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.box.add_widget(self.bottom_bar) self.add_widget(self.box) def skeleton_frame2(self, instance): # Displays all decks on the app #self.box.remove_widget(self.complete_label) self.box.remove_widget(self.count_grid) 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.box.add_widget(self.bottom_bar) self.add_widget(self.box) 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.review_deck) self.list.add_widget(self.items) conn.commit() conn.close() # screen will display the review section def review_deck(self, instance): self.num = 0 self.count = 0 self.review_cardname = ["This deck is empty"] self.review_definition = ["This deck is empty"] self.scrollview.remove_widget(self.list) self.box.remove_widget(self.bottom_bar) con = sqlite3.connect("flashcard_app.db") cur = con.cursor() cur.execute( """ SELECT CardName, Definition FROM Cards WHERE DeckName = ? """, (instance.text, )) row = cur.fetchall() for cardname, definition in row: self.review_cardname.append(cardname) self.review_definition.append(definition) self.front = cardname self.back = definition print(self.front, self.back) print(self.review_cardname) if len(self.review_cardname) != 1 and len(self.review_definition) != 1: self.review_cardname.remove("This deck is empty") self.review_definition.remove("This deck is empty") con.commit() con.close() self.click_action() def click_action(self): if self.predicate == True: self.button = Button(text=self.review_cardname[self.num], 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.review_definition[self.num], 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.review_cardname[self.num], 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.review_definition[self.num], 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() def bottom_bar_name_def(self): self.bottom_bar = MDToolbar() self.pass_button = MDIconButton(icon="check-bold", pos_hint={ 'center_x': 0.5, 'center_y': 0.5 }, on_release=self.next_card_pass) self.fail_button = MDIconButton(icon="close-box-outline", pos_hint={ 'center_x': 0.5, 'center_y': 0.5 }, on_release=self.next_card_fail) self.tag_button = MDIconButton(icon="star-circle", pos_hint={ 'center_x': 0.5, 'center_y': 0.5 }) #self.back_button.bind(on_press=self.back_display_cards) self.bottom_bar.add_widget(MDLabel()) self.bottom_bar.add_widget(MDLabel()) self.bottom_bar.add_widget(self.fail_button) self.bottom_bar.add_widget(MDLabel()) self.bottom_bar.add_widget(MDLabel()) self.bottom_bar.add_widget(self.tag_button) self.bottom_bar.add_widget(MDLabel()) self.bottom_bar.add_widget(MDLabel()) self.bottom_bar.add_widget(self.pass_button) self.bottom_bar.add_widget(MDLabel()) self.bottom_bar.add_widget(MDLabel()) self.add_widget(self.bottom_bar) def bottom_bar_complete(self): self.bottom_bar = MDToolbar() self.return_review = MDFlatButton(text="Return to Decks", pos_hint={ 'center_x': .5, 'center_y': .5 }, on_release=self.skeleton_frame2) self.bottom_bar.add_widget(self.return_review) 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() def next_card_pass(self, instance): self.count += 1 self.num += 1 self.predicate = True if self.num == len(self.review_cardname): self.box.remove_widget(self.scrollview) self.remove_widget(self.bottom_bar) self.get_result() #self.complete_label = MDLabel(text="Complete") #self.box.add_widget(self.complete_label) self.bottom_bar_complete() else: self.click_action2(instance) def next_card_fail(self, instance): self.num += 1 self.predicate = True if self.num == len(self.review_cardname): self.box.remove_widget(self.scrollview) self.remove_widget(self.bottom_bar) self.get_result() #self.complete_label = MDLabel(text="Complete") #self.box.add_widget(self.complete_label) self.bottom_bar_complete() else: self.click_action2(instance) def get_result(self): self.count_grid = MDGridLayout(cols=3) self.count_label = MDLabel(text=str(self.count), size_hint_x=None, width=20) self.divider = MDLabel(text="/", size_hint_x=None, width=20) self.total_num = MDLabel(text=str(len(self.review_cardname)), size_hint_x=None, width=20) self.count_grid.add_widget(self.count_label) self.count_grid.add_widget(self.divider) self.count_grid.add_widget(self.total_num) self.box.add_widget(self.count_grid) self.box.add_widget(MDLabel()) self.box.add_widget(MDLabel())
class DecksMenu(RelativeLayout): def __init__(self, cards, setts, username, **kwargs): super().__init__(**kwargs) self.username = username self.acc_decks = [cards[card] for card in cards] self.acc_decks = [Deck(deck) for deck in self.acc_decks] self.acc_settings = setts self.cardWidth = 100 self.spacingSize = 10 self.paddingSize = 50 Window.clearcolor = colors.GRAY self.scroll = ScrollView() self.scroll.size = (Window.width, Window.height) self.scroll.bar_color = colors.WHITE self.scroll.bar_width = dp(12) self.scroll.scroll_distance = dp(80) # * default oreintation is horizontal self.load() self.add_widget(self.scroll) self.bottom_buttons = BoxLayout() self.new_deck_button = Button() self.new_deck_button.text = "New Deck" self.new_deck_button.size_hint = (1, None) self.new_deck_button.height = dp(50) self.new_deck_button.on_press = self.goto_deck_adding self.stats_button = Button() self.stats_button.text = "Stats" self.stats_button.size_hint = (1, None) self.stats_button.height = dp(50) self.stats_button.on_press = self.goto_stats self.manage_button = Button() self.manage_button.text = "Manage" self.manage_button.size_hint = (1, None) self.manage_button.height = dp(50) self.bottom_buttons.add_widget(self.new_deck_button) self.bottom_buttons.add_widget(self.stats_button) self.bottom_buttons.add_widget(self.manage_button) self.add_widget(self.bottom_buttons) self.top_loc = StackLayout() self.top_loc.orientation = "rl-tb" self.top_buttons = BoxLayout() self.settings_button = Button() self.settings_button.text = "Settings" self.settings_button.size_hint = (None, None) self.settings_button.size = (dp(100), dp(50)) self.settings_button.on_press = self.goto_settings self.search_button = Button() self.search_button.text = "Search" self.search_button.size_hint = (None, None) self.search_button.size = (dp(100), dp(50)) self.top_bar = TextInput() self.top_bar.multiline = False self.top_bar.hint_text = "Search Query" self.top_bar.size_hint = (None, None) self.top_bar.height = dp(50) self.top_bar.width = dp(500) self.top_bar.background_normal = '' self.top_bar.background_color = colors.GRAY self.top_bar.foreground_color = colors.WHITE self.top_bar.font_name = "Comfortaa" self.top_bar.font_size = 40 self.top_loc.add_widget(self.top_bar) self.top_loc.add_widget(self.search_button) self.top_loc.add_widget(self.settings_button) # self.top_loc.add_widget(self.top_buttons) self.add_widget(self.top_loc) def goto_settings(self): self.add_widget(SettingsPage()) def goto_deck_adding(self): self.add_widget(DeckAddPage()) def goto_stats(self): self.add_widget(StatsPage()) def load(self): try: for deck in self.acc_decks[:-1]: self.boxes.remove_widget(deck.cardview) except AttributeError: pass try: self.scroll.remove_widget(self.boxes) except AttributeError: pass self.init_boxes() for deck in self.acc_decks: deck.cardview.size_hint = (None, None) deck.cardview.size = (dp(self.cardWidth), dp(self.cardWidth * 1.5)) self.boxes.add_widget(deck.cardview) def init_boxes(self): self.boxes = StackLayout() self.boxes.bind(minimum_height=self.boxes.setter('height')) self.boxes.padding = dp(self.paddingSize) self.boxes.size_hint = (1, None) self.boxes.orientation = "lr-tb" self.boxes.spacing = dp(self.spacingSize) self.boxes.background_color = colors.PGREEN self.scroll.add_widget(self.boxes)
class Orders(BoxLayout): global cartitem global nud def set(self): self.orientation = 'vertical' self.size_hint = (.3,1) self.padding = (10,10) self.spacing = 10 self.cart = Label(text='Your Cart',color=(0,0,0,1),size_hint= (1,None),height=15) self.add_widget(self.cart) self.bl = BoxLayout(orientation='horizontal',size_hint =(1,None),height=15) self.i = Label(text='Items',color=(0,0,0,1),size_hint= (.4,1)) self.bl.add_widget(self.i) self.q = Label(text='Quantity',color=(0,0,0,1),size_hint= (.3,1)) self.p = Label(text='Price',color=(0,0,0,1),size_hint= (.3,1)) self.bl.add_widget(self.q) self.bl.add_widget(self.p) self.add_widget(self.bl) self.gl = GridLayout(cols=1, spacing=10, size_hint_y=None) self.gl.bind(minimum_height = self.gl.setter('height')) self.sv = ScrollView(size_hint=(1, 1), size=(self.width, self.height),do_scroll_x = False) self.add_widget(self.sv) self.tbl = BoxLayout(orientation = 'horizontal',size_hint = (1,None),height = 15) self.total = 0 self.tbl.add_widget(Label(text='Total',size_hint=(.5,1),color = (0,0,0,1))) self.totalprice = Label(text=str(self.total),size_hint=(.5,1),color = (0,0,0,1)) self.tbl.add_widget(self.totalprice) self.add_widget(self.tbl) self.sbl = BoxLayout(orientation = 'horizontal',size_hint = (1,None),height = 15) self.sbl.add_widget(Button(text='Save',size_hint = (.5,1),on_press = self.back)) self.sbl.add_widget(Button(text = 'Pay Off',size_hint = (.5,1),on_press = self.back)) self.add_widget(self.sbl) self.shown = [] self.obj = [] self.bk = False nud = False def back(self,a): self.bk = True self.query = 'insert into reslog values (%s,%s)'%(self.total,random.randint(10,10000)) cursor.execute(self.query) hmdb.commit() def up(self,a): global nud global cartitem self.similar = False for i in self.obj: if i.rm == True: self.gl.remove_widget(i) i.rm = False if nud == True: self.sv.remove_widget(self.gl) for i in range(len(cartitem)): for j in range(len(self.shown)): if self.shown[j][0] == cartitem[i][0]: self.similar = True self.objj = j self.obji = i if self.similar == True: self.obj[self.obji].price.text = str(int(cartitem[self.obji][1]) * int(cartitem[self.obji][2])) self.obj[self.obji].quantity.text = str(cartitem[self.obji][2]) self.similar = False else: self.obj.append(Order()) self.obj[i] = self.obj[i].set(cartitem[i]) self.gl.add_widget(self.obj[i]) self.a = cartitem[i] self.shown.append(self.a) nud = False self.total = 0 for i in range(len(self.shown)): self.total += int(self.obj[i].price.text) self.totalprice.text = str(self.total) self.sv.add_widget(self.gl) else: pass
class ViewerScreen(Screen): src = StringProperty("") label_text = StringProperty("") slider_value = NumericProperty(1) def __init__(self, firebase, **kwargs): super(ViewerScreen, self).__init__(**kwargs) with self.canvas: self.bg = Rectangle(source='app_data/background.jpg', pos=self.pos, size=self.size) self.bind(pos=self.update_bg) self.bind(size=self.update_bg) self.firebase = firebase self.event = None self._popup = None self.user_data = None self.page = 0 self.default_zoom = [1, 2.79] self.num_pages = 0 self.timeout = 30 box_layout = BoxLayout( orientation='vertical' ) bar_panel = BarPanel( orientation='horizontal', size_hint=(1, None), height=80, padding=7 ) image = Image( size_hint=(None, 1), width=150, source='app_data/master_fitness_logo_w_noaddr.png' ) self.label = Label( size_hint=(1, 1), font_size=20, italic=True, text=self.label_text ) self.labelPage = Label( size_hint=(None, 1), width=50, font_size=30, italic=True ) self.qr_button_anchor = AnchorLayout( size_hint=(None, 1), width=100, anchor_x='center', anchor_y='center' ) self.qr_button = Button( size_hint=(None, None), width=70, height=70, valign='center', halign='center', background_normal='app_data/qr_normal.png', background_down='app_data/qr_down.png', border=(0,0,0,0), on_release=self.on_release_qr_button ) self.close_button = Button( size_hint=(None, None), width=70, height=70, valign='center', halign='center', background_normal='app_data/close_normal.png', background_down='app_data/close_down.png', border=(0,0,0,0), on_release=self.on_release_close_button ) self.left_button = Button( size_hint=(None, None), width=70, height=70, valign='center', halign='center', background_normal='app_data/left_normal.png', background_down='app_data/left_down.png', border=(0,0,0,0), on_release=self.on_release_left_button ) self.right_button = Button( size_hint=(None, None), width=70, height=70, valign='center', halign='center', background_normal='app_data/right_normal.png', background_down='app_data/right_down.png', border=(0,0,0,0), on_release=self.on_release_right_button ) self.zoomOut_button = Button( size_hint=(None, None), width=70, height=70, valign='center', halign='center', background_normal='app_data/zoomOut_normal.png', background_down='app_data/zoomOut_down.png', border=(0,0,0,0), on_release=self.on_release_zoomOut_button ) self.zoomIn_button = Button( size_hint=(None, None), width=70, height=70, valign='center', halign='center', background_normal='app_data/zoomIn_normal.png', background_down='app_data/zoomIn_down.png', border=(0,0,0,0), on_release=self.on_release_zoomIn_button ) anchor_layout = AnchorLayout( size_hint=(1, 0.8), anchor_x='right' ) self.scrollview = ScrollView( size_hint=(1, 1), bar_color=[0,0,0,0], bar_inactive_color=[0,0,0,0], effect_cls=ScrollEffect ) self.slider = Slider( orientation='vertical', size_hint=(None, 1), width=50, min=0, max=1, step=0.01, value=self.slider_value, cursor_image='app_data/kettlebell.png', cursor_size=('45sp', '45sp'), background_vertical='app_data/slider.png', background_width='3sp', padding='30sp' ) self.scrollview.bind(scroll_y=self.slider_change) self.slider.bind(value=self.scroll_change) self.img_view = None #Image(size_hint=(1, None), height=1450, nocache=True, source=self.src) bar_panel.add_widget(image) bar_panel.add_widget(self.qr_button_anchor) self.qr_button_anchor.add_widget(self.qr_button) bar_panel.add_widget(self.label) bar_panel.add_widget(self.zoomOut_button) bar_panel.add_widget(self.zoomIn_button) bar_panel.add_widget(self.left_button) bar_panel.add_widget(self.labelPage) bar_panel.add_widget(self.right_button) bar_panel.add_widget(self.close_button) #self.scrollview.add_widget(self.img_view) anchor_layout.add_widget(self.scrollview) anchor_layout.add_widget(self.slider) box_layout.add_widget(bar_panel) box_layout.add_widget(anchor_layout) self.add_widget(box_layout) def reschedule(self): Clock.unschedule(self.event) self.event = Clock.schedule_once(self.go_to_home, self.timeout) def on_pre_enter(self): self.scrollview.remove_widget(self.img_view) self.img_view = None self.num_pages = self.user_data['num_pages'] self.page = self.user_data['page'] if self.page + 1 > self.num_pages: self.page = self.num_pages - 1 self.labelPage.text=str(self.page+1)+"/"+str(self.num_pages) self.label_text = "Scheda di "+self.user_data['name']+" "+self.user_data['surname'] self.setSourcePath("storage_data/"+str(self.user_data['rfid'])+"/scheda_"+str(self.page)+".jpg") self.img_view = Image( size_hint=(self.default_zoom[0], self.default_zoom[1]), allow_stretch = True, nocache=True, source=self.src ) self.img_view.bind(size_hint=self.on_img_hint_update) self.scrollview.add_widget(self.img_view) try: self.slider_value = self.user_data['slider_y'] self.scrollview.scroll_x = self.user_data['slider_x'] zoom = self.user_data['zoom'] if zoom[0] == 0 and zoom[1] == 0: zoom = self.default_zoom self.img_view.size_hint = (zoom[0], zoom[1]) except: self.slider_value = 1 self.scrollview.scroll_x = 0.5 self.img_view.size_hint = (self.default_zoom[0], self.default_zoom[1]) self.reschedule() def on_pre_leave(self): Clock.unschedule(self.event) if self._popup : self._popup.dismiss() self._popup = None def on_leave(self): if self.user_data : data = { "page": self.page, "zoom": self.img_view.size_hint, "slider_x": self.scrollview.scroll_x, "slider_y": self.slider_value } self.saveUserData(self.user_data['rfid'], data) self.scrollview.remove_widget(self.img_view) self.img_view = None def go_to_home(self, *largs): self.manager.current = 'home' def scroll_change(self, instance, value): self.slider_value = value self.scrollview.scroll_y = value self.reschedule() def slider_change(self, instance, value): if value >= 0: #this to avoid 'maximum recursion depth exceeded' error self.slider_value = value self.reschedule() def on_release_close_button(self, instance): self.go_to_home() def on_release_qr_button(self, instance): self.reschedule() content = QrDialog(rfid=str(self.user_data['rfid'])) self._popup = Popup(title="Scansiona il QR Code", content=content, size_hint=(None, None), width=250, height=300) self._popup.open() def changePage(self, new_page): self.reschedule() if path.isfile("storage_data/"+str(self.user_data['rfid'])+"/scheda_"+str(new_page)+".jpg"): self.page=new_page self.labelPage.text=str(self.page+1)+"/"+str(self.num_pages) self.setSourcePath("storage_data/"+str(self.user_data['rfid'])+"/scheda_"+str(self.page)+".jpg") self.slider_value = 1 def on_release_left_button(self, instance): self.changePage(new_page=self.page-1) def on_release_right_button(self, instance): self.changePage(new_page=self.page+1) def on_img_hint_update(self, instance, value): scroll_x = self.scrollview.scroll_x self.scrollview.scroll_x = scroll_x self.reschedule() def on_release_zoomOut_button(self, instance): if self.img_view.size_hint_x / 1.2 >= 1: if self.img_view: self.img_view.size_hint = (self.img_view.size_hint_x / 1.2, self.img_view.size_hint_y / 1.2) self.img_view.width = 0 else: self.scrollview.scroll_x = 0.5 def on_release_zoomIn_button(self, instance): if self.img_view.size_hint_x * 1.2 <= 3: if self.img_view: self.img_view.size_hint = (self.img_view.size_hint_x * 1.2, self.img_view.size_hint_y * 1.2) self.img_view.width = 0 def on_src(self, instance, value): if self.img_view: self.img_view.source = value def on_label_text(self, instance, value): self.label.text = value def on_slider_value(self, isinstance, value): self.slider.value = value def update_bg(self, *args): self.bg.pos = self.pos self.bg.size = self.size def setSourcePath(self, path, *largs): self.src = path def saveUserData(self, rfid, data): if self.firebase: self.firebase.update("users/"+rfid, data) def setUserData(self, user_data, *largs): self.user_data = user_data
class SchedulePage(BoxLayout): def __init__(self, **kwargs): super(SchedulePage, self).__init__(**kwargs) self.orientation = "vertical" self.previous_screen = "" self.date = None self.button_to_block = {} # Title - "Schedule" at top - left aligned self.title = Label(text="Schedule", font_size=25, halign="left", valign="middle", padding=(10, 0)) self.title.bind(size=self.title.setter('text_size')) self.title.size_hint_y = None self.title.height = 58 self.add_widget(self.title) # Scrolling area for schedule self.scroll = ScrollView() self.scroll.size_hint_y = None self.scroll.height = 500 self.add_widget(self.scroll) # generate schedule self.gen_schedule(remove=False) # Buttons self.button1 = Button(text="Add Work/Break Block", font_size=20) self.button1.bind(on_press=self.button1_act) self.add_widget(self.button1) self.button2 = Button(text="Back to Calendar", font_size=20) self.button2.bind(on_press=self.button2_act) self.add_widget(self.button2) def update_date(self, date): self.date = date self.title.text = "Schedule " + str(date[1]) + '/' + str(date[0]) self.title.text += '/' + str(date[2]) def gen_schedule(self, remove=True): self.button_to_block = {} # Wrapper widget for schedule - using FloatLayout if remove: self.scroll.remove_widget(self.float) self.float = FloatLayout(size_hint_y=None) self.scroll.add_widget(self.float) # some variables for making the schedule hrs = [12] hrs.extend(range(1, 13)) hrs.extend(range(1, 13)) mins = ["00", "30"] block_size = 90 # set height of float to fit schedule self.float.height = block_size * 2 * len(hrs) + 20 # y pos for lines - start at 20px (room for label) y = self.float.height - 20 # Add lines and time stamps is_PM = True with self.float.canvas: for hr in hrs: if hr == 12: is_PM = not is_PM for min in mins: Line(points=[0, y, Window.width, y], width=1) if not is_PM: label = Label(text="%d:%s AM" % (hr, min), pos=(-200, y - self.float.height / 2 + 10), font_size=20) else: label = Label(text="%d:%s PM" % (hr, min), pos=(-200, y - self.float.height / 2 + 10), font_size=20) self.float.add_widget(label) y -= block_size # Add the blocks if self.date != None: date = datetime.datetime(day=self.date[0], month=self.date[1], year=self.date[2]) day = datetime.date(day=self.date[0], month=self.date[1], year=self.date[2]) blocks = db.get_blocks(day) for block in blocks: start_delta = (block.start - date).total_seconds() / 60 duration = (block.end - block.start).total_seconds() / 60 start_px = 20 + start_delta * 3 height = duration * 3 text = block.type text += block.start.strftime(' %I:%M %p') text += block.end.strftime(' - %I:%M %p') button = Button(text=text, font_size=20) if block.type == "Work": button.background_color = [1, 0, 0, 1] # red RGBA button.bind(on_press=self.work_act) elif block.type == "Break": button.background_color = [0, 1, 0, 1] # green RGBA button.bind(on_press=self.break_act) else: print("ERROR: Invalid Block Type") button.x = 200 button.y = self.float.height - start_px - height button.size_hint_x = None button.size_hint_y = None button.width = 300 button.height = height self.float.add_widget(button) self.button_to_block[button] = block # remove block button button = Button(text="X", font_size=20) button.x = 100 button.y = self.float.height - start_px - height button.size_hint_x = None button.size_hint_y = None button.width = 100 button.height = height button.bind(on_press=self.remove_block) self.float.add_widget(button) self.button_to_block[button] = block def remove_block(self, instance): block = self.button_to_block[instance] db.remove_block(block.id) self.gen_schedule() def work_act(self, instance): block = self.button_to_block[instance] nag_bot_app.to_do_page.update_block(block) nag_bot_app.screen_manager.transition.direction = 'up' nag_bot_app.screen_manager.current = "To Do List" nag_bot_app.to_do_page.previous_screen = "Schedule" def break_act(self, instance): block = self.button_to_block[instance] nag_bot_app.edit_block_page.edit_block(block) nag_bot_app.screen_manager.transition.direction = 'left' nag_bot_app.screen_manager.current = "Edit Block" nag_bot_app.edit_block_page.previous_screen = "Schedule" # Button1 - Add Work/Break Block def button1_act(self, instance): rst_date = datetime.date(day=self.date[0], month=self.date[1], year=self.date[2]) nag_bot_app.edit_block_page.reset(rst_date) nag_bot_app.screen_manager.transition.direction = 'left' nag_bot_app.screen_manager.current = "Edit Block" nag_bot_app.edit_block_page.previous_screen = "Schedule" # Button 2 - Back to Calendar - go back to the CalendarPage def button2_act(self, instance): nag_bot_app.screen_manager.transition.direction = 'right' nag_bot_app.screen_manager.current = "Calendar" nag_bot_app.calendar_page.previous_screen = "Schedule"
class cWidgetScrollList(cWidgetPicture): """ WikiDoc:Doc WikiDoc:Context:Widgets WikiDoc:Page:Widgets-SCROLLLIST WikiDoc:TOCTitle:ScrollList = ScrollList = The scrolllist widget is a container widget to place lines of widget in a scrollable widget The scrolllist widget is based on the picture widget, please use the documentation for the common attributes To Identify the the source widget in actions triggered by widgets in the scroll list: The "SCROLLLISTVALUE" value is added to the action pars which refers to the widget text The "SCROLLLISTINDEX" index is added to the action pars which refers to the line order, eg: "0" is the first line in the list The "SCROLLLISTVARINDEX" index is added to the action pars which refers to the index number of the vararray The list of lines within the container is build from the vararry of minimum one widget within the line definition. So, one widget must have a caption with an array variable You can place all kind of widgets (with the exception of dropdowns in a row/line of the container All widgets got an index "[x]" added to the widget name, to manage them thought the actions The following attributes are additional attributes to common picture attributes <div style="overflow:auto; "> {| class="wikitable" ! align="left" | Attribute ! align="left" | Description |- |type |fixed: needs to be "SCROLLCONTAINER". Capital letters! |- |container |A string, which identifies the container AND all elements to place into the row of the container. If blank, a random value is used |- |rowheight |The rowheigth of a full line within the container: The line definition (all widgets in a line) must fir the this number |}</div> Below you see an example for a container definition <div style="overflow-x: auto;"><syntaxhighlight lang="xml"> <element name='Anchor1' type='ANCHOR' posx='%2' posy='%20' width='%30' height='%60' > <elements> <element name="ScrollBox Left" type="SCROLLLIST" picturenormal="background boxes" container="container_1" rowheight="%25" /> <element name='Anchor1 Inner' type='ANCHOR' height='%25' > <element name="First Button" type="BUTTON" posx="left" posy="top" height="%100" width="%40" picturenormal='button wide*' container="container_1" caption="First Button" action="Show Page" actionpars='{"pagename":"Page_Main"}' /> <element name="Second Button Top" type="BUTTON" posx="right" posy="top" height="%50" width="%60" picturenormal="button wide*" container="container_1" caption="$var(scrollcontent_button1_text[])" action="Show Page" actionpars='{"pagename":"Page_Main"}' /> <element name="Second Button Down" type="BUTTON" posx="right" posy="bottom" height="%50" width="%60" picturenormal="button wide*" container="container_1" caption="$var(scrollcontent_button2_text[])" action="Show Page" actionpars='{"pagename":"Page_Main"}' /> </element> </elements> </element> </syntaxhighlight></div> A second example with automated container assignment <div style="overflow-x: auto;"><syntaxhighlight lang="xml"> </syntaxhighlight></div> WikiDoc:End """ # noinspection PyUnusedLocal def __init__(self,**kwargs): super().__init__() self.oObjectContent:Union[FloatLayout,None] = None self.oObjectScroll:Union[ScrollView,None] = None self.uRowHeightInit:str = u'' self.iRowHeightScreen:int = 0 self.iRowHeight:int = 0 self.iNumRows:int = 0 self.aListChilds:List[cWidgetBase] = [] self.aChilds:List[cWidgetBase] = [] def InitWidgetFromXml(self,*,oXMLNode:Element,oParentScreenPage:cScreenPage, uAnchor:str) -> bool: """ Reads further Widget attributes from a xml node """ self.uRowHeightInit = GetXMLTextAttribute(oXMLNode=oXMLNode,uTag="rowheight",bMandatory=True,vDefault="%20") return super().InitWidgetFromXml(oXMLNode=oXMLNode,oParentScreenPage=oParentScreenPage ,uAnchor=uAnchor) def Create(self,oParent:Widget) -> bool: """ creates the Widget """ aChilds:List[cWidgetBase] aChilds:cWidgetBase aCaptions:List[str] self.iNumRows = 1 if super().Create(oParent): self.CreateScrollList() return True return False def GetChilds(self) -> List[cWidgetBase]: aRet:List[cWidgetBase] = [] # in case of recreation: Lets add the childs to the list of Screenpage widgets for oChild in self.aChilds: self.oParentScreenPage.RegisterWidget(oWidget=oChild) # and remove the from the local list del self.aChilds[:] # save a copy of the screenpage widgets locally and mark them for deletion for oWidget in self.oParentScreenPage.dWidgetsID.values(): if oWidget.uContainer==self.uContainer and oWidget!=self: aRet.append(oWidget) self.aChilds.append(copy(oWidget)) self.oParentScreenPage.aErrorWidgets.append(oWidget) return aRet def GetCaptions(self,aChilds:List[cWidgetBase]) -> List[List[Tuple[str,str]]]: aCaptions:List[List[Tuple[str,str]]] = [] aTmp:List[Tuple] tItem: Tuple aChildCaptions: List[Tuple[str, str]] for oChild in aChilds: aChildCaptions = [] if hasattr(oChild,'uOrgCaption'): if oChild.uOrgCaption.endswith("[])"): aTmp = Var_GetArrayEx(uVarName=oChild.uOrgCaption[5:-1], iLevel=1, bSort=False) for tItem in aTmp: aChildCaptions.append((u"$var(" + tItem[0] + ")",tItem[1])) self.iNumRows = max(self.iNumRows, len(aChildCaptions)) aCaptions.append(aChildCaptions) return aCaptions def CreateScrollList(self): aChilds:List[cWidgetBase] = self.GetChilds() aCaptions:List[List[Tuple[str,str]]] = self.GetCaptions(aChilds) self.iRowHeight = self.CalculateHeight(uHeight=self.uRowHeightInit, iAnchorHeight=self.iAnchorHeight) self.iRowHeightScreen = self.iRowHeight / self.oDef.fRationY self.oObjectScroll = ScrollView(size=self.oObject.size, pos=self.oObject.pos, do_scroll_x=False, scroll_type=['bars', 'content'], size_hint=(1, None), bar_width='10dp') self.oObjectContent = Widget(size=(self.oObject.width, self.iRowHeightScreen * self.iNumRows), size_hint=(1, None)) self.oObject.add_widget(self.oObjectScroll) self.oObjectScroll.add_widget(self.oObjectContent) self.CreateChilds(aChilds, aCaptions) def DeleteScrollList(self): self.DeleteChilds() self.oObjectScroll.remove_widget(self.oObjectContent) self.oObject.remove_widget(self.oObjectScroll) def CreateChilds(self,aChilds:List[cWidgetBase],aCaptions:List[List[Tuple[str,str]]]): iIndex:int iSubIndex: int yPos:int iAdd:int uVarIndex:str dTmpdActionPars:Dict = {} for u in range(self.iNumRows): iIndex = 0 uVarIndex = u'' # by purpose, we don't set it by child, we use the last known index, in case we have widgets without vars eg Buttons for oChild in aChilds: if hasattr(oChild,"dActionPars"): dTmpdActionPars = CopyDict(oChild.dActionPars) oTmpChild = copy(oChild) oTmpChild.uName = "%s[%s]" % (oTmpChild.uName, str(u)) oTmpChild.iHeightInit = self.iRowHeight * (oChild.iHeightInit/oChild.iAnchorHeight) oTmpChild.iPosXInit = oTmpChild.iPosXInit - self.iPosXInit oTmpChild.iGapY = (self.iPosY *-1) + (self.iRowHeightScreen * (u + 0)) if isinstance(oChild,cWidgetSwitch): if oTmpChild.uDestVar: oTmpChild.uDestVar=oTmpChild.uDestVar+"_"+str(u) if len(aCaptions[iIndex]) > u: if hasattr(oTmpChild,"uCaption"): oTmpChild.uOrgCaption = aCaptions[iIndex][u][0] oTmpChild.uCaption = ReplaceVars(aCaptions[iIndex][u][0]) uVarIndex = ReplaceVars(aCaptions[iIndex][u][1]) oTmpChild.Create(self.oObjectContent) if hasattr(oTmpChild,"dActionPars"): try: oTmpChild.dActionPars["SCROLLLISTVALUE"] = oTmpChild.oObject.text except: oTmpChild.dActionPars["SCROLLLISTVALUE"] = "" oTmpChild.dActionPars["SCROLLLISTINDEX"] = str(u) oTmpChild.dActionPars["SCROLLLISTVARINDEX"] = uVarIndex self.aListChilds.append(oTmpChild) self.oParentScreenPage.aAddWidgets.append(oTmpChild) oChild.dActionPars=dTmpdActionPars iIndex += 1 def DeleteChilds(self): for oChild in self.aListChilds: self.oObjectContent.remove_widget(oChild.oObject) oChild.oObject = None self.oParentScreenPage.RemoveWidget(oWidget=oChild) del self.aListChilds[:] self.iNumRows = 0 def UpdateWidget(self) -> None: super().UpdateWidget() if self.oObjectScroll is not None: self.DeleteScrollList() self.CreateScrollList() self.oParentScreenPage.PostHandleErrorWidgets() return def EnableWidget(self, *, bEnable:bool) -> bool: super(cWidgetScrollList, self).EnableWidget(bEnable=bEnable) if self.oObjectScroll: if bEnable: self.oObjectScroll.opacity=1 else: self.oObjectScroll.opacity=0 return self.bIsEnabled