class view: def __init__(self, f): self.bgc = "white" self.form = f self.presenter = present(self) self.place_startpage() ############################################################################## # 1. Start page def init_startpage(self): table_headings = ["Название", "Длина", "Дата создания"] self.route_table = Treeview(self.form, selectmode="browse", \ show='headings', height = 25) self.route_table["columns"] = table_headings self.route_table["displaycolumns"] = table_headings for head in table_headings: self.route_table.heading(head, text=head, anchor=CENTER) colomn_width = 200 self.route_table.column("Название", anchor=CENTER, width=colomn_width) self.route_table.column("Длина", anchor=CENTER, width=colomn_width) self.route_table.column("Дата создания", anchor=CENTER, width=colomn_width) self.about_route_button = Button(self.form, text="Подробно",\ width=15,height=3, command=self.about_route) self.delete_route_button = Button(self.form, text='Удалить',\ width=15,height=3, command=self.delete_route) self.create_route_button = Button(self.form, text='Создать',\ width=15,height=3, command=self.create_route) self.import_route_button = Button(self.form, text='Импорт',\ width=15,height=3, command=self.import_route) self.presenter.fill_routes_table() def about_route(self): self.remove_startpage() self.place_about_route() def delete_route(self): pass def create_route(self): self.remove_startpage() self.place_create_route() def import_route(self): pass def place_startpage(self): self.init_startpage() but_y = 530 self.route_table.place(x=100, y=0) self.about_route_button.place(x=0, y=but_y) self.delete_route_button.place(x=220, y=but_y) self.create_route_button.place(x=430, y=but_y) self.import_route_button.place(x=650, y=but_y) def remove_startpage(self): self.route_table.destroy() self.about_route_button.destroy() self.delete_route_button.destroy() self.create_route_button.destroy() self.import_route_button.destroy() ############################################################################## # 2. About route def init_about_route(self): table_headings = ["№ точки", "Долгота", "Широта", "Высота"] self.point_table = Treeview(self.form, selectmode="browse", \ show='headings', height = 25) self.point_table["columns"] = table_headings self.point_table["displaycolumns"] = table_headings for head in table_headings: self.point_table.heading(head, text=head, anchor=CENTER) colomn_width = 150 self.point_table.column("№ точки", anchor=CENTER, width=colomn_width) self.point_table.column("Долгота", anchor=CENTER, width=colomn_width) self.point_table.column("Широта", anchor=CENTER, width=colomn_width) self.point_table.column("Высота", anchor=CENTER, width=colomn_width) self.edit_point_button = Button(self.form, text="Редактировать",\ width=15,height=3, command=self.edit_point) self.back_from_point_to_start_button = Button(self.form, text='Назад',\ width=15,height=3, command=self.back_from_point_to_start) self.point_edit_entry = Text(self.form, height=1.2, width=16, font='Arial 12') #self.presenter. def edit_point(self): pass def back_from_point_to_start(self): self.remove_about_route() self.place_startpage() def place_about_route(self): self.init_about_route() self.point_table.place(x=100, y=0) self.edit_point_button.place(x=250, y=530) self.back_from_point_to_start_button.place(x=550, y=530) self.point_edit_entry.place(x=70, y=547) def remove_about_route(self): self.point_table.destroy() self.edit_point_button.destroy() self.back_from_point_to_start_button.destroy() self.point_edit_entry.destroy() ############################################################################## # 2. About route def init_create_route(self): table_headings = ["№ точки", "Долгота", "Широта", "Высота"] self.point_table_create = Treeview(self.form, selectmode="browse", \ show='headings', height = 25) self.point_table_create["columns"] = table_headings self.point_table_create["displaycolumns"] = table_headings for head in table_headings: self.point_table_create.heading(head, text=head, anchor=CENTER) colomn_width = 150 self.point_table_create.column("№ точки", anchor=CENTER, width=colomn_width) self.point_table_create.column("Долгота", anchor=CENTER, width=colomn_width) self.point_table_create.column("Широта", anchor=CENTER, width=colomn_width) self.point_table_create.column("Высота", anchor=CENTER, width=colomn_width) self.add_point_button = Button(self.form, text="Добавить",\ width=15,height=3, command=self.add_point) self.save_route_button = Button(self.form, text='Сохранить',\ width=15,height=3, command=self.save_route) self.new_route_name_entry = Text(self.form, height=1.2, width=16, font='Arial 12') self.new_route_name_label = Label(text='Имя маршрута:',\ font = 'Arial 16', bg = self.bgc) self.new_point_entry = Text(self.form, height=1.2, width=16, font='Arial 12') def add_point(self): pass def save_route(self): pass def place_create_route(self): self.init_create_route() self.point_table_create.place(x=100, y=50) self.add_point_button.place(x=200, y=610) self.save_route_button.place(x=450, y=600) self.new_route_name_label.place(x=225, y=0) self.new_route_name_entry.place(x=380, y=4) self.new_point_entry.place(x=200, y=580) ############################################################################## # Interfaces def insert_into_route_table(self, routes): for i in range(len(routes)): self.route_table.insert('', END, values=tuple(routes[i]))
class user: def __init__(self, root, background_color, user_login, cursor): self.r = root self.bgc = background_color self.login = user_login self.cur = cursor self.cur.execute( "select client_id from client where client_login = '******';") tmp = self.cur.fetchall() self.userid = tmp[0][0] self.today_date = '{0:%Y-%m-%d %H:%M:%S} '.format( datetime.datetime.now()) ############################################################################## # 1. START # 1.1 INIT def init_start_widgets(self): self.choose_button = Button(self.r, text="Записаться", width=20, height=7, command=self.choose) self.my_workouts_button = Button(self.r, text="Мои занятия", width=20, height=7, command=self.show_my_workouts) # 1.2 PLACE def place_start(self): self.init_start_widgets() self.choose_button.place(x=200, y=240) self.my_workouts_button.place(x=400, y=240) # 1.3 REMOVE def remove_start(self): self.choose_button.destroy() self.my_workouts_button.destroy() # 1.4 COMMANDS def choose(self): self.remove_start() self.place_choose() def show_my_workouts(self): self.remove_start() self.place_my_worklouts() ############################################################################## ############################################################################## # 2. CHOOSE CLUB AND KIND OF SPORT # 2.1 INIT def init_choose_widgets(self, root): self.choose_label = Label(text='Выберите клуб и вид спорта:',\ font = 'Arial 20', bg = self.bgc) q = get_all_clubs() self.cur.execute(q) tmp = self.cur.fetchall() clubs = [] for i in range(len(tmp)): clubs.append(tmp[i][0]) self.variable_c = StringVar(root) self.variable_c.set(clubs[0]) # default value self.clubs_option_menu = OptionMenu(root, self.variable_c, *clubs) self.clubs_option_menu.config(width=20, height=3, bg=self.bgc, font=16) q = get_all_sports() self.cur.execute(q) tmp = self.cur.fetchall() kind_of_sport = [] for i in range(len(tmp)): kind_of_sport.append(tmp[i][0]) self.variable_k = StringVar(root) self.variable_k.set(kind_of_sport[0]) self.kind_of_sport_option_menu = OptionMenu(root, self.variable_k, *kind_of_sport) self.kind_of_sport_option_menu.config(width=20, height=3, bg=self.bgc, font=16) self.next_in_choose_button = Button(root, text='Далее',width=15,\ height=3,command=self.next_in_choose) self.back_to_start_button = Button(root, text='Назад',width=15,height=3,\ command=self.back_to_start) # 2.2 PLACE def place_choose(self): self.init_choose_widgets(self.r) self.choose_label.place(x=200, y=160) self.clubs_option_menu.place(x=260, y=200) self.kind_of_sport_option_menu.place(x=260, y=300) self.next_in_choose_button.place(x=305, y=400) self.back_to_start_button.place(x=305, y=500) # 2.3 REMOVE def remove_choose(self): self.choose_label.destroy() self.clubs_option_menu.destroy() self.kind_of_sport_option_menu.destroy() self.next_in_choose_button.destroy() self.back_to_start_button.destroy() # 2.3 COMMANDS def next_in_choose(self): club = self.variable_c.get() kind_of_sport = self.variable_k.get() self.remove_choose() self.place_trainlist(club, kind_of_sport) def back_to_start(self): self.remove_choose() self.place_start() ############################################################################## ############################################################################## # 3. TRAINLIST # 3.1 INIT def init_trainlist_widgets(self, root, club, sport): headings = ["вид спорта", "тренер", "рейтинг","тип", "места", "дата",\ "длительность"] self.trains_table = Treeview(root, selectmode="browse", show='headings', height=25) self.trains_table["columns"] = headings self.trains_table["displaycolumns"] = headings for head in headings: self.trains_table.heading(head, text=head, anchor=CENTER) self.trains_table.column("вид спорта", anchor=CENTER, width=180) self.trains_table.column("тренер", anchor=CENTER, width=180) self.trains_table.column("рейтинг", anchor=CENTER, width=70) self.trains_table.column("тип", anchor=CENTER, width=40) self.trains_table.column("места", anchor=CENTER, width=60) self.trains_table.column("дата", anchor=CENTER, width=145) self.trains_table.column("длительность", anchor=CENTER, width=120) q = get_actual_workouts(self.userid, self.today_date, club, sport) self.cur.execute(q) tmp = self.cur.fetchall() self.w_ids = [] for train in tmp: train = list(train) poped = train.pop(len(train) - 1) self.w_ids.append(poped) self.trains_table.insert('', END, values=tuple(train)) self.choose_train_button = Button(root, text="Выбрать", width=15, height=3, command=self.choose_train) self.back_to_choose_button = Button(root, text='Назад',width=15,height=3,\ command=self.back_to_choose) # 3.2 PLACE def place_trainlist(self, club, kind_of_sport): self.init_trainlist_widgets(self.r, club, kind_of_sport) self.trains_table.place(x=0, y=0) self.choose_train_button.place(x=320, y=530) self.back_to_choose_button.place(x=0, y=530) # 3.3 REMOVE def remove_trainlist(self): self.trains_table.destroy() self.choose_train_button.destroy() self.back_to_choose_button.destroy() # 3.4 COMMANDS def choose_train(self): indd = self.trains_table.focus() if indd == "": messagebox.showinfo("", "Выберите тренировку") else: ind = int(convert_base(indd[1:], to_base=10, from_base=16)) - 1 curr_workout_id = self.w_ids[ind] q = generate_insert_into_client_workout(self.userid, curr_workout_id) self.cur.execute(q) q = generate_update_for_places_count(curr_workout_id) self.cur.execute(q) self.remove_trainlist() self.place_start() messagebox.showinfo("", "Подтверждено") def back_to_choose(self): self.remove_trainlist() self.place_choose() ############################################################################## ############################################################################## # 4. MY_WORKOUTS # 4.1 INIT def init_my_workouts_widgets(self, root): self.my_workouts_label = Label(text='Мои занятия:',\ font = 'Arial 20', bg = self.bgc) self.past_workouts_button = Button(root,text="Прошедшие",width=17,height=10,\ command=self.show_past) self.future_workouts_button = Button(root,text="Предстоящие",width=17,height=10,\ command=self.show_future) self.back_to_start_button2 = Button(root, text='Назад',width=17,height=3,\ command=self.back_to_start2) # 4.2 PLACE def place_my_worklouts(self): self.init_my_workouts_widgets(self.r) self.my_workouts_label.place(x=315, y=80) self.past_workouts_button.place(x=315, y=120) self.future_workouts_button.place(x=315, y=300) self.back_to_start_button2.place(x=315, y=500) # 4.3 REMOVE def remove_my_workouts(self): self.my_workouts_label.destroy() self.past_workouts_button.destroy() self.future_workouts_button.destroy() self.back_to_start_button2.destroy() # 4.4 COMMANDS def show_past(self): self.remove_my_workouts() self.place_past_workouts() def show_future(self): self.remove_my_workouts() self.place_future_workouts() def back_to_start2(self): self.remove_my_workouts() self.place_start() ############################################################################## ############################################################################## # 5. PAST WORKOUTS # 5.1 INIT def init_past_workouts_widgets(self, root): self.past_workouts_table = Treeview(root, selectmode="browse", show='headings', height=25) headings = [ "клуб", "вид спорта", "тренер", "дата", "длительность", "ваша оценка" ] self.past_workouts_table["columns"] = headings self.past_workouts_table["displaycolumns"] = headings for head in headings: self.past_workouts_table.heading(head, text=head, anchor=CENTER) self.past_workouts_table.column("клуб", anchor=CENTER, width=115) self.past_workouts_table.column("вид спорта", anchor=CENTER, width=155) self.past_workouts_table.column("тренер", anchor=CENTER, width=165) self.past_workouts_table.column("дата", anchor=CENTER, width=135) self.past_workouts_table.column("длительность", anchor=CENTER, width=110) self.past_workouts_table.column("ваша оценка", anchor=CENTER, width=125) q = get_user_past_workouts(self.userid, self.today_date) self.cur.execute(q) tmp = self.cur.fetchall() self.w_ids_for_rating = [] for train in tmp: train = list(train) poped = train.pop(len(train) - 1) self.w_ids_for_rating.append(poped) self.past_workouts_table.insert('', END, values=tuple(train)) self.set_rating_button = Button(root,text="Поставить оценку",width=15,height=1, \ command=self.set_rating) self.back_to_my_workouts_button = Button(root, text='Назад',width=15,height=3,\ command=self.back_to_my_workouts) self.rating_entry = Text(root, height=1.2, width=16, font='Arial 12') # 5.2 PLACE def place_past_workouts(self): self.init_past_workouts_widgets(self.r) self.past_workouts_table.place(x=0, y=0) self.set_rating_button.place(x=320, y=530) self.back_to_my_workouts_button.place(x=0, y=530) self.rating_entry.place(x=320, y=560) # 5.3 REMOVE def remove_past_workouts(self): self.past_workouts_table.destroy() self.set_rating_button.destroy() self.back_to_my_workouts_button.destroy() self.rating_entry.destroy() # 5.4 COMMANDS def set_rating(self): indd = self.past_workouts_table.focus() if indd == "": messagebox.showinfo("", "Выберите тренировку") else: ind = int(convert_base(indd[1:], to_base=10, from_base=16)) - 1 curr_workout_id = self.w_ids_for_rating[ind] q = get_current_workout_rating(self.userid, curr_workout_id) self.cur.execute(q) tmp = self.cur.fetchall() current_train_rating = tmp[0][0] if current_train_rating == " ": input_rating = self.rating_entry.get('1.0', 'end-1c') if input_rating.replace(".", "", 1).isdigit() == False: messagebox.showinfo("", "Оценка введена некоректно") elif float(input_rating) < 0 or float(input_rating) > 5: messagebox.showinfo( "", "Оценка ставиться по пятибальной шкале") else: input_rating = round(float(input_rating), 2) q = update_rating(self.userid, curr_workout_id, input_rating) self.cur.execute(q) q = get_current_coach_id_rating(curr_workout_id) self.cur.execute(q) tmp = self.cur.fetchall() tmp_coach_id = int(tmp[0][0]) tmp_coach_rating = tmp[0][1] tmp_coach_marked_w_count = tmp[0][2] new_rating = (tmp_coach_rating * tmp_coach_marked_w_count + input_rating) / (tmp_coach_marked_w_count + 1) q = update_coach_rating(tmp_coach_id, new_rating) self.cur.execute(q) self.remove_past_workouts() self.place_past_workouts() else: messagebox.showinfo( "", "Оценка уже выставлена. В соответствии с нашими правилами оценка выставляется один раз и не подлежит изменению" ) def back_to_my_workouts(self): self.remove_past_workouts() self.place_my_worklouts() ############################################################################## ############################################################################## # 6. FUTURE WORKOUTS # 6.1 INIT def init_future_workouts_widgets(self, root): self.future_workouts_table = Treeview(root, selectmode="browse", show='headings', height=25) headings = [ "клуб", "вид спорта", "тренер", "дата", "длительность", "рейтинг" ] self.future_workouts_table["columns"] = headings self.future_workouts_table["displaycolumns"] = headings for head in headings: self.future_workouts_table.heading(head, text=head, anchor=CENTER) self.future_workouts_table.column("клуб", anchor=CENTER, width=115) self.future_workouts_table.column("вид спорта", anchor=CENTER, width=155) self.future_workouts_table.column("тренер", anchor=CENTER, width=165) self.future_workouts_table.column("дата", anchor=CENTER, width=150) self.future_workouts_table.column("длительность", anchor=CENTER, width=110) self.future_workouts_table.column("рейтинг", anchor=CENTER, width=110) q = get_user_future_workouts(self.userid, self.today_date) self.cur.execute(q) tmp = self.cur.fetchall() self.w_ids_for_remove_workout = [] for train in tmp: train = list(train) poped = train.pop(len(train) - 1) self.w_ids_for_remove_workout.append(poped) self.future_workouts_table.insert('', END, values=tuple(train)) self.remove_workout_button = Button(root, text="Отменить тренировку", width=15, height=3, command=self.remove_workout) self.back_to_my_workouts_button2 = Button(root, text='Назад',width=15,height=3,\ command=self.back_to_my_workouts2) # 6.2 PLACE def place_future_workouts(self): self.init_future_workouts_widgets(self.r) self.future_workouts_table.place(x=0, y=0) self.remove_workout_button.place(x=300, y=530) self.back_to_my_workouts_button2.place(x=0, y=530) # 6.3 REMOVE def remove_future_workouts(self): self.future_workouts_table.destroy() self.remove_workout_button.destroy() self.back_to_my_workouts_button2.destroy() # 6.4 COMMANDS def remove_workout(self): indd = self.future_workouts_table.focus() if indd == "": messagebox.showinfo("", "Выберите тренировку") else: ind = int(convert_base(indd[1:], to_base=10, from_base=16)) - 1 curr_workout_id = self.w_ids_for_remove_workout[ind] q = delete_cancel_workout(self.userid, curr_workout_id) self.cur.execute(q) q = update_places(curr_workout_id) self.cur.execute(q) self.remove_future_workouts() self.place_future_workouts() def back_to_my_workouts2(self): self.remove_future_workouts() self.place_my_worklouts()
class SearchFrame(Frame): def __init__(self, parent, controller): Frame.__init__(self, parent) self.analyzer = analysis.Analyzer() self.controller = controller # set the controller self.title = "Article Search" # ttile of the window #title path = 'cyspider.jpg' self.img = ImageTk.PhotoImage(Image.open(path)) self.panel = Label(self, image=self.img) self.panel.pack() self.searchwindow() #search window populates the window with widgets for searching def searchwindow(self): #keyword entry self.largefont = ('Veranda', 24) self.ent_keyword = Entry(self, width=40, relief='raised', font=self.largefont, bd=1) #todo <Return> and entry is not empty call search() self.ent_keyword.bind('<Escape>', self.clear_text) self.ent_keyword.bind( '<Key>', lambda event: self.callEnable(event, 'DefaultSearch')) self.var = IntVar() self.var.set(0) self.check_filter = Checkbutton(self, text="Advanced Filter", variable=self.var, onvalue=1, offvalue=0, command=self.filter_op, font="Veranda 16") if self.var.get() is 0: self.but_search = Button( self, text='Search', width=15, state='disable', font="Veranda 16", command=lambda: self.search( 'http://cbrown686-test.apigee.net/cyberapi/articles?q=keywordtitlebody&title=' + self.ent_keyword.get() + '&body=' + self.ent_keyword.get( ))) self.but_search.place(relx=.505, rely=.6, anchor=W) else: self.searchButton() #window placements #ENTRY BOX for keyword self.ent_keyword.place(relx=.5, rely=.5, anchor=CENTER) #check button self.check_filter.place(relx=.495, rely=.6, relheight=.059, anchor=E) #todo if the user selects to load a search it will simply jump to results def searchButton(self, event): if self.box.current() is 0: self.but_search = Button( self, text='Search', width=15, state='disable', command=lambda: self.search( 'http://cbrown686-test.apigee.net/cyberapi/articles?q=keywordtitlebody&title=' + self.ent_keyword.get() + '&body=' + self.ent_keyword.get( ))) self.but_search.place(relx=.505, rely=.6, anchor=W) self.enableSearch2() elif self.box.current() is 1: self.but_search = Button( self, text='Search', width=15, state='disable', command=lambda: self.search( 'http://cbrown686-test.apigee.net/cyberapi/articles?q=keywordtitle&title=' + self.ent_keyword.get())) self.but_search.place(relx=.505, rely=.6, anchor=W) self.enableSearch2() elif self.box.current() is 2: self.but_search = Button( self, text='Search', width=15, state='disable', command=lambda: self.search( 'http://cbrown686-test.apigee.net/cyberapi/articles?q=bodyonly&body=' + self.ent_keyword.get())) self.but_search.place(relx=.505, rely=.6, anchor=W) self.enableSearch2() elif self.box.current() is 3: self.but_search = Button( self, text='Search', width=15, state='disable', command=lambda: self.search( 'http://cbrown686-test.apigee.net/cyberapi/articles?q=uri&uripath=' + self.ent_keyword.get())) self.but_search.place(relx=.505, rely=.6, anchor=W) self.enableSearch2() #Hitting escape when editing the ENTRY box will clear it and disable the search button from being able to be used. def clear_text(self, event): self.ent_keyword.delete(0, 'end') self.but_search.configure(state='disable') #filter options populate uppon check box of Advanced search option def filter_op(self): if self.var.get() == 1: #appearing self.appearing_label = Label(self, text='Appearing In:', background='#282828', font=15, foreground='#5DE0DC') self.box_value = StringVar() self.box = Combobox(self, textvariable=self.box_value) self.box['values'] = ('Default', 'Title', 'Body', 'URL') self.box.current(0) self.box.bind('<<ComboboxSelected>>', self.searchButton) #author self.author_label = Label(self, text='Author:', background='#282828', font=15, foreground='#5DE0DC') self.author_entry = Entry(self, width=22, bd=2, background='#9A9A9A') #subjectivity self.fsub_label = Label(self, text='Subjectivity:', background='#282828', font=15, foreground='#5DE0DC') self.var2 = IntVar() self.var2.set(1) self.fsub_nv = Radiobutton(self, text="Don't Care", variable=self.var2, value=1, background='#282828', foreground='#5DE0DC') self.fsub_gt = Radiobutton(self, text='More Subjective', variable=self.var2, value=2, background='#282828', foreground='#5DE0DC') self.fsub_lt = Radiobutton(self, text='More Objective', variable=self.var2, value=3, background='#282828', foreground='#5DE0DC') #date self.fD_label = Label(self, text='Date:', background='#282828', font=15, foreground='#5DE0DC') self.fD_format = Label(self, text='00/00/0000', background='#282828', foreground='#BBBBBB') self.fD_format.configure(foreground='grey') self.fD_beinlab = Label(self, text='From:', background='#282828', foreground='#BBBBBB') self.fD_endlab = Label(self, text='To:', background='#282828', foreground='#BBBBBB') self.fD_ent = Entry(self, width=10, bd=2, background='#9A9A9A') self.fD_ent.insert('end', '01/01/0001') self.fD_ent2 = Entry(self, width=10, bd=2, background='#9A9A9A') self.fD_ent2.insert('end', strftime('%m/%d/%Y')) # window placements #appearing labael offset = 100 self.appearing_label.place(x=400, y=380 + offset) #appearing pick self.box.place(x=510, y=380 + offset) #author label self.author_label.place(x=400, y=405 + offset) #author entry self.author_entry.place(x=510, y=405 + offset) #subjectivity self.fsub_label.place(x=400, y=430 + offset) self.fsub_nv.place(x=510, y=430 + offset) self.fsub_gt.place(x=510, y=455 + offset) self.fsub_lt.place(x=510, y=480 + offset) #date self.fD_label.place(x=400, y=505 + offset) self.fD_format.place(x=440, y=507 + offset) self.fD_beinlab.place(x=510, y=505 + offset) self.fD_ent.place(x=555, y=505 + offset) self.fD_endlab.place(x=590, y=505 + offset) self.fD_ent2.place(x=625, y=505 + offset) # if the button gets unchecked it will destroy the labels and entry widgets. elif self.var.get() == 0: self.appearing_label.destroy() self.box.destroy() self.author_label.destroy() self.author_entry.destroy() self.fsub_label.destroy() self.fsub_nv.destroy() self.fsub_gt.destroy() self.fsub_lt.destroy() self.fD_label.destroy() self.fD_format.destroy() self.fD_ent.destroy() self.fD_beinlab.destroy() self.fD_endlab.destroy() self.fD_ent2.destroy() # does just that clears some shit bra def clearshit(self): # check to see if the lables and entry boxes exist from a previous search options # if they do then destroy them then create the new search label and entry box self.ent_keyword.destroy() self.check_filter.destroy() self.but_search.destroy() if hasattr(self, 'appearing_label'): self.ent_keyword.destroy() self.check_filter.destroy() self.but_search.destroy() self.appearing_label.destroy() self.box.destroy() self.author_label.destroy() self.author_entry.destroy() self.fsub_label.destroy() self.fsub_nv.destroy() self.fsub_gt.destroy() self.fsub_lt.destroy() self.fD_label.destroy() self.fD_format.destroy() self.fD_ent.destroy() self.fD_beinlab.destroy() self.fD_endlab.destroy() self.fD_ent2.destroy() #undoes the hide of the seach buttons so that they can edit the search def undohide(self): self.ent_keyword.place(relx=.5, rely=.5, anchor=CENTER) self.check_filter.place(relx=.495, rely=.6, relheight=.059, anchor=E) self.but_search.place(relx=.505, rely=.6, anchor=W) offset = 100 if self.var.get() == 1: # window placements # appearing labael self.appearing_label.place(x=400, y=380 + offset) # appearing pick self.box.place(x=510, y=380 + offset) # author label self.author_label.place(x=400, y=405 + offset) # author entry self.author_entry.place(x=510, y=405 + offset) # subjectivity self.fsub_label.place(x=400, y=430 + offset) self.fsub_nv.place(x=510, y=430 + offset) self.fsub_gt.place(x=510, y=455 + offset) self.fsub_lt.place(x=510, y=480 + offset) # date self.fD_label.place(x=400, y=505 + offset) self.fD_format.place(x=440, y=507 + offset) self.fD_beinlab.place(x=510, y=505 + offset) self.fD_ent.place(x=555, y=505 + offset) self.fD_endlab.place(x=590, y=505 + offset) self.fD_ent2.place(x=625, y=505 + offset) #hides the widgets to display the search results def hideshit(self): self.ent_keyword.place_forget() self.check_filter.place_forget() self.but_search.place_forget() if self.var.get() == 1: # self.ent_keyword.place(x=(-100), y=(-100)) # self.check_filter.place(x=(-100), y=(-100)) # self.but_search.place(x=(-100), y=(-100)) self.appearing_label.place(x=(-100), y=(-100)) self.box.place(x=(-100), y=(-100)) self.author_label.place(x=(-100), y=(-100)) self.author_entry.place(x=(-100), y=(-100)) self.fsub_label.place(x=(-100), y=(-100)) self.fsub_nv.place(x=(-100), y=(-100)) self.fsub_gt.place(x=(-100), y=(-100)) self.fsub_lt.place(x=(-100), y=(-100)) self.fD_label.place(x=(-100), y=(-100)) self.fD_format.place(x=(-100), y=(-100)) self.fD_ent.place(x=(-100), y=(-100)) self.fD_beinlab.place(x=(-100), y=(-100)) self.fD_endlab.place(x=(-100), y=(-100)) self.fD_ent2.place(x=(-100), y=(-100)) #search for that almighty data mine. def search(self, url): print(url) if self.var.get(): au = self.author_entry.get() au = au.replace(' ', '+') # var2 is the state of the radio check button if self.var2.get() == 2: url = url + '&author=' + au + '&sub=gt&sdate=' + self.fD_ent.get( ) + '&edate=' + self.fD_ent2.get() # print(url) elif self.var2.get() == 3: url = url + '&author=' + au + '&sub=gt&sdate=' + self.fD_ent.get( ) + '&edate=' + self.fD_ent2.get() else: url = url + '&author=' + au + '&sub=&sdate=' + self.fD_ent.get( ) + '&edate=' + self.fD_ent2.get() else: url = url + '&author=&sub=&sdate=01/01/0001&edate=' + strftime( '%m/%d/%Y') print(url) self.data = requests.get(url).json() #print(data) self.hideshit() style = Style(self) style.configure("Treeview", rowheight=30) self.tree = Treeview(self) self.tree.heading('#0', text='Results by Title') self.tree.column('#0', stretch=True) self.tree.place(relx=.3, relheight=1, relwidth=.7) # sunken box that topics print out into self.style = Style() self.style.configure('My.TFrame', background='#383838') # frame for individual analysis self.sf = Frame(self, width=550, height=150, style='My.TFrame') self.sf['relief'] = 'sunken' self.sf.place(relx=0, rely=.055, relwidth=.3, relheight=.4) # labels for article topics self.topicsHead = Label(self, text='Key Article Subjects', font="times 16 underline", background='#282828', foreground='#5DE0DC') self.topics = Label(self, text='Click on an article to see more info', wraplength=500, font='times 14', background='#383838', foreground='#5DE0DC', anchor=W, justify=LEFT) self.topicsHead.place(relx=.01, rely=.01, relwidth=.28) self.topics.place(relx=.01, rely=.065, relwidth=.28) # frame for results analysis self.sf2 = Frame(self, width=550, height=150, style='My.TFrame') self.sf2['relief'] = 'sunken' self.sf2.place(relx=0, rely=.51, relwidth=.3, relheight=.4) self.resultTopicHead = Label(self, text='Most Mentioned Phrases in Results', font="times 16 underline", background='#282828', foreground='#5DE0DC') self.resultTopics = Label(self, text='', wraplength=500, font='times 14', background='#383838', foreground='#5DE0DC', anchor=W, justify=LEFT) self.resultTopicHead.place(relx=.01, rely=.465, relwidth=.28) self.resultTopics.place(relx=.01, rely=.52, relwidth=.28) # New Search Edit Search Save Search self.new_search = Button(self, text='New Search', background='#383838', foreground='#5DE0DC', command=self.NewSearch) self.edit_search = Button(self, text='Edit Search', background='#383838', foreground='#5DE0DC', command=self.EditSearch) self.save_search = Button(self, text='Save Search', background='#383838', foreground='#5DE0DC', command=self.saveMenu) if self.data: for item in self.data: # remove BOM images first from body >uffff item['body'] = ''.join( c for c in unicodedata.normalize('NFC', item['body']) if c <= '\uFFFF') self.tree.insert( '', 'end', text=item['title'], values=(item['uri'], item['body'], item['title'], item['author'], parser.parse(item['date']).strftime('%B, %d, %Y')), tag='data') self.tree.tag_configure('data', font='Verdana 14') self.tree.bind('<Double-1>', self.on_click) self.tree.bind('<<TreeviewSelect>>', self.on_single_click) results = '\n\n'.join([ '\n'.join( textwrap.wrap('*({}): '.format(phrase[1]) + str(phrase[0]), width=33)) for phrase in self.master.master.analyzer.getMostCommonNounPhrases( 5, [item['body'] for item in self.data]) ]) self.resultTopics.config(text=results) self.new_search.place(x=1, y=675) self.edit_search.place(x=75, y=675) self.save_search.place(x=145, y=675) else: self.edit_search = Button(self, text='Edit Search', background='#383838', foreground='#5DE0DC', command=self.EditSearch) self.edit_search.place(x=1, y=675) self.topics.config(text='No Articles Matching Search') self.resultTopics.config(text='') # on_click "double clicking on the article from the tree window opens up the article to be viewed" def NewSearch(self): self.deletesearch() self.searchwindow() def EditSearch(self): self.deletesearch() self.undohide() def saveMenu(self): # create main directory and subdir(current date) if not made already path = os.getcwd() + "/Sessions/" + str(datetime.date.today()) if not os.path.exists(path): os.makedirs(path) # get a filename from the user or default to current time currentTime = datetime.datetime.now().strftime("%H_%M_%S") filename = filedialog.asksaveasfilename(defaultextension="txt", initialdir=path, initialfile=currentTime) if filename: self.saveFilename = filename with open(filename, 'w') as outfile: json.dump(self.data, outfile) # with open(filename, 'w') as f: # f.write("Testing Save As/No Current Save") #defind clear search def deletesearch(self): self.tree.destroy() self.sf.destroy() self.topicsHead.destroy() self.topics.destroy() self.sf2.destroy() self.resultTopicHead.destroy() self.resultTopics.destroy() self.new_search.destroy() self.edit_search.destroy() self.save_search.destroy() #on click gets the articles information and displays it in the Key Article Subjects window def on_single_click(self, event): self.topicsHead.config(text="Key Article Subjects") item = self.tree.item(self.tree.selection()[0], 'values') topicStr = '\n\n'.join([ '\n'.join(textwrap.wrap('*' + phrase[0], width=33)) for phrase in self.master.master.analyzer.getMostCommonNounPhrases( 5, [item[1]]) ]) self.topics.config(text=topicStr) #on d click will open the article for display def on_click(self, event): item = self.tree.selection()[0] self.n = self.tree.item(item, 'values') tw = Toplevel(self) xoffset = int(self.winfo_screenwidth() / 2 - 1280 / 2) yoffset = int(self.winfo_screenheight() / 2 - 800 / 2) tw.geometry("%dx%d+%d+%d" % (800, 600, xoffset, yoffset)) # set geometry of window tw.title(self.n[2]) tb = Text(tw, width=90, height=40, font="Times 14", wrap=WORD) tb.insert('end', self.n[1]) link = Label(tw, text=self.n[0]) link.configure(foreground='blue', cursor='hand2') link.bind('<1>', self.op_link) auth = Label(tw, text='Author: ' + self.n[3]) articledate = Label(tw, text='Date Published: ' + self.n[4]) # window formatting for tw link.place(x=0, y=0, relwidth=1) tb.place(y=20, relwidth=1, relheight=1) auth.pack(side=LEFT, anchor='sw') articledate.pack(side=RIGHT, anchor='se') # op_link "double click on the link at the top of the page opens up the url link def op_link(self, event): webbrowser.open_new(self.n[0]) def callEnable(self, event, searchType): self.after(100, lambda: self.enableSearch(event, searchType)) # event bind when Return is entered after a title keyword is entered will enable the search button. def enableSearch(self, event, searchType): string = '' if searchType == 'DefaultSearch': string = self.ent_keyword.get() if string.strip() != '': self.but_search.configure(state='normal') else: self.but_search.configure(state='disabled') # check for when no event bind is present to be used to pass in and no need for searchType def enableSearch2(self): string = self.ent_keyword.get() if string.strip() != '': self.but_search.configure(state='normal') else: self.but_search.configure(state='disabled')
class Multicolumn_Listbox(Frame): _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 state 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 CheckDownload(): """ 检测需要下载的URL是否存在于数据库,展示面板 """ def __init__(self, master, transaction, tuple_result, ori_args ): self.master = master self.tuple_result = tuple_result #已经分好类的URL元组 self.oriurl = ori_args[0] self.orilable = ori_args[1] self.transaction = transaction self.frame2 = Frame(self.master,width=10, height=2) # self.frame2.pack() self.frame2.grid(row=0, column=0) label = Label(self.frame2, text="数据库中已经存在的数据",width = 30,height = 3) label.grid(row=1, column=1) self.tree_date = Treeview(self.master, columns=['URL', 'Lable', 'Time'], show='headings', height=23) # self.tree_date.pack() self.tree_date.grid(row=2) # 设置列宽度 self.tree_date.column('URL', width=600, anchor='center') self.tree_date.column('Lable', width=350, anchor='center') self.tree_date.column('Time', width=250, anchor='center') # 添加列名 self.tree_date.heading('URL', text='URL') self.tree_date.heading('Lable', text='标签') self.tree_date.heading('Time', text='上次下载时间') # 绑定事件 self.tree_date.bind('<Double-3>', self.deleteItem) self.frame3 = Frame(self.master) btn_yes = tk.Button(self.frame3, text='所列URL重新下载', command=self.downloadNewData) btn_no = tk.Button(self.frame3, text='使用数据库数据', command=self.usingOldData) self.frame3.grid(row=3) btn_no.grid(row=3, column=1) btn_yes.grid(row=3, column=2) # 将存在于数据库中的URL数据展示出来 for key, value in self.tuple_result[1].items(): self.tree_date.insert('', 1, values=(key, self.orilable[self.oriurl.index(key)], value['creattime_'])) def deleteItem(self, event): # 右键双击删除 for item in self.tree_date.selection(): self.tree_date.delete(item) def downloadNewData(self): kids = self.tree_date.get_children() urllists = [] lablelist = [] for item in kids: # 对输入的值进行去重 url_ = self.tree_date.item(item, "values")[0] lable_ = self.tree_date.item(item, "values")[1] if url_ not in urllists: urllists.append(url_) lablelist.append(lable_) url_download = urllists + list(self.tuple_result[0].keys()) # 此时urllists意味着需要新下载的数据,数据库中的旧数据需要即刻清除 # p = Process(target=self.transaction.downloadDatas, args=(downloadqueue, self.oriurl, self.orilable, url_download, urllists)) # p.start() p = threading.Thread(target=self.transaction.downloadDatas, args=(downloadqueue, self.oriurl, self.orilable, url_download, urllists)) p.start() self.workSurfaceUI([self.oriurl, self.orilable]) def usingOldData(self): kids = self.tree_date.get_children() urllists = [] for item in kids: # 对输入的值进行去重 url_ = self.tree_date.item(item, "values")[0] if url_ not in urllists: urllists.append(url_) # print("self.transaction.urllists:") # print(self.transaction.urllists) # print("urllists:") # print(urllists) download_urls = list(set(self.transaction.urllists) - set(urllists)) delete_urls = list(set(self.tuple_result[1].keys()) - set(urllists)) # print("本次数据URL: ") # print(download_urls) # print(delete_urls) if len(download_urls) != 0: # p = Process(target=self.transaction.downloadDatas, args=(downloadqueue, self.oriurl, self.orilable, download_urls, delete_urls)) # p.start() p = threading.Thread(target=self.transaction.downloadDatas, args=(downloadqueue, self.oriurl, self.orilable, download_urls, delete_urls)) p.start() else: # print("usingOldData方法中 len(download_urls)!=0 所以执行 downloadqueue.put(1)") downloadqueue.put("no_download_urls") self.workSurfaceUI([self.oriurl, self.orilable]) def workSurfaceUI(self, args): self.frame2.destroy() self.frame3.destroy() self.tree_date.destroy() WorkSurface(self.master, self.transaction, self.tuple_result, args)
class initface(): def __init__(self, master,transaction, args): self.transaction = transaction self.master = master self.isOkToNextUI = True #判断是否可以进入URL分析程序 self.isOkToSelectSurface = True #判断是否可以进入选择界面 self.classify_result = None #用于储存元组数据 self.frame2 = Frame(self.master, height=200) # self.frame2.pack() self.frame2.grid(row=0, column=0) selectbtn = Button(self.frame2, text="选择数据", command=self.selectDatasSurface) label = Label(self.frame2, text="URL: ") self.name = StringVar() self.entryName = Entry(self.frame2, textvariable=self.name, width=80) label2 = Label(self.frame2, text="标签: ") self.lable2 = StringVar() self.entryName2 = Entry(self.frame2, textvariable=self.lable2, width=30) btGetName = Button(self.frame2, text="添加URL", command=self.processAddURL) startDlButton = Button(self.frame2, text="开始下载", command=self.processDownload) selectbtn.grid(row=1,column = 0) label.grid(row=1, column=1) self.entryName.grid(row=1, column=2) label2.grid(row=1, column=3) self.entryName2.grid(row=1, column=4) btGetName.grid(row=1, column=5) startDlButton.grid(row=1, column=6) self.tree_date = Treeview(self.master, columns=['URL','LABLE2'], show='headings', height=30) # self.tree_date.pack() self.tree_date.grid(row=2) # 设置列宽度 self.tree_date.column('URL', width=758, anchor='center') self.tree_date.column('LABLE2', width=442, anchor='center') # 添加列名 self.tree_date.heading('URL', text='URL') self.tree_date.heading('LABLE2', text='标签') # 绑定事件 self.tree_date.bind('<Double-3>', self.deleteItem) # 当从数据分析页面返回时调用 if self.transaction.urllists != []: for index in range(len(args[0])): self.tree_date.insert('', 1, values=(args[0][index], args[1][index])) # for key,value in self.receptdata[0].items(): # self.tree_date.insert('', 1, values=(key,value['lable_'])) # for key,value in self.receptdata[1].items(): # self.tree_date.insert('', 1, values=(key, value['lable_'])) # for item in self.transaction.urllists: # self.tree_date.insert('', 1, values=item) def selectDatasSurface(self): # print('点击了选择按钮') # 获取合适的URL if self.isOkToSelectSurface: self.isOkToSelectSurface = False t_classify = threading.Thread(target=self.loadAllDatas) t_classify.start() else: tkinter.messagebox.showinfo('TBProject Info', '请等待数据库数据提取完毕!') def loadAllDatas(self): # t_judge = MyThread(func=self.transaction.loadAllDatasFromDetials, args=("loadAllDatasFromDetials",)) # t_judge.start() # t_judge.join() # # threadingqueue.put(1) # result_datas = t_judge.get_result() try: result_datas = self.transaction.loadAllDatasFromDetials() except: self.isOkToSelectSurface = True tkinter.messagebox.showerror('TBProject Error', 'initface ---> loadAllDatas: 数据库链接出现错误,请重试!') return self.frame2.destroy() self.tree_date.destroy() SelectionSurface(self.master, self.transaction, result_datas) def deleteItem(self, event): # 右键双击删除 for item in self.tree_date.selection(): self.tree_date.delete(item) # item_text = self.tree_date.item(item, "values") # print(item_text[0]) # 输出所选行的第一列的值 def processAddURL(self): url_ = self.name.get().strip() if url_==None or url_.strip()=="": self.entryName.delete(0, END) self.entryName2.delete(0, END) return if url_[0:4] != 'http': self.entryName.delete(0, END) self.entryName2.delete(0, END) tkinter.messagebox.showinfo('TBProject Info', "非正确网址格式: \r\n" + url_) return if ('tmall' not in url_) and ('taobao' not in url_): self.entryName.delete(0, END) self.entryName2.delete(0, END) tkinter.messagebox.showinfo('TBProject Info', "此URL不属于目标网站: \r\n" + url_) return lable_ = self.lable2.get() if lable_==None or lable_.strip()=="": lable_ = "-Default Lable-" self.tree_date.insert('', 1, values=(url_,lable_)) self.entryName.delete(0,END) self.entryName2.delete(0, END) def processDownload(self): if len(self.tree_date.get_children())==0: return None # 获取合适的URL if self.isOkToNextUI: self.isOkToNextUI = False kids = self.tree_date.get_children() urllists = [] lablelist = [] for item in kids: # 对输入的值进行去重 url_ = self.tree_date.item(item, "values")[0] lable_ = self.tree_date.item(item, "values")[1] if url_ not in urllists: urllists.append(url_) lablelist.append(lable_) # 如果可用网址为0,则清空treeview if len(urllists)==0: self.entryName.delete(0, END) for item in kids: self.tree_date.delete(item) return self.transaction.urllists = urllists t_classify = threading.Thread(target=self.classifyURL, args=(urllists,lablelist)) t_classify.start() else: tkinter.messagebox.showinfo('TBProject Info', '请等待URL分析完毕') def classifyURL(self, urllists, lablelist): try: self.classify_result = self.transaction.classifyURLNewOrOld(urllists, lablelist) except: self.isOkToNextUI = True tkinter.messagebox.showerror('TBProject Error', 'initface ---> classifyURL: 数据库链接出现错误,请重试!') return self.judgeNextUI(urllists, lablelist) def judgeNextUI(self, oriurl, orilable): if len(self.classify_result[0]) != 0: newurllists = list(self.classify_result[0].keys()) else: newurllists = [] oldurllists = self.classify_result[1] if len(oldurllists) == 0: #说明没有旧数据 # p = Process(target=self.transaction.downloadDatas, args=(downloadqueue, oriurl, orilable, newurllists)) # p.start() p = threading.Thread(target=self.transaction.downloadDatas, args=(downloadqueue, oriurl, orilable, newurllists)) p.start() self.workSurfaceUI([oriurl, orilable]) else: #说明存在一些URL在数据库中有存 # 将两个列表都传给下一个界面,在下一个界面将数据分类展示 self.checkDownloadUI(self.classify_result, oriurl, orilable) def workSurfaceUI(self, args): self.frame2.destroy() self.tree_date.destroy() WorkSurface(self.master, self.transaction, self.classify_result, args) def checkDownloadUI(self, args, oriurl, orilable): self.frame2.destroy() self.tree_date.destroy() CheckDownload(self.master, self.transaction, args, [oriurl, orilable])
class handleDatasSurface(): def __init__(self, master, transaction, tuple_result, args): self.transaction = transaction self.master = master self.args = args self.tuple_result = tuple_result self.deleteurls = [] self.frame2 = Frame(self.master, width=10, height=2) # self.frame2.pack() self.frame2.grid(row=0, column=0) label = Label(self.frame2, text="本次运行时候使用的数据", width=30, height=3) label.grid(row=1, column=1) self.tree_date = Treeview(self.master, columns=['URL', 'Lable', 'Time'], show='headings', height=23) # self.tree_date.pack() self.tree_date.grid(row=2, column=0) # 设置列宽度 self.tree_date.column('URL', width=450, anchor='center') self.tree_date.column('Lable', width=500, anchor='center') self.tree_date.column('Time', width=250, anchor='center') # 添加列名 self.tree_date.heading('URL', text='URL') self.tree_date.heading('Lable', text='标签') self.tree_date.heading('Time', text='上次下载时间') # 绑定事件 # 绑定左键单击 选中 self.tree_date.bind('<Double-Button-1>', self.selectone) # 绑定右键单击 取消选中 self.tree_date.bind('<Double-3>', self.refuseone) # 绑定键盘 Enter事件,展示URL self.tree_date.bind('<Return>', self.infoURL) self.frame3 = Frame(self.master) btn_yes = tk.Button(self.frame3, text='删除已经选择的数据', command=self.useSelectedData) # btn_no = tk.Button(self.frame3, text='使用数据库数据', command=self.usingOldData) self.frame3.grid(row=3) # btn_no.grid(row=3, column=1) btn_yes.grid(row=3, column=2) self.vsb = tk.ttk.Scrollbar(self.master, orient="vertical", command=self.tree_date.yview) # vsb.place(x=30 + 1100, y=95, height=300 + 20) self.tree_date.configure(yscrollcommand=self.vsb.set) # vsb.grid(row=2, columns = 1,sticky=NS) self.vsb.place(x=1182, y=60, height=480 + 20) # vsb.place(x=50 + 200, y=95, height=200 + 20) # 将存在于数据库中的URL数据展示出来 # for key, value in self.tuple_result[1].items(): # self.tree_date.insert('', 1, values=(key, self.orilable[self.oriurl.index(key)], value['creattime_'])) tuple_ = self.tuple_result[0].copy() tuple_.update(self.tuple_result[1]) for key,value in tuple_.items(): self.tree_date.insert('', 1, values=(key, value['lable_'], value['creattime_']), tags=self.getrandomtgs()) def deleteItem(self, event): # 右键双击删除 for item in self.tree_date.selection(): self.tree_date.delete(item) def selectone(self, event): for item in self.tree_date.selection(): # self.tree_date.columnconfigure (0,weight=1,background='yellow', foreground="red") # self.tree_date.configure ( background = 'yellow',foreground="red") # tages = self.tree_date.item(item, "values")[0] tages = self.tree_date.item(item, "tags")[0] url_ = self.tree_date.item(item, "values")[0].strip() if url_ not in self.deleteurls: self.deleteurls.append(url_) self.tree_date.tag_configure(tages, background='yellow', foreground="red") def refuseone(self, event): for item in self.tree_date.selection(): tages = self.tree_date.item(item, "tags")[0] try: self.deleteurls.remove(self.tree_date.item(item, "values")[0].strip()) except: pass self.tree_date.tag_configure(tages, background='white', foreground="black") def infoURL(self, event): for item in self.tree_date.selection(): url_ = self.tree_date.item(item, "values")[0].strip() lable_ = self.tree_date.item(item, "values")[1] pyperclip.copy(url_) tkinter.messagebox.showinfo('TBProject Info', '选中的url为:\r\n%s' % url_ + "\r\n选中的标签为:\r\n%s" % lable_) def getrandomtgs(self): return ''.join(random.SystemRandom().choice(string.ascii_uppercase + string.digits) for _ in range(6)) def useSelectedData(self): try: if len(self.deleteurls) != 0: t_classify = threading.Thread(target=self.transaction.deleteOldDatas, args=(self.deleteurls,)) t_classify.start() except: tkinter.messagebox.showerror('TBProject Error', 'tryAnalysize: 数据库链接出现错误,请重试!') return tuple_ = self.tuple_result[0].copy() tuple_.update(self.tuple_result[1]) for item in self.deleteurls: tuple_[item]['creattime_'] = "- Deleted -" self.frame2.destroy() self.frame3.destroy() self.tree_date.destroy() self.vsb.destroy() # self.transaction.urllists = 1 WorkSurface(self.master, self.transaction, self.tuple_result, self.args, ishandle = True)
class SelectionSurface(): def __init__(self, master, transaction, result_data): self.transaction = transaction self.master = master self.result_data = result_data self.selecturl = [] self.selectlable = [] self.selecttime = [] self.frame2 = Frame(self.master, width=10, height=2) # self.frame2.pack() self.frame2.grid(row=0, column=0) label = Label(self.frame2, text="数据库中已经存在的数据", width=30, height=3) label.grid(row=1, column=1) self.tree_date = Treeview(self.master, columns=['URL', 'Lable', 'Time'], show='headings', height=23) # self.tree_date.pack() self.tree_date.grid(row=2,column=0) # 设置列宽度 self.tree_date.column('URL', width=450, anchor='center') self.tree_date.column('Lable', width=500, anchor='center') self.tree_date.column('Time', width=250, anchor='center') # 添加列名 self.tree_date.heading('URL', text='URL') self.tree_date.heading('Lable', text='标签') self.tree_date.heading('Time', text='上次下载时间') # 绑定事件 # 绑定左键单击 选中 self.tree_date.bind('<Double-Button-1>', self.selectone) # 绑定右键单击 取消选中 self.tree_date.bind('<Double-3>', self.refuseone) # 绑定键盘 Enter事件,展示URL self.tree_date.bind('<Return>', self.infoURL) self.frame3 = Frame(self.master) btn_yes = tk.Button(self.frame3, text='使用已经挑选的数据', command=self.useSelectedData) # btn_no = tk.Button(self.frame3, text='使用数据库数据', command=self.usingOldData) self.frame3.grid(row=3) # btn_no.grid(row=3, column=1) btn_yes.grid(row=3, column=2) self.vsb = tk.ttk.Scrollbar(self.master, orient="vertical", command=self.tree_date.yview) # vsb.place(x=30 + 1100, y=95, height=300 + 20) self.tree_date.configure(yscrollcommand=self.vsb.set) # vsb.grid(row=2, columns = 1,sticky=NS) self.vsb.place(x=1182, y=60, height=480 + 20) # vsb.place(x=50 + 200, y=95, height=200 + 20) # 将存在于数据库中的URL数据展示出来 # for key, value in self.tuple_result[1].items(): # self.tree_date.insert('', 1, values=(key, self.orilable[self.oriurl.index(key)], value['creattime_'])) for item in self.result_data: self.tree_date.insert('', 1, values=(item[0], item[1], item[2]), tags=self.getrandomtgs()) def deleteItem(self, event): # 右键双击删除 for item in self.tree_date.selection(): self.tree_date.delete(item) def selectone(self, event): for item in self.tree_date.selection(): # self.tree_date.columnconfigure (0,weight=1,background='yellow', foreground="red") # self.tree_date.configure ( background = 'yellow',foreground="red") # tages = self.tree_date.item(item, "values")[0] tages = self.tree_date.item(item, "tags")[0] url_ = self.tree_date.item(item, "values")[0].strip() lable_ = self.tree_date.item(item, "values")[1] time_ = self.tree_date.item(item, "values")[2] if url_ not in self.selecturl: self.selecturl.append(url_) self.selectlable.append(lable_) self.selecttime.append(time_) self.tree_date.tag_configure (tages, background = 'yellow',foreground="red") def refuseone(self, event): for item in self.tree_date.selection(): tages = self.tree_date.item(item, "tags")[0] try: self.selecturl.remove(self.tree_date.item(item, "values")[0].strip()) self.selectlable.remove(self.tree_date.item(item, "values")[1]) self.selecttime.remove(self.tree_date.item(item, "values")[2]) except: pass self.tree_date.tag_configure(tages, background='white', foreground="black") def infoURL(self, event): for item in self.tree_date.selection(): url_ = self.tree_date.item(item, "values")[0].strip() lable_ = self.tree_date.item(item, "values")[1] pyperclip.copy(url_) tkinter.messagebox.showinfo('TBProject Info', '选中的url为:\r\n%s'%url_+"\r\n选中的标签为:\r\n%s"%lable_) def getrandomtgs(self): return ''.join(random.SystemRandom().choice(string.ascii_uppercase + string.digits) for _ in range(6)) def useSelectedData(self): self.frame2.destroy() self.frame3.destroy() self.tree_date.destroy() self.vsb.destroy() self.transaction.urllists = 1 initface(self.master, self.transaction, [self.selecturl,self.selectlable, self.selecttime])
class SearchFrame(Frame): content = None def __init__(self, parent, controller): Frame.__init__(self, parent) self.analysisthread = None self.controller = controller # set the controller self.title = "Article Search" # title of the window #title path = os.getcwd() + '\\resources\cyspider.jpg' self.img = ImageTk.PhotoImage(Image.open(path)) self.panel = Label(self, image=self.img) self.panel.pack() # widgets for results page # frame for individual analysis self.sf = LabelFrame(self, width=550, height=150, background='#383838', bd=6) # frame for results analysis self.sf2 = LabelFrame(self, width=550, height=150, background='#383838', bd=6) # labels for article topics self.topicsHead = Label(self, text='Key Article Subjects', font="times 16 underline", background='#282828', foreground='#5DE0DC') self.topics = Label(self, text='Click on an article to see more info', wraplength=500, font='times 16', background='#383838', foreground='#5DE0DC', anchor=W, justify=LEFT) calltipwindow.createToolTip( self.topicsHead, "These are a few subjects that were mentioned in the article") # labels for results analysis self.resultTopicHead = Label(self, text='Most Mentioned Phrases in Results', font="times 16 underline", background='#282828', foreground='#5DE0DC') self.resultTopics = Label(self, text='Processing Data (0%)', wraplength=500, font='times 16', background='#383838', foreground='#5DE0DC', anchor=W, justify=LEFT) calltipwindow.createToolTip( self.resultTopicHead, "These are the most mentioned phrases in the resulting articles.") # helper class to improve code readability self.helper = cyhelper.SearchHelper(self) self.helper.showsearch() def search(self, url): # queue to share between gui and threads q = queue.Queue() self.helper.hidefilters() if SearchFrame.content is None: searchprogress = Progressbar(self, orient="horizontal", style='mongo.Horizontal.TProgressbar', length=700, mode="indeterminate") searchprogress.place(relx=.5, rely=.8, anchor=CENTER) searchprogress.start() proglabel = Label(self, text="Fetching Results...", font="Times 14", bg="#282828", fg="#FFFFFF") proglabel.place(relx=.5, rely=.765, anchor=CENTER) # get additional info from filters if they exist url = self.helper.addurlfilters(url) # start thread to get data from url thread = GetDataThread(url, q) thread.start() # wait until thread is done, then get data from queue self.updateuntildata(q, searchprogress) self.data = q.get(0) # get rid of progress bar searchprogress.destroy() proglabel.destroy() else: self.data = SearchFrame.content # make sure search didn't time out if self.data != "ReadTimeout": self.master.master.updateque.queue.clear() # start thread to analyze data and repeat process self.analysisthread = ResultsAnalysisThread( self.data, self.master.master.analyzer, q, self.resultTopics) self.analysisthread.start() self.resultTopics.config(text="Processing Data...(0%)") self.processingloop('percent') self.processingloop('dots') self.helper.hidesearch() style = Style(self) style.configure("Treeview", rowheight=30, fieldbackground='#bdbdbd') style.configure("Treeview.Heading", background="#707070", rowheight=60, font="Ariel 14 bold") self.tree = Treeview(self, columns=('date', 'title'), selectmode='browse') self.tree['show'] = 'headings' self.tree.column('date', width=100, anchor=CENTER) self.tree.heading('date', text="Date", command=lambda: self.treeview_sort_column( self.tree, 'date', False)) self.tree.column('title', width=900) self.tree.heading('title', text="Article Title", anchor=W, command=lambda: self.treeview_sort_column( self.tree, 'title', False)) self.tree.heading('title', text="Article Title", anchor=W, command=lambda: self.treeview_sort_column( self.tree, 'title', False)) #self.tree.place(relx=.3, relheight=1, width=1200) self.tree.place(x=330, relheight=1, width=760) self.treeyscb = Scrollbar(self, orient="vertical", command=self.tree.yview) self.treeyscb.place(relx=1, rely=.5, relheight=1, anchor=E) self.tree.configure(yscrollcommand=self.treeyscb.set) self.treexscb = Scrollbar(self, orient="horizontal", command=self.tree.xview) self.treexscb.place(relx=.3, rely=.999, width=755, anchor=SW) self.tree.configure(xscrollcommand=self.treexscb.set) self.sf.place(relx=0, rely=.055, relwidth=.30, relheight=.4) self.topicsHead.place(relx=.01, rely=.024, relwidth=.28, relheight=.03) self.topics.place(relx=.01, rely=.065, relwidth=.28) # frame for results analysis self.sf2.place(relx=0, rely=.51, relwidth=.30, relheight=.4) self.resultTopicHead.place(relx=.01, rely=.475, relwidth=.28, relheight=.03) self.resultTopics.place(relx=.01, rely=.52, relwidth=.28) # New Search Edit Search Save Search self.new_search = Button(self, text='New Search', background='#383838', foreground='#5DE0DC', font="Veranda 14", command=self.NewSearch) self.edit_search = Button(self, text='Edit Search', background='#383838', foreground='#5DE0DC', font="Veranda 14", command=self.EditSearch) self.save_search = Button(self, text='Save Search', background='#383838', foreground='#5DE0DC', font="Veranda 14", command=self.saveMenu) if self.data: for count, item in enumerate(self.data): # remove BOM images first from body >uffff item['body'] = ''.join( c for c in unicodedata.normalize('NFC', item['body']) if c <= '\uFFFF') tagname = 'even' if count % 2 == 0 else 'odd' self.tree.insert('', 'end', values=(parser.parse( item['date']).strftime('%m/%d/%y'), item['title'], item['uri'], item['author'], item['body']), tag=tagname) self.tree.tag_configure('even', font='Verdana 14', background="#9fedea") self.tree.tag_configure('odd', font='Verdana 14', background="#dedede") self.tree.bind('<Double-1>', self.on_click) self.tree.bind('<<TreeviewSelect>>', self.on_single_click) self.treeview_sort_column(self.tree, 'date', True) else: self.topics.config(text='No Articles Matching Search') self.resultTopics.config(text='') self.new_search.place(relx=0, rely=.95, relwidth=.1, relheight=.05, anchor=NW) if SearchFrame.content is None: self.edit_search.place(relx=.1, rely=.95, relwidth=.1, relheight=.05, anchor=NW) if len(self.data) > 0: self.save_search.place(relx=.2, rely=.95, relwidth=.1, relheight=.05, anchor=NW) else: messagebox.showerror( "Too Broad", "Search is too broad. Try refining with filters.") self.helper.ent_keyword.focus_set() SearchFrame.content = None pass def NewSearch(self): self.analysisthread.stopthread() self.deletesearch() self.helper.resetsearch() self.helper.showsearch() def EditSearch(self): self.analysisthread.stopthread() self.deletesearch() self.helper.showsearch() def saveMenu(self): # create main directory and subdir(current date) if not made already path = os.getcwd() + "/Sessions/" + str(datetime.date.today()) if not os.path.exists(path): os.makedirs(path) # get a filename from the user or default to current time currentTime = datetime.datetime.now().strftime("%H_%M_%S") filename = filedialog.asksaveasfilename(defaultextension="txt", initialdir=path, initialfile=currentTime) if filename: self.saveFilename = filename with open(filename, 'w') as outfile: json.dump(self.data, outfile) # with open(filename, 'w') as f: # f.write("Testing Save As/No Current Save") #defind clear search def deletesearch(self): self.tree.destroy() self.sf.place_forget() self.topicsHead.place_forget() self.topics.place_forget() self.sf2.place_forget() self.resultTopicHead.place_forget() self.resultTopics.place_forget() self.new_search.destroy() self.treexscb.destroy() self.treeyscb.destroy() try: self.edit_search.destroy() self.save_search.destroy() except AttributeError: pass #on click gets the articles information and displays it in the Key Article Subjects window def on_single_click(self, event): self.topicsHead.config(text="Key Article Subjects") item = self.tree.item(self.tree.selection()[0], 'values') topicStr = '\n\n'.join([ '\n '.join(textwrap.wrap('\u27a2' + phrase[0], width=33)) for phrase in self.master.master.analyzer.getMostCommonNounPhrases( 5, [item[4]], threading.Event(), 'one') ]) self.topics.config(text=topicStr) #on d click will open the article for display def on_click(self, event): try: item = self.tree.selection()[0] except IndexError: return self.n = self.tree.item(item, 'values') tw = Toplevel(self) xoffset = int(self.winfo_screenwidth() / 2 - 1280 / 2) yoffset = int(self.winfo_screenheight() / 2 - 800 / 2) tw.geometry("%dx%d+%d+%d" % (800, 600, xoffset, yoffset)) # set geometry of window tw.title(self.n[1]) tb = Text(tw, width=90, height=40, font="Times 14", wrap=WORD) makemenu.ArticleMenu(tw, tb, self.n) tb.insert('end', self.n[4]) tb.config(state=DISABLED) link = Label(tw, text=self.n[2]) link.configure(foreground='blue', cursor='hand2') link.bind('<1>', self.op_link) auth = Label(tw, text='Author: ' + self.n[3]) articledate = Label(tw, text='Date Published: ' + self.n[0]) # window formatting for tw link.place(x=0, y=0, relwidth=1) tb.place(y=20, relwidth=1, relheight=1) auth.pack(side=LEFT, anchor='sw') articledate.pack(side=RIGHT, anchor='se') # op_link "double click on the link at the top of the page opens up the url link def op_link(self, event): webbrowser.open_new(self.n[2]) def callEnable(self, event, searchtype): self.helper.callenable(event, searchtype) def updateuntildata(self, q, progress): while q.empty(): time.sleep(.01) progress.step(1) progress.master.update() def processingloop(self, updatetype): string = self.resultTopics.cget('text') if len(string) and string[0] == 'P': if updatetype == 'percent': if not self.master.master.updateque.empty(): string = "{}({}%)".format( re.search('Processing Data(\.|\s)*', string).group(0), str(self.master.master.updateque.get(0))) self.after(300, lambda: self.processingloop('percent')) else: self.after(100, lambda: self.processingloop('percent')) elif updatetype == 'dots': numdots = len(string.split('.')) % 4 string = "Processing Data" + numdots * '.' + ( 3 - numdots) * ' ' + re.search('\(.+\)', string).group(0) self.after(300, lambda: self.processingloop('dots')) self.resultTopics.config(text=string) def treeview_sort_column(self, tv, col, reverse=False): l = [(tv.set(k, col), k) for k in tv.get_children('')] if col == 'date': l.sort(key=lambda t: "{}/{}/{}".format(t[0].split('/')[2], t[ 0].split('/')[0], t[0].split('/')[1]), reverse=reverse) else: l.sort(key=lambda t: t[0], reverse=reverse) for index, (val, k) in enumerate(l): tv.move(k, '', index) for count, child in enumerate(tv.get_children()): tagn = 'even' if count % 2 == 0 else 'odd' tv.item(child, tag=tagn) tv.heading( col, command=lambda: self.treeview_sort_column(tv, col, not reverse))