def show(frame, iterator): """Выводит на экран выборку, заданную в iterator""" scrollbar = Scrollbar(frame) tree = Treeview(frame, selectmode='none', padding=3, style='Custom.Treeview', height=REPORT_HEIGHT, yscrollcommand=scrollbar.set) tree.pack(side=LEFT, fill=BOTH, expand=YES) scrollbar.config(command=tree.yview) scrollbar.pack(side=LEFT, fill=Y) tree.tag_configure('1', font=('Verdana', FONT_SIZE_REPORT)) tree.tag_configure('2', font=('Verdana', FONT_SIZE_REPORT), background='#f5f5ff') Style().configure('Custom.Treeview', rowheight=FONT_SIZE_REPORT*2) columns = ['#' + str(x + 1) for x in range(8)] tree.configure(columns=columns) for q in range(len(header)): tree.heading('#%d' % (q + 1), text=header[q], anchor='w') tree.column('#%d' % (q + 1), width=REPORT_SCALE * col_width[q + 1], anchor='w') tree.heading('#0', text='', anchor='w') tree.column('#0', width=0, anchor='w', minwidth=0) flag = True summ = 0 for item in iterator: value = item.quantity * item.price * (100 - item.discount) / 100 summ += value col = [] col.append(add_s(item.check.id)) col.append(add_s(item.goods.cathegory.name)) col.append(add_s(item.goods.name)) col.append(add_s(item.quantity)) col.append(add_s(item.discount) +'%' if item.discount else ' -- ') col.append(add_s(u'%6.2f грн.' % value)) col.append(add_s(item.check.date_time.strftime('%d.%m.%Y'))) col.append(add_s(item.check.date_time.time())[:8]) flag = not flag if flag: tree.insert('', 'end', text='', values=col, tag='2') else: tree.insert('', 'end', text='', values=col, tag='1') return summ
def sort_by(self, tree: ttk.Treeview, col, descending): # Sort tree contents when a column is clicked on. # grab values to sort data = [(tree.set(child, col), child) for child in tree.get_children('')] # reorder data if data and all([self.is_float(element[0]) for element in data]): data.sort(reverse=descending, key=self.my_func) else: data.sort(reverse=descending) num = 'Even' for indx, item in enumerate(data): tree.move(item[1], '', indx) if bool(self.row_color) is True: if num == 'Even': tree.item(item[1], tags=('evenrow', )) num = 'Odd' elif num == 'Odd': tree.item(item[1], tags=('oddrow', )) num = 'Even' else: pass if self.row_color is True: tree.tag_configure('evenrow', background='#FFF') tree.tag_configure('oddrow', background='#EAECEE') else: pass # switch the heading so that it will sort in the opposite direction tree.heading(col, command=lambda col=col: self.sort_by( tree, col, int(not descending)))
def show(frame, iterator): """Выводит на экран выборку, заданную в iterator""" scrollbar = Scrollbar(frame) tree = Treeview(frame, selectmode='none', padding=3, style='Custom.Treeview', height=REPORT_HEIGHT, yscrollcommand=scrollbar.set) tree.pack(side=LEFT, fill=BOTH, expand=YES) scrollbar.config(command=tree.yview) scrollbar.pack(side=LEFT, fill=Y) tree.tag_configure('1', font=('Verdana', FONT_SIZE_REPORT)) tree.tag_configure('2', font=('Verdana', FONT_SIZE_REPORT), background='#f5f5ff') Style().configure('Custom.Treeview', rowheight=FONT_SIZE_REPORT*2) columns = ['#' + str(x + 1) for x in range(7)] tree.configure(columns=columns) for q in range(len(header)): tree.heading('#%d' % (q + 1), text=header[q], anchor='w') tree.column('#%d' % (q + 1), width=REPORT_SCALE * col_width[q + 1], anchor='w') tree.heading('#0', text='', anchor='w') tree.column('#0', width=0, anchor='w', minwidth=0) flag = True for item in iterator: col = [] col.append(add_s(item.goods.cathegory.name if item.goods.cathegory else u'-Нет-')) col.append(add_s(item.goods.name)) col.append(add_s(item.quantity)) col.append(add_s(item.goods.measure)) col.append(add_s(item.date_time.strftime('%d.%m.%Y'))) col.append(add_s(item.reason.reason)) col.append(form(item.full_reason)) flag = not flag if flag: tree.insert('', 'end', text='', values=col, tag='2') else: tree.insert('', 'end', text='', values=col, tag='1')
class Multicolumn_Listbox(object): _style_index = 0 class List_Of_Rows(object): def __init__(self, multicolumn_listbox): self._multicolumn_listbox = multicolumn_listbox def data(self, index): return self._multicolumn_listbox.row_data(index) def get(self, index): return Row(self._multicolumn_listbox, index) def insert(self, data, index=None): self._multicolumn_listbox.insert_row(data, index) def delete(self, index): self._multicolumn_listbox.delete_row(index) def update(self, index, data): self._multicolumn_listbox.update_row(index, data) def select(self, index): self._multicolumn_listbox.select_row(index) def deselect(self, index): self._multicolumn_listbox.deselect_row(index) def set_selection(self, indices): self._multicolumn_listbox.set_selection(indices) def __getitem__(self, index): return self.get(index) def __setitem__(self, index, value): return self._multicolumn_listbox.update_row(index, value) def __delitem__(self, index): self._multicolumn_listbox.delete_row(index) def __len__(self): return self._multicolumn_listbox.number_of_rows class List_Of_Columns(object): def __init__(self, multicolumn_listbox): self._multicolumn_listbox = multicolumn_listbox def data(self, index): return self._multicolumn_listbox.get_column(index) def get(self, index): return Column(self._multicolumn_listbox, index) def delete(self, index): self._multicolumn_listbox.delete_column(index) def update(self, index, data): self._multicolumn_listbox.update_column(index, data) def __getitem__(self, index): return self.get(index) def __setitem__(self, index, value): return self._multicolumn_listbox.update_column(index, value) def __delitem__(self, index): self._multicolumn_listbox.delete_column(index) def __len__(self): return self._multicolumn_listbox.number_of_columns def __init__(self, master, columns, data=None, command=None, sort=True, select_mode=None, heading_anchor=CENTER, cell_anchor=W, style=None, height=None, padding=None, adjust_heading_to_content=False, stripped_rows=None, selection_background=None, selection_foreground=None, field_background=None, heading_font=None, heading_background=None, heading_foreground=None, cell_pady=2, cell_background=None, cell_foreground=None, cell_font=None, headers=True): self._stripped_rows = stripped_rows self._columns = columns self._number_of_rows = 0 self._number_of_columns = len(columns) self.row = self.List_Of_Rows(self) self.column = self.List_Of_Columns(self) s = Style() if style is None: style_name = "Multicolumn_Listbox%s.Treeview" % self._style_index self._style_index += 1 else: style_name = style style_map = {} if selection_background is not None: style_map["background"] = [('selected', selection_background)] if selection_foreground is not None: style_map["foeground"] = [('selected', selection_foreground)] if style_map: s.map(style_name, **style_map) style_config = {} if cell_background is not None: style_config["background"] = cell_background if cell_foreground is not None: style_config["foreground"] = cell_foreground if cell_font is None: font_name = s.lookup(style_name, "font") cell_font = nametofont(font_name) else: if not isinstance(cell_font, Font): if isinstance(cell_font, basestring): cell_font = nametofont(cell_font) else: if len(font) == 1: cell_font = Font(family=cell_font[0]) elif len(font) == 2: cell_font = Font(family=cell_font[0], size=cell_font[1]) elif len(font) == 3: cell_font = Font(family=cell_font[0], size=cell_font[1], weight=cell_font[2]) else: raise ValueError( "Not possible more than 3 values for font") style_config["font"] = cell_font self._cell_font = cell_font self._rowheight = cell_font.metrics("linespace") + cell_pady style_config["rowheight"] = self._rowheight if field_background is not None: style_config["fieldbackground"] = field_background s.configure(style_name, **style_config) heading_style_config = {} if heading_font is not None: heading_style_config["font"] = heading_font if heading_background is not None: heading_style_config["background"] = heading_background if heading_foreground is not None: heading_style_config["foreground"] = heading_foreground heading_style_name = style_name + ".Heading" s.configure(heading_style_name, **heading_style_config) treeview_kwargs = {"style": style_name} if height is not None: treeview_kwargs["height"] = height if padding is not None: treeview_kwargs["padding"] = padding if headers: treeview_kwargs["show"] = "headings" else: treeview_kwargs["show"] = "" if select_mode is not None: treeview_kwargs["selectmode"] = select_mode self.interior = Treeview(master, columns=columns, **treeview_kwargs) if command is not None: self._command = command self.interior.bind("<<TreeviewSelect>>", self._on_select) for i in range(0, self._number_of_columns): if sort: self.interior.heading( i, text=columns[i], anchor=heading_anchor, command=lambda col=i: self.sort_by(col, descending=False)) else: self.interior.heading(i, text=columns[i], anchor=heading_anchor) if adjust_heading_to_content: self.interior.column(i, width=Font().measure(columns[i])) self.interior.column(i, anchor=cell_anchor) if data is not None: for row in data: self.insert_row(row) @property def row_height(self): return self._rowheight @property def font(self): return self._cell_font def configure_column(self, index, width=None, minwidth=None, anchor=None, stretch=None): kwargs = {} for config_name in ("width", "anchor", "stretch", "minwidth"): config_value = locals()[config_name] if config_value is not None: kwargs[config_name] = config_value self.interior.column('#%s' % (index + 1), **kwargs) def row_data(self, index): try: item_ID = self.interior.get_children()[index] except IndexError: raise ValueError("Row index out of range: %d" % index) return self.item_ID_to_row_data(item_ID) def update_row(self, index, data): try: item_ID = self.interior.get_children()[index] except IndexError: raise ValueError("Row index out of range: %d" % index) if len(data) == len(self._columns): self.interior.item(item_ID, values=data) else: raise ValueError("The multicolumn listbox has only %d columns" % self._number_of_columns) def delete_row(self, index): list_of_items = self.interior.get_children() try: item_ID = list_of_items[index] except IndexError: raise ValueError("Row index out of range: %d" % index) self.interior.delete(item_ID) self._number_of_rows -= 1 if self._stripped_rows: for i in range(index, self._number_of_rows): self.interior.tag_configure(list_of_items[i + 1], background=self._stripped_rows[i % 2]) def insert_row(self, data, index=None): if len(data) != self._number_of_columns: raise ValueError("The multicolumn listbox has only %d columns" % self._number_of_columns) if index is None: index = self._number_of_rows - 1 item_ID = self.interior.insert('', index, values=data) self.interior.item(item_ID, tags=item_ID) self._number_of_rows += 1 if self._stripped_rows: list_of_items = self.interior.get_children() self.interior.tag_configure(item_ID, background=self._stripped_rows[index % 2]) for i in range(index + 1, self._number_of_rows): self.interior.tag_configure(list_of_items[i], background=self._stripped_rows[i % 2]) def column_data(self, index): return [ self.interior.set(child_ID, index) for child_ID in self.interior.get_children('') ] def update_column(self, index, data): for i, item_ID in enumerate(self.interior.get_children()): data_row = self.item_ID_to_row_data(item_ID) data_row[index] = data[i] self.interior.item(item_ID, values=data_row) return data def clear(self): # Another possibility: # self.interior.delete(*self.interior.get_children()) for row in self.interior.get_children(): self.interior.delete(row) self._number_of_rows = 0 def update(self, data): self.clear() for row in data: self.insert_row(row) def focus(self, index=None): if index is None: return self.interior.item(self.interior.focus()) else: item = self.interior.get_children()[index] self.interior.focus(item) def state(self, state=None): if stateSpec is None: return self.interior.state() else: self.interior.state(state) @property def number_of_rows(self): return self._number_of_rows @property def number_of_columns(self): return self._number_of_columns def toogle_selection(self, index): list_of_items = self.interior.get_children() try: item_ID = list_of_items[index] except IndexError: raise ValueError("Row index out of range: %d" % index) self.interior.selection_toggle(item_ID) def select_row(self, index): list_of_items = self.interior.get_children() try: item_ID = list_of_items[index] except IndexError: raise ValueError("Row index out of range: %d" % index) self.interior.selection_add(item_ID) def deselect_row(self, index): list_of_items = self.interior.get_children() try: item_ID = list_of_items[index] except IndexError: raise ValueError("Row index out of range: %d" % index) self.interior.selection_remove(item_ID) def deselect_all(self): self.interior.selection_remove(self.interior.selection()) def set_selection(self, indices): list_of_items = self.interior.get_children() self.interior.selection_set(" ".join(list_of_items[row_index] for row_index in indices)) @property def selected_rows(self): data = [] for item_ID in self.interior.selection(): data_row = self.item_ID_to_row_data(item_ID) data.append(data_row) return data @property def indices_of_selected_rows(self): list_of_indices = [] for index, item_ID in enumerate(self.interior.get_children()): if item_ID in self.interior.selection(): list_of_indices.append(index) return list_of_indices def delete_all_selected_rows(self): selected_items = self.interior.selection() for item_ID in selected_items: self.interior.delete(item_ID) number_of_deleted_rows = len(selected_items) self._number_of_rows -= number_of_deleted_rows return number_of_deleted_rows def _on_select(self, event): for item_ID in event.widget.selection(): data_row = self.item_ID_to_row_data(item_ID) self._command(data_row) def item_ID_to_row_data(self, item_ID): item = self.interior.item(item_ID) return item["values"] @property def table_data(self): data = [] for item_ID in self.interior.get_children(): data_row = self.item_ID_to_row_data(item_ID) data.append(data_row) return data @table_data.setter def table_data(self, data): self.update(data) def cell_data(self, row, column): """Get the value of a table cell""" try: item = self.interior.get_children()[row] except IndexError: raise ValueError("Row index out of range: %d" % row) return self.interior.set(item, column) def update_cell(self, row, column, value): """Set the value of a table cell""" item_ID = self.interior.get_children()[row] data = self.item_ID_to_row_data(item_ID) data[column] = value self.interior.item(item_ID, values=data) def __getitem__(self, index): if isinstance(index, tuple): row, column = index return self.cell_data(row, column) else: raise Exception("Row and column indices are required") def __setitem__(self, index, value): if isinstance(index, tuple): row, column = index self.update_cell(row, column, value) else: raise Exception("Row and column indices are required") def bind(self, event, handler): self.interior.bind(event, handler) def sort_by(self, col, descending): """ sort tree contents when a column header is clicked """ # grab values to sort data = [(self.interior.set(child_ID, col), child_ID) for child_ID in self.interior.get_children('')] # if the Demo_programs to be sorted is numeric change to float try: data = [(float(number), child_ID) for number, child_ID in data] except ValueError: pass # now sort the Demo_programs in place data.sort(reverse=descending) for idx, item in enumerate(data): self.interior.move(item[1], '', idx) # switch the heading so that it will sort in the opposite direction self.interior.heading( col, command=lambda col=col: self.sort_by(col, not descending)) if self._stripped_rows: list_of_items = self.interior.get_children('') for i in range(len(list_of_items)): self.interior.tag_configure(list_of_items[i], background=self._stripped_rows[i % 2]) def destroy(self): self.interior.destroy() def item_ID(self, index): return self.interior.get_children()[index]
class Tree(Treeview): """ Класс, формирующий таблицу """ def __init__(self, root, frame, num, logit, all_values, list_styles_names): Treeview.__init__(self, root) self.root = root self.num = num self.frame = frame self.name = "MOXA-%s" % str(self.num) self.tree = Treeview(frame, style=list_styles_names[num]) self.tree["columns"] = ("one", "two", "three") self.tree.heading("#0", text="") self.tree.column("#0", minwidth=0, width=5, stretch=NO) self.tree.heading("one", text="Port") self.tree.column("one", minwidth=0, width=30, stretch=NO) self.tree.column("two", minwidth=0, width=name_column, stretch=NO) self.tree.heading("three", text="State") self.tree.column("three", minwidth=0, width=state_column, stretch=YES) self.tree['height'] = 32 self.tree.tag_configure('green', background='gray7', foreground='green2') self.tree.tag_configure('red', background='gray7', foreground='tomato2') self.tree.tag_configure('blue', background='gray7', foreground='RoyalBlue') self.tree.tag_configure('yellow', background='gray7', foreground='yellow') self.tree.tag_configure('ready', background='gray7', foreground='white') self.tree.tag_configure( 'focus', background='yellow', ) self.tree.bind("<Motion>", self.mycallback) self.last_focus = None self.tree.pack(side=LEFT) self.logit = logit self.moxa = all_values[self.num][0] self.wraplength = 180 for key in self.moxa.keys(): self.tree.insert("", "end", values=(str(key), self.moxa[key], "<><><>"), tags=("green", )) def mycallback(self, event): """ Функция, отображающая комментарий при наведении мыши на канал """ _iid = self.tree.identify_row(event.y) if _iid != self.last_focus: if self.last_focus: try: if self.tw: self.tw.destroy() except: pass if _iid: row = self.tree.item(_iid) key = row["values"][0] if os.path.isfile('comments/comment_%s_%s.txt' % (self.num, key)): with open('comments/comment_%s_%s.txt' % (self.num, key), 'a+') as comment: file_log = comment.read() param = self.tree.bbox(_iid) x = (param[0] + space_X) * self.num y = param[1] + space_Y self.tw = tk.Toplevel() self.tw.wm_overrideredirect(True) self.tw.wm_geometry("+%d+%d" % (x, y)) label = tk.Label(self.tw, text=file_log, justify='left', background="yellow2", relief='solid', borderwidth=1, wraplength=self.wraplength, font=tkFont.Font(family=main_font, size=size_font)) label.pack() self.last_focus = _iid
class Multicolumn_Listbox(object): _style_index = 0 class List_Of_Rows(object): def __init__(self, multicolumn_listbox): self._multicolumn_listbox = multicolumn_listbox def data(self, index): return self._multicolumn_listbox.row_data(index) def get(self, index): return Row(self._multicolumn_listbox, index) def insert(self, data, index=None): self._multicolumn_listbox.insert_row(data, index) def delete(self, index): self._multicolumn_listbox.delete_row(index) def update(self, index, data): self._multicolumn_listbox.update_row(index, data) def select(self, index): self._multicolumn_listbox.select_row(index) def deselect(self, index): self._multicolumn_listbox.deselect_row(index) def set_selection(self, indices): self._multicolumn_listbox.set_selection(indices) def __getitem__(self, index): return self.get(index) def __setitem__(self, index, value): return self._multicolumn_listbox.update_row(index, value) def __delitem__(self, index): self._multicolumn_listbox.delete_row(index) def __len__(self): return self._multicolumn_listbox.number_of_rows class List_Of_Columns(object): def __init__(self, multicolumn_listbox): self._multicolumn_listbox = multicolumn_listbox def data(self, index): return self._multicolumn_listbox.get_column(index) def get(self, index): return Column(self._multicolumn_listbox, index) def delete(self, index): self._multicolumn_listbox.delete_column(index) def update(self, index, data): self._multicolumn_listbox.update_column(index, data) def __getitem__(self, index): return self.get(index) def __setitem__(self, index, value): return self._multicolumn_listbox.update_column(index, value) def __delitem__(self, index): self._multicolumn_listbox.delete_column(index) def __len__(self): return self._multicolumn_listbox.number_of_columns def __init__(self, master, columns, data=None, command=None, sort=True, select_mode=None, heading_anchor = CENTER, cell_anchor=W, style=None, height=None, padding=None, adjust_heading_to_content=False, stripped_rows=None, selection_background=None, selection_foreground=None, field_background=None, heading_font= None, heading_background=None, heading_foreground=None, cell_pady=2, cell_background=None, cell_foreground=None, cell_font=None, headers=True): self._stripped_rows = stripped_rows self._columns = columns self._number_of_rows = 0 self._number_of_columns = len(columns) self.row = self.List_Of_Rows(self) self.column = self.List_Of_Columns(self) s = Style() if style is None: style_name = "Multicolumn_Listbox%s.Treeview"%self._style_index self._style_index += 1 else: style_name = style style_map = {} if selection_background is not None: style_map["background"] = [('selected', selection_background)] if selection_foreground is not None: style_map["foeground"] = [('selected', selection_foreground)] if style_map: s.map(style_name, **style_map) style_config = {} if cell_background is not None: style_config["background"] = cell_background if cell_foreground is not None: style_config["foreground"] = cell_foreground if cell_font is None: font_name = s.lookup(style_name, "font") cell_font = nametofont(font_name) else: if not isinstance(cell_font, Font): if isinstance(cell_font, basestring): cell_font = nametofont(cell_font) else: if len(font) == 1: cell_font = Font(family=cell_font[0]) elif len(font) == 2: cell_font = Font(family=cell_font[0], size=cell_font[1]) elif len(font) == 3: cell_font = Font(family=cell_font[0], size=cell_font[1], weight=cell_font[2]) else: raise ValueError("Not possible more than 3 values for font") style_config["font"] = cell_font self._cell_font = cell_font self._rowheight = cell_font.metrics("linespace")+cell_pady style_config["rowheight"]=self._rowheight if field_background is not None: style_config["fieldbackground"] = field_background s.configure(style_name, **style_config) heading_style_config = {} if heading_font is not None: heading_style_config["font"] = heading_font if heading_background is not None: heading_style_config["background"] = heading_background if heading_foreground is not None: heading_style_config["foreground"] = heading_foreground heading_style_name = style_name + ".Heading" s.configure(heading_style_name, **heading_style_config) treeview_kwargs = {"style": style_name} if height is not None: treeview_kwargs["height"] = height if padding is not None: treeview_kwargs["padding"] = padding if headers: treeview_kwargs["show"] = "headings" else: treeview_kwargs["show"] = "" if select_mode is not None: treeview_kwargs["selectmode"] = select_mode self.interior = Treeview(master, columns=columns, **treeview_kwargs) if command is not None: self._command = command self.interior.bind("<<TreeviewSelect>>", self._on_select) for i in range(0, self._number_of_columns): if sort: self.interior.heading(i, text=columns[i], anchor=heading_anchor, command=lambda col=i: self.sort_by(col, descending=False)) else: self.interior.heading(i, text=columns[i], anchor=heading_anchor) if adjust_heading_to_content: self.interior.column(i, width=Font().measure(columns[i])) self.interior.column(i, anchor=cell_anchor) if data is not None: for row in data: self.insert_row(row) @property def row_height(self): return self._rowheight @property def font(self): return self._cell_font def configure_column(self, index, width=None, minwidth=None, anchor=None, stretch=None): kwargs = {} for config_name in ("width", "anchor", "stretch", "minwidth"): config_value = locals()[config_name] if config_value is not None: kwargs[config_name] = config_value self.interior.column('#%s'%(index+1), **kwargs) def row_data(self, index): try: item_ID = self.interior.get_children()[index] except IndexError: raise ValueError("Row index out of range: %d"%index) return self.item_ID_to_row_data(item_ID) def update_row(self, index, data): try: item_ID = self.interior.get_children()[index] except IndexError: raise ValueError("Row index out of range: %d"%index) if len(data) == len(self._columns): self.interior.item(item_ID, values=data) else: raise ValueError("The multicolumn listbox has only %d columns"%self._number_of_columns) def delete_row(self, index): list_of_items = self.interior.get_children() try: item_ID = list_of_items[index] except IndexError: raise ValueError("Row index out of range: %d"%index) self.interior.delete(item_ID) self._number_of_rows -= 1 if self._stripped_rows: for i in range(index, self._number_of_rows): self.interior.tag_configure(list_of_items[i+1], background=self._stripped_rows[i%2]) def insert_row(self, data, index=None): if len(data) != self._number_of_columns: raise ValueError("The multicolumn listbox has only %d columns"%self._number_of_columns) if index is None: index = self._number_of_rows-1 item_ID = self.interior.insert('', index, values=data) self.interior.item(item_ID, tags=item_ID) self._number_of_rows += 1 if self._stripped_rows: list_of_items = self.interior.get_children() self.interior.tag_configure(item_ID, background=self._stripped_rows[index%2]) for i in range(index+1, self._number_of_rows): self.interior.tag_configure(list_of_items[i], background=self._stripped_rows[i%2]) def column_data(self, index): return [self.interior.set(child_ID, index) for child_ID in self.interior.get_children('')] def update_column(self, index, data): for i, item_ID in enumerate(self.interior.get_children()): data_row = self.item_ID_to_row_data(item_ID) data_row[index] = data[i] self.interior.item(item_ID, values=data_row) return data def clear(self): # Another possibility: # self.interior.delete(*self.interior.get_children()) for row in self.interior.get_children(): self.interior.delete(row) self._number_of_rows = 0 def update(self, data): self.clear() for row in data: self.insert_row(row) def focus(self, index=None): if index is None: return self.interior.item(self.interior.focus()) else: item = self.interior.get_children()[index] self.interior.focus(item) def state(self, state=None): if stateSpec is None: return self.interior.state() else: self.interior.state(state) @property def number_of_rows(self): return self._number_of_rows @property def number_of_columns(self): return self._number_of_columns def toogle_selection(self, index): list_of_items = self.interior.get_children() try: item_ID = list_of_items[index] except IndexError: raise ValueError("Row index out of range: %d"%index) self.interior.selection_toggle(item_ID) def select_row(self, index): list_of_items = self.interior.get_children() try: item_ID = list_of_items[index] except IndexError: raise ValueError("Row index out of range: %d"%index) self.interior.selection_add(item_ID) def deselect_row(self, index): list_of_items = self.interior.get_children() try: item_ID = list_of_items[index] except IndexError: raise ValueError("Row index out of range: %d"%index) self.interior.selection_remove(item_ID) def deselect_all(self): self.interior.selection_remove(self.interior.selection()) def set_selection(self, indices): list_of_items = self.interior.get_children() self.interior.selection_set(" ".join(list_of_items[row_index] for row_index in indices)) @property def selected_rows(self): data = [] for item_ID in self.interior.selection(): data_row = self.item_ID_to_row_data(item_ID) data.append(data_row) return data @property def indices_of_selected_rows(self): list_of_indices = [] for index, item_ID in enumerate(self.interior.get_children()): if item_ID in self.interior.selection(): list_of_indices.append(index) return list_of_indices def delete_all_selected_rows(self): selected_items = self.interior.selection() for item_ID in selected_items: self.interior.delete(item_ID) number_of_deleted_rows = len(selected_items) self._number_of_rows -= number_of_deleted_rows return number_of_deleted_rows def _on_select(self, event): for item_ID in event.widget.selection(): data_row = self.item_ID_to_row_data(item_ID) self._command(data_row) def item_ID_to_row_data(self, item_ID): item = self.interior.item(item_ID) return item["values"] @property def table_data(self): data = [] for item_ID in self.interior.get_children(): data_row = self.item_ID_to_row_data(item_ID) data.append(data_row) return data @table_data.setter def table_data(self, data): self.update(data) def cell_data(self, row, column): """Get the value of a table cell""" try: item = self.interior.get_children()[row] except IndexError: raise ValueError("Row index out of range: %d"%row) return self.interior.set(item, column) def update_cell(self, row, column, value): """Set the value of a table cell""" item_ID = self.interior.get_children()[row] data = self.item_ID_to_row_data(item_ID) data[column] = value self.interior.item(item_ID, values=data) def __getitem__(self, index): if isinstance(index, tuple): row, column = index return self.cell_data(row, column) else: raise Exception("Row and column indices are required") def __setitem__(self, index, value): if isinstance(index, tuple): row, column = index self.update_cell(row, column, value) else: raise Exception("Row and column indices are required") def bind(self, event, handler): self.interior.bind(event, handler) def sort_by(self, col, descending): """ sort tree contents when a column header is clicked """ # grab values to sort data = [(self.interior.set(child_ID, col), child_ID) for child_ID in self.interior.get_children('')] # if the data to be sorted is numeric change to float try: data = [(float(number), child_ID) for number, child_ID in data] except ValueError: pass # now sort the data in place data.sort(reverse=descending) for idx, item in enumerate(data): self.interior.move(item[1], '', idx) # switch the heading so that it will sort in the opposite direction self.interior.heading(col, command=lambda col=col: self.sort_by(col, not descending)) if self._stripped_rows: list_of_items = self.interior.get_children('') for i in range(len(list_of_items)): self.interior.tag_configure(list_of_items[i], background=self._stripped_rows[i%2]) def destroy(self): self.interior.destroy() def item_ID(self, index): return self.interior.get_children()[index]
class MainWindowUI: # | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | # +-------+-------+-------+-------+-------+-------+-------+-------+-------+-------+-------+-------+ # | menu bar | # +-------+-------+-------+-------+-------+-------+-------+-------+-------+-------+-------+-------+ # | | search bar | # | | search entry | button| # | +-------+-------+-------+-------+-------+-------+-------+-------+-------+-------+ # | | | | # | | | | # | | | | # | treeview | | | # | | text area 1 | text area 2 | # | | | | # | | | | # | | | | # | | | | # +-------+-------+-------+-------+-------+-------+-------+-------+-------+-------+-------+-------+ # | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | # Rows fileTreeRow = filePathLabelsRow = 0 searchTextRow = 1 uniScrollbarRow = lineNumbersRow = textAreasRow = 2 horizontalScrollbarRow = 3 # Columns fileTreeCol = 0 fileTreeScrollbarCol = 1 leftLineNumbersCol = leftFilePathLabelsCol = 2 # should span at least two columns leftTextAreaCol = leftHorizontalScrollbarCol = 3 uniScrollbarCol = 4 rightLineNumbersCol = rightFilePathLabelsCol = 5 # should span at least two columns rightTextAreaCol = rightHorizontalScrollbarCol = 6 # Colors whiteColor = '#ffffff' redColor = '#ffc4c4' darkredColor = '#ff8282' grayColor = '#dddddd' lightGrayColor = '#eeeeee' greenColor = '#c9fcd6' darkgreenColor = '#50c96e' yellowColor = '#f0f58c' darkYellowColor = '#ffff00' purpleLight = '#F5EBFC' def __init__(self, window): self.main_window = window self.main_window.grid_rowconfigure(self.filePathLabelsRow, weight=0) self.main_window.grid_rowconfigure(self.searchTextRow, weight=0) self.main_window.grid_rowconfigure(self.textAreasRow, weight=1) self.main_window.grid_columnconfigure(self.fileTreeCol, weight=0) self.main_window.grid_columnconfigure(self.fileTreeScrollbarCol, weight=0) self.main_window.grid_columnconfigure(self.leftLineNumbersCol, weight=0) self.main_window.grid_columnconfigure(self.leftTextAreaCol, weight=1) self.main_window.grid_columnconfigure(self.uniScrollbarCol, weight=0) self.main_window.grid_columnconfigure(self.rightLineNumbersCol, weight=0) self.main_window.grid_columnconfigure(self.rightTextAreaCol, weight=1) self.menubar = Menu(self.main_window) self.menus = {} self.text_area_font = 'TkFixedFont' # Center window and set its size def center_window(self): sw = self.main_window.winfo_screenwidth() sh = self.main_window.winfo_screenheight() w = 0.7 * sw h = 0.7 * sh x = (sw - w)/2 y = (sh - h)/2 self.main_window.geometry('%dx%d+%d+%d' % (w, h, x, y)) self.main_window.minsize(int(0.3 * sw), int(0.3 * sh)) # Menu bar def add_menu(self, menuName, commandList): self.menus[menuName] = Menu(self.menubar,tearoff=0) for c in commandList: if 'separator' in c: self.menus[menuName].add_separator() else: self.menus[menuName].add_command(label=c['name'], command=c['command'], accelerator=c['accelerator'] if 'accelerator' in c else '') self.menubar.add_cascade(label=menuName, menu=self.menus[menuName]) self.main_window.config(menu=self.menubar) # Labels def create_file_path_labels(self): self.leftFileLabel = Label(self.main_window, anchor='center', width=1000, background=self.lightGrayColor) self.leftFileLabel.grid(row=self.filePathLabelsRow, column=self.leftFilePathLabelsCol, columnspan=2) self.rightFileLabel = Label(self.main_window, anchor='center', width=1000, background=self.lightGrayColor) self.rightFileLabel.grid(row=self.filePathLabelsRow, column=self.rightFilePathLabelsCol, columnspan=2) # Search text entry def create_search_text_entry(self, searchButtonCallback): self.searchTextDialog = SearchTextDialog(self.main_window, [self.leftFileTextArea, self.rightFileTextArea], searchButtonCallback) self.searchTextDialog.grid(row=self.searchTextRow, column=self.leftFilePathLabelsCol, columnspan=5, sticky=EW) self.searchTextDialog.grid_remove() # File treeview def create_file_treeview(self): self.fileTreeView = Treeview(self.main_window) self.fileTreeYScrollbar = Scrollbar(self.main_window, orient='vertical', command=self.fileTreeView.yview) self.fileTreeXScrollbar = Scrollbar(self.main_window, orient='horizontal', command=self.fileTreeView.xview) self.fileTreeView.configure(yscroll=self.fileTreeYScrollbar.set, xscroll=self.fileTreeXScrollbar.set) self.fileTreeView.grid(row=self.fileTreeRow, column=self.fileTreeCol, sticky=NS, rowspan=3) self.fileTreeYScrollbar.grid(row=self.fileTreeRow, column=self.fileTreeScrollbarCol, sticky=NS, rowspan=3) self.fileTreeXScrollbar.grid(row=self.horizontalScrollbarRow, column=self.fileTreeCol, sticky=EW) self.fileTreeView.tag_configure('red', background=self.redColor) self.fileTreeView.tag_configure('green', background=self.greenColor) self.fileTreeView.tag_configure('yellow', background=self.yellowColor) self.fileTreeView.tag_configure('purpleLight', background=self.purpleLight) # hide it until needed self.fileTreeView.grid_remove() self.fileTreeYScrollbar.grid_remove() self.fileTreeXScrollbar.grid_remove() # Text areas def create_text_areas(self): self.leftFileTextArea = Text(self.main_window, padx=5, pady=5, width=1, height=1, bg=self.grayColor) self.leftFileTextArea.grid(row=self.textAreasRow, column=self.leftTextAreaCol, sticky=NSEW) self.leftFileTextArea.config(font=self.text_area_font) self.leftFileTextArea.config(wrap='none') self.rightFileTextArea = Text(self.main_window, padx=5, pady=5, width=1, height=1, bg=self.grayColor) self.rightFileTextArea.grid(row=self.textAreasRow, column=self.rightTextAreaCol, sticky=NSEW) self.rightFileTextArea.config(font=self.text_area_font) self.rightFileTextArea.config(wrap='none') # configuring highlight tags self.leftFileTextArea.tag_configure('red', background=self.redColor) self.leftFileTextArea.tag_configure('darkred', background=self.darkredColor) self.leftFileTextArea.tag_configure('gray', background=self.grayColor) self.leftFileTextArea.tag_configure('search', background=self.darkYellowColor) self.rightFileTextArea.tag_configure('green', background=self.greenColor) self.rightFileTextArea.tag_configure('darkgreen', background=self.darkgreenColor) self.rightFileTextArea.tag_configure('gray', background=self.grayColor) self.rightFileTextArea.tag_configure('search', background=self.darkYellowColor) self.rightFileTextArea.tag_configure('purpleLight', background=self.purpleLight) # disable the text areas self.leftFileTextArea.config(state=DISABLED) self.rightFileTextArea.config(state=DISABLED) # Line numbers def create_line_numbers(self): self.leftLinenumbers = Text(self.main_window, width=3, padx=5, pady=5, height=1, bg=self.lightGrayColor) self.leftLinenumbers.grid(row=self.lineNumbersRow, column=self.leftLineNumbersCol, sticky=NS) self.leftLinenumbers.config(font=self.text_area_font) self.leftLinenumbers.tag_configure('line', justify='right') self.rightLinenumbers = Text(self.main_window, width=3, padx=5, pady=5, height=1, bg=self.lightGrayColor) self.rightLinenumbers.grid(row=self.lineNumbersRow, column=self.rightLineNumbersCol, sticky=NS) self.rightLinenumbers.config(font=self.text_area_font) self.rightLinenumbers.tag_configure('line', justify='right') # disable the line numbers self.leftLinenumbers.config(state=DISABLED) self.rightLinenumbers.config(state=DISABLED) # Scroll bars def scrollBoth(self, action, position, type=None): self.leftFileTextArea.yview_moveto(position) self.rightFileTextArea.yview_moveto(position) self.leftLinenumbers.yview_moveto(position) self.rightLinenumbers.yview_moveto(position) def updateScroll(self, first, last, type=None): self.leftFileTextArea.yview_moveto(first) self.rightFileTextArea.yview_moveto(first) self.leftLinenumbers.yview_moveto(first) self.rightLinenumbers.yview_moveto(first) self.uniScrollbar.set(first, last) def create_scroll_bars(self): self.uniScrollbar = Scrollbar(self.main_window) self.uniScrollbar.grid(row=self.uniScrollbarRow, column=self.uniScrollbarCol, sticky=NS) self.uniScrollbar.config(command=self.scrollBoth) self.leftFileTextArea.config(yscrollcommand=self.updateScroll) self.rightFileTextArea.config(yscrollcommand=self.updateScroll) self.leftLinenumbers.config(yscrollcommand=self.updateScroll) self.rightLinenumbers.config(yscrollcommand=self.updateScroll) leftHorizontalScrollbar = Scrollbar(self.main_window, orient=HORIZONTAL) leftHorizontalScrollbar.grid(row=self.horizontalScrollbarRow, column=self.leftHorizontalScrollbarCol, sticky=EW) leftHorizontalScrollbar.config(command=self.leftFileTextArea.xview) self.leftFileTextArea.config(xscrollcommand=leftHorizontalScrollbar.set) rightHorizontalScrollbar = Scrollbar(self.main_window, orient=HORIZONTAL) rightHorizontalScrollbar.grid(row=self.horizontalScrollbarRow, column=self.rightHorizontalScrollbarCol, sticky=EW) rightHorizontalScrollbar.config(command=self.rightFileTextArea.xview) self.rightFileTextArea.config(xscrollcommand=rightHorizontalScrollbar.set)
class Example(Frame): def __init__(self): Frame.__init__(self) self.style = Style() self.style.theme_use("default") self.master.title("Log viewer") self.pack(fill=BOTH, expand=True) self.used = [] # List of currently plotted series ([str]) self.series = {} # List of all series ({str -> [number]}) self.names = [] # List of all nodes in tree view ([str]) self.queues = [] # List of all queues ([str]) self.logs = {} # List of all text logs ({str -> [str]}) self.rowconfigure(1, weight=1) self.columnconfigure(6, weight=3) self.columnconfigure(11, weight=1) # Series selection takes row 1-2, col 0-2 self.series_ui = Treeview(self) self.series_ui.grid(row=1, column=0, columnspan=2, rowspan=2, sticky=N+S) self.series_ui.configure(show="tree") self.series_ui.bind("<Double-Button-1>", self.onselect) self.series_ui.tag_configure("graphall", foreground="#070") self.series_ui.tag_configure("graphnone", foreground="#000") self.series_ui.tag_configure("graphsome", foreground="#007") series_ui_scroll = Scrollbar(self, command=self.series_ui.yview, orient=VERTICAL) series_ui_scroll.grid(row=1, column=2, rowspan=2, sticky=N+S) self.series_ui["yscrollcommand"] = series_ui_scroll.set # The plot takes row 1-2, col 3-6 move_mode = StringVar() move_mode.set("pan") show_path = IntVar() show_path.set(0) event_bars = IntVar() event_bars.set(1) show_debug = IntVar() show_debug.set(1) show_error = IntVar() show_error.set(1) show_warning = IntVar() show_warning.set(1) show_info = IntVar() show_info.set(1) self.plot = HackPlot(self, move_mode, show_path, event_bars, [(show_debug, "[DEBUG]"), (show_error, "[ERROR]"), (show_warning, "[WARNING]"), (show_info, "[INFO]")]) self.plot.canvas.grid(row=1, column=3, columnspan=4, rowspan=2, sticky=N+S+E+W) # Text logs take row 1-2, col 7-12 self.plot.listbox.grid(row=1, column=7, columnspan=5, sticky=N+S+E+W) listbox_yscroll = Scrollbar(self, command=self.plot.listbox.yview, orient=VERTICAL) listbox_yscroll.grid(row=1, column=12, sticky=N+S) self.plot.listbox["yscrollcommand"] = listbox_yscroll.set listbox_xscroll = Scrollbar(self, command=self.plot.listbox.xview, orient=HORIZONTAL) listbox_xscroll.grid(row=2, column=7, columnspan=5, sticky=E+W) self.plot.listbox["xscrollcommand"] = listbox_xscroll.set # Controls take row 0, col 0-12 Button(self, text="Load Directory", command=self.loaddir).grid(row=0, column=0) Button(self, text="Load File", command=self.loadfile).grid(row=0, column=1) Button(self, text="Fit X", command=self.plot.fit_x).grid(row=0, column=3, sticky=W) Button(self, text="Fit Y", command=self.plot.fit_y).grid(row=0, column=4, sticky=W) Button(self, text="Fit Auto", command=self.plot.fit_auto).grid(row=0, column=5, sticky=W) Button(self, text="Fit Tele", command=self.plot.fit_tele).grid(row=0, column=6, sticky=W) # Plot controls in a subframe to manage padding so it doesn't look awful move_mode_control = Frame(self, padx=10) Radiobutton(move_mode_control, text="Pan", value="pan", variable=move_mode).grid(row=0, column=0, sticky=W) Radiobutton(move_mode_control, text="Zoom In", value="zoomin", variable=move_mode).grid(row=0, column=1, sticky=W) Radiobutton(move_mode_control, text="Zoom Out", value="zoomout", variable=move_mode).grid(row=0, column=2, sticky=W) move_mode_control.grid(row=0, column=7, sticky=W) Checkbutton(self, text="Event Bars", variable=event_bars, command=self.plot.show_textlogs).grid(row=0, column=8, sticky=W) Checkbutton(self, text="Debug", variable=show_debug, command=self.plot.show_textlogs).grid(row=0, column=9, sticky=W) Checkbutton(self, text="Error", variable=show_error, command=self.plot.show_textlogs).grid(row=0, column=10, sticky=W) Checkbutton(self, text="Warning", variable=show_warning, command=self.plot.show_textlogs).grid(row=0, column=11, sticky=W) Checkbutton(self, text="Info", variable=show_info, command=self.plot.show_textlogs).grid(row=0, column=12, sticky=W) Checkbutton(self, text="Directories", variable=show_path, command=self.plot.show_textlogs).grid(row=0, column=13, sticky=E) # Open Directory button clicked def loaddir(self): dirname = tkFileDialog.askdirectory(initialdir=log_dir) if dirname != "" and dirname != (): # Cancel and (x) not pressed # Empty the data self.used = [] self.series = {} self.names = [] self.queues = [] self.logs = {} self.plot.reset() for node in self.series_ui.get_children(): self.series_ui.delete(node) # For every csv file in the directory, checking recursively and alphabetically for subdirname, subsubdirnames, filenames in os.walk(dirname): subsubdirnames.sort() filenames.sort() for filename in filenames: if filename.endswith(".csv") or filename.endswith(".log"): # The name of the directory without the name of the directory selected, # and the name of the file without the extension, separated by "."s # For example if directory selected is /tmp/logs, subdirname is /tmp/logs/beta/666, # and filename is foo.csv, nodeprefix is "beta.666.foo". nodeprefix = ".".join(subdirname[len(dirname)+1:].split("/") + [filename[:-4]]) if nodeprefix.startswith("."): nodeprefix = nodeprefix[1:] # Add the file's data self.readfile(subdirname + "/" + filename, nodeprefix) for name in self.names: # Add name to (name with everything after last dot removed), as the last child, # with text (everything after last dot of name) and tags graphnone and (whether name represents data) self.series_ui.insert(".".join(name.split(".")[0:-1]), "end", name, text=name.split(".")[-1], tags=["graphnone"]) # Open File button clicked def loadfile(self): filename = tkFileDialog.askopenfilename(filetypes=[("CSV Files", "*.csv"), ("Text log file", "*.log")], initialdir=log_dir) if filename != "" and filename != (): # Cancel and (x) not pressed # Empty the data self.used = [] self.series = {} self.names = [] self.queues = [] self.logs = {} self.plot.reset() for node in self.series_ui.get_children(): self.series_ui.delete(node) # Add the file's data self.readfile(filename, "") for name in self.names: # Add name to (name with everything after last dot removed), as the last child, # with text (everything after last dot of name) and tags graphnone and (whether name represents data) self.series_ui.insert(".".join(name.split(".")[0:-1]), "end", name, text=name.split(".")[-1], tags=["graphnone"]) # Add a file's data # nodeprefix is a string to add before every name in the file, represents file's name in the tree def readfile(self, filename, nodeprefix): try: if filename.endswith(".csv"): # For csv files this will always be concatenated with something if nodeprefix != "": nodeprefix += "." csvfile = open(filename, "rb") reader = csv.DictReader(csvfile) series = {} self.queues.append(nodeprefix[:-1]) for name in reader.fieldnames: # Add ancestor_names to names, without creating duplicates self.names = list(OrderedDict.fromkeys(self.names + ancestor_names(nodeprefix + name))) # Create a series for this field series[nodeprefix + name] = [] for row in reader: for name in reader.fieldnames: try: # Add cell to series if it represents a number series[nodeprefix + name].append(float(row[name])) except ValueError: # Not a number, no problem, could be game_specific_string or something pass self.series.update(series) else: self.names.append(nodeprefix) self.logs[nodeprefix] = open(filename, "r").readlines() except IOError: tkMessageBox.showerror(message="Could not open file: " + str(filename)) # Tree element was double clicked def onselect(self, _): series = self.series_ui.focus() # Set it to graph if no children are graphed, and not to graph if all or some are self.setgraphed(series, self.series_ui.tag_has("graphnone", series)) self.checkgraphed(series) # Set a node and its children to be either all or none graphed def setgraphed(self, node, shouldgraph): if shouldgraph: self.series_ui.item(node, tags=["graphall"]) # If the node represents data and it isn't already graphed, graph it if node in self.series and node not in self.used: self.used.append(node) # Timestamp is queue that contains node + ".timestamp" timestamp_name = [queue for queue in self.queues if node.startswith(queue)][0] + ".timestamp" self.plot.add_plot(self.series[timestamp_name], self.series[node], node) if node in self.logs and node not in self.used: self.used.append(node) self.plot.add_textlog(self.logs[node], node) # If nothing else is plotted, fit the plot to this if len(self.used) == 1: self.plot.fit_x() self.plot.fit_y() for child in self.series_ui.get_children(node): self.setgraphed(child, True) else: # Set tags to be (whether node represents data) and graphnone self.series_ui.item(node, tags=["graphnone"]) if node in self.used: self.used.remove(node) if node in self.logs: self.plot.remove_textlog(node) if node in self.series: self.plot.remove_plot(node) for child in self.series_ui.get_children(node): self.setgraphed(child, False) # Update the tags (and color) on a node and its ancestors, should always be called after setgraphed def checkgraphed(self, node): # Top level nodes are children of "" if node == "": return # True unless a child doesn't share this tag or there are no children graphall = True graphnone = True for child in self.series_ui.get_children(node): if not self.series_ui.tag_has("graphall", child): graphall = False if not self.series_ui.tag_has("graphnone", child): graphnone = False graphtag = "" if graphall and graphnone: # There are no children, check the used list instead graphtag = "graphall" if node in self.used else "graphnone" elif graphall: graphtag = "graphall" elif graphnone: graphtag = "graphnone" else: graphtag = "graphsome" # Set tags to be (whether node represents data) and the computed status self.series_ui.item(node, tags=[graphtag]) # Now that the status of this node is known, check the parent self.checkgraphed(self.series_ui.parent(node))
def show(frame, iterator): """Выводит на экран выборку, заданную в iterator""" scrollbar = Scrollbar(frame) tree = Treeview(frame, selectmode='none', padding=3, style='Custom.Treeview', height=REPORT_HEIGHT, yscrollcommand=scrollbar.set) tree.pack(side=LEFT, fill=BOTH, expand=YES) scrollbar.config(command=tree.yview) scrollbar.pack(side=LEFT, fill=Y) tree.tag_configure('1', font=('Verdana', FONT_SIZE_REPORT)) tree.tag_configure('2', font=('Verdana', FONT_SIZE_REPORT), background='#f5f5ff') tree.tag_configure('red1', font=('Verdana', FONT_SIZE_REPORT), foreground='red') tree.tag_configure('red2', font=('Verdana', FONT_SIZE_REPORT), background='#f5f5ff', foreground='red') tree.tag_configure('grey1', font=('Verdana', FONT_SIZE_REPORT), foreground='#dddddd') tree.tag_configure('grey2', font=('Verdana', FONT_SIZE_REPORT), background='#f5f5ff', foreground='#dddddd') Style().configure('Custom.Treeview', rowheight=FONT_SIZE_REPORT*2) columns = ['#' + str(x + 1) for x in range(4)] tree.configure(columns=columns) for q in range(len(header)): tree.heading('#%d' % (q + 1), text=header[q], anchor='w') tree.column('#%d' % (q + 1), width=REPORT_SCALE * col_width[q + 1], anchor='w') tree.heading('#0', text='', anchor='w') tree.column('#0', width=0, anchor='w', minwidth=0) flag = True for item in iterator: if not item.calculation: col = [] col.append(add_s(item.cathegory.name if item.cathegory else u'-Нет-')) col.append(add_s(item.name)) storage = queries.items_in_storage(item) col.append(add_s(storage)) col.append(add_s(item.measure)) if int(storage) > 0: flag = not flag if flag: tree.insert('', 'end', text='', values=col, tag='2') else: tree.insert('', 'end', text='', values=col, tag='1') elif storage == '0': flag = not flag if flag: tree.insert('', 'end', text='', values=col, tag='grey2') else: tree.insert('', 'end', text='', values=col, tag='grey1') else: flag = not flag if flag: tree.insert('', 'end', text='', values=col, tag='red2') else: tree.insert('', 'end', text='', values=col, tag='red1')
class MainWindowUI: # | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | # +-------+-------+-------+-------+-------+-------+-------+-------+-------+-------+-------+-------+ # | menu bar | # +-------+-------+-------+-------+-------+-------+-------+-------+-------+-------+-------+-------+ # | | search bar | # | | search entry | button| # | +-------+-------+-------+-------+-------+-------+-------+-------+-------+-------+ # | | | | # | | | | # | | | | # | treeview | | | # | | text area 1 | text area 2 | # | | | | # | | | | # | | | | # | | | | # +-------+-------+-------+-------+-------+-------+-------+-------+-------+-------+-------+-------+ # | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | # Rows fileTreeRow = filePathLabelsRow = 0 searchTextRow = 1 uniScrollbarRow = lineNumbersRow = textAreasRow = 2 horizontalScrollbarRow = 3 # Columns fileTreeCol = 0 fileTreeScrollbarCol = 1 leftLineNumbersCol = leftFilePathLabelsCol = 2 # should span at least two columns leftTextAreaCol = leftHorizontalScrollbarCol = 3 uniScrollbarCol = 4 rightLineNumbersCol = rightFilePathLabelsCol = 5 # should span at least two columns rightTextAreaCol = rightHorizontalScrollbarCol = 6 # Colors whiteColor = '#ffffff' redColor = '#ffc4c4' darkredColor = '#ff8282' grayColor = '#dddddd' lightGrayColor = '#eeeeee' greenColor = '#c9fcd6' darkgreenColor = '#50c96e' yellowColor = '#f0f58c' darkYellowColor = '#ffff00' def __init__(self, window): self.main_window = window self.main_window.grid_rowconfigure(self.filePathLabelsRow, weight=0) self.main_window.grid_rowconfigure(self.searchTextRow, weight=0) self.main_window.grid_rowconfigure(self.textAreasRow, weight=1) self.main_window.grid_columnconfigure(self.fileTreeCol, weight=0) self.main_window.grid_columnconfigure(self.fileTreeScrollbarCol, weight=0) self.main_window.grid_columnconfigure(self.leftLineNumbersCol, weight=0) self.main_window.grid_columnconfigure(self.leftTextAreaCol, weight=1) self.main_window.grid_columnconfigure(self.uniScrollbarCol, weight=0) self.main_window.grid_columnconfigure(self.rightLineNumbersCol, weight=0) self.main_window.grid_columnconfigure(self.rightTextAreaCol, weight=1) self.menubar = Menu(self.main_window) self.menus = {} self.text_area_font = 'TkFixedFont' # Center window and set its size def center_window(self): sw = self.main_window.winfo_screenwidth() sh = self.main_window.winfo_screenheight() w = 0.7 * sw h = 0.7 * sh x = (sw - w)/2 y = (sh - h)/2 self.main_window.geometry('%dx%d+%d+%d' % (w, h, x, y)) self.main_window.minsize(int(0.3 * sw), int(0.3 * sh)) # Menu bar def add_menu(self, menuName, commandList): self.menus[menuName] = Menu(self.menubar,tearoff=0) for c in commandList: if 'separator' in c: self.menus[menuName].add_separator() else: self.menus[menuName].add_command(label=c['name'], command=c['command'], accelerator=c['accelerator'] if 'accelerator' in c else '') self.menubar.add_cascade(label=menuName, menu=self.menus[menuName]) self.main_window.config(menu=self.menubar) # Labels def create_file_path_labels(self): self.leftFileLabel = Label(self.main_window, anchor='center', width=1000, background=self.lightGrayColor) self.leftFileLabel.grid(row=self.filePathLabelsRow, column=self.leftFilePathLabelsCol, columnspan=2) self.rightFileLabel = Label(self.main_window, anchor='center', width=1000, background=self.lightGrayColor) self.rightFileLabel.grid(row=self.filePathLabelsRow, column=self.rightFilePathLabelsCol, columnspan=2) # Search text entnry def create_search_text_entry(self, searchButtonCallback): self.searchTextDialog = SearchTextDialog(self.main_window, [self.leftFileTextArea, self.rightFileTextArea], searchButtonCallback) self.searchTextDialog.grid(row=self.searchTextRow, column=self.leftFilePathLabelsCol, columnspan=5, sticky=EW) self.searchTextDialog.grid_remove() # File treeview def create_file_treeview(self): self.fileTreeView = Treeview(self.main_window) self.fileTreeYScrollbar = Scrollbar(self.main_window, orient='vertical', command=self.fileTreeView.yview) self.fileTreeXScrollbar = Scrollbar(self.main_window, orient='horizontal', command=self.fileTreeView.xview) self.fileTreeView.configure(yscroll=self.fileTreeYScrollbar.set, xscroll=self.fileTreeXScrollbar.set) self.fileTreeView.grid(row=self.fileTreeRow, column=self.fileTreeCol, sticky=NS, rowspan=3) self.fileTreeYScrollbar.grid(row=self.fileTreeRow, column=self.fileTreeScrollbarCol, sticky=NS, rowspan=3) self.fileTreeXScrollbar.grid(row=self.horizontalScrollbarRow, column=self.fileTreeCol, sticky=EW) self.fileTreeView.tag_configure('red', background=self.redColor) self.fileTreeView.tag_configure('green', background=self.greenColor) self.fileTreeView.tag_configure('yellow', background=self.yellowColor) # hide it until needed self.fileTreeView.grid_remove() self.fileTreeYScrollbar.grid_remove() self.fileTreeXScrollbar.grid_remove() # Text areas def create_text_areas(self): self.leftFileTextArea = Text(self.main_window, padx=5, pady=5, width=1, height=1, bg=self.grayColor) self.leftFileTextArea.grid(row=self.textAreasRow, column=self.leftTextAreaCol, sticky=NSEW) self.leftFileTextArea.config(font=self.text_area_font) self.leftFileTextArea.config(wrap='none') self.rightFileTextArea = Text(self.main_window, padx=5, pady=5, width=1, height=1, bg=self.grayColor) self.rightFileTextArea.grid(row=self.textAreasRow, column=self.rightTextAreaCol, sticky=NSEW) self.rightFileTextArea.config(font=self.text_area_font) self.rightFileTextArea.config(wrap='none') # configuring highlight tags self.leftFileTextArea.tag_configure('red', background=self.redColor) self.leftFileTextArea.tag_configure('darkred', background=self.darkredColor) self.leftFileTextArea.tag_configure('gray', background=self.grayColor) self.leftFileTextArea.tag_configure('search', background=self.darkYellowColor) self.rightFileTextArea.tag_configure('green', background=self.greenColor) self.rightFileTextArea.tag_configure('darkgreen', background=self.darkgreenColor) self.rightFileTextArea.tag_configure('gray', background=self.grayColor) self.rightFileTextArea.tag_configure('search', background=self.darkYellowColor) # disable the text areas self.leftFileTextArea.config(state=DISABLED) self.rightFileTextArea.config(state=DISABLED) # Line numbers def create_line_numbers(self): self.leftLinenumbers = Text(self.main_window, width=3, padx=5, pady=5, height=1, bg=self.lightGrayColor) self.leftLinenumbers.grid(row=self.lineNumbersRow, column=self.leftLineNumbersCol, sticky=NS) self.leftLinenumbers.config(font=self.text_area_font) self.leftLinenumbers.tag_configure('line', justify='right') self.rightLinenumbers = Text(self.main_window, width=3, padx=5, pady=5, height=1, bg=self.lightGrayColor) self.rightLinenumbers.grid(row=self.lineNumbersRow, column=self.rightLineNumbersCol, sticky=NS) self.rightLinenumbers.config(font=self.text_area_font) self.rightLinenumbers.tag_configure('line', justify='right') # disable the line numbers self.leftLinenumbers.config(state=DISABLED) self.rightLinenumbers.config(state=DISABLED) # Scroll bars def scrollBoth(self, action, position, type=None): self.leftFileTextArea.yview_moveto(position) self.rightFileTextArea.yview_moveto(position) self.leftLinenumbers.yview_moveto(position) self.rightLinenumbers.yview_moveto(position) def updateScroll(self, first, last, type=None): self.leftFileTextArea.yview_moveto(first) self.rightFileTextArea.yview_moveto(first) self.leftLinenumbers.yview_moveto(first) self.rightLinenumbers.yview_moveto(first) self.uniScrollbar.set(first, last) def create_scroll_bars(self): self.uniScrollbar = Scrollbar(self.main_window) self.uniScrollbar.grid(row=self.uniScrollbarRow, column=self.uniScrollbarCol, sticky=NS) self.uniScrollbar.config(command=self.scrollBoth) self.leftFileTextArea.config(yscrollcommand=self.updateScroll) self.rightFileTextArea.config(yscrollcommand=self.updateScroll) self.leftLinenumbers.config(yscrollcommand=self.updateScroll) self.rightLinenumbers.config(yscrollcommand=self.updateScroll) leftHorizontalScrollbar = Scrollbar(self.main_window, orient=HORIZONTAL) leftHorizontalScrollbar.grid(row=self.horizontalScrollbarRow, column=self.leftHorizontalScrollbarCol, sticky=EW) leftHorizontalScrollbar.config(command=self.leftFileTextArea.xview) self.leftFileTextArea.config(xscrollcommand=leftHorizontalScrollbar.set) rightHorizontalScrollbar = Scrollbar(self.main_window, orient=HORIZONTAL) rightHorizontalScrollbar.grid(row=self.horizontalScrollbarRow, column=self.rightHorizontalScrollbarCol, sticky=EW) rightHorizontalScrollbar.config(command=self.rightFileTextArea.xview) self.rightFileTextArea.config(xscrollcommand=rightHorizontalScrollbar.set)
class GUIMainMenu(Frame): """Main menu for test of Genesi i.MX53 systems""" def __init__(self,master=None): """Initialize the base class""" Frame.__init__(self,master) """Set window title""" self.master.title("Select System Test") """System Tests""" self.createTestEntries() """Constants""" self.TEST_COL=0 self.STATUS_COL=1 self.TEXT_ROW=0 self.TREEVIEW_ROW=1 self.BUTTON_ROW=2 """Display main window with padding""" self.grid() self.createWidgets() def createTestEntries(self): #TODO must be a better way. Pickle? self.tests = [TestInfo("Audio", AudioGUI), TestInfo("Clock", Dummy1), TestInfo("Display", Dummy1), TestInfo("Keyboard", Dummy1), TestInfo("Network", Dummy1), TestInfo("SSD", Dummy2), TestInfo("Video", VideoGUI)] self.testsLookup = {} for te in self.tests: self.testsLookup.update({te.name : te}) def createWidgets(self): """Create all the initial widgets for this menu""" """Labels""" lbl = Label(self, text="Select test below", justify=LEFT) lbl.grid(row=self.TEXT_ROW, column=self.TEST_COL) """Tests""" self.trv = Treeview(self, columns=("Status"), displaycolumns='#all') for test in self.tests: treeviewInsertTest(self.trv, test) self.trv.column('#0', width=100) self.trv.heading('#0', text="Test") self.trv.heading('Status', text='Status') self.trv.grid(column=self.TEST_COL, row=self.TREEVIEW_ROW, columnspan=2) """Buttons""" self.btnOK = Button(self, text="OK", command=self.launchTest) self.btnOK.grid(row=self.BUTTON_ROW, column=0) self.btnQuit = Button(self, text="Quit", command=self.quit) self.btnQuit.grid(row=self.BUTTON_ROW, column=1) def launchTest(self): # get the item in focus testItem = self.trv.item(self.trv.focus()) if not testItem['text'] == '': testInfo = self.testsLookup[testItem['text']] testInfo.launchTest(self) def processResults(self, testInfo): self.trv.item(testInfo.name, values=(testInfo.status), tags=(testInfo.status)) # update color notifications self.trv.tag_configure('Success', foreground='green') self.trv.tag_configure('Failure', foreground='red') self.deiconify() def withdraw(self): """Helpful function to hide window""" self.master.withdraw() def deiconify(self): """Helpful function to restore window""" self.master.deiconify()