def __init__(self, parent, funnel, index, command_stack): tk.Frame.__init__(self, parent, borderwidth=4, relief="raised") Subscriber.__init__(self, funnel) Observable.__init__(self) self._funnel = funnel self._command_stack = command_stack self._active_var = tk.IntVar() self._active_var.trace_add("write", self._switch_active) self._y_var = tk.StringVar() self._y_var.set(0) self._y_var.trace_add("write", self._set_position) self._x_var = tk.StringVar() self._x_var.set(0) self._x_var.trace_add("write", self._set_position) self._oval_var = tk.IntVar() self._oval_var.trace_add("write", self._switch_oval) self._update() self.bind("<Button-1>", self._on_click) is_active = Checkbutton( self, text=f"Funnel n°{index}: ", variable=self._active_var) is_active.grid(columnspan=3) is_active.bind("<FocusIn>", self._on_get_focus) is_active.bind("<FocusOut>", self._on_lost_focus) x_label = Label(self, text="\u21d5", anchor=tk.CENTER) x_label.grid(sticky=tk.E + tk.W) x_label.bind("<Button-1>", self._on_click) self.x_entry = Entry(self, textvariable=self._x_var, width=6) self.x_entry.grid(row=2, column=0, sticky=tk.W + tk.E) self.x_entry.bind("<FocusIn>", self._on_get_focus) self.x_entry.bind("<FocusOut>", self._on_lost_focus) y_label = Label(self, text="\u21d4", anchor=tk.CENTER) y_label.grid(row=1, column=1, sticky=tk.E+tk.W) y_label.bind("<Button-1>", self._on_click) self.y_entry = Entry(self, textvariable=self._y_var, width=6) self.y_entry.grid(row=2, column=1, sticky=tk.W + tk.E) self.y_entry.bind("<FocusIn>", self._on_get_focus) self.y_entry.bind("<FocusOut>", self._on_lost_focus) is_oval = Checkbutton(self, text="Is Oval", variable=self._oval_var) is_oval.grid(row=1, column=2) is_oval.bind("<FocusIn>", self._on_get_focus) is_oval.bind("<FocusOut>", self._on_lost_focus) force_centerline = Button( self, text="force on centerline", command=self._force_centerline) force_centerline.grid(row=2, column=2) self.columnconfigure(0, weight=1) self.columnconfigure(1, weight=1) self.columnconfigure(2, weight=1)
class FrmAccess(Frame): def __init__(self, root, controller): super().__init__(root) self.controller = controller self.lbl_access = Label(self, text='View access page', foreground='blue', cursor='hand2') self.lbl_access.pack(side=RIGHT, padx=PADX, pady=PADY) self.lbl_access.bind('<Button-1>', self.controller.open_url)
def add_underline_link_on_hover(l_widget: ttk.Label, change_page_func: Callable): """ Underlines the label widget when the user hovers over it indicating a clickable link to them. :param l_widget: the ttk label widget which the user hovers over. Should have a font attribute already set (otherwise font may change on hover) :param change_page_func: the change page function to be called when the user clicks (mouse button 1) the label. First argument must be able to accept tkinter event details: e.g. func(event, a, b): ... """ l_widget.bind('<Button-1>', change_page_func) # noinspection PyUnusedLocal def enter(tk_event: tk.Event): f = font.Font(l_widget, l_widget.cget('font')) f.configure(underline=True) l_widget.configure(font=f) # noinspection PyUnusedLocal def leave(tk_event: tk.Event): f = font.Font(l_widget, l_widget.cget('font')) f.configure(underline=False) l_widget.configure(font=f) l_widget.bind('<Enter>', enter) l_widget.bind('<Leave>', leave)
class StopwatchView(Frame): """ Provides an interface for the controller to the GUI code. """ WINDOW_TITLE = "PyTimer" def __init__(self, root, controller): super().__init__(root) self.controller = controller self.stopwatch_label_var = StringVar() self._create() self._arrange() def _create(self): self.timer_label = Label(self, textvariable=self.stopwatch_label_var, font=("Arial", 36)) self.timer_label.bind( "<Button-1>", lambda event: self.controller.set_time_callback()) self.toggle = Button(self, text="Start/Stop", command=self.controller.toggle_callback) self.reset = Button(self, text="Reset", command=self.controller.reset_callback) def _arrange(self): self.timer_label.pack(fill=X, expand=NO) self.toggle.pack(fill=X) self.reset.pack(fill=X)
def __init__(self, master): """Create about dialog.""" Toplevel.__init__(self, master, class_='MyNotes') self.title(_("About MyNotes")) self.image = PhotoImage(file=IM_ICON_48, master=self) style = Style(self) style.configure("url.TLabel", foreground="blue") Label(self, image=self.image).grid(row=0, columnspan=2, pady=10) Label(self, text=_("MyNotes %(version)s") % ({ "version": __version__ })).grid(row=1, columnspan=2) Label(self, text=_("Sticky notes/post-it system tray app")).grid( row=2, columnspan=2, padx=10) Label(self, text="Copyright (C) Juliette Monsel 2016-2019").grid( row=3, columnspan=2, padx=10) Label(self, text="*****@*****.**").grid(row=4, columnspan=2, padx=10) github = Label(self, text="https://github.com/j4321/MyNotes", cursor="hand1", style="url.TLabel", font="TkDefaultFont 10 underline") github.grid(row=5, columnspan=2, padx=10, pady=(10, 0), sticky="w") sourceforge = Label(self, cursor="hand1", style="url.TLabel", text="https://sourceforge.net/projects/my-notes", font="TkDefaultFont 10 underline") sourceforge.grid(row=6, columnspan=2, padx=10, pady=(0, 10), sticky="w") github.bind("<Button-1>", lambda e: webOpen("https://github.com/j4321/MyNotes")) sourceforge.bind( "<Button-1>", lambda e: webOpen("https://sourceforge.net/projects/my-notes/")) Button(self, text=_("License"), command=self._license).grid(row=7, column=0, pady=10, padx=6, sticky="e") Button(self, text=_("Close"), command=self.exit).grid(row=7, column=1, pady=10, padx=6, sticky="w") self.initial_focus = self self.protocol("WM_DELETE_WINDOW", self.exit) self.resizable(0, 0) self.initial_focus.focus_set() self.wait_window(self)
def insert_label(self, frame, value, key): label = Label(master=frame, text=value.pop("label", key), font=("Helvetica", 9, "bold"), anchor="w") label.pack(fill="both", pady=(10, 0), padx=10) if "help" in value: label.bind("<Button-1>", lambda e, m=value["help"]: self.show_message(m))
def _criar_label(self, label): ''' Criar label. ''' frame = Frame(self, width=150, height=50) label = Label(frame, text=label, anchor='center', style='Slider.TLabel') label.bind('<Double-Button-1>', lambda e: self._spinbox.focus()) label.pack(fill='both', expand=True, padx=5, pady=5) frame.pack(side='left') frame.pack_propagate(False)
def update_findings(self): self.frame_finding.destroy() self.frame_finding = Frame(self.master) self.frame_finding.pack(fill=X) findings = db.get_findings_by_project_name(project.id) for finding in findings: label_txt = "{:0>3d} \t {}".format(finding.id, finding.name) finding_lbl = Label(self.frame_finding, text=label_txt) finding_lbl.pack(side=TOP, anchor=W, padx=10) finding_lbl.bind("<Double-Button-1>", lambda event, finding_var=finding: self. double_click_finding(event, finding_var))
def __init__(self): self.root = Tk() self.root.title("VkMessageStat") self.root.iconbitmap(os.path.join(base_dir, "icon.ico")) self.root.geometry('661x617') Style().configure("Login.TLabel", foreground="#777777", font=("Arial", 12)) Style().configure("Link.TLabel", foreground="#039be5", font=("Arial", 12)) Style().configure("TFrame", bg="#ff0000") self.is_working = False self.login_status_label = Label(self.root, text="Проверка логина...", style="Login.TLabel") self.login_status_label.pack(side=TOP, pady=10) frame = Frame(self.root) lab = Label(frame, text="Автор", style="Link.TLabel", cursor='hand2') lab.bind('<Button-1>', lambda x=None: webbrowser.open("https://vk.com/zettroke")) lab.pack(side=LEFT, padx=5) lab = Label(frame, text="GitHub", style="Link.TLabel", cursor='hand2') lab.bind('<Button-1>', lambda x=None: webbrowser.open( "https://github.com/Zettroke/VkMessageStat")) lab.pack(side=LEFT, padx=5) frame.place(x=0, y=0) self.login_button = Button(self.root, text='Войти', state=DISABLED, command=self.proceed_login) self.login_button.pack() self.root.after(50, self.login_check) self.is_logged_in = False self.access_token = '' self.root.bind("<Return>", self.bnd) self.current_progress = 0 self.progress_value = DoubleVar() self.users = [] self.root.mainloop()
class Handle(Frame): def __init__(self, panedwindow, sash_index, disallow_dragging=False, on_click=None, **kw): image = kw.pop("image", None) # 取出图片对象,如果不存在则返回None Frame.__init__(self, panedwindow, class_="Handle", **kw) self._sash_index = sash_index if image: # 如果图片对象存在,则加载图片 self._event_area = Label(self, image=image) self._event_area.pack() else: self._event_area = self # 获取PanedWindow的中心点 self._center = int(self._event_area.winfo_reqwidth() / 2), int(self._event_area.winfo_reqheight() / 2) if disallow_dragging: # 如果不允许拖动 if on_click: self._event_area.bind('<Button-1>', lambda event: on_click()) # 绑定鼠标左键点击事件 else: self._event_area.bind('<Button-1>', self._initiate_motion) # 绑定鼠标左键点击事件 self._event_area.bind('<B1-Motion>', self._on_dragging) # 绑定按住左键拖动事件 self._event_area.bind('<ButtonRelease-1>', self.master._on_release) # 绑定左键释放事件 def _initiate_motion(self, event): # 获取拖动前初始位置 self.master._active_sash = self._sash_index self._dx = event.x self._dy = event.y @property def sash_index(self): return self._sash_index def _on_dragging(self): raise NotImplementedError
def __init__(self): ThemedTk.__init__(self, theme='black') self.title('Обновление F_Reference_H') self.geometry('500x140') x = (self.winfo_screenwidth() - self.winfo_reqwidth()) / 2 y = (self.winfo_screenheight() - self.winfo_reqheight()) / 2 self.wm_geometry("+%d+%d" % (x - 150, y)) self.resizable(width=False, height=False) self.iconphoto(True, PhotoImage(file='settings/ico/ico_main.png')) flow_hack_png = Image.open(f'settings/ico/mini_flowhack.png') flow_hack_png = ImageTk.PhotoImage(flow_hack_png) self.frame = Frame(self) self.frame.place(relwidth=1, relheight=1) flow_1 = Label(self.frame, image=flow_hack_png, cursor='heart') flow_1.bind('<Button-1>', lambda no_matter: webopen(VK)) flow_1.place(relx=.09, rely=.085, anchor='center') flow_2 = Label(self.frame, image=flow_hack_png, cursor='heart') flow_2.bind('<Button-1>', lambda no_matter: webopen(VK)) flow_2.place(relx=.91, rely=.085, anchor='center') self.lbl_done = Label(self.frame, text='ОБНОВЛЕНИЕ', font=('Times New Roman', 12, 'bold italic')) self.lbl_done.place(relx=.5, rely=.1, anchor='c') self.lable_second = Label( self.frame, text='Нам понадобится интернет!\nМы всё сделаем сами, это не ' 'займё много времени!', font=('Times New Roman', 10, 'bold italic'), justify='center') self.lable_second.place(relx=.5, rely=.35, anchor='c') self.btn_update = Button(self.frame, text='Обновить', cursor='hand1', command=self.updater_window) self.btn_update.place(relx=.5, rely=.65, anchor='c') self.license = Label( self.frame, cursor='hand1', text='Нажимая "Обновить" вы принимаете лицензионное соглашение', font=('Times New Roman', 10, 'bold italic'), foreground='black') self.license.bind('<Button-1>', lambda no_matter: webopen(SAIT)) self.license.place(relx=.5, rely=.92, anchor='c') self.mainloop()
def initItems(self): """Initialize all widgets here""" # An entry to enter feet value. self.feet_entry = Entry(self, width=7) self.feet_entry.grid(column=2, row=1, sticky=(W, E)) # A label to display translated meters. self.meters_lbl = Label(self, textvariable=self.meters_value) self.meters_value.set(0) self.meters_lbl.grid(column=2, row=2, sticky=(W, E)) # Different labels for text only. Label(self, text='feet').grid(column=3, row=1, sticky=W) Label(self, text='is equivalent to').grid(column=1, row=2, sticky=E) Label(self, text='meters').grid(column=3, row=2, sticky=W) # Button to calculate things. calc_btn = Button(self, text='Calculate', command=lambda: calculate(self)) calc_btn.grid(column=3, row=3, sticky=W) # This widget is just for fun. # Also it shows how to get an event callback when Entry widget is modified def callback(str): print(str.get()) entry_str = StringVar() entry_str.trace('w', lambda name, index, mode, str=entry_str: callback(str)) self.entry_widg = Entry(self, width=10, textvariable=entry_str) self.entry_widg.grid(column=1, row=4, sticky=(W, E)) # A really simple way to change label text: test_lbl = Label(self) test_lbl.grid(column=3, row=4, sticky=E) test_lbl['text'] = 'hello!' # Handling label's events ev_lbl = Label(self, text='Do something with me...', width=30) ev_lbl.grid(column=1, row=5, columnspan=2, rowspan=2) ev_lbl.bind('<Enter>', lambda e: ev_lbl.configure(text='Moved mouse inside')) ev_lbl.bind('<Leave>', lambda e: ev_lbl.configure(text='Moved mouse outside')) ev_lbl.bind( '<1>', lambda e: ev_lbl.configure(text='Clicked left mouse button!')) ev_lbl.bind( '<Double-1>', lambda e: ev_lbl.configure( text='Double clicked left mouse button!')) # Configure pads for all grid cells for child in self.winfo_children(): child.grid_configure(padx=5, pady=5) # As default, entry is focused self.feet_entry.focus()
def file_entry(text_var: tk.StringVar, container: ttk.Frame, row: int, label: ttk.Label): """ Creates a labeled entry with a browse button for the excel file. :param text_var: the variable that will store the entry value :param container: the container to add the widgets to :param row: the row of the container grid to add the widget to :param label: the row label, used for binding an onClick handler """ label.bind("<Button-1>", lambda _: mbox.showinfo("File name", text_var.get())) docs_photo = ImageTk.PhotoImage(DOCS_ICON) browse_button = ttk.Button(container, image=docs_photo, command=lambda: browse_file(text_var), width=10) browse_button.grid(column=4, row=row, sticky=(tk.E, tk.W), padx=5, pady=5) browse_button.image = docs_photo
def __init__(self, parent, funnel, index, command_stack): tk.Frame.__init__(self, parent, borderwidth=4, relief="raised") Subscriber.__init__(self, funnel) Observable.__init__(self) self._funnel = funnel self._command_stack = command_stack self._active_var = tk.IntVar() self._active_var.trace_add("write", self._switch_active) self._position_var = tk.StringVar() self._position_var.trace_add("write", self._set_position) self._oval_var = tk.IntVar() self._oval_var.trace_add("write", self._switch_oval) self._update() self.bind("<Button-1>", self._on_click) is_active = Checkbutton(self, text=f"Funnel n°{index}: ", variable=self._active_var) is_active.grid(columnspan=3) is_active.bind("<FocusIn>", self._on_get_focus) is_active.bind("<FocusOut>", self._on_lost_focus) pos_label = Label(self, text=" Position: ") pos_label.grid(sticky=tk.E) pos_label.bind("<Button-1>", self._on_click) self._pos_entry = Entry(self, textvariable=self._position_var, width=6) self._pos_entry.grid(row=1, column=1, sticky=tk.W) self._pos_entry.bind("<FocusIn>", self._on_get_focus) self._pos_entry.bind("<FocusOut>", self._on_lost_focus) is_oval = Checkbutton(self, text="Is Oval", variable=self._oval_var) is_oval.grid(row=1, column=2) is_oval.bind("<FocusIn>", self._on_get_focus) is_oval.bind("<FocusOut>", self._on_lost_focus) self.columnconfigure(0, weight=1) self.columnconfigure(1, weight=1) self.columnconfigure(2, weight=1)
def display_evts(self): def wrap(event): l = event.widget if l.master.winfo_ismapped(): l.configure(wraplength=l.winfo_width()) week = self.master.get_next_week_events() date_today = datetime.now().date() today = date_today.strftime('%A') children = list(self.display.children.values()) for ch in children: ch.destroy() for day, evts in week.items(): if day == today: text = _('Today') else: text = day.capitalize() Label(self.display, text=text, style='day.Events.TLabel').grid(sticky='w', pady=(4, 0), padx=4) for ev, desc in evts: if desc.strip(): tf = ToggledFrame(self.display, text=ev.strip(), style='Events.TFrame') l = Label(tf.interior, text=desc.strip(), style='Events.TLabel') l.pack(padx=4, fill='both', expand=True) l.configure(wraplength=l.winfo_width()) l.bind('<Configure>', wrap) tf.grid(sticky='we', pady=2, padx=(8, 4)) else: l = Label(self.display, text=ev.strip(), style='Events.TLabel') l.bind('<Configure>', wrap) l.grid(sticky='ew', pady=2, padx=(21, 10))
def create_content(self, **kw): self.rowconfigure(2, weight=1) self.columnconfigure(0, weight=1) self.minsize(50, 50) self.hide_completed = CONFIG.getboolean('Tasks', 'hide_completed') # --- elements label = Label(self, text=_('Tasks').upper(), style='title.Tasks.TLabel', anchor='center') label.grid(row=0, columnspan=2, pady=4, sticky='ew') Separator(self, style='Tasks.TSeparator').grid(row=1, columnspan=2, sticky='we') self.display = Text(self, width=20, height=10, relief='flat', cursor='arrow', wrap='word', highlightthickness=0, state='disabled', spacing1=5, tabs=('35', 'right', '45', 'left')) self.display.grid(sticky='nsew', row=2, column=0, padx=2, pady=2) scroll = AutoScrollbar(self, orient='vertical', style='Tasks.Vertical.TScrollbar', command=self.display.yview) scroll.grid(row=2, column=1, sticky='ns', pady=(2, 16)) self.display.configure(yscrollcommand=scroll.set) self.display_tasks() corner = Sizegrip(self, style="Tasks.TSizegrip") corner.place(relx=1, rely=1, anchor='se') # --- bindings self.bind('<3>', lambda e: self.menu.tk_popup(e.x_root, e.y_root)) label.bind('<ButtonPress-1>', self._start_move) label.bind('<ButtonRelease-1>', self._stop_move) label.bind('<B1-Motion>', self._move)
def __init__(self, parent, structure, command_stack, on_get_focus): tk.Frame.__init__(self, parent) self.command_stack = command_stack self._structure = structure self._fill_var = tk.IntVar() self._fill_var.set(self._structure.fill) (Checkbutton(self, text="Fill", variable=self._fill_var).grid( row=EditZone._FILL_CHECK_ROW, column=0, columnspan=2)) self._fill_var.trace_add("write", self._set_fill) self._point_index = -1 self._point_index_var = tk.StringVar() top_label = Label(self, textvariable=self._point_index_var) top_label.grid(row=EditZone._POINT_INDEX_ROW, column=0, columnspan=2) top_label.bind("<Button-1>", on_get_focus) x_label = Label(self, text="\u21d5:") x_label.grid(row=EditZone._X_ROW, column=0, sticky=tk.E) x_label.bind("<Button-1>", on_get_focus) y_label = Label(self, text="\u21d4:") y_label.grid(row=EditZone._Y_ROW, column=0, sticky=tk.E) y_label.bind("<Button-1>", on_get_focus) #the updating_ booleans allow to detect if the stringvars are edited #because the point is selected #or if the user changed their value self.inhibit_callbacks = True self.editable_x = tk.StringVar() self.editable_y = tk.StringVar() setx = Entry(self, textvariable=self.editable_x, width=6) setx.grid(row=EditZone._X_ROW, column=1, sticky=tk.W) setx.bind("<FocusIn>", on_get_focus) sety = Entry(self, textvariable=self.editable_y, width=6) sety.grid(row=EditZone._Y_ROW, column=1, sticky=tk.W) sety.bind("<FocusIn>", on_get_focus) self.editable_x.trace_add("write", self._point_edited) self.editable_y.trace_add("write", self._point_edited) (Button(self, text="Add Vertex", command=self._add_point).grid(row=EditZone._ADD_ROW, column=0, columnspan=2, sticky=tk.E + tk.W)) (Button(self, text="Delete", command=self._delete_point).grid(row=EditZone._DEL_ROW, column=0, columnspan=2, sticky=tk.E + tk.W)) (Button(self, text="Symmetry", command=self._apply_symmetry).grid(row=EditZone._SYMM_ROW, column=0, columnspan=2, sticky=tk.E + tk.W))
class Handle(Frame): def __init__(self, panedwindow, sash_index, disallow_dragging=False, on_click=None, **kw): image = kw.pop("image", None) Frame.__init__(self, panedwindow, class_="Handle", **kw) self._sash_index = sash_index if image: self._event_area = Label(self, image=image) self._event_area.pack() else: self._event_area = self self._center = int(self._event_area.winfo_reqwidth() / 2), int( self._event_area.winfo_reqheight() / 2) if disallow_dragging: if on_click: self._event_area.bind('<Button-1>', lambda event: on_click()) else: # noinspection PyProtectedMember self._event_area.bind('<Button-1>', self._initiate_motion) # noinspection PyProtectedMember self._event_area.bind('<B1-Motion>', self._on_dragging) # noinspection PyProtectedMember self._event_area.bind('<ButtonRelease-1>', self.master._on_release) def _initiate_motion(self, event): self.master._active_sash = self._sash_index self._dx = event.x self._dy = event.y @property def sash_index(self): return self._sash_index def _on_dragging(self, event): raise NotImplementedError
class Example(Toplevel): def __init__(self, parent): Toplevel.__init__(self, parent) self.initUI() def initUI(self): self.overrideredirect(True) ## removes the window decoration bitmap = BitmapImage( data=BITMAP) ## a bitmap is created from the data provided msg = "Click on the grip to move\nRight click to terminate" self.label = Label(self, text=msg) self.grip = Label(self, image=bitmap) self.grip.image = bitmap self.grip.pack(side="left", fill="y") self.label.pack(side="right", fill="both", padx=3, expand=True) self.grip.bind("<ButtonPress -1>", self.startMove) self.grip.bind("<ButtonRelease -1>", self.stopMove) self.grip.bind("<B1-Motion >", self.onMotion) self.bind("<ButtonPress -3>", self.onRightClick) self.geometry("+300+300") def startMove(self, e): self.x = e.x self.y = e.y ''' onMotion is called for every pixel moved, I bet. and gives a more or less smooth move. ''' def onMotion(self, e): deltax = e.x - self.x deltay = e.y - self.y x = self.winfo_x() + deltax y = self.winfo_y() + deltay self.geometry("+%s+%s" % (x, y)) def stopMove(self, e): e.x = None e.y = None def onRightClick(self, e): self.quit()
def create_content(self, **kw): self.minsize(50, 50) self.rowconfigure(2, weight=1) self.columnconfigure(0, weight=1) label = Label(self, text=_('Events').upper(), style='title.Events.TLabel', anchor='center') label.grid(row=0, columnspan=2, pady=4, sticky='ew') Separator(self, style='Events.TSeparator').grid(row=1, columnspan=2, sticky='we') self.canvas = Canvas(self, highlightthickness=0) self.canvas.grid(sticky='nsew', row=2, column=0, padx=2, pady=2) scroll = AutoScrollbar(self, orient='vertical', style='Events.Vertical.TScrollbar', command=self.canvas.yview) scroll.grid(row=2, column=1, sticky='ns', pady=(2, 16)) self.canvas.configure(yscrollcommand=scroll.set) self.display = Frame(self.canvas, style='Events.TFrame') self.canvas.create_window(0, 0, anchor='nw', window=self.display, tags=('display', )) self.display_evts() corner = Sizegrip(self, style="Events.TSizegrip") corner.place(relx=1, rely=1, anchor='se') # --- bindings self.bind('<3>', lambda e: self.menu.tk_popup(e.x_root, e.y_root)) label.bind('<ButtonPress-1>', self._start_move) label.bind('<ButtonRelease-1>', self._stop_move) label.bind('<B1-Motion>', self._move) self.bind('<4>', lambda e: self._scroll(-1)) self.bind('<5>', lambda e: self._scroll(1)) self.update_idletasks() self.canvas.configure(scrollregion=self.canvas.bbox('all'))
class autoClicker(Frame): def __init__(self, parent): Frame.__init__(self, parent) self.parent = parent self.initUI() def initUI(self): self.sliderTime=0 self.running = 0 self.leftclick = 0 self.middleclick = 0 self.rightclick = 0 self.parent.overrideredirect(True) self.style = Style() self.style.theme_use("default") self.parent.wm_attributes("-topmost", 1) self.parent.resizable(0,0) self.gripBar = BitmapImage(data=GRIPBAR) self.closeBox = BitmapImage(data=CLOSEBOX) self.closeHover = BitmapImage(data=CLOSEHOVER) self.leftClick = BitmapImage(data=LEFTCLICK) self.leftClickDown = BitmapImage(data=LEFTCLICKDOWN) self.middleClick = BitmapImage(data=MIDDLECLICK) self.middleClickDown = BitmapImage(data=MIDDLECLICKDOWN) self.rightClick = BitmapImage(data=RIGHTCLICK) self.rightClickDown = BitmapImage(data=RIGHTCLICKDOWN) self.barFrame = Frame(self) self.barFrame.pack(side=TOP, fill=BOTH) self.clickFrame = Frame(self, borderwidth=0) self.clickFrame.pack(side=TOP, fill=BOTH, padx=12, expand=1) self.sliderScale = Scale(self, from_=0, to=1, resolution=.01, orient=HORIZONTAL, borderwidth=0, showvalue=0) self.sliderScale.pack(side=TOP, fill="x", expand=1) self.buttonFrame = Frame(self, borderwidth=0) self.buttonFrame.pack(side=TOP, fill=BOTH, expand=1) self.grip = Label(self.barFrame, image=self.gripBar) self.grip.image=self.gripBar self.grip.pack(side=LEFT, fill="x") self.grip.bind("<ButtonPress-1>", self.startMove) self.grip.bind("<ButtonRelease-1>", self.stopMove) self.grip.bind("<B1-Motion>", self.onMotion) self.closeButton = Label(self.barFrame, image=self.closeBox) self.closeButton.image=self.closeBox self.closeButton.pack(side=RIGHT, fill="none") self.closeButton.bind("<ButtonPress-1>", self.sysExit) self.closeButton.bind("<Enter>", self.onHover) self.closeButton.bind("<Leave>", self.onLeave) self.leftClickToggle = Label(self.clickFrame, image=self.leftClick, borderwidth=0) self.leftClickToggle.image=self.leftClick self.leftClickToggle.pack(side=LEFT, expand=1) self.leftClickToggle.bind("<Button-1>", self.leftToggle) self.middleClickToggle = Label(self.clickFrame, image=self.middleClick, borderwidth=0) self.middleClickToggle.image=self.middleClick self.middleClickToggle.pack(side=LEFT, expand=1) self.middleClickToggle.bind("<Button-1>", self.middleToggle) self.rightClickToggle = Label(self.clickFrame, image=self.rightClick, borderwidth=0) self.rightClickToggle.image=self.rightClick self.rightClickToggle.pack(side=LEFT, expand=1) self.rightClickToggle.bind("<Button-1>", self.rightToggle) self.startButton = Button(self.buttonFrame, text="Start", relief=FLAT, activebackground="lightgrey", borderwidth=0) self.startButton.pack(fill=BOTH, expand=1) self.startButton.bind("<Button-1>", self.startClick) self.startButton.bind("<space>", self.startClick) w = 116 h = 74 ws = self.winfo_screenwidth() # width of the screen hs = self.winfo_screenheight() # height of the screen x = (ws/2) - (w/2) y = (hs/2) - (h/2) self.parent.geometry('%dx%d+%d+%d' % (w, h, x, y)) self.parent.config(bg="black") self.pack(fill="both", padx=1, pady=1) def leftToggle(self,event): if self.running == 0: if self.leftclick == 0: event.widget.configure(image=self.leftClickDown) self.leftclick = 1; else: event.widget.configure(image=self.leftClick) self.leftclick = 0; def middleToggle(self,event): if self.running == 0: if self.middleclick == 0: event.widget.configure(image=self.middleClickDown) self.middleclick = 1; else: event.widget.configure(image=self.middleClick) self.middleclick = 0; def rightToggle(self,event): if self.running == 0: if self.rightclick == 0: event.widget.configure(image=self.rightClickDown) self.rightclick = 1; else: event.widget.configure(image=self.rightClick) self.rightclick = 0; def onHover(self,event): event.widget.configure(image=self.closeHover) def onLeave(self,event): event.widget.configure(image=self.closeBox) def startMove(self,event): self.parent.x = event.x self.parent.y = event.y def onMotion(self, event): deltax = event.x - self.parent.x deltay = event.y - self.parent.y x = self.parent.winfo_x() + deltax y = self.parent.winfo_y() + deltay self.parent.geometry("+%s+%s" % (x, y)) def stopMove(self, event): event.x = None event.y = None def sysExit(self, event): self.running = 0 sys.exit() def startClick(self, event): if self.running == 0 and not (self.leftclick == 0 and self.middleclick==0 and self.rightclick == 0): self.running = 1 event.widget.config(text="Stop") currentMouseX, currentMouseY = pyautogui.position() pyautogui.moveTo(currentMouseX, currentMouseY+50) threading.Thread(target=self.startLoop, args=()).start() else: self.running = 0 event.widget.config(text="Start") time.sleep(0.2) return def startLoop(self): while self.running == 1: if self.leftclick == 1: pyautogui.click() if self.middleclick == 1: pyautogui.click(button="middle") if self.rightclick == 1: pyautogui.click(button="right") delay = self.sliderScale.get() time.sleep(delay) return
class Timer(BaseWidget): def __init__(self, master): BaseWidget.__init__(self, 'Timer', master) def create_content(self, **kw): self.minsize(50, 120) self._time = [0, 0, 0] self._on = False self._after_id = '' self.img_play = PhotoImage(master=self, file=IM_START) self.img_pause = PhotoImage(master=self, file=IM_PAUSE) self.img_stop = PhotoImage(master=self, file=IM_STOP) self.rowconfigure(2, weight=1) self.columnconfigure(0, weight=1) self.columnconfigure(1, weight=1) # --- GUI elements self.display = Label(self, text='%i:%.2i:%.2i' % tuple(self._time), anchor='center', style='timer.TLabel') self.intervals = Text(self, highlightthickness=0, relief='flat', height=3, width=1, inactiveselectbackground=self.style.lookup('TEntry', 'selectbackground')) self.intervals.tag_configure('center', justify='center') self.intervals.configure(state='disabled') self.b_interv = Button(self, text=_('Interval'), style='timer.TButton', command=self.add_interval) self.b_interv.state(('disabled',)) self.b_launch = Button(self, image=self.img_play, padding=2, command=self.launch, style='timer.TButton') self.b_stop = Button(self, image=self.img_stop, padding=2, command=self.stop, style='timer.TButton') # --- placement self.display.grid(row=0, columnspan=2, sticky='ew', padx=8, pady=(4, 0)) Label(self, text=_('Intervals:'), style='timer.TLabel').grid(row=1, columnspan=2, sticky='w', padx=4) self.intervals.grid(row=2, columnspan=2, sticky='eswn') self.b_interv.grid(row=3, columnspan=2, sticky='ew') self.b_launch.grid(row=4, column=0, sticky='ew') self.b_stop.grid(row=4, column=1, sticky='ew') self._corner = Sizegrip(self, style="timer.TSizegrip") self._corner.place(relx=1, rely=1, anchor='se') # --- bindings self.intervals.bind("<1>", lambda event: self.intervals.focus_set()) self.bind('<3>', lambda e: self.menu.tk_popup(e.x_root, e.y_root)) self.display.bind('<ButtonPress-1>', self._start_move) self.display.bind('<ButtonRelease-1>', self._stop_move) self.display.bind('<B1-Motion>', self._move) self.b_stop.bind('<Enter>', self._on_enter) self.b_stop.bind('<Leave>', self._on_leave) def update_style(self): self.attributes('-alpha', CONFIG.get(self.name, 'alpha', fallback=0.85)) bg = CONFIG.get('Timer', 'background') fg = CONFIG.get('Timer', 'foreground') active_bg = active_color(*self.winfo_rgb(bg)) self.configure(bg=bg) self.menu.configure(bg=bg, fg=fg, selectcolor=fg, activeforeground=fg, activebackground=active_bg) self.menu_pos.configure(bg=bg, fg=fg, selectcolor=fg, activeforeground=fg, activebackground=active_bg) self.display.configure(font=CONFIG.get('Timer', 'font_time')) self.intervals.configure(bg=bg, fg=fg, font=CONFIG.get('Timer', 'font_intervals')) self.style.configure('timer.TButton', background=bg, relief='flat', foreground=fg, borderwidth=0) self.style.configure('timer.TLabel', background=bg, foreground=fg) self.style.configure('timer.TSizegrip', background=bg) self.style.map('timer.TSizegrip', background=[('active', active_bg)]) self.style.map('timer.TButton', background=[('disabled', bg), ('!disabled', 'active', active_bg)]) def _on_enter(self, event=None): self._corner.state(('active',)) def _on_leave(self, event=None): self._corner.state(('!active',)) def show(self): self.deiconify() self.update_idletasks() self.withdraw() if self._position.get() == 'above': self.overrideredirect(True) else: self.overrideredirect(False) BaseWidget.show(self) self.update_idletasks() self.withdraw() self.deiconify() def _run(self): if self._on: self._time[2] += 1 if self._time[2] == 60: self._time[2] = 0 self._time[1] += 1 if self._time[1] == 60: self._time[1] = 0 self._time[0] += 1 self.display.configure(text='%i:%.2i:%.2i' % tuple(self._time)) self._after_id = self.after(1000, self._run) def launch(self): if self._on: self._on = False self.b_launch.configure(image=self.img_play) self.b_interv.state(('disabled',)) else: self._on = True self.b_interv.state(('!disabled',)) self.b_launch.configure(image=self.img_pause) self.after(1000, self._run) def add_interval(self): tps = '\n%i:%.2i:%.2i' % tuple(self._time) if self.intervals.get('1.0', 'end') == '\n': tps = tps[1:] self.intervals.configure(state='normal') self.intervals.insert('end', tps, 'center') self.intervals.configure(state='disabled') def stop(self): self._on = False self.b_interv.state(('disabled',)) self.b_launch.configure(image=self.img_play) self._time = [0, 0, 0] self.intervals.configure(state='normal') self.intervals.delete('1.0', 'end') self.intervals.configure(state='disabled') self.display.configure(text='%i:%.2i:%.2i' % tuple(self._time))
def define_login_window(self): """ Define login screen with all visual elements (Fields, Buttons, ...) """ self.login_window.title("Login") # Create the label Label(self.login_window, text="Please enter login details:").grid(row=0, column=0, columnspan=2, sticky="ew", padx=10, pady=10) # USERNAME ENTRY Label(self.login_window, text="Username").grid(row=1, column=0, sticky="e", padx=10) Entry(self.login_window, textvariable=self.username_login).grid(row=1, column=1, sticky="e", padx=10) # PASSWORD ENTRY Label(self.login_window, text="Password").grid(row=2, column=0, sticky="e", padx=10) Entry(self.login_window, textvariable=self.password_login, show='*').grid(row=2, column=1, sticky="e", padx=10) # LOGIN button Button(self.login_window, text="Login", width=10, height=1, command=self.login_handler).grid(row=3, column=1, sticky="ew", padx=10, pady=5) # NEW ACCOUNT Label new_account_label = Label(self.login_window, text="No account yet? Sign up!") new_account_label.grid(row=4, column=0, columnspan=2, sticky="ew", padx=10, pady=10) f = font.Font(new_account_label, new_account_label.cget("font")) f.configure(underline=True) new_account_label.configure(font=f) new_account_label.bind("<Button-1>", self.generate_signup_window) # This function self.close_login_window, # is called when pushing the cross button right top to close the window, self.login_window.protocol("WM_DELETE_WINDOW", self.close_login_window)
class Pomodoro(BaseWidget): """ Chronometre de temps de travail pour plus d'efficacité """ def __init__(self, master): BaseWidget.__init__(self, 'Pomodoro', master) def create_content(self, **kw): self.minsize(190, 190) self.on = False # is the timer on? if not CONFIG.options("Tasks"): CONFIG.set("Tasks", _("Work"), CMAP[0]) self._stats = None # --- colors self.background = { _("Work"): CONFIG.get("Pomodoro", "work_bg"), _("Break"): CONFIG.get("Pomodoro", "break_bg"), _("Rest"): CONFIG.get("Pomodoro", "rest_bg") } self.foreground = { _("Work"): CONFIG.get("Pomodoro", "work_fg"), _("Break"): CONFIG.get("Pomodoro", "break_fg"), _("Rest"): CONFIG.get("Pomodoro", "rest_fg") } self.rowconfigure(1, weight=1) self.columnconfigure(0, weight=1) self.columnconfigure(1, weight=1) # nombre de séquence de travail effectuées d'affilée (pour # faire des pauses plus longues tous les 4 cycles) self.nb_cycles = 0 self.pomodori = IntVar(self, 0) # --- images self.im_go = PhotoImage(master=self, file=IM_START) self.im_stop = PhotoImage(master=self, file=IM_STOP) self.im_tomate = PhotoImage(master=self, file=IM_POMODORO) self.im_graph = PhotoImage(master=self, file=IM_GRAPH) # --- tasks list tasks_frame = Frame(self, style='pomodoro.TFrame') tasks_frame.grid(row=3, column=0, columnspan=3, sticky="wnse") tasks = [t.capitalize() for t in CONFIG.options("PomodoroTasks")] tasks.sort() self.task = StringVar(self, tasks[0]) self.menu_tasks = Menu(tasks_frame, relief='sunken', activeborderwidth=0) self.choose_task = Menubutton(tasks_frame, textvariable=self.task, menu=self.menu_tasks, style='pomodoro.TMenubutton') Label(tasks_frame, text=_("Task: "), style='pomodoro.TLabel', font="TkDefaultFont 12", width=6, anchor="e").pack(side="left", padx=4) self.choose_task.pack(side="right", fill="x", pady=4) # --- display self.tps = [CONFIG.getint("Pomodoro", "work_time"), 0] # time: min, sec self.activite = StringVar(self, _("Work")) self.titre = Label(self, textvariable=self.activite, font='TkDefaultFont 14', style='timer.pomodoro.TLabel', anchor="center") self.titre.grid(row=0, column=0, columnspan=2, sticky="we", pady=(4, 0), padx=4) self.temps = Label(self, text="{0:02}:{1:02}".format(self.tps[0], self.tps[1]), style='timer.pomodoro.TLabel', anchor="center") self.temps.grid(row=1, column=0, columnspan=2, sticky="nswe", padx=4) self.aff_pomodori = Label(self, textvariable=self.pomodori, anchor='e', padding=(20, 4, 20, 4), image=self.im_tomate, compound="left", style='timer.pomodoro.TLabel', font='TkDefaultFont 14') self.aff_pomodori.grid(row=2, columnspan=2, sticky="ew", padx=4) # --- buttons self.b_go = Button(self, image=self.im_go, command=self.go, style='pomodoro.TButton') self.b_go.grid(row=4, column=0, sticky="ew") self.b_stats = Button(self, image=self.im_graph, command=self.display_stats, style='pomodoro.TButton') self.b_stats.grid(row=4, column=1, sticky="ew") self._corner = Sizegrip(self, style="pomodoro.TSizegrip") self._corner.place(relx=1, rely=1, anchor='se') # --- bindings self.bind('<3>', lambda e: self.menu.tk_popup(e.x_root, e.y_root)) tasks_frame.bind('<ButtonPress-1>', self._start_move) tasks_frame.bind('<ButtonRelease-1>', self._stop_move) tasks_frame.bind('<B1-Motion>', self._move) self.titre.bind('<ButtonPress-1>', self._start_move) self.titre.bind('<ButtonRelease-1>', self._stop_move) self.titre.bind('<B1-Motion>', self._move) self.temps.bind('<ButtonPress-1>', self._start_move) self.temps.bind('<ButtonRelease-1>', self._stop_move) self.temps.bind('<B1-Motion>', self._move) self.b_stats.bind('<Enter>', self._on_enter) self.b_stats.bind('<Leave>', self._on_leave) def update_style(self): self.menu_tasks.delete(0, 'end') tasks = [t.capitalize() for t in CONFIG.options('PomodoroTasks')] tasks.sort() for task in tasks: self.menu_tasks.add_radiobutton(label=task, value=task, variable=self.task) if self.task.get() not in tasks: self.stop(False) self.task.set(tasks[0]) self.attributes('-alpha', CONFIG.get(self.name, 'alpha', fallback=0.85)) bg = CONFIG.get('Pomodoro', 'background') fg = CONFIG.get('Pomodoro', 'foreground') active_bg = active_color(*self.winfo_rgb(bg)) self.style.configure('pomodoro.TMenubutton', background=bg, relief='flat', foreground=fg, borderwidth=0, arrowcolor=fg) self.style.configure('pomodoro.TButton', background=bg, relief='flat', foreground=fg, borderwidth=0) self.style.configure('pomodoro.TLabel', background=bg, foreground=fg) self.style.configure('pomodoro.TFrame', background=bg) self.style.configure('pomodoro.TSizegrip', background=bg) self.style.map('pomodoro.TSizegrip', background=[('active', active_bg)]) self.style.map('pomodoro.TButton', background=[('disabled', bg), ('!disabled', 'active', active_bg)]) self.style.map('pomodoro.TMenubutton', background=[('disabled', bg), ('!disabled', 'active', active_bg)]) self.configure(bg=bg) self.menu.configure(bg=bg, fg=fg, selectcolor=fg, activeforeground=fg, activebackground=active_bg) self.menu_pos.configure(bg=bg, fg=fg, selectcolor=fg, activeforeground=fg, activebackground=active_bg) self.menu_tasks.configure(bg=bg, activebackground=active_bg, fg=fg, selectcolor=fg, activeforeground=fg) self.background = { _("Work"): CONFIG.get("Pomodoro", "work_bg"), _("Break"): CONFIG.get("Pomodoro", "break_bg"), _("Rest"): CONFIG.get("Pomodoro", "rest_bg") } self.foreground = { _("Work"): CONFIG.get("Pomodoro", "work_fg"), _("Break"): CONFIG.get("Pomodoro", "break_fg"), _("Rest"): CONFIG.get("Pomodoro", "rest_fg") } act = self.activite.get() self.style.configure('timer.pomodoro.TLabel', font=CONFIG.get("Pomodoro", "font"), foreground=self.foreground[act], background=self.background[act]) def _on_enter(self, event=None): self._corner.state(('active', )) def _on_leave(self, event=None): self._corner.state(('!active', )) def _start_move(self, event): self.x = event.x self.y = event.y def _stop_move(self, event): self.x = None self.y = None self.configure(cursor='arrow') def _move(self, event): if self.x is not None and self.y is not None: self.configure(cursor='fleur') deltax = event.x - self.x deltay = event.y - self.y x = self.winfo_x() + deltax y = self.winfo_y() + deltay self.geometry("+%s+%s" % (x, y)) def hide(self): if self._stats is not None: self._stats.destroy() BaseWidget.hide(self) def stats(self, time=None): """Save stats.""" if time is None: time = CONFIG.getint("Pomodoro", "work_time") today = dt.date.today().toordinal() task = self.task.get().lower().replace(' ', '_') db = sqlite3.connect(PATH_STATS) cursor = db.cursor() try: cursor.execute('SELECT * FROM {} ORDER BY id DESC LIMIT 1'.format( scrub(task))) key, date, work = cursor.fetchone() except sqlite3.OperationalError: cursor.execute('''CREATE TABLE {} (id INTEGER PRIMARY KEY, date INTEGER, work INTEGER)'''.format( scrub(task))) cursor.execute( 'INSERT INTO {}(date, work) VALUES (?, ?)'.format(scrub(task)), (today, time)) else: if today != date: cursor.execute( 'INSERT INTO {}(date, work) VALUES (?, ?)'.format( scrub(task)), (today, time)) else: # update day's value cursor.execute( 'UPDATE {} SET work=? WHERE id=?'.format(scrub(task)), (work + time, key)) finally: db.commit() db.close() def display_stats(self): """ affiche les statistiques """ if self._stats is None: self._stats = Stats(self) self._stats.bind('<Destroy>', self._on_close_stats) else: self._stats.lift() def _on_close_stats(self, event): self._stats = None def go(self): if self.on: self.stop() else: self.on = True self.choose_task.state(["disabled"]) self.b_go.configure(image=self.im_stop) self.after(1000, self.affiche) logging.info('Start work cycle for task ' + self.task.get()) def stop(self, confirmation=True): """ Arrête le décompte du temps et le réinitialise, demande une confirmation avant de le faire si confirmation=True """ tps = int( CONFIG.getint("Pomodoro", "work_time") - self.tps[0] - self.tps[1] / 60) self.on = False rep = True if confirmation: rep = askyesno( title=_("Confirmation"), message=_( "Are you sure you want to give up the current session?")) if rep: self.choose_task.state(["!disabled"]) self.b_go.configure(image=self.im_go) if self.activite.get() == _("Work"): self.stats(tps) self.pomodori.set(0) self.nb_cycles = 0 self.tps = [CONFIG.getint("Pomodoro", "work_time"), 0] self.temps.configure( text="{0:02}:{1:02}".format(self.tps[0], self.tps[1])) act = _("Work") self.activite.set(act) self.style.configure('timer.pomodoro.TLabel', background=self.background[act], foreground=self.foreground[act]) logging.info('Pomodoro session interrupted.') else: self.on = True self.affiche() return rep @staticmethod def ting(): """ joue le son marquant le changement de période """ if not CONFIG.getboolean("Pomodoro", "mute", fallback=False): Popen([ CONFIG.get("General", "soundplayer"), CONFIG.get("Pomodoro", "beep") ]) def affiche(self): if self.on: self.tps[1] -= 1 if self.tps[1] == 0: if self.tps[0] == 0: self.ting() if self.activite.get() == _("Work"): self.pomodori.set(self.pomodori.get() + 1) self.nb_cycles += 1 self.choose_task.state(["!disabled"]) logging.info( 'Pomodoro: completed work session for task ' + self.task.get()) if self.nb_cycles % 4 == 0: # pause longue self.stats() self.activite.set(_("Rest")) self.tps = [ CONFIG.getint("Pomodoro", "rest_time"), 0 ] else: # pause courte self.stats() self.activite.set(_("Break")) self.tps = [ CONFIG.getint("Pomodoro", "break_time"), 0 ] else: self.choose_task.state(["disabled"]) self.activite.set(_("Work")) self.tps = [CONFIG.getint("Pomodoro", "work_time"), 0] act = self.activite.get() self.style.configure('timer.pomodoro.TLabel', background=self.background[act], foreground=self.foreground[act]) elif self.tps[1] == -1: self.tps[0] -= 1 self.tps[1] = 59 self.temps.configure(text="{0:02}:{1:02}".format(*self.tps)) self.after(1000, self.affiche)
class Update(ThemedTk): def __init__(self): ThemedTk.__init__(self, theme='black') self.title('Обновление F_Reference_H') self.geometry('500x140') x = (self.winfo_screenwidth() - self.winfo_reqwidth()) / 2 y = (self.winfo_screenheight() - self.winfo_reqheight()) / 2 self.wm_geometry("+%d+%d" % (x - 150, y)) self.resizable(width=False, height=False) self.iconphoto(True, PhotoImage(file='settings/ico/ico_main.png')) flow_hack_png = Image.open(f'settings/ico/mini_flowhack.png') flow_hack_png = ImageTk.PhotoImage(flow_hack_png) self.frame = Frame(self) self.frame.place(relwidth=1, relheight=1) flow_1 = Label(self.frame, image=flow_hack_png, cursor='heart') flow_1.bind('<Button-1>', lambda no_matter: webopen(VK)) flow_1.place(relx=.09, rely=.085, anchor='center') flow_2 = Label(self.frame, image=flow_hack_png, cursor='heart') flow_2.bind('<Button-1>', lambda no_matter: webopen(VK)) flow_2.place(relx=.91, rely=.085, anchor='center') self.lbl_done = Label(self.frame, text='ОБНОВЛЕНИЕ', font=('Times New Roman', 12, 'bold italic')) self.lbl_done.place(relx=.5, rely=.1, anchor='c') self.lable_second = Label( self.frame, text='Нам понадобится интернет!\nМы всё сделаем сами, это не ' 'займё много времени!', font=('Times New Roman', 10, 'bold italic'), justify='center') self.lable_second.place(relx=.5, rely=.35, anchor='c') self.btn_update = Button(self.frame, text='Обновить', cursor='hand1', command=self.updater_window) self.btn_update.place(relx=.5, rely=.65, anchor='c') self.license = Label( self.frame, cursor='hand1', text='Нажимая "Обновить" вы принимаете лицензионное соглашение', font=('Times New Roman', 10, 'bold italic'), foreground='black') self.license.bind('<Button-1>', lambda no_matter: webopen(SAIT)) self.license.place(relx=.5, rely=.92, anchor='c') self.mainloop() def updater_window(self): try: if name == 'nt': with open(NAME_FILE, "wb") as f: response = requests.get(URL_FILE, stream=True) total_length = int(response.headers.get('content-length')) self.btn_update.configure( text=f'Размер: {total_length / 1024 / 1024:0.2f} Mb') self.btn_update.update() if total_length is None: f.write(response.content) else: dl = 0 for data in response.iter_content(chunk_size=4096): dl += len(data) f.write(data) done = int(50 * dl / total_length) self.license.configure( text=f'\r{"=" * done}{" " * (50 - done)}') self.license.update() sys.stdout.flush() self.lbl_done.configure(text='Готово!', foreground='#DA9958') self.btn_update.configure(text='Открыть программу', command=open_app) elif name == 'posix': showerror('Error', 'К сожалению на Linux пока нельзя обновиться') self.btn_update.configure(text='Закрыть', command=open_app) except requests.exceptions.ConnectionError: showerror( 'Error', 'Произошла ошибка!\n\nПохоже, что у вас отсутствует ' 'подключение к интернету!\n\nЕсли не получается решить ' 'проблему, то напишите мне в блоке "Обратная связь" ')
def __init__(self, parent=None, title="", message="", traceback="", report_msg=False, button=_("Ok"), image="error"): """ Create an error messagebox. Arguments: parent: parent of the toplevel window title: message box title message: message box text (that can be selected) button: message displayed on the button traceback: error traceback to display below the error message report_msg: if True display a suggestion to report error image: image displayed at the left of the message, either a PhotoImage or a string """ Toplevel.__init__(self, parent, class_='Scheduler') self.transient(parent) self.resizable(False, False) self.title(title) self.result = "" self.button = button style = Style(self) style.configure("url.TLabel", foreground="blue") style.configure("txt.TFrame", background='white') if not parent: style.theme_use('clam') if isinstance(image, str): data = ICONS.get(image) if data: self.img = PhotoImage(master=self, data=data) else: self.img = PhotoImage(master=self, file=image) image = self.img frame = Frame(self) frame.rowconfigure(0, weight=1) frame.columnconfigure(1, weight=1) l = len(message) l2 = len(traceback) w = max(1, min(max(l, l2), 50)) h = 0 for line in message.splitlines(): h += 1 + len(line) // w h2 = 0 for line in traceback.splitlines(): h2 += 1 + len(line) // w if h + h2 < 3: w = min(l, 35) h = 0 for line in message.splitlines(): h += 1 + len(line) // w h2 = 0 for line in traceback.splitlines(): h2 += 1 + len(line) // w display = Text(frame, relief='flat', highlightthickness=0, font="TkDefaultFont 10 bold", bg=self.cget('bg'), height=h, width=w, wrap="word") display.configure(inactiveselectbackground=display.cget("selectbackground")) display.insert("1.0", message) display.configure(state="disabled") display.grid(row=0, column=1, pady=(10, 4), padx=4, sticky="ewns") display.bind("<Button-1>", lambda event: display.focus_set()) if image: Label(frame, image=image).grid(row=0, column=0, padx=4, pady=(10, 4)) frame2 = Frame(self) frame2.columnconfigure(0, weight=1) frame2.rowconfigure(0, weight=1) report_frame = Frame(self) if traceback: txt_frame = Frame(frame2, style='txt.TFrame', relief='sunken', borderwidth=1) error_msg = Text(txt_frame, width=w, wrap='word', font="TkDefaultFont 10", bg='white', height=8, highlightthickness=0) error_msg.bind("<Button-1>", lambda event: error_msg.focus_set()) error_msg.insert('1.0', traceback) error_msg.configure(state="disabled") scrolly = Scrollbar(frame2, orient='vertical', command=error_msg.yview) scrolly.grid(row=0, column=1, sticky='ns') scrollx = Scrollbar(frame2, orient='horizontal', command=error_msg.xview) scrollx.grid(row=1, column=0, sticky='ew') error_msg.configure(yscrollcommand=scrolly.set, xscrollcommand=scrollx.set) error_msg.pack(side='left', fill='both', expand=True) txt_frame.grid(row=0, column=0, sticky='ewsn') if report_msg: Label(report_frame, text=_("Please report this bug on ")).pack(side="left") url = Label(report_frame, style="url.TLabel", cursor="hand1", font="TkDefaultFont 10 underline", text="https://github.com/j4321/MyNotes/issues") url.pack(side="left") url.bind("<Button-1>", lambda e: url_open("https://github.com/j4321/MyNotes/issues")) b = Button(self, text=button, command=self.validate) frame.pack(fill='x') frame2.pack(fill='both', padx=4, pady=(4, 4)) report_frame.pack(fill="x", padx=4, pady=(4, 0)) b.pack(padx=10, pady=10) self.grab_set() b.focus_set()
class ManagerItem(Frame): def __init__(self, master, note_data, toggle_visibility_cmd): Frame.__init__(self, master, class_='ManagerItem', style='manager.TFrame') self.columnconfigure(0, weight=0, minsize=18) self.columnconfigure(1, weight=1, minsize=198) self.columnconfigure(2, weight=1, minsize=198) self.columnconfigure(3, weight=0, minsize=85) self.columnconfigure(4, weight=0, minsize=22) self.toggle_visibility_cmd = toggle_visibility_cmd title = note_data['title'] if title: title = title[:17] + (len(title) > 17) * '...' title = title.replace('\t', ' ') date = note_data.get('date', '??') txt = note_data['txt'].splitlines() if txt: txt = txt[0][:17] + (len(txt[0]) > 17 or len(txt) > 1) * '...' else: txt = '' txt = txt.replace('\t', ' ') self._data = {'title': title, 'text': txt, 'date': date} self.title = Label(self, text=title, anchor='w', style='manager.TLabel') self.text = Label(self, text=txt, anchor='w', style='manager.TLabel') self.date = Label(self, text=date, anchor='center', style='manager.TLabel') self.checkbutton = Checkbutton(self, style='manager.TCheckbutton') self.visibility = BooleanVar(self, note_data['visible']) self.toggle_visibility = Checkbutton(self, style='manager.Toggle', variable=self.visibility, command=self.toggle_visibility) self.checkbutton.grid(row=0, column=0, padx=(2, 0), pady=4, sticky='nsew') self.title.grid(row=0, column=1, padx=4, pady=4, sticky='ew') self.text.grid(row=0, column=2, padx=4, pady=4, sticky='ew') self.date.grid(row=0, column=3, padx=4, pady=4, sticky='ew') self.toggle_visibility.grid(row=0, column=4, padx=(0, 2), pady=4, sticky='wens') self.bind('<Enter>', self._on_enter) self.bind('<Leave>', self._on_leave) self.checkbutton.bind('<Enter>', self._on_enter) # override class binding self.checkbutton.bind('<Leave>', self._on_leave) # override class binding self.toggle_visibility.bind('<Enter>', self._on_enter) # override class binding self.toggle_visibility.bind('<Leave>', self._on_leave) # override class binding self.bind('<ButtonRelease-1>', self._on_click) self.text.bind('<ButtonRelease-1>', self._on_click) self.title.bind('<ButtonRelease-1>', self._on_click) self.date.bind('<ButtonRelease-1>', self._on_click) def state(self, statespec=None): return self.checkbutton.state(statespec) def toggle_visibility(self): self.toggle_visibility_cmd(self.visibility.get()) def get(self, key): if key == 'visibility': return self.visibility.get() else: return self._data[key] def get_values(self): return (self._data['title'], self._data['text'], self._data['date'], self.visibility.get()) def _on_enter(self, event): self.title.state(('active', )) self.text.state(('active', )) self.date.state(('active', )) self.checkbutton.state(('active', )) self.toggle_visibility.state(('active', )) Frame.state(self, ('active', )) return "break" def _on_leave(self, event): self.title.state(('!active', )) self.text.state(('!active', )) self.date.state(('!active', )) self.checkbutton.state(('!active', )) self.toggle_visibility.state(('!active', )) Frame.state(self, ('!active', )) return "break" def _on_click(self, event): self.checkbutton.invoke() return "break"
class App(ThemedTk): def __init__(self): ThemedTk.__init__(self, theme='black') self.title('Установщик F_Reference_H') self.geometry('500x200') x = (self.winfo_screenwidth() - self.winfo_reqwidth()) / 2 y = (self.winfo_screenheight() - self.winfo_reqheight()) / 2 self.wm_geometry("+%d+%d" % (x - 150, y - 20)) self.resizable(width=False, height=False) self.iconphoto( True, PhotoImage(file='bin/ico/ico_main.png') ) flow_hack_png = Image.open(f'bin/ico/max_flowhack.png') flow_hack_png = ImageTk.PhotoImage(flow_hack_png) browse_png = Image.open(f'bin/ico/browse.png') browse_png = ImageTk.PhotoImage(browse_png) self.frame = Frame(self) self.frame.place(relwidth=1, relheight=1) self.url = '' self._path = getcwd() flow_hack_label = Label( self.frame, image=flow_hack_png, cursor='heart' ) flow_hack_label.bind('<Button-1>', open_web) flow_hack_label.place(anchor='c', relx=.5, rely=.1) self.check_icon = BooleanVar() self.check_icon.set(bool(True)) Checkbutton( self.frame, text='Создать ярлык на рабочем столе', var=self.check_icon, cursor='cross' ).place(relx=.5, y=60, anchor='c') Label( self.frame, text='Выберите папку для установки', font=('Times New Roman', 10, 'bold italic') ).place(relx=.5, rely=.485, anchor='c') self.input_url = Entry( self.frame, state=DISABLED, font=('Times New Roman', 9, 'bold italic'), foreground='black' ) self.input_url.place( rely=.6, relx=.5, height=20, relwidth=.7, anchor='c' ) Button( self.frame, image=browse_png, cursor='hand1', command=self.directory ).place(relx=.86, rely=.455) Button( self.frame, image=browse_png, cursor='hand1', command=self.directory ).place(relx=.045, rely=.455) Button( self.frame, text='Установить', cursor='hand1', command=self.install ).place(relx=.5, rely=.75, anchor='c') self.license = Label( self.frame, text='Для подтверждения согласия с лицензионным ' 'соглашением\nНажмите на "Установить" правой кнопкой мыши', font=('Times New Roman', 9, 'bold italic'), foreground='black', cursor='hand1', justify='center' ) self.license.bind( '<Button-1>', lambda no_matter: webopen('https://flowhack.github.io/') ) self.license.place(relx=.5, rely=.93, anchor='c') self.mainloop() def directory(self): fits: bool = False while fits == bool(False): self.url = askdirectory() if ('\\' not in self.url) and ('/' not in self.url): showerror( 'Error', 'Мы заметили, что вы выбрали неверный адрес!' ) else: fits: bool = True self.input_url.configure(state=NORMAL) self.input_url.insert(END, self.url) self.input_url.after( 6000, lambda: self.input_url.configure(state=DISABLED) ) def install(self): url = path.join(self.url) try: if url == '': raise NameError('is empty') elif ('\\' not in self.url) and ('/' not in self.url): raise NameError('not file') move_file('bin/dist/F_Reference_H', url) if self.check_icon.get(): system( f'@powershell \"$x=(New-Object -ComObject ' f'WScript.Shell).CreateShortcut(' f'\'%USERPROFILE%/Desktop/F_Reference_H.lnk\');$x' f'.TargetPath=\'' f'{url}/F_Reference_H/F_Reference_H.exe\';$x' f'.WorkingDirectory=\'' f'{url}/F_Reference_H\';$x.Save()\" ' ) system( f'@powershell \"$x=(New-Object -ComObject ' f'WScript.Shell).CreateShortcut(' f'\'%APPDATA%\Microsoft\Windows\Start ' f'Menu\Programs\F_Reference_H.lnk\');$x' f'.TargetPath=\'' f'{url}/F_Reference_H/F_Reference_H.exe\';$x' f'.WorkingDirectory=\'{url}/F_Reference_H\';$x.Save()\"') showinfo('Successfully', 'Установка прошла успешно!') exit_ex() except NameError as error: if str(error) == 'is empty': showerror('Error', 'Пустое поле пути к папке!') if str(error) == 'not file': showerror( 'Error', 'Мы заметили, что вы выбрали неверный адрес!' )
class Sticky(Toplevel): """ Sticky note class """ def __init__(self, master, key, **kwargs): """ Create a new sticky note. master: main app key: key identifying this note in master.note_data kwargs: dictionnary of the other arguments (title, txt, category, color, tags, geometry, locked, checkboxes, images, rolled) """ Toplevel.__init__(self, master) # --- window properties self.id = key self.is_locked = not (kwargs.get("locked", False)) self.images = [] self.links = {} self.latex = {} self.nb_links = 0 self.title('mynotes%s' % key) self.attributes("-type", "splash") self.attributes("-alpha", CONFIG.getint("General", "opacity") / 100) self.focus_force() # window geometry self.update_idletasks() self.geometry(kwargs.get("geometry", '220x235')) self.save_geometry = kwargs.get("geometry", '220x235') self.update() self.rowconfigure(1, weight=1) self.minsize(10, 10) self.protocol("WM_DELETE_WINDOW", self.hide) # --- style self.style = Style(self) self.style.configure(self.id + ".TCheckbutton", selectbackground="red") self.style.map('TEntry', selectbackground=[('!focus', '#c3c3c3')]) selectbg = self.style.lookup('TEntry', 'selectbackground', ('focus', )) self.style.configure("sel.TCheckbutton", background=selectbg) self.style.map("sel.TCheckbutton", background=[("active", selectbg)]) # --- note elements # title font_title = "%s %s" % (CONFIG.get("Font", "title_family").replace( " ", "\ "), CONFIG.get("Font", "title_size")) style = CONFIG.get("Font", "title_style").split(",") if style: font_title += " " font_title += " ".join(style) self.title_var = StringVar(master=self, value=kwargs.get("title", _("Title"))) self.title_label = Label(self, textvariable=self.title_var, anchor="center", style=self.id + ".TLabel", font=font_title) self.title_entry = Entry(self, textvariable=self.title_var, exportselection=False, justify="center", font=font_title) # buttons/icons self.roll = Label(self, image="img_roll", style=self.id + ".TLabel") self.close = Label(self, image="img_close", style=self.id + ".TLabel") self.im_lock = PhotoImage(master=self, file=IM_LOCK) self.cadenas = Label(self, style=self.id + ".TLabel") # corner grip self.corner = Sizegrip(self, style=self.id + ".TSizegrip") # texte font_text = "%s %s" % (CONFIG.get("Font", "text_family").replace( " ", "\ "), CONFIG.get("Font", "text_size")) self.txt = Text(self, wrap='word', undo=True, selectforeground='white', inactiveselectbackground=selectbg, selectbackground=selectbg, tabs=(10, 'right', 21, 'left'), relief="flat", borderwidth=0, highlightthickness=0, font=font_text) # tags self.txt.tag_configure("bold", font="%s bold" % font_text) self.txt.tag_configure("italic", font="%s italic" % font_text) self.txt.tag_configure("bold-italic", font="%s bold italic" % font_text) self.txt.tag_configure("underline", underline=True, selectforeground="white") self.txt.tag_configure("overstrike", overstrike=True, selectforeground="white") self.txt.tag_configure("center", justify="center") self.txt.tag_configure("left", justify="left") self.txt.tag_configure("right", justify="right") self.txt.tag_configure("link", foreground="blue", underline=True, selectforeground="white") self.txt.tag_configure("list", lmargin1=0, lmargin2=21, tabs=(10, 'right', 21, 'left')) self.txt.tag_configure("todolist", lmargin1=0, lmargin2=21, tabs=(10, 'right', 21, 'left')) margin = 2 * Font(self, font=font_text).measure("m") self.txt.tag_configure("enum", lmargin1=0, lmargin2=margin + 5, tabs=(margin, 'right', margin + 5, 'left')) for coul in TEXT_COLORS.values(): self.txt.tag_configure(coul, foreground=coul, selectforeground="white") self.txt.tag_configure(coul + "-underline", foreground=coul, selectforeground="white", underline=True) self.txt.tag_configure(coul + "-overstrike", foreground=coul, overstrike=True, selectforeground="white") # --- menus # --- * menu on title self.menu = Menu(self, tearoff=False) # note color menu_note_color = Menu(self.menu, tearoff=False) colors = list(COLORS.keys()) colors.sort() for coul in colors: menu_note_color.add_command( label=coul, command=lambda key=coul: self.change_color(key)) # category self.category = StringVar( self, kwargs.get("category", CONFIG.get("General", "default_category"))) self.menu_categories = Menu(self.menu, tearoff=False) categories = CONFIG.options("Categories") categories.sort() for cat in categories: self.menu_categories.add_radiobutton(label=cat.capitalize(), value=cat, variable=self.category, command=self.change_category) # position: normal, always above, always below self.position = StringVar( self, kwargs.get("position", CONFIG.get("General", "position"))) menu_position = Menu(self.menu, tearoff=False) menu_position.add_radiobutton(label=_("Always above"), value="above", variable=self.position, command=self.set_position_above) menu_position.add_radiobutton(label=_("Always below"), value="below", variable=self.position, command=self.set_position_below) menu_position.add_radiobutton(label=_("Normal"), value="normal", variable=self.position, command=self.set_position_normal) # mode: note, list, todo list menu_mode = Menu(self.menu, tearoff=False) self.mode = StringVar(self, kwargs.get("mode", "note")) menu_mode.add_radiobutton(label=_("Note"), value="note", variable=self.mode, command=self.set_mode_note) menu_mode.add_radiobutton(label=_("List"), value="list", variable=self.mode, command=self.set_mode_list) menu_mode.add_radiobutton(label=_("ToDo List"), value="todolist", variable=self.mode, command=self.set_mode_todolist) menu_mode.add_radiobutton(label=_("Enumeration"), value="enum", variable=self.mode, command=self.set_mode_enum) self.menu.add_command(label=_("Delete"), command=self.delete) self.menu.add_cascade(label=_("Category"), menu=self.menu_categories) self.menu.add_cascade(label=_("Color"), menu=menu_note_color) self.menu.add_command(label=_("Lock"), command=self.lock) self.menu.add_cascade(label=_("Position"), menu=menu_position) self.menu.add_cascade(label=_("Mode"), menu=menu_mode) # --- * menu on main text self.menu_txt = Menu(self.txt, tearoff=False) # style menu_style = Menu(self.menu_txt, tearoff=False) menu_style.add_command(label=_("Bold"), command=lambda: self.toggle_text_style("bold")) menu_style.add_command( label=_("Italic"), command=lambda: self.toggle_text_style("italic")) menu_style.add_command(label=_("Underline"), command=self.toggle_underline) menu_style.add_command(label=_("Overstrike"), command=self.toggle_overstrike) # text alignment menu_align = Menu(self.menu_txt, tearoff=False) menu_align.add_command(label=_("Left"), command=lambda: self.set_align("left")) menu_align.add_command(label=_("Right"), command=lambda: self.set_align("right")) menu_align.add_command(label=_("Center"), command=lambda: self.set_align("center")) # text color menu_colors = Menu(self.menu_txt, tearoff=False) colors = list(TEXT_COLORS.keys()) colors.sort() for coul in colors: menu_colors.add_command(label=coul, command=lambda key=coul: self. change_sel_color(TEXT_COLORS[key])) # insert menu_insert = Menu(self.menu_txt, tearoff=False) menu_insert.add_command(label=_("Symbols"), command=self.add_symbols) menu_insert.add_command(label=_("Checkbox"), command=self.add_checkbox) menu_insert.add_command(label=_("Image"), command=self.add_image) menu_insert.add_command(label=_("Date"), command=self.add_date) menu_insert.add_command(label=_("Link"), command=self.add_link) if LATEX: menu_insert.add_command(label="LaTex", command=self.add_latex) self.menu_txt.add_cascade(label=_("Style"), menu=menu_style) self.menu_txt.add_cascade(label=_("Alignment"), menu=menu_align) self.menu_txt.add_cascade(label=_("Color"), menu=menu_colors) self.menu_txt.add_cascade(label=_("Insert"), menu=menu_insert) # --- restore note content/appearence self.color = kwargs.get("color", CONFIG.get("Categories", self.category.get())) self.txt.insert('1.0', kwargs.get("txt", "")) self.txt.edit_reset() # clear undo stack # restore inserted objects (images and checkboxes) # we need to restore objects with increasing index to avoid placment errors indexes = list(kwargs.get("inserted_objects", {}).keys()) indexes.sort(key=sorting) for index in indexes: kind, val = kwargs["inserted_objects"][index] if kind == "checkbox": ch = Checkbutton(self.txt, takefocus=False, style=self.id + ".TCheckbutton") if val: ch.state(("selected", )) self.txt.window_create(index, window=ch) elif kind == "image": if os.path.exists(val): self.images.append(PhotoImage(master=self.txt, file=val)) self.txt.image_create(index, image=self.images[-1], name=val) # restore tags for tag, indices in kwargs.get("tags", {}).items(): if indices: self.txt.tag_add(tag, *indices) for link in kwargs.get("links", {}).values(): self.nb_links += 1 self.links[self.nb_links] = link self.txt.tag_bind("link#%i" % self.nb_links, "<Button-1>", lambda e, l=link: open_url(l)) for img, latex in kwargs.get("latex", {}).items(): self.latex[img] = latex if LATEX: self.txt.tag_bind(img, '<Double-Button-1>', lambda e, im=img: self.add_latex(im)) mode = self.mode.get() if mode != "note": self.txt.tag_add(mode, "1.0", "end") self.txt.focus_set() self.lock() if kwargs.get("rolled", False): self.rollnote() if self.position.get() == "above": self.set_position_above() elif self.position.get() == "below": self.set_position_below() # --- placement # titlebar if CONFIG.get("General", "buttons_position") == "right": # right = lock icon - title - roll - close self.columnconfigure(1, weight=1) self.roll.grid(row=0, column=2, sticky="e") self.close.grid(row=0, column=3, sticky="e", padx=(0, 2)) self.cadenas.grid(row=0, column=0, sticky="w") self.title_label.grid(row=0, column=1, sticky="ew", pady=(1, 0)) else: # left = close - roll - title - lock icon self.columnconfigure(2, weight=1) self.roll.grid(row=0, column=1, sticky="w") self.close.grid(row=0, column=0, sticky="w", padx=(2, 0)) self.cadenas.grid(row=0, column=3, sticky="e") self.title_label.grid(row=0, column=2, sticky="ew", pady=(1, 0)) # body self.txt.grid(row=1, columnspan=4, column=0, sticky="ewsn", pady=(1, 4), padx=4) self.corner.lift(self.txt) self.corner.place(relx=1.0, rely=1.0, anchor="se") # --- bindings self.bind("<FocusOut>", self.save_note) self.bind('<Configure>', self.bouge) self.bind('<Button-1>', self.change_focus, True) self.close.bind("<Button-1>", self.hide) self.close.bind("<Enter>", self.enter_close) self.close.bind("<Leave>", self.leave_close) self.roll.bind("<Button-1>", self.rollnote) self.roll.bind("<Enter>", self.enter_roll) self.roll.bind("<Leave >", self.leave_roll) self.title_label.bind("<Double-Button-1>", self.edit_title) self.title_label.bind("<ButtonPress-1>", self.start_move) self.title_label.bind("<ButtonRelease-1>", self.stop_move) self.title_label.bind("<B1-Motion>", self.move) self.title_label.bind('<Button-3>', self.show_menu) self.title_entry.bind("<Return>", lambda e: self.title_entry.place_forget()) self.title_entry.bind("<FocusOut>", lambda e: self.title_entry.place_forget()) self.title_entry.bind("<Escape>", lambda e: self.title_entry.place_forget()) self.txt.tag_bind("link", "<Enter>", lambda event: self.txt.configure(cursor="hand1")) self.txt.tag_bind("link", "<Leave>", lambda event: self.txt.configure(cursor="")) self.txt.bind("<FocusOut>", self.save_note) self.txt.bind('<Button-3>', self.show_menu_txt) # add binding to the existing class binding so that the selected text # is erased on pasting self.txt.bind("<Control-v>", self.paste) self.corner.bind('<ButtonRelease-1>', self.resize) # --- keyboard shortcuts self.txt.bind('<Control-b>', lambda e: self.toggle_text_style('bold')) self.txt.bind('<Control-i>', lambda e: self.toggle_text_style('italic')) self.txt.bind('<Control-u>', lambda e: self.toggle_underline()) self.txt.bind('<Control-r>', lambda e: self.set_align('right')) self.txt.bind('<Control-l>', lambda e: self.set_align('left')) def __setattr__(self, name, value): object.__setattr__(self, name, value) if name == "color": self.style.configure(self.id + ".TSizegrip", background=self.color) self.style.configure(self.id + ".TLabel", background=self.color) self.style.configure("close" + self.id + ".TLabel", background=self.color) self.style.configure("roll" + self.id + ".TLabel", background=self.color) self.style.map(self.id + ".TLabel", background=[("active", self.color)]) self.style.configure(self.id + ".TCheckbutton", background=self.color) self.style.map(self.id + ".TCheckbutton", background=[("active", self.color), ("disabled", self.color)]) self.style.map("close" + self.id + ".TLabel", background=[("active", self.color)]) self.style.map("roll" + self.id + ".TLabel", background=[("active", self.color)]) self.configure(bg=self.color) self.txt.configure(bg=self.color) def paste(self, event): """ delete selected text before pasting """ if self.txt.tag_ranges("sel"): self.txt.delete("sel.first", "sel.last") def delete(self, confirmation=True): """ Delete this note """ if confirmation: rep = askokcancel(_("Confirmation"), _("Delete the note?")) else: rep = True if rep: del (self.master.note_data[self.id]) del (self.master.notes[self.id]) self.master.save() self.destroy() def lock(self): """ Put note in read-only mode to avoid unwanted text insertion """ if self.is_locked: selectbg = self.style.lookup('TEntry', 'selectbackground', ('focus', )) self.txt.configure(state="normal", selectforeground='white', selectbackground=selectbg, inactiveselectbackground=selectbg) self.style.configure("sel.TCheckbutton", background=selectbg) self.style.map("sel.TCheckbutton", background=[("active", selectbg)]) self.is_locked = False for checkbox in self.txt.window_names(): ch = self.txt.children[checkbox.split(".")[-1]] ch.configure(state="normal") self.cadenas.configure(image="") self.menu.entryconfigure(3, label=_("Lock")) self.title_label.bind("<Double-Button-1>", self.edit_title) self.txt.bind('<Button-3>', self.show_menu_txt) else: self.txt.configure(state="disabled", selectforeground='black', inactiveselectbackground='#c3c3c3', selectbackground='#c3c3c3') self.style.configure("sel.TCheckbutton", background='#c3c3c3') self.style.map("sel.TCheckbutton", background=[("active", '#c3c3c3')]) self.cadenas.configure(image=self.im_lock) for checkbox in self.txt.window_names(): ch = self.txt.children[checkbox.split(".")[-1]] ch.configure(state="disabled") self.is_locked = True self.menu.entryconfigure(3, label=_("Unlock")) self.title_label.unbind("<Double-Button-1>") self.txt.unbind('<Button-3>') self.save_note() def save_info(self): """ Return the dictionnary containing all the note data """ data = {} data["txt"] = self.txt.get("1.0", "end")[:-1] data["tags"] = {} for tag in self.txt.tag_names(): if tag not in ["sel", "todolist", "list", "enum"]: data["tags"][tag] = [ index.string for index in self.txt.tag_ranges(tag) ] data["title"] = self.title_var.get() data["geometry"] = self.save_geometry data["category"] = self.category.get() data["color"] = self.color data["locked"] = self.is_locked data["mode"] = self.mode.get() data["inserted_objects"] = {} data["rolled"] = not self.txt.winfo_ismapped() data["position"] = self.position.get() data["links"] = {} for i, link in self.links.items(): if self.txt.tag_ranges("link#%i" % i): data["links"][i] = link data["latex"] = {} for img, latex in self.latex.items(): if self.txt.tag_ranges(img): data["latex"][img] = latex for image in self.txt.image_names(): data["inserted_objects"][self.txt.index(image)] = ( "image", image.split('#')[0]) for checkbox in self.txt.window_names(): ch = self.txt.children[checkbox.split(".")[-1]] data["inserted_objects"][self.txt.index(checkbox)] = ( "checkbox", "selected" in ch.state()) return data def change_color(self, key): self.color = COLORS[key] self.save_note() def change_category(self, category=None): if category: self.category.set(category) self.color = CONFIG.get("Categories", self.category.get()) self.save_note() def set_position_above(self): e = ewmh.EWMH() for w in e.getClientList(): if w.get_wm_name() == 'mynotes%s' % self.id: e.setWmState(w, 1, '_NET_WM_STATE_ABOVE') e.setWmState(w, 0, '_NET_WM_STATE_BELOW') e.display.flush() self.save_note() def set_position_below(self): e = ewmh.EWMH() for w in e.getClientList(): if w.get_wm_name() == 'mynotes%s' % self.id: e.setWmState(w, 0, '_NET_WM_STATE_ABOVE') e.setWmState(w, 1, '_NET_WM_STATE_BELOW') e.display.flush() self.save_note() def set_position_normal(self): e = ewmh.EWMH() for w in e.getClientList(): if w.get_wm_name() == 'mynotes%s' % self.id: e.setWmState(w, 0, '_NET_WM_STATE_BELOW') e.setWmState(w, 0, '_NET_WM_STATE_ABOVE') e.display.flush() self.save_note() def set_mode_note(self): self.txt.tag_remove("list", "1.0", "end") self.txt.tag_remove("todolist", "1.0", "end") self.txt.tag_remove("enum", "1.0", "end") self.save_note() def set_mode_list(self): end = int(self.txt.index("end").split(".")[0]) lines = self.txt.get("1.0", "end").splitlines() for i, l in zip(range(1, end), lines): # remove checkboxes try: ch = self.txt.window_cget("%i.0" % i, "window") self.txt.children[ch.split('.')[-1]].destroy() self.txt.delete("%i.0" % i) except TclError: # there is no checkbox # remove enumeration res = re.match('^\t[0-9]+\.\t', l) if res: self.txt.delete("%i.0" % i, "%i.%i" % (i, res.end())) if self.txt.get("%i.0" % i, "%i.3" % i) != "\t•\t": self.txt.insert("%i.0" % i, "\t•\t") self.txt.tag_add("list", "1.0", "end") self.txt.tag_remove("todolist", "1.0", "end") self.txt.tag_remove("enum", "1.0", "end") self.save_note() def set_mode_enum(self): self.txt.configure(autoseparators=False) self.txt.edit_separator() end = int(self.txt.index("end").split(".")[0]) lines = self.txt.get("1.0", "end").splitlines() for i, l in zip(range(1, end), lines): # remove checkboxes try: ch = self.txt.window_cget("%i.0" % i, "window") self.txt.children[ch.split('.')[-1]].destroy() self.txt.delete("%i.0" % i) except TclError: # there is no checkbox # remove bullets if self.txt.get("%i.0" % i, "%i.3" % i) == "\t•\t": self.txt.delete("%i.0" % i, "%i.3" % i) if not re.match('^\t[0-9]+\.', l): self.txt.insert("%i.0" % i, "\t0.\t") self.txt.tag_add("enum", "1.0", "end") self.txt.tag_remove("todolist", "1.0", "end") self.txt.tag_remove("list", "1.0", "end") self.update_enum() self.txt.configure(autoseparators=True) self.txt.edit_separator() self.save_note() def set_mode_todolist(self): end = int(self.txt.index("end").split(".")[0]) lines = self.txt.get("1.0", "end").splitlines() for i, l in zip(range(1, end), lines): res = re.match('^\t[0-9]+\.\t', l) if res: self.txt.delete("%i.0" % i, "%i.%i" % (i, res.end())) elif self.txt.get("%i.0" % i, "%i.3" % i) == "\t•\t": self.txt.delete("%i.0" % i, "%i.3" % i) try: ch = self.txt.window_cget("%i.0" % i, "window") except TclError: ch = Checkbutton(self.txt, takefocus=False, style=self.id + ".TCheckbutton") self.txt.window_create("%i.0" % i, window=ch) self.txt.tag_remove("enum", "1.0", "end") self.txt.tag_remove("list", "1.0", "end") self.txt.tag_add("todolist", "1.0", "end") self.save_note() # --- bindings def enter_roll(self, event): """ mouse is over the roll icon """ self.roll.configure(image="img_rollactive") def leave_roll(self, event): """ mouse leaves the roll icon """ self.roll.configure(image="img_roll") def enter_close(self, event): """ mouse is over the close icon """ self.close.configure(image="img_closeactive") def leave_close(self, event): """ mouse leaves the close icon """ self.close.configure(image="img_close") def change_focus(self, event): if not self.is_locked: event.widget.focus_force() def show_menu(self, event): self.menu.tk_popup(event.x_root, event.y_root) def show_menu_txt(self, event): self.menu_txt.tk_popup(event.x_root, event.y_root) def resize(self, event): self.save_geometry = self.geometry() def bouge(self, event): geo = self.geometry().split("+")[1:] self.save_geometry = self.save_geometry.split("+")[0] \ + "+%s+%s" % tuple(geo) def edit_title(self, event): self.title_entry.place(x=self.title_label.winfo_x() + 5, y=self.title_label.winfo_y(), anchor="nw", width=self.title_label.winfo_width() - 10) def start_move(self, event): self.x = event.x self.y = event.y self.configure(cursor='fleur') def stop_move(self, event): self.x = None self.y = None self.configure(cursor='') def move(self, event): if self.x is not None and self.y is not None: deltax = event.x - self.x deltay = event.y - self.y x = self.winfo_x() + deltax y = self.winfo_y() + deltay self.geometry("+%s+%s" % (x, y)) def save_note(self, event=None): data = self.save_info() data["visible"] = True self.master.note_data[self.id] = data self.master.save() def rollnote(self, event=None): if self.txt.winfo_ismapped(): self.txt.grid_forget() self.corner.place_forget() self.geometry("%sx22" % self.winfo_width()) else: self.txt.grid(row=1, columnspan=4, column=0, sticky="ewsn", pady=(1, 4), padx=4) self.corner.place(relx=1.0, rely=1.0, anchor="se") self.geometry(self.save_geometry) self.save_note() def hide(self, event=None): """ Hide note (can be displayed again via app menu) """ cat = self.category.get() self.master.add_note_to_menu(self.id, self.title_var.get().strip(), cat) data = self.save_info() data["visible"] = False self.master.note_data[self.id] = data del (self.master.notes[self.id]) self.master.save() self.destroy() # --- Settings update def update_title_font(self): font = "%s %s" % (CONFIG.get("Font", "title_family").replace( " ", "\ "), CONFIG.get("Font", "title_size")) style = CONFIG.get("Font", "title_style").split(",") if style: font += " " font += " ".join(style) self.title_label.configure(font=font) def update_text_font(self): font = "%s %s" % (CONFIG.get("Font", "text_family").replace( " ", "\ "), CONFIG.get("Font", "text_size")) self.txt.configure(font=font) self.txt.tag_configure("bold", font="%s bold" % font) self.txt.tag_configure("italic", font="%s italic" % font) self.txt.tag_configure("bold-italic", font="%s bold italic" % font) margin = 2 * Font(self, font=font).measure("m") self.txt.tag_configure("enum", lmargin1=0, lmargin2=margin + 5, tabs=(margin, 'right', margin + 5, 'left')) def update_menu_cat(self, categories): """ Update the category submenu """ self.menu_categories.delete(0, "end") for cat in categories: self.menu_categories.add_radiobutton(label=cat.capitalize(), value=cat, variable=self.category, command=self.change_category) def update_titlebar(self): if CONFIG.get("General", "buttons_position") == "right": # right = lock icon - title - roll - close self.columnconfigure(1, weight=1) self.columnconfigure(2, weight=0) self.roll.grid_configure(row=0, column=2, sticky="e") self.close.grid_configure(row=0, column=3, sticky="e", padx=(0, 2)) self.cadenas.grid_configure(row=0, column=0, sticky="w") self.title_label.grid_configure(row=0, column=1, sticky="ew", pady=(1, 0)) else: # left = close - roll - title - lock icon self.columnconfigure(2, weight=1) self.columnconfigure(1, weight=0) self.roll.grid_configure(row=0, column=1, sticky="w") self.close.grid_configure(row=0, column=0, sticky="w", padx=(2, 0)) self.cadenas.grid_configure(row=0, column=3, sticky="e") self.title_label.grid_configure(row=0, column=2, sticky="ew", pady=(1, 0)) # --- Text edition def add_link(self): def ok(eveny=None): lien = link.get() txt = text.get() if lien: if not txt: txt = lien self.nb_links += 1 if self.txt.tag_ranges("sel"): index = self.txt.index("sel.first") self.txt.delete('sel.first', 'sel.last') else: index = "current" tags = self.txt.tag_names(index) + ("link", "link#%i" % self.nb_links) self.txt.insert("current", txt, tags) if not lien[:4] == "http": lien = "http://" + lien self.links[self.nb_links] = lien self.txt.tag_bind("link#%i" % self.nb_links, "<Button-1>", lambda e: open_url(lien)) top.destroy() top = Toplevel(self) top.transient(self) top.update_idletasks() top.geometry("+%i+%i" % top.winfo_pointerxy()) top.grab_set() top.resizable(True, False) top.title(_("Link")) top.columnconfigure(1, weight=1) text = Entry(top) link = Entry(top) if self.txt.tag_ranges('sel'): txt = self.txt.get('sel.first', 'sel.last') else: txt = '' text.insert(0, txt) text.icursor("end") Label(top, text=_("Text")).grid(row=0, column=0, sticky="e", padx=4, pady=4) Label(top, text=_("Link")).grid(row=1, column=0, sticky="e", padx=4, pady=4) text.grid(row=0, column=1, sticky="ew", padx=4, pady=4) link.grid(row=1, column=1, sticky="ew", padx=4, pady=4) Button(top, text="Ok", command=ok).grid(row=2, columnspan=2, padx=4, pady=4) text.focus_set() text.bind("<Return>", ok) link.bind("<Return>", ok) def add_checkbox(self): ch = Checkbutton(self.txt, takefocus=False, style=self.id + ".TCheckbutton") self.txt.window_create("current", window=ch) def add_date(self): self.txt.insert("current", strftime("%x")) def add_latex(self, img_name=None): def ok(event): latex = r'%s' % text.get() if latex: if img_name is None: l = [ int(os.path.splitext(f)[0]) for f in os.listdir(PATH_LATEX) ] l.sort() if l: i = l[-1] + 1 else: i = 0 img = "%i.png" % i self.txt.tag_bind(img, '<Double-Button-1>', lambda e: self.add_latex(img)) self.latex[img] = latex else: img = img_name im = os.path.join(PATH_LATEX, img) try: math_to_image(latex, im, fontsize=CONFIG.getint("Font", "text_size") - 2) self.images.append(PhotoImage(file=im, master=self)) if self.txt.tag_ranges("sel"): index = self.txt.index("sel.first") self.txt.delete('sel.first', 'sel.last') else: index = self.txt.index("current") self.txt.image_create(index, image=self.images[-1], name=im) self.txt.tag_add(img, index) top.destroy() except Exception as e: showerror(_("Error"), str(e)) top = Toplevel(self) top.transient(self) top.update_idletasks() top.geometry("+%i+%i" % top.winfo_pointerxy()) top.grab_set() top.resizable(True, False) top.title("LaTex") text = Entry(top, justify='center') if img_name is not None: text.insert(0, self.latex[img_name]) else: if self.txt.tag_ranges('sel'): text.insert(0, self.txt.get('sel.first', 'sel.last')) else: text.insert(0, '$$') text.icursor(1) text.pack(fill='x', expand=True) text.bind('<Return>', ok) text.focus_set() def add_image(self): fichier = askopenfilename(defaultextension=".png", filetypes=[("PNG", "*.png")], initialdir="", initialfile="", title=_('Select PNG image')) if os.path.exists(fichier): self.images.append(PhotoImage(master=self.txt, file=fichier)) self.txt.image_create("current", image=self.images[-1], name=fichier) elif fichier: showerror("Erreur", "L'image %s n'existe pas" % fichier) def add_symbols(self): symbols = pick_symbol( self, CONFIG.get("Font", "text_family").replace(" ", "\ "), CONFIG.get("General", "symbols")) self.txt.insert("current", symbols) def toggle_text_style(self, style): '''Toggle the style of the selected text''' if self.txt.tag_ranges("sel"): current_tags = self.txt.tag_names("sel.first") if style in current_tags: # first char is in style so 'unstyle' the range self.txt.tag_remove(style, "sel.first", "sel.last") elif style == "bold" and "bold-italic" in current_tags: self.txt.tag_remove("bold-italic", "sel.first", "sel.last") self.txt.tag_add("italic", "sel.first", "sel.last") elif style == "italic" and "bold-italic" in current_tags: self.txt.tag_remove("bold-italic", "sel.first", "sel.last") self.txt.tag_add("bold", "sel.first", "sel.last") elif style == "bold" and "italic" in current_tags: self.txt.tag_remove("italic", "sel.first", "sel.last") self.txt.tag_add("bold-italic", "sel.first", "sel.last") elif style == "italic" and "bold" in current_tags: self.txt.tag_remove("bold", "sel.first", "sel.last") self.txt.tag_add("bold-italic", "sel.first", "sel.last") else: # first char is normal, so apply style to the whole selection self.txt.tag_add(style, "sel.first", "sel.last") def toggle_underline(self): if self.txt.tag_ranges("sel"): current_tags = self.txt.tag_names("sel.first") if "underline" in current_tags: # first char is in style so 'unstyle' the range self.txt.tag_remove("underline", "sel.first", "sel.last") for coul in TEXT_COLORS.values(): self.txt.tag_remove(coul + "-underline", "sel.first", "sel.last") else: self.txt.tag_add("underline", "sel.first", "sel.last") for coul in TEXT_COLORS.values(): r = text_ranges(self.txt, coul, "sel.first", "sel.last") if r: for deb, fin in zip(r[::2], r[1::2]): self.txt.tag_add(coul + "-underline", "sel.first", "sel.last") def toggle_overstrike(self): if self.txt.tag_ranges("sel"): current_tags = self.txt.tag_names("sel.first") if "overstrike" in current_tags: # first char is in style so 'unstyle' the range self.txt.tag_remove("overstrike", "sel.first", "sel.last") for coul in TEXT_COLORS.values(): self.txt.tag_remove(coul + "-overstrike", "sel.first", "sel.last") else: self.txt.tag_add("overstrike", "sel.first", "sel.last") for coul in TEXT_COLORS.values(): r = text_ranges(self.txt, coul, "sel.first", "sel.last") if r: for deb, fin in zip(r[::2], r[1::2]): self.txt.tag_add(coul + "-overstrike", "sel.first", "sel.last") def change_sel_color(self, color): """ change the color of the selection """ if self.txt.tag_ranges("sel"): for coul in TEXT_COLORS.values(): self.txt.tag_remove(coul, "sel.first", "sel.last") self.txt.tag_remove(coul + "-overstrike", "sel.first", "sel.last") self.txt.tag_remove(coul + "-underline", "sel.first", "sel.last") if not color == "black": self.txt.tag_add(color, "sel.first", "sel.last") underline = text_ranges(self.txt, "underline", "sel.first", "sel.last") overstrike = text_ranges(self.txt, "overstrike", "sel.first", "sel.last") for deb, fin in zip(underline[::2], underline[1::2]): self.txt.tag_add(color + "-underline", deb, fin) for deb, fin in zip(overstrike[::2], overstrike[1::2]): self.txt.tag_add(color + "-overstrike", deb, fin) def set_align(self, alignment): """ Align the text according to alignment (left, right, center) """ if self.txt.tag_ranges("sel"): line = self.txt.index("sel.first").split(".")[0] line2 = self.txt.index("sel.last").split(".")[0] deb, fin = line + ".0", line2 + ".end" if not "\t" in self.txt.get(deb, fin): # tabulations don't support right/center alignment # remove old alignment tag self.txt.tag_remove("left", deb, fin) self.txt.tag_remove("right", deb, fin) self.txt.tag_remove("center", deb, fin) # set new alignment tag self.txt.tag_add(alignment, deb, fin) def update_enum(self): """ update enumeration numbers """ lines = self.txt.get("1.0", "end").splitlines() indexes = [] for i, l in enumerate(lines): res = re.match('^\t[0-9]+\.\t', l) res2 = re.match('^\t[0-9]+\.', l) if res: indexes.append((i, res.end())) elif res2: indexes.append((i, res2.end())) for j, (i, end) in enumerate(indexes): self.txt.delete("%i.0" % (i + 1), "%i.%i" % (i + 1, end)) self.txt.insert("%i.0" % (i + 1), "\t%i.\t" % (j + 1)) self.txt.tag_add("enum", "1.0", "end")
def __init__(self): ThemedTk.__init__(self, theme='black') self.title('Установщик F_Reference_H') self.geometry('500x200') x = (self.winfo_screenwidth() - self.winfo_reqwidth()) / 2 y = (self.winfo_screenheight() - self.winfo_reqheight()) / 2 self.wm_geometry("+%d+%d" % (x - 150, y - 20)) self.resizable(width=False, height=False) self.iconphoto( True, PhotoImage(file='bin/ico/ico_main.png') ) flow_hack_png = Image.open(f'bin/ico/max_flowhack.png') flow_hack_png = ImageTk.PhotoImage(flow_hack_png) browse_png = Image.open(f'bin/ico/browse.png') browse_png = ImageTk.PhotoImage(browse_png) self.frame = Frame(self) self.frame.place(relwidth=1, relheight=1) self.url = '' self._path = getcwd() flow_hack_label = Label( self.frame, image=flow_hack_png, cursor='heart' ) flow_hack_label.bind('<Button-1>', open_web) flow_hack_label.place(anchor='c', relx=.5, rely=.1) self.check_icon = BooleanVar() self.check_icon.set(bool(True)) Checkbutton( self.frame, text='Создать ярлык на рабочем столе', var=self.check_icon, cursor='cross' ).place(relx=.5, y=60, anchor='c') Label( self.frame, text='Выберите папку для установки', font=('Times New Roman', 10, 'bold italic') ).place(relx=.5, rely=.485, anchor='c') self.input_url = Entry( self.frame, state=DISABLED, font=('Times New Roman', 9, 'bold italic'), foreground='black' ) self.input_url.place( rely=.6, relx=.5, height=20, relwidth=.7, anchor='c' ) Button( self.frame, image=browse_png, cursor='hand1', command=self.directory ).place(relx=.86, rely=.455) Button( self.frame, image=browse_png, cursor='hand1', command=self.directory ).place(relx=.045, rely=.455) Button( self.frame, text='Установить', cursor='hand1', command=self.install ).place(relx=.5, rely=.75, anchor='c') self.license = Label( self.frame, text='Для подтверждения согласия с лицензионным ' 'соглашением\nНажмите на "Установить" правой кнопкой мыши', font=('Times New Roman', 9, 'bold italic'), foreground='black', cursor='hand1', justify='center' ) self.license.bind( '<Button-1>', lambda no_matter: webopen('https://flowhack.github.io/') ) self.license.place(relx=.5, rely=.93, anchor='c') self.mainloop()