コード例 #1
0
    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)
コード例 #2
0
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)
コード例 #3
0
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)
コード例 #4
0
ファイル: stopwatch_view.py プロジェクト: Cjreynol-zz/PyTimer
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)
コード例 #5
0
    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)
コード例 #6
0
 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))
コード例 #7
0
    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)
コード例 #8
0
    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))
コード例 #9
0
ファイル: gui.py プロジェクト: Zettroke/VkMessageStat
    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()
コード例 #10
0
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
コード例 #11
0
    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()
コード例 #12
0
ファイル: feet_to_meter.py プロジェクト: honchardev/Fun
    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()
コード例 #13
0
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
コード例 #14
0
    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)
コード例 #15
0
ファイル: event_widget.py プロジェクト: j4321/Scheduler
    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))
コード例 #16
0
    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)
コード例 #17
0
    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))
コード例 #18
0
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
コード例 #19
0
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()
コード例 #20
0
ファイル: event_widget.py プロジェクト: j4321/Scheduler
    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'))
コード例 #21
0
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
コード例 #22
0
ファイル: timer_widget.py プロジェクト: j4321/Scheduler
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))
コード例 #23
0
    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)
コード例 #24
0
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)
コード例 #25
0
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Если не получается решить '
                'проблему, то напишите мне в блоке "Обратная связь" ')
コード例 #26
0
    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()
コード例 #27
0
ファイル: notemanager.py プロジェクト: zMoooooritz/MyNotes
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"
コード例 #28
0
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',
                    'Мы заметили, что вы выбрали неверный адрес!'
                )
コード例 #29
0
ファイル: sticky.py プロジェクト: Vistaus/MyNotes
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")
コード例 #30
0
    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()