def __init__(self, parent_widget, titles=None, initial_sort=None, ascending=True, *args, **kwargs): Box.__init__(self, parent_widget, *args, **kwargs) self.header = titles self.sort_column = initial_sort self.sort_column_ascending = ascending self.rows = [] self.header_row = [] self.header_box = Box(self, size_hint_weight=EXPAND_HORIZ, size_hint_align=FILL_HORIZ) self.header_box.horizontal = True self.header_box.show() scr = Scroller(self, size_hint_weight=EXPAND_BOTH, size_hint_align=FILL_BOTH) self.list_box = Box(self, size_hint_weight=EXPAND_BOTH, size_hint_align=FILL_BOTH) self.list_box.horizontal = True self.list_box.show() scr.policy_set(ELM_SCROLLER_POLICY_OFF, ELM_SCROLLER_POLICY_ON) scr.content = self.list_box scr.show() self.lists = [] self.pack_end(self.header_box) self.pack_end(scr) self.show() if titles is not None: self.header_row_pack(titles)
def __init__(self, parent_widget, *args, titles=None, initial_sort=0, ascending=True, **kwargs): Box.__init__(self, parent_widget, *args, **kwargs) self.header = titles self.sort_column = initial_sort self.sort_column_ascending = ascending self.rows = [] self.header_row = [] self.header_box = Box(self, size_hint_weight=EXPAND_HORIZ, size_hint_align=FILL_HORIZ) self.header_box.horizontal = True self.header_box.show() scr = Scroller(self, size_hint_weight=EXPAND_BOTH, size_hint_align=FILL_BOTH) self.list_box = Box(self, size_hint_weight=EXPAND_BOTH, size_hint_align=FILL_BOTH) self.list_box.horizontal = True self.list_box.show() scr.policy_set(ELM_SCROLLER_POLICY_OFF, ELM_SCROLLER_POLICY_ON) scr.content = self.list_box scr.show() self.lists = [] self.pack_end(self.header_box) self.pack_end(scr) self.show() if titles is not None: self.header_row_pack(titles)
class SortedList(Scroller): """ A "spread sheet like" widget for elementary. Argument "titles" is a list, with each element being a tuple: (<Display Text>, <Sortable>) """ def __init__(self, parent_widget, titles=None, initial_sort=0, ascending=True, *args, **kwargs): Scroller.__init__(self, parent_widget, *args, **kwargs) self.policy_set(ELM_SCROLLER_POLICY_AUTO, ELM_SCROLLER_POLICY_OFF) self.mainBox = Box(self, size_hint_weight=EXPAND_BOTH, size_hint_align=FILL_BOTH) self.mainBox.show() self.header = titles self.sort_column = initial_sort self.sort_column_ascending = ascending self.rows = [] self.header_row = [] headerPane = Panes(self, size_hint_weight=EXPAND_HORIZ, size_hint_align=FILL_HORIZ) headerPane.callback_unpress_add(self.paneResized) headerPane.show() listPane = Panes(self, size_hint_weight=EXPAND_BOTH, size_hint_align=FILL_BOTH) listPane.callback_unpress_add(self.paneResized) listPane.style_set("flush") listPane.show() headerPane.data["related"] = listPane listPane.data["related"] = headerPane self.mainScr = Scroller(self, size_hint_weight=EXPAND_BOTH, size_hint_align=FILL_BOTH) self.mainScr.policy_set(ELM_SCROLLER_POLICY_OFF, ELM_SCROLLER_POLICY_AUTO) self.mainScr.content = listPane self.mainScr.show() self.headerPanes = [] self.headerPanes.append(headerPane) self.listPanes = [] self.listPanes.append(listPane) self.lists = [] #self.pack_end(self.header_box) if titles is not None: self.header_row_pack(titles) self.mainBox.pack_end(headerPane) self.mainBox.pack_end(self.mainScr) self.content = self.mainBox self.show() def header_row_pack(self, titles): """Takes a list (or a tuple) of tuples (string, bool, int) and packs them to the first row of the table.""" assert isinstance(titles, (list, tuple)) for t in titles: assert isinstance(t, tuple) assert len(t) == 2 title, sortable = t try: assert isinstance(title, basestring) except: assert isinstance(title, str) assert isinstance(sortable, bool) def sort_btn_cb(button, col): if self.sort_column == col: self.reverse() else: self.sort_by_column(col) titleCount = len(titles) for count, t in enumerate(titles): title, sortable = t btn = Button(self, size_hint_weight=EXPAND_HORIZ, size_hint_align=FILL_HORIZ, text=title) btn.callback_clicked_add(sort_btn_cb, count) if not sortable: btn.disabled = True btn.show() self.header_row.append(btn) bx = Box(self, size_hint_weight=EXPAND_BOTH, size_hint_align=FILL_BOTH) bx.show() if len(self.listPanes) < titleCount: wdth = 1.0 / (titleCount - count) self.listPanes[count].part_content_set("left", bx) self.listPanes[count].content_left_size = wdth nextList = Panes(self, size_hint_weight=EXPAND_BOTH, size_hint_align=FILL_BOTH) nextList.callback_unpress_add(self.paneResized) nextList.style_set("flush") nextList.show() self.listPanes[count].part_content_set("right", nextList) self.listPanes.append(nextList) self.headerPanes[count].part_content_set("left", btn) self.headerPanes[count].content_left_size = wdth nextHeader = Panes(self, size_hint_weight=EXPAND_HORIZ, size_hint_align=FILL_HORIZ) nextHeader.callback_unpress_add(self.paneResized) nextHeader.show() self.headerPanes[count].part_content_set("right", nextHeader) self.headerPanes.append(nextHeader) nextList.data["related"] = nextHeader nextHeader.data["related"] = nextList else: self.listPanes[count - 1].part_content_set("right", bx) self.headerPanes[count - 1].part_content_set("right", btn) self.lists.append(bx) def paneResized(self, obj): leftSize = obj.content_left_size rightSize = obj.content_right_size related = obj.data["related"] related.content_left_size = leftSize related.content_right_size = rightSize def row_pack(self, row, sort=True): """Takes a list of items and packs them to the table.""" assert len(row) == len(self.header_row), ( "The row you are trying to add to this sorted list has the wrong " "number of items! expected: %i got: %i" % (len(self.header_row), len(row))) self.rows.append(row) self.add_row(row) if sort: self.sort_by_column(self.sort_column) def add_row(self, row): #print("Test %s"%row) for count, item in enumerate(row): self.lists[count].pack_end(item) def row_unpack(self, row, delete=False): """Unpacks and hides, and optionally deletes, a row of items. The argument row can either be the row itself or its index number. """ if isinstance(row, int): row_index = row else: row_index = self.rows.index(row) + 1 # print("row index: " + str(row_index-1)) # print("length: " + str(len(self.rows))) # print("sort_data: " + str(row[self.sort_column].data["sort_data"])) row = self.rows.pop(row_index - 1) for count, item in enumerate(row): self.lists[count].unpack(item) if delete: item.delete() else: item.hide() self.sort_by_column(self.sort_column, ascending=self.sort_column_ascending) def unpack_all(self): tmplist = list(self.rows) for rw in tmplist: self.row_unpack(rw) def reverse(self): rev_order = reversed(list(range(len(self.rows)))) for bx in self.lists: bx.unpack_all() for new_y in rev_order: self.add_row(self.rows[new_y]) lb = self.header_row[self.sort_column].part_content_get("icon") if lb is not None: if self.sort_column_ascending: lb.text = u"⬆" self.sort_column_ascending = False else: lb.text = u"⬇" self.sort_column_ascending = True self.rows.reverse() def sort_by_column(self, col, ascending=True): assert col >= 0 assert col < len(self.header_row) self.header_row[self.sort_column].icon = None btn = self.header_row[col] ic = Label(btn) btn.part_content_set("icon", ic) ic.show() if ascending == True: #ascending: ic.text = u"⬇" self.sort_column_ascending = True else: ic.text = u"⬆" self.sort_column_ascending = False orig_col = [ (i, x[col].data.get("sort_data", x[col].text)) \ for i, x in enumerate(self.rows) ] sorted_col = sorted(orig_col, key=lambda e: e[1]) new_order = [x[0] for x in sorted_col] # print(new_order) if not ascending: new_order.reverse() # print(new_order) for bx in self.lists: bx.unpack_all() for new_y in new_order: self.add_row(self.rows[new_y]) self.rows.sort(key=lambda e: e[col].data.get("sort_data", e[col].text), #reverse=False if ascending else True ) self.sort_column = col def update(self): self.sort_by_column(self.sort_column, self.sort_column_ascending)
class SortedList(Scroller): """ A "spread sheet like" widget for elementary. Argument "titles" is a list, with each element being a tuple: (<Display Text>, <Sortable>) """ def __init__(self, parent_widget, titles=None, initial_sort=0, ascending=True, *args, **kwargs): Scroller.__init__(self, parent_widget, *args, **kwargs) self.policy_set(ELM_SCROLLER_POLICY_AUTO, ELM_SCROLLER_POLICY_OFF) self.mainBox = Box(self, size_hint_weight=EXPAND_BOTH, size_hint_align=FILL_BOTH) self.mainBox.show() self.header = titles self.sort_column = initial_sort self.sort_column_ascending = ascending self.rows = [] self.header_row = [] headerPane = Panes(self, size_hint_weight=EXPAND_HORIZ, size_hint_align=FILL_HORIZ) headerPane.callback_unpress_add(self.paneResized) headerPane.show() listPane = Panes(self, size_hint_weight=EXPAND_BOTH, size_hint_align=FILL_BOTH) listPane.callback_unpress_add(self.paneResized) listPane.style_set("flush") listPane.show() headerPane.data["related"] = listPane listPane.data["related"] = headerPane self.mainScr = Scroller(self, size_hint_weight=EXPAND_BOTH, size_hint_align=FILL_BOTH) self.mainScr.policy_set(ELM_SCROLLER_POLICY_OFF, ELM_SCROLLER_POLICY_AUTO) self.mainScr.content = listPane self.mainScr.show() self.headerPanes = [] self.headerPanes.append(headerPane) self.listPanes = [] self.listPanes.append(listPane) self.lists = [] #self.pack_end(self.header_box) if titles is not None: self.header_row_pack(titles) self.mainBox.pack_end(headerPane) self.mainBox.pack_end(self.mainScr) self.content = self.mainBox self.show() def header_row_pack(self, titles): """Takes a list (or a tuple) of tuples (string, bool, int) and packs them to the first row of the table.""" assert isinstance(titles, (list, tuple)) for t in titles: assert isinstance(t, tuple) assert len(t) == 2 title, sortable = t try: assert isinstance(title, basestring) except: assert isinstance(title, str) assert isinstance(sortable, bool) def sort_btn_cb(button, col): if self.sort_column == col: self.reverse() else: self.sort_by_column(col) titleCount = len(titles) for count, t in enumerate(titles): title, sortable = t btn = Button(self, size_hint_weight=EXPAND_HORIZ, size_hint_align=FILL_HORIZ, text=title) btn.callback_clicked_add(sort_btn_cb, count) if not sortable: btn.disabled = True btn.show() self.header_row.append(btn) bx = Box(self, size_hint_weight=EXPAND_BOTH, size_hint_align=FILL_BOTH) bx.show() if len(self.listPanes) < titleCount: wdth = 1.0 / (titleCount - count) self.listPanes[count].part_content_set("left", bx) self.listPanes[count].content_left_size = wdth nextList = Panes(self, size_hint_weight=EXPAND_BOTH, size_hint_align=FILL_BOTH) nextList.callback_unpress_add(self.paneResized) nextList.style_set("flush") nextList.show() self.listPanes[count].part_content_set("right", nextList) self.listPanes.append(nextList) self.headerPanes[count].part_content_set("left", btn) self.headerPanes[count].content_left_size = wdth nextHeader = Panes(self, size_hint_weight=EXPAND_HORIZ, size_hint_align=FILL_HORIZ) nextHeader.callback_unpress_add(self.paneResized) nextHeader.show() self.headerPanes[count].part_content_set("right", nextHeader) self.headerPanes.append(nextHeader) nextList.data["related"] = nextHeader nextHeader.data["related"] = nextList else: self.listPanes[count - 1].part_content_set("right", bx) self.headerPanes[count - 1].part_content_set("right", btn) self.lists.append(bx) def paneResized(self, obj): leftSize = obj.content_left_size rightSize = obj.content_right_size related = obj.data["related"] related.content_left_size = leftSize related.content_right_size = rightSize def row_pack(self, row, sort=True): """Takes a list of items and packs them to the table.""" assert len(row) == len(self.header_row), ( "The row you are trying to add to this sorted list has the wrong " "number of items! expected: %i got: %i" % ( len(self.header_row), len(row) ) ) self.rows.append(row) self.add_row(row) if sort: self.sort_by_column(self.sort_column) def add_row(self, row): #print("Test %s"%row) for count, item in enumerate(row): self.lists[count].pack_end(item) def row_unpack(self, row, delete=False): """Unpacks and hides, and optionally deletes, a row of items. The argument row can either be the row itself or its index number. """ if isinstance(row, int): row_index = row else: row_index = self.rows.index(row)+1 # print("row index: " + str(row_index-1)) # print("length: " + str(len(self.rows))) # print("sort_data: " + str(row[self.sort_column].data["sort_data"])) row = self.rows.pop(row_index-1) for count, item in enumerate(row): self.lists[count].unpack(item) if delete: item.delete() else: item.hide() self.sort_by_column(self.sort_column, ascending=self.sort_column_ascending) def unpack_all(self): tmplist = list(self.rows) for rw in tmplist: self.row_unpack(rw) def reverse(self): rev_order = reversed(list(range(len(self.rows)))) for bx in self.lists: bx.unpack_all() for new_y in rev_order: self.add_row(self.rows[new_y]) lb = self.header_row[self.sort_column].part_content_get("icon") if lb is not None: if self.sort_column_ascending: lb.text = u"⬆" self.sort_column_ascending = False else: lb.text = u"⬇" self.sort_column_ascending = True self.rows.reverse() def sort_by_column(self, col, ascending=True): assert col >= 0 assert col < len(self.header_row) self.header_row[self.sort_column].icon = None btn = self.header_row[col] ic = Label(btn) btn.part_content_set("icon", ic) ic.show() if ascending == True: #ascending: ic.text = u"⬇" self.sort_column_ascending = True else: ic.text = u"⬆" self.sort_column_ascending = False orig_col = [ (i, x[col].data.get("sort_data", x[col].text)) \ for i, x in enumerate(self.rows) ] sorted_col = sorted(orig_col, key=lambda e: e[1]) new_order = [x[0] for x in sorted_col] # print(new_order) if not ascending: new_order.reverse() # print(new_order) for bx in self.lists: bx.unpack_all() for new_y in new_order: self.add_row(self.rows[new_y]) self.rows.sort( key=lambda e: e[col].data.get("sort_data", e[col].text), #reverse=False if ascending else True ) self.sort_column = col def update(self): self.sort_by_column(self.sort_column, self.sort_column_ascending)
class SortedList(Scroller): ''' A "spread sheet like" widget for elementary. Argument "titles" is a list, with each element being a tuple: (<Display Text>, <Sortable>) ''' def __init__(self, parent_widget, *args, titles=None, initial_sort=0, ascending=True, **kwargs): Scroller.__init__(self, parent_widget, *args, **kwargs) self.policy_set(ELM_SCROLLER_POLICY_AUTO, ELM_SCROLLER_POLICY_OFF) self.main_box = Box(self, size_hint_weight=EXPAND_BOTH, size_hint_align=FILL_BOTH) self.main_box.show() self.header = titles self.sort_column = initial_sort self.sort_column_ascending = ascending self.rows = [] self.header_row = [] header = Panes(self, size_hint_weight=EXPAND_HORIZ, size_hint_align=FILL_HORIZ) header.callback_unpress_add(self.cb_resize_pane) header.show() list_pane = Panes(self, size_hint_weight=EXPAND_BOTH, size_hint_align=FILL_BOTH) list_pane.callback_unpress_add(self.cb_resize_pane) list_pane.style_set("flush") list_pane.show() header.data["related"] = list_pane list_pane.data["related"] = header self.scroller = Scroller(self, size_hint_weight=EXPAND_BOTH, size_hint_align=FILL_BOTH) self.scroller.policy_set(ELM_SCROLLER_POLICY_OFF, ELM_SCROLLER_POLICY_AUTO) self.scroller.content = list_pane self.scroller.show() self.headers = [] self.headers.append(header) self.list_panes = [] self.list_panes.append(list_pane) self.lists = [] if titles is not None: self.header_row_pack(titles) self.main_box.pack_end(header) self.main_box.pack_end(self.scroller) self.content = self.main_box self.show() def header_row_pack(self, titles): '''Takes a list (or a tuple) of tuples (string, bool, int) and packs them to the first row of the table.''' assert isinstance(titles, (list, tuple)) for _t in titles: assert isinstance(_t, tuple) assert len(_t) == 2 title, sortable = _t assert isinstance(title, str) assert isinstance(sortable, bool) def cb_sort_btn(button, col): '''Aux function''' if self.sort_column == col: self.reverse() else: self.sort_by_column(col) title_cnt = len(titles) for count, flag in enumerate(titles): title, sortable = flag btn = Button(self, size_hint_weight=EXPAND_HORIZ, size_hint_align=FILL_HORIZ, text=title) btn.callback_clicked_add(cb_sort_btn, count) if not sortable: btn.disabled = True btn.show() self.header_row.append(btn) box = Box(self, size_hint_weight=EXPAND_BOTH, size_hint_align=FILL_BOTH) box.show() if len(self.list_panes) < title_cnt: wdth = 1.0 / (title_cnt - count) self.list_panes[count].part_content_set("left", box) self.list_panes[count].content_left_size = wdth next_list = Panes(self, size_hint_weight=EXPAND_BOTH, size_hint_align=FILL_BOTH) next_list.callback_unpress_add(self.cb_resize_pane) next_list.style_set("flush") next_list.show() self.list_panes[count].part_content_set("right", next_list) self.list_panes.append(next_list) self.headers[count].part_content_set("left", btn) self.headers[count].content_left_size = wdth next_header = Panes(self, size_hint_weight=EXPAND_HORIZ, size_hint_align=FILL_HORIZ) next_header.callback_unpress_add(self.cb_resize_pane) next_header.show() self.headers[count].part_content_set("right", next_header) self.headers.append(next_header) next_list.data["related"] = next_header next_header.data["related"] = next_list else: self.list_panes[count - 1].part_content_set("right", box) self.headers[count - 1].part_content_set("right", btn) self.lists.append(box) # pylint: disable=no-self-use def cb_resize_pane(self, obj): '''Resize display pane''' left = obj.content_left_size right = obj.content_right_size related = obj.data["related"] related.content_left_size = left related.content_right_size = right def row_pack(self, row, sort=True): '''Takes a list of items and packs them to the table.''' assert len(row) == len(self.header_row), ( "The row you are trying to add to this sorted list has the wrong " "number of items! expected: %i got: %i" % (len(self.header_row), len(row))) self.rows.append(row) self.add_row(row) if sort: self.sort_by_column(self.sort_column) def add_row(self, row): '''Add Row to list''' # print("Test %s"%row) for count, item in enumerate(row): self.lists[count].pack_end(item) def row_unpack(self, row, delete=False): '''Unpacks and hides, and optionally deletes, a row of items. The argument row can either be the row itself or its index number. ''' if isinstance(row, int): row_index = row else: row_index = self.rows.index(row) + 1 # print("row index: " + str(row_index-1)) # print("length: " + str(len(self.rows))) # print("sort_data: " + str(row[self.sort_column].data["sort_data"])) row = self.rows.pop(row_index - 1) for count, item in enumerate(row): self.lists[count].unpack(item) if delete: item.delete() else: item.hide() self.sort_by_column(self.sort_column, ascending=self.sort_column_ascending) def unpack_all(self): '''Clear row''' tmplist = list(self.rows) for row in tmplist: self.row_unpack(row) def reverse(self): '''Reverse list''' rev_order = reversed(list(range(len(self.rows)))) for box in self.lists: box.unpack_all() for new_y in rev_order: self.add_row(self.rows[new_y]) label = self.header_row[self.sort_column].part_content_get("icon") if label is not None: if self.sort_column_ascending: label.text = u"⬆" self.sort_column_ascending = False else: label.text = u"⬇" self.sort_column_ascending = True self.rows.reverse() def sort_by_column(self, col, ascending=True): '''Sort column''' assert col >= 0 assert col < len(self.header_row) self.header_row[self.sort_column].icon = None btn = self.header_row[col] label = Label(btn) btn.part_content_set("labelon", label) label.show() if ascending: # sascending: label.text = u"⬇" self.sort_column_ascending = True else: label.text = u"⬆" self.sort_column_ascending = False orig_col = [ (i, x[col].data.get("sort_data", x[col].text)) for i, x in enumerate(self.rows) ] sorted_col = sorted(orig_col, key=lambda e: e[1]) new_order = [x[0] for x in sorted_col] if not ascending: new_order.reverse() for box in self.lists: box.unpack_all() for new_y in new_order: self.add_row(self.rows[new_y]) self.rows.sort(key=lambda e: e[col].data.get("sort_data", e[col].text)) self.sort_column = col def update(self): '''Update''' self.sort_by_column(self.sort_column, self.sort_column_ascending)