Beispiel #1
0
def style_for_warning_entry() -> None:
    """
    Функция создания стиля для пустого Entry
    :return:
    """
    style = Style()
    try:
        style.element_create('plain.field', 'from', 'clam')
    except TclError as error:
        if str(error) == 'Duplicate element plain.field':
            pass
    style.layout('Warning.TEntry', [('Entry.plain.field', {
        'children': [('Entry.background', {
            'children': [('Entry.padding', {
                'children': [('Entry.textarea', {
                    'sticky': 'nswe'
                })],
                'sticky': 'nswe'
            })],
            'sticky':
            'nswe'
        })],
        'border':
        '2',
        'sticky':
        'nswe'
    })])
    style.configure('Warning.TEntry', fieldbackground='#FFA3AD')
Beispiel #2
0
    def __init__(self):
        Tk.__init__(self)
        self.title("BSE Kafka Tool")
        self.set_window_center(900, 500)
        self.resizable(True, True)
        self.win_success = None

        # Treeview style
        style = Style()
        style.element_create("Custom.Treeheading.border", "from", "default")
        style.layout("Custom.Treeview.Heading", [
            ("Custom.Treeheading.cell", {
                'sticky': 'nswe'
            }),
            ("Custom.Treeheading.border", {
                'sticky':
                'nswe',
                'children': [("Custom.Treeheading.padding", {
                    'sticky':
                    'nswe',
                    'children': [("Custom.Treeheading.text", {
                        'sticky': 'we'
                    })]
                })]
            }),
        ])
        style.configure("Custom.Treeview.Heading",
                        background="grey",
                        foreground="white",
                        relief="flat")

        configuration_window.ConfigurationWindow()
class PomodoroNotebook(ThemedTk):
    def __init__(self):
        ThemedTk.__init__(self)
        self.iconbitmap('pomodoro_icon.ico')
        self.resizable(False, False)
        self.set_theme('radiance')
        self.style = Style()
        self.style.configure('.', font=('Times', 13), takfocus=0, xpad=10)
        self.style.configure('TFrame', background='#471d0f')
        self.style.configure('TButton', 'Button.focus' == {'sticky': '0'})
        print(self.style.layout('TButton'))
        self.title('Pomodoro')
        self.protocol("WM_DELETE_WINDOW", self.quit_event)

        self.note = Notebook(self)
        self.page_one = Page1(self.note)
        self.page_two = Page2(self.note)
        self.page_three = Page3(self.note)

    def batch_grid(self):
        self.note.add(self.page_one, text='Task Generation')
        self.note.add(self.page_two, text='Current Task')
        self.note.add(self.page_three, text='History')

        self.note.pack(fill='both')
        self.mainloop()

    def quit_event(self):
        try:
            pass
        except Exception as error:
            logging.debug(error)
        finally:
            self.destroy()
Beispiel #4
0
class ProgBar(object):
    def __init__(self, top):
        print("this is Progress bar status")
        #进度条窗口
        #status bar
        self.fm_status = tk.Frame(top)
        for i in range(1):
            tk.Label(self.fm_status, text='').grid(row=i, column=0)

        self.v_status = tk.StringVar()
        self.v_status.set('Start')
        self.label_status = tk.Label(self.fm_status,textvariable=self.v_status, bd=1,\
         justify='left')
        self.label_status.grid(row=3, column=1, sticky=tk.S)

        #进度条
        self.style_bar = Style(top)
        self.style_bar.layout("LabeledProgressbar",
                              [('LabeledProgressbar.trough', {
                                  'children': [('LabeledProgressbar.pbar', {
                                      'side': 'left',
                                      'sticky': 'ns'
                                  }),
                                               ("LabeledProgressbar.label", {
                                                   "sticky": ""
                                               })],
                                  'sticky':
                                  'nswe'
                              })])

        self.p_bar = Progressbar(self.fm_status, orient=tk.HORIZONTAL,\
         length=100, mode='determinate',style="LabeledProgressbar")
        self.style_bar.configure("LabeledProgressbar", text="0 %      ")
        self.p_bar.grid(row=3, column=0)
        self.p_bar["maximum"] = 100.
        self.p_bar["value"] = 0

    def update_log(self, s):
        self.v_status.set(s)

    def show_status(self, flag=True):
        if flag:
            self.fm_status.pack(side=tk.LEFT)
        else:
            self.fm_status.pack_forget()
Beispiel #5
0
    def __init__(self, master, kw_vals, default_text='Any', **kwargs):
        super().__init__(master, **kwargs)

        self.default_text = default_text
        self.kw_vals = kw_vals
        self.kw_vals_inv = dict(map(reversed, kw_vals.items()))

        ui_style = Style()
        ui_style.configure('MultiCombobox.TMenubutton',
                           relief=RAISED,
                           padding=3,
                           anchor=CENTER)
        ui_style.layout('MultiCombobox.TMenubutton', _layout)
        self.config(style='MultiCombobox.TMenubutton')

        menu = Menu(self,
                    tearoff=False,
                    activeforeground='SystemHighlightText',
                    activebackground='SystemHighlight',
                    foreground='SystemWindowText',
                    background='SystemWindow',
                    disabledforeground='SystemGrayText',
                    bd=0,
                    activeborderwidth=1)
        self.configure(menu=menu)

        self.any_var = BooleanVar(value=True)
        menu.add_checkbutton(label=default_text,
                             variable=self.any_var,
                             onvalue=True,
                             offvalue=False,
                             command=self.anySelected)

        self.choices = {}
        for i, choice in enumerate(kw_vals):
            self.choices[choice] = BooleanVar()
            # columnbreak = (i+1) % 4 == 0
            columnbreak = False
            menu.add_checkbutton(label=choice,
                                 variable=self.choices[choice],
                                 onvalue=True,
                                 offvalue=False,
                                 columnbreak=columnbreak,
                                 command=self.updateValue)
        self.updateValue()
class Table:
    """Table class used to display a table with database rows."""
    def __init__(self, root, lst: list, fields: list, row: int, column: int, size=False):
        """
        Constructor.
        :param root: - the frame where it will be displayed the table.
        :param lst: - list of rows from database.
        :param fields: - column names.
        :param row: - integer, to position table on Frame grid.
        :param column: - integer, to position table on Frame grid.
        :param size: - boolean, to define height of the table. If no rows to display,
                        height is 0 else height is 20 rows. Default 4 rows.
        """
        col, height = tuple([i for i in range(len(fields))]), 4
        if len(lst) < 1:
            height = 0
        if size:
            height = 20
        # Style for the treeview
        self.style = Style()
        # Modify the font of the body
        self.style.configure("Treeview", highlightthickness=3, bd=3, background=st.colors['table'],
                             font=st.fonts['table'])
        # Modify the font of the headings
        self.style.configure("Treeview.Heading", font=st.fonts['heading'])
        # Remove the borders
        self.style.layout("Treeview", [('Treeview.treearea', {'sticky': 'news'})])
        # Creating the Table
        self.table = Treeview(root, column=col,
                              height=height, show='headings', style='Treeview')
        self.table.grid(row=row, column=column, sticky="news", padx=12)
        # Creating scroll bar for the table
        self.scroll = Scrollbar(root, orient='vertical', command=self.table.yview)
        self.scroll.grid(row=row, column=column, sticky='nes', padx=12)
        # Adding the scroll bar to the table
        self.table.configure(yscrollcommand=self.scroll.set)
        # First column/ID width
        for item in range(len(fields)):
            if item == 0:
                self.table.column(item, width=30)
            self.table.heading(item, text=fields[item], anchor='nw')
        # Populating the table with database rows
        for row_ in lst:
            self.table.insert('', 'end', values=" ".join(str(i).strip("\'") for i in row_))
 def __init__(self):
     global root
     self.master = Toplevel(root)
     self.master.withdraw()
     self.master.protocol('WM_DELETE_WINDOW', root.destroy)
     self.master.iconbitmap(imgdir)
     self.master.geometry("400x150")
     self.master.resizable(False, False)
     self.master.title("Adb & Fastboot Installer - By @Pato05")
     estyle = Style()
     estyle.element_create("plain.field", "from", "clam")
     estyle.layout("White.TEntry",
                   [('Entry.plain.field', {'children': [(
                       'Entry.background', {'children': [(
                           'Entry.padding', {'children': [(
                               'Entry.textarea', {'sticky': 'nswe'})],
                               'sticky': 'nswe'})], 'sticky': 'nswe'})],
                       'border': '4', 'sticky': 'nswe'})])
     estyle.configure("White.TEntry",
                      background="white",
                      foreground="black",
                      fieldbackground="white")
     window = Frame(self.master, relief=FLAT)
     window.pack(padx=10, pady=5, fill=BOTH)
     Label(window, text='Installation path:').pack(fill=X)
     self.syswide = IntVar()
     self.instpath = StringVar()
     self.e = Entry(window, state='readonly',
                    textvariable=self.instpath, style='White.TEntry')
     self.e.pack(fill=X)
     self.toggleroot()
     Label(window, text='Options:').pack(pady=(10, 0), fill=X)
     inst = Checkbutton(window, text="Install Adb and Fastboot system-wide?",
                        variable=self.syswide, command=self.toggleroot)
     inst.pack(fill=X)
     self.path = IntVar(window, value=1)
     Checkbutton(window, text="Put Adb and Fastboot in PATH?",
                 variable=self.path).pack(fill=X)
     Button(window, text='Install', command=self.install).pack(anchor='se')
     self.master.deiconify()
Beispiel #8
0
class show_status():
    def __init__(self):
        # get program-call from arguments
        call = sys.argv[0]

        # was it an .exe-call ?
        if call.find('.exe') >= 0:
            # yes, perform all following calls as exe-calls
            self.scriptsAsExe = True
        else:
            # yes, perform all following calls as python-calls
            self.scriptsAsExe = False

        # check working-directory, is it already the build-dir?
        if (not os.getcwd().find(buildPath) >= 0):
            os.chdir("." + bs + buildPath)

        # set name of the progressFile
        self.progressFileName = progressFileName

        # creating tkinter window
        self.root = Tk()
        self.root.title('The Strak Machine V1.1')

        # Same size will be defined in variable for center screen in Tk_Width and Tk_height
        Tk_Width = 400
        Tk_Height = 300

        #calculate coordination of screen and window form
        x_Left = int(self.root.winfo_screenwidth() * 2 / 3 - Tk_Width / 2)
        y_Top = int(self.root.winfo_screenheight() / 2 - Tk_Height / 2)

        # Write following format for center screen
        self.root.geometry("+{}+{}".format(x_Left, y_Top))

        # set background-colour
        self.root.configure(bg=bg_colour)

        # display logo of the strak machine
        imagename = (".." + bs + ressourcesPath + bs + logoName)

        # Creates a Tkinter-compatible photo image, which can be used everywhere
        # Tkinter expects an image object.
        img = ImageTk.PhotoImage(Image.open(imagename).resize((400, 100)))

        # The Label widget is a standard Tkinter widget used to display a text
        # or image on the screen.
        panel = tk.Label(self.root, image=img, bg=bg_colour)

        # The Pack geometry manager packs widgets in rows or columns.
        panel.pack(side="top", fill="both", expand="yes")

        # configure progress-bars
        self.s_main = Style(self.root)
        self.s_sub = Style(self.root)

        # add the label to the progressbar style
        self.s_main.layout("MainProgressbar", [('MainProgressbar.trough', {
            'children': [('MainProgressbar.pbar', {
                'side': 'left',
                'sticky': 'ns'
            }), ("MainProgressbar.label", {
                "sticky": ""
            })],
            'sticky':
            'nswe'
        })])

        # add the label to the progressbar style
        self.s_sub.layout("SubProgressbar", [('SubProgressbar.trough', {
            'children': [('SubProgressbar.pbar', {
                'side': 'left',
                'sticky': 'ns'
            }), ("SubProgressbar.label", {
                "sticky": ""
            })],
            'sticky':
            'nswe'
        })])

        # main-Progress bar widget
        self.main_progressBar = Progressbar(self.root,
                                            orient="horizontal",
                                            length=300,
                                            mode='determinate',
                                            style="MainProgressbar")

        # sub-Progress bar widget
        self.sub_progressBar = Progressbar(self.root,
                                           orient="horizontal",
                                           length=300,
                                           mode='determinate',
                                           style="SubProgressbar")

        self.main_progressBar.pack(pady=10)
        self.sub_progressBar.pack(pady=10)

        # change the text of the progressbar,
        # the trailing spaces are here to properly center the text
        self.s_main.configure("MainProgressbar",
                              text="0 %      ",
                              background='green2')
        self.s_sub.configure("SubProgressbar",
                             text="0 %      ",
                             background='green2')

        # create a scrollbar
        scrollbar = tk.Scrollbar(self.root)
        scrollbar.pack(side='right', fill='y')

        # create textbox to display content of progress-file
        self.progressLog = tk.Listbox(self.root,
                                      height=10,
                                      width=100,
                                      yscrollcommand=scrollbar.set)
        self.progressLog.pack(pady=10)
        scrollbar.config(command=self.progressLog.yview)

        # This button will start the visualizer
        Button(self.root,
               text='Start Visualizer',
               command=self.start_visualizer).pack(pady=10)

        # This button will Quit the application
        #Button(self.root, text = 'Quit', command = self.quit).pack(pady = 10)

        # update with actual values
        self.update_progressbars()

        # infinite loop
        self.root.mainloop()

    def read_progressFile(self):
        file_content = None
        airfoilname = ""
        #global main_progress Debug
        main_progress = 0.0
        sub_progress = 0.0

        try:
            file = open(self.progressFileName, 'r')
            file_content = file.readlines()
            file.close()
        except:
            print("Error, File %s could not be opened !" %
                  self.progressFileName)
            sys.exit(-1)

        for line in file_content:
            # look for name of current airfoil
            if line.find("current airfoil") >= 0:
                splitlines = line.split(": ")
                airfoilname = splitlines[1]

            # look for main-task-progress
            if line.find("main-task progress") >= 0:
                splitlines = line.split(": ")
                main_progress = float(splitlines[1])

            # look for sub-task-progress
            if line.find("sub-task progress") >= 0:
                splitlines = line.split(": ")
                sub_progress = float(splitlines[1])

        return (main_progress, sub_progress, airfoilname, file_content)

    # gets the name of the airfoil that is currently processed by the strak-machine
    def get_CurrentAirfoilName(self):
        file_content = None
        airfoilname = ""

        try:
            file = open(self.progressFileName, 'r')
            file_content = file.readlines()
            file.close()
        except:
            print("Error, File %s could not be opened !" %
                  self.progressFileName)
            sys.exit(-1)

        for line in file_content:
            # look for name of current airfoil
            if (line.find("finalizing airfoil") >= 0) or\
               (line.find("creating preliminary-airfoil") >=0):
                splitlines = line.split(": ")
                airfoilname = splitlines[1]
                airfoilname = airfoilname.strip("\r\n\t '")

        return airfoilname

    # function to filter out some kind of output
    def filterLines(self, line):
        filteredLine = line

        # several filters
        if (line.find("progress") >= 0):
            filteredLine = None

        if (line.find("task") >= 0):
            filteredLine = None

        if (line.find("timestamp") >= 0):
            filteredLine = None

        return filteredLine

    # Function responsible for the update of the progress bar values
    def update_progressbars(self):
        global old_length
        global new_length
        global finished

        # read actual values from progress-file
        (main_progress, sub_progress, current_airfoil,
         content) = self.read_progressFile()

        # store lengths
        old_length = new_length
        new_length = len(content)

        # update progress-bars
        self.main_progressBar['value'] = main_progress
        self.sub_progressBar['value'] = sub_progress
        self.s_main.configure(
            "MainProgressbar",
            text="all airfoils: {0} %      ".format(main_progress))
        self.s_sub.configure(
            "SubProgressbar",
            text="current airfoil: {0} %      ".format(sub_progress))

        # update progress-log-widget (only the new lines)
        for idx in range(old_length, new_length):
            line = self.filterLines(content[idx])
            if line != None:
                self.progressLog.insert(tk.END, content[idx])
                # always show the last line, if there is a new one
                self.progressLog.see(tk.END)

        self.root.update()

        # check if strak-machine has finished
        if (finished == False):
            if (main_progress == 100.0):
                print(os.getcwd())
                soundFileName = '..' + bs + ressourcesPath + bs + finishSound
                winsound.PlaySound(soundFileName,
                                   winsound.SND_FILENAME | winsound.SND_NOWAIT)
                finished = True

        # setup next cylce
        self.root.after(200, self.update_progressbars)

    def start_visualizer(self):
        # get current airfoilname from progressfile for starting the visualizer
        airfoilname = self.get_CurrentAirfoilName()

        # setup tool-calls
        exeCallString = " .." + bs + exePath + bs
        pythonCallString = pythonInterpreterName + ' ..' + bs + scriptPath + bs

        if (self.scriptsAsExe):
            xoptfoilVisualizerCall = exeCallString + xoptfoilVisualizerName + '.exe'
        else:
            xoptfoilVisualizerCall = pythonCallString + xoptfoilVisualizerName + '.py'

        # compose subprocess-string
        cmd = (" %s -o 3 -c %s\n") % (xoptfoilVisualizerCall, airfoilname)

        # now open subprocess
        p = subprocess.Popen(cmd, shell=True)

    def quit(self):
        self.root.destroy()
class ytDownloader:
    """
    ytDownloader e' un youtube video downloader
    """
    def __init__(self, _root):
        # start objects
        self.root = _root
        self.selected_language = 'ENG'
        self.lang = Translator(language)
        self.root.geometry("960x346")

        self.root.title("Yt Video Downloader")
        # self.root.title(self.lang.title)
        self.root.resizable(False, False)
        self.init_objects()
        self.v_counter = 0
        self.v_down = 0
        self.context_menu = Menu(self.root, tearoff=0)
        self.context_menu.add_command(label="Cut")
        self.context_menu.add_command(label="Copy")
        self.context_menu.add_command(label="Paste")
        self.downloading = False
        self.global_downloading = False
        self.ThreadLauncher = None
        self.root.protocol('WM_DELETE_WINDOW', self.prevent_close)

    def change_language(self, _language):
        self.lang.set_language(_language)
        self.set_values()
        # changing language menubar
        self.menubar.set_language()
        self.root.update_idletasks()

    def prevent_close(self):
        '''
        Check if Thread is running then delete it
        :return: None
        '''
        _title = ''
        _message = ''
        if self.global_downloading:
            _title = self.lang.running
            _message = f"{self.lang.running_msg_1}"\
                f"\n {self.lang.close_app}"
            question = messagebox.askyesno(title=_title, message=_message)
            if question:
                # destroy thread runnning
                self.stop_download()
            else:
                return None
        self.root.destroy()

        # messagebox.showinfo('Running', 'The downloader app is already running')
        # root.destroy()

    def reset_values(self):
        self.v_counter = 0
        self.v_down = 0

    def popup(self, event, element):
        self.context_menu.post(event.x_root, event.y_root)
        self.context_menu.entryconfigure(
            "Cut", command=lambda: element.event_generate("<<Cut>>"))
        self.context_menu.entryconfigure(
            "Copy", command=lambda: element.event_generate("<<Copy>>"))
        self.context_menu.entryconfigure(
            "Paste", command=lambda: element.event_generate("<<Paste>>"))

    def init_objects(self):
        def _redo(text_object):
            var = text_object.edit_redo

        def _undo(text_object):
            var = text_object.edit_undo

        self.s = Style(self.root)
        self.s.theme_use('default')
        self.s.layout(
            "LabeledProgressbar",
            [(
                'LabeledProgressbar.trough',
                {
                    'children': [
                        ('LabeledProgressbar.pbar', {
                            'side': 'left',
                            'sticky': 'ns'
                        }),
                        (
                            "LabeledProgressbar.label",  # label inside the bar
                            {
                                "sticky": ""
                            })
                    ],
                    'sticky':
                    'nswe'
                })])
        self.s.configure("LabeledProgressbar", background='#06b025')
        self.font_title = ('consolas', 14)
        self.font_specs = ('consolas', 11)
        # variables used on proccess
        self.link = StringVar()
        self.save_path = StringVar()
        self.save_path.set(os.path.expanduser('~/Downloads'))
        self.title_var = StringVar()
        self.lb_title = Label(self.root,
                              textvariable=self.title_var,
                              font="consolas 14 bold")
        self.lb_title.grid(row=0, column=0, columnspan=3, padx=(10, 20))
        self.d_descr_link = StringVar()
        self.descr_link = Label(self.root,
                                textvariable=self.d_descr_link,
                                font="consolas 11")
        self.descr_link.grid(row=1, column=0)
        self.d_lab_one = StringVar()
        self.lab_one = Label(self.root,
                             textvariable=self.d_lab_one,
                             font="Consolas 10")
        self.lab_one.grid(row=2, column=0)

        # frame for text where put the links
        self.my_frame = Frame(self.root)
        self.my_scroll = Scrollbar(self.my_frame, orient=VERTICAL)
        self.my_text = Text(self.my_frame,
                            width=55,
                            height=8,
                            font=self.font_specs,
                            yscrollcommand=self.my_scroll.set,
                            undo=True)
        self.my_text.bind('<Control-z>', _undo(self.my_text))
        self.my_text.bind('<Control-y>', _redo(self.my_text))
        self.my_text.bind("<Button-3>",
                          lambda event, text_element=self.my_text: self.popup(
                              event=event, element=text_element))
        self.my_scroll.config(command=self.my_text.yview)
        self.my_scroll.pack(side=RIGHT, fill=Y)
        self.my_frame.grid(row=3, column=0, padx=10)
        self.my_text.pack()

        # adding buttons
        self.button_frame = Frame(self.root)
        self.button_frame.grid(row=4, column=0, padx=10, pady=10)
        # clear button
        self.d_clear_button = StringVar()
        self.clear_button = Button(self.button_frame,
                                   textvariable=self.d_clear_button,
                                   command=self.clear_text)
        self.clear_button.grid(row=0, column=0, padx=10)
        self.d_start_down_btn = StringVar()
        self.start_down_btn = Button(self.button_frame,
                                     textvariable=self.d_start_down_btn,
                                     command=self.launch_down,
                                     fg="blue")
        self.start_down_btn.grid(row=0, column=1, padx=10)

        #stop button
        self.button_frame1 = Frame(self.root)
        self.button_frame1.grid(row=4, column=1, padx=10, pady=10)
        self.d_stop_button = StringVar()
        self.stop_button = Button(self.button_frame1,
                                  textvariable=self.d_stop_button,
                                  command=self.stop_download,
                                  fg="red")
        self.stop_button.grid(row=0, column=0, padx=10)
        self.stop_button.grid_remove()
        self.d_lb_save_in = StringVar()
        self.lb_save_in = Label(self.root,
                                textvariable=self.d_lb_save_in,
                                font="Consolas 11")
        self.lb_save_in.grid(row=1, column=1)

        # frame for path and button
        self.search_frame = Frame(self.root)
        self.search_frame.grid(row=2, column=1, sticky='w', padx=10)
        self.path_saver = Entry(self.search_frame,
                                textvariable=self.save_path,
                                width=65)
        self.path_saver.grid(row=0, column=0, sticky='w')
        self.d_brownse_btn = StringVar()
        self.browse_btn = Button(self.search_frame,
                                 textvariable=self.d_brownse_btn,
                                 command=self.browse_button)
        self.browse_btn.grid(row=0, column=1)

        # format file option
        # options frame
        self.option_format = IntVar()
        self.option_buttons = Frame(self.root)
        self.option_buttons.grid(row=5, column=0, sticky='w', padx=10)
        self.R1 = Radiobutton(self.option_buttons,
                              text="Video",
                              variable=self.option_format,
                              value=1)
        self.R1.grid(row=0, column=1)
        self.R2 = Radiobutton(self.option_buttons,
                              text="Audio",
                              variable=self.option_format,
                              value=2)
        self.R2.grid(row=0, column=2)
        # set value on audio
        self.option_format.set(2)

        # adding status frame
        self.status_frame = Frame(self.root, bd=1, relief=SUNKEN)
        self.status_frame.grid(row=6,
                               column=0,
                               columnspan=3,
                               sticky=W + E,
                               pady=(20, 0))

        Label(self.status_frame,
              text="EA Yt Downloader",
              font="consolas 11 bold").grid(row=0, column=0, padx=10)
        self.status_text = StringVar()
        self.status_text_label = Label(self.status_frame,
                                       textvariable=self.status_text,
                                       font="consolas 11").grid(row=0,
                                                                column=1,
                                                                sticky='e')
        # adding status bar
        self.my_progress = ttk.Progressbar(self.status_frame,
                                           orient=HORIZONTAL,
                                           length=250,
                                           mode='determinate',
                                           style="LabeledProgressbar")
        self.my_progress.grid(row=0, column=2, sticky='e')
        # hiding progressbar
        self.my_progress.grid_remove()

        # debug text
        self.deb_frame = Frame(self.root)
        self.scr_deb = Scrollbar(self.deb_frame, orient=VERTICAL)

        self.my_text1 = Text(self.deb_frame,
                             state='disabled',
                             width=55,
                             height=8,
                             yscrollcommand=self.scr_deb.set,
                             bg="white")
        self.scr_deb.config(command=self.my_text1.yview)
        self.scr_deb.pack(side=RIGHT, fill=Y)
        self.deb_frame.grid(row=3, column=1, columnspan=2, padx=10)

        self.my_text1.pack(side=LEFT, fill=BOTH, expand=YES)

        self.menubar = Menubar(self)
        self.statusbar = Statusbar(self)
        self.set_values()

    def set_values(self):
        '''
        setting values of label, messages and buttons
        :return: None
        '''
        try:
            self.title_var.set(self.lang.title)
            self.d_descr_link.set(self.lang.title_entry)
            self.d_lab_one.set(self.lang.one_line)
            self.d_clear_button.set(self.lang.clear)
            self.d_start_down_btn.set(self.lang.start_download)
            self.d_stop_button.set(self.lang.stop_download)
            self.d_lb_save_in.set(self.lang.save_title)
            self.d_brownse_btn.set(self.lang.browse)
        except AttributeError:
            # at the moment do nothing
            pass

    def clear_text(self):
        self.my_text.delete(1.0, END)

    def browse_button(self):
        # Allow user to select a directory and store it in global var
        # called folder_path
        # global save_path
        self.filename = filedialog.askdirectory()
        if self.filename != '':
            self.save_path.set(self.filename)

    def stop_download(self):
        '''
        stop download thread and reset all necessary values
        '''
        if not self.ThreadLauncher.stopped():
            self.ThreadLauncher.terminate()
        self.ThreadLauncher.join()
        # reset values
        self.global_downloading = False
        # set message download stopped
        # get message on current lang
        self.status_text.set(self.lang.down_videos_stopped)
        # hide stop button
        self.stop_button.grid_remove()
        return None

    def launch_down(self):
        if self.global_downloading:
            messagebox.showinfo(self.lang.running, self.lang.running_msg)
            return None

        self.ThreadLauncher = DownloaderThread(target=self.download)
        self.ThreadLauncher.start()
        # pass

    def download(self):
        # using try and except to execute program without errors
        try:
            # reset counters
            self.reset_values()
            # global v_counter, v_down
            format_video = ''
            if self.option_format.get() == 1:
                # video
                format_video = 'bestvideo+bestaudio/best'
            elif self.option_format.get() == 2:
                # audio
                format_video = 'bestaudio/best'
            else:
                raise RuntimeError(
                    "Opzione formato di download non selezionato")
            self.where_save = self.save_path.get()
            self.my_progress.grid_remove()
            # default for audio format
            for_audio = {
                'postprocessors': [{
                    'key': 'FFmpegExtractAudio',
                    'preferredcodec': 'mp3',
                    'preferredquality': '192',
                }]
            }
            download_options = {
                'format': f'{format_video}',
                'outtmpl': f'{self.where_save}\\%(title)s.%(ext)s',
                'getfilename': '--get-filename',
                '--get-filename': True,
                'progress_hooks': [self.my_hook],
            }
            if self.option_format.get() == 2:
                download_options.update(for_audio)

            list_links = self.my_text.get(1.0, END)
            list_down = list_links.splitlines()
            list_down = [line.rstrip('\n') for line in list_down]
            # check for correct links
            c_l = 0
            for v_l in list_down:
                c_l += 1
                if v_l.count('http') > 1 or v_l.count('HTTP') > 1:
                    # self.status_text.set(f"Url not valid at line: {c_l}")
                    raise RuntimeError(f"{self.lang.url_invalid}: {c_l}")

            self.v_counter = len(list_down)
            # check if empty list
            if (self.v_counter == 0
                    or (len(list_down) and list_down[0] == '')):
                self.status_text.set(self.lang.no_videos)
                return None
            with youtube_dl.YoutubeDL(download_options) as dl:
                self.my_progress.grid()
                self.stop_button.grid()
                self.global_downloading = True
                for video_link in list_down:
                    if video_link == '':
                        continue
                    self.v_down += 1
                    dl.download([video_link])
                self.status_text.set(
                    f"{self.lang.all_downloaded} [{self.v_down}/{self.v_counter}]"
                )
            self.global_downloading = False
            self.stop_button.grid_remove()
            # link.set("Video downloaded successfully")
        except RuntimeError as e:
            self.status_text.set(e)
            pass
        except Exception as e:
            self.status_text.set(e)
            self.global_downloading = False
            # hide stop button
            self.stop_button.grid_remove()
            print(e)
            pass

    def my_hook(self, d):
        try:
            # global percentage, curr_progress_bar
            # tmpfilename
            # here we should check if stop process is requested or not
            file_tuple = os.path.split(os.path.abspath(d['filename']))
            # tmp_file_tuple = os.path.split(os.path.abspath(d['tmpfilename']))
            # print(tmp_file_tuple)
            if not self.downloading:
                self.my_text1.configure(state='normal')
                self.my_text1.insert(
                    'end', f"{self.v_down}) {self.lang.starts_down_video}:"
                    f"\n{file_tuple[1]}\n")
                self.my_text1.configure(state='disabled')
                self.downloading = True

            if d['status'] == 'finished':
                now = datetime.now()
                date_up = time.mktime(now.timetuple())
                os.utime(d['filename'], (date_up, date_up))
                # message_fin.set(f"Video \n {file_tuple[1]} \ndownloaded successfully")
                self.my_progress['value'] = 100
                self.downloading = False
                self.my_text1.configure(state='normal')
                self.my_text1.insert(
                    'end', f"{self.v_down}) {self.lang.video_downloaded}\n")
                self.my_text1.configure(state='disabled')
                # self.percentage.config(
                #    text=f"Downloaded... {self.my_progress['value']}%")
                self.s.configure("LabeledProgressbar",
                                 text=f"{self.my_progress['value']} %      ")
                self.status_text.set(
                    f"{self.lang.downloaded}... [{self.v_down}/{self.v_counter}]"
                )
                self.root.update_idletasks()

            if d['status'] == 'downloading':
                p = d['_percent_str']
                p = p.replace('%', '')
                p = d['_percent_str']
                p = p.replace('%', '')
                percentage = float(p)
                self.my_progress['value'] = percentage
                self.status_text.set(
                    f"{self.lang.downloading}... [{self.v_down}/{self.v_counter}]"
                )
                self.s.configure("LabeledProgressbar",
                                 text=f"{self.my_progress['value']} %      ")
                self.root.update_idletasks()
        except Exception as e:
            self.status_text.set(e)
            print(e)
            raise Exception(e)
class RegularityRallyGUI(RegularityRally):
    STATES = {-1: 'Select configuration',
              0: 'Ready',
              1: 'Fast Lap',
              2: 'Untimed Lap',
              3: 'Set Lap',
              4: 'Confirmation Lap'}

    def __init__(self):
        super().__init__()

        # Data attribute initialization.
        self.root_dir = pathlib.Path(__file__).parent.parent.absolute()
        self.config_dir = os.path.join(self.root_dir, 'config')

        # Overwrite initial state. Config read is mandatory here.
        self.state = -1

        # GUI attribute initialization.
        self.master = None
        self.font = None
        self.w = None
        self.h = None

        self.l_state = None
        self.l_mark = None
        self.l_cur_lap = None
        self.l_cur_lap_disp = None
        self.l_set_lap = None
        self.l_set_lap_disp = None
        self.t_laps = None
        self.bar_progress = None
        self.style_progress = None

        # Get start time.
        self.time_stamps = []

        # Window initialization.
        self.init_window()

    def init_window(self):
        # Create main window
        self.master = Tk()
        self.master.title('Regularity Rally Timer')

        # Resize window.
        self.master.state('zoomed')
        self.w = self.master.winfo_screenwidth()
        self.h = self.master.winfo_screenheight()

        # Init font variable.
        self.font = tk_font.Font(family="Helvetica", size=36, weight="bold")

        # Create menu
        menu_bar = Menu(self.master)

        file_menu = Menu(menu_bar, tearoff=0)
        file_menu.add_command(label='New', command=self.new_cb)
        file_menu.add_command(label='Exit', command=self.master.quit)
        menu_bar.add_cascade(label="File", menu=file_menu)

        extras_menu = Menu(menu_bar, tearoff=0)
        extras_menu.add_command(label='Set new start time', command=None)
        extras_menu.add_command(label='Manage Config Files', command=None)
        extras_menu.add_command(label='Options', command=None)
        menu_bar.add_cascade(label="Extras", menu=extras_menu)

        self.master.config(menu=menu_bar)

        # Init Widgets.
        # TODO: Resize and anchor Labels.
        # Information row.
        row_count = 0
        self.l_state = Label(self.master, text='Select Configuration', font=self.font)
        self.l_state.grid(row=row_count, column=0)
        self.l_mark = Label(self.master, text='', font=self.font)
        self.l_mark.grid(row=row_count, column=1)
        self.t_laps = Text(self.master, width=20, font=("Consolas", 32))
        self.t_laps.grid(row=row_count, column=2, rowspan=3)
        self.master.grid_rowconfigure(row_count, weight=1)

        # Labels row.
        row_count += 1
        self.l_cur_lap = Label(self.master, text='Current Lap', anchor='w', font=self.font)
        self.l_cur_lap.grid(row=row_count, column=0)
        self.l_set_lap = Label(self.master, text='Current Set Lap', anchor='w', font=self.font)
        self.l_set_lap.grid(row=row_count, column=1)
        self.master.grid_rowconfigure(row_count, weight=1)

        # Time display row.
        row_count += 1
        self.l_cur_lap_disp = Label(self.master, text='__:__:__._', anchor='w', font=self.font)
        self.l_cur_lap_disp.grid(row=row_count, column=0)
        self.l_set_lap_disp = Label(self.master, text='__:__:__._', anchor='w', font=self.font)
        self.l_set_lap_disp.grid(row=row_count, column=1)
        self.master.grid_rowconfigure(row_count, weight=1)

        # Progressbar and countdown row.
        row_count += 1
        # Create the progressbar style to be labeled.
        self.style_progress = Style(self.master)
        self.style_progress.layout("LabeledProgressbar",
                                   [('LabeledProgressbar.trough',
                                     {'children': [('LabeledProgressbar.pbar',
                                                    {'side': 'left', 'sticky': 'ns'}),
                                                   ("LabeledProgressbar.label",  # label inside the bar
                                                    {"sticky": ""})],
                                      'sticky': 'nswe'})])
        self.bar_progress = Progressbar(self.master, orient='horizontal', length=1000, mode='determinate',
                                        style="LabeledProgressbar")
        self.bar_progress.grid(row=row_count, column=0, columnspan=3, ipady=25)

        # Column configuration.
        self.master.grid_columnconfigure(0, weight=1)
        self.master.grid_columnconfigure(1, weight=1)

        # Define Binds.
        self.master.bind('1', self.one_cb)
        self.master.bind('2', self.two_cb)

        # Start master mainloop.
        self.master.after(10, self.gui_update)
        self.master.mainloop()

    def gui_update(self):
        # Calculate time delta of current lap.
        if self.state > 0:

            # Call regularity update.
            self.reg_update()

            # Update current lap time display.
            self.l_cur_lap_disp['text'] = '{:02}:{:02}:{:02}.{}'.format(self.curlap_decoded[0],
                                                                        self.curlap_decoded[1],
                                                                        self.curlap_decoded[2],
                                                                        floor(self.curlap_decoded[3]/100))

            # Update countdown display, if confirmation lap.
            if self.state == 4:
                # Update progress bar.
                self.bar_progress['value'] = self.curlap_countdown_seconds
                self.style_progress.configure("LabeledProgressbar", text='{:.2f}'.format(self.curlap_countdown_seconds))
                self.bar_progress.update()

                # Update mark label.
                if self.mark_count < len(self.mark_labels):
                    self.l_mark['text'] = self.mark_labels[self.mark_count]

            else:
                self.bar_progress['value'] = 0
                self.style_progress.configure("LabeledProgressbar", text='')

        # Schedule next call.
        self.master.after(10, self.gui_update)

    # Method called, when new race should be created.
    def new_cb(self):
        # Select and open a configuration.
        conf_file = open(filedialog.askopenfilename(initialdir=self.config_dir,
                                                    title='Select file',
                                                    filetypes=(('Configuration', "*.cfg"), ("all files", "*.*"))))

        # Read configuration.
        self.read_config(conf_file.name)

        # Write state.
        self.state = 0
        self.l_state['text'] = 'Ready'

    # Method for new lap.
    # Only update displays here. Set data in regularityRally.reg_new_lap()
    def one_cb(self, _):
        if self.state == -1:
            self.new_cb()
        else:
            # Store last state.
            last_state = self.state

            # Perform new lap method.
            self.reg_new_lap()

            # Change label.
            self.l_state['text'] = self.STATES[self.state]

            if self.state in [3, 4]:
                marks = list(self.config['marks'].keys())
                self.l_mark['text'] = marks[0]

            # Update lap times text field.
            self.t_laps.delete(1.0, 'end')
            for lt_id, lt in enumerate(self.lap_times_decoded):
                # Get text char from config. If id out of config, set 'F.
                if lt_id < len(self.config['states']):
                    state_char = self.STATES[self.config['states'][lt_id]][0]
                else:
                    state_char = 'F'

                # Set char for each lap.
                self.t_laps.insert('end', '{:>2}: {:02}:{:02}:{:02}.{:03} {}\n'.format(lt_id + 1,
                                                                                       lt[0], lt[1], lt[2], lt[3],
                                                                                       state_char))

            # Update GUI items related to set lap.
            if self.cur_set_time is not None:
                # Update shown set time.
                self.l_set_lap_disp['text'] = '{:02}:{:02}:{:02}.{:01}'.format(self.cur_set_time_decoded[0],
                                                                               self.cur_set_time_decoded[1],
                                                                               self.cur_set_time_decoded[2],
                                                                               floor(self.cur_set_time_decoded[3]/100))

                # Update progressbar maximum to set lap time to show countdown.
                self.bar_progress['maximum'] = self.cur_set_time

    def two_cb(self, _):
        # Execute superclass method.
        self.mark_reached()

        # Write next mark to label.
        marks = list(self.config['marks'].keys())
        if len(marks) > self.mark_count:
            self.l_mark['text'] = marks[self.mark_count]
        else:
            self.l_mark['text'] = 'countdown'
Beispiel #11
0
and a standard ttk theme is not used. 

Most ttk widgets set the font when using configure, Entry is an exception in that we set the
font as a property.
'''
from tkinter import Tk
from tkinter.ttk import Style, Entry

root_window = Tk()

estyle = Style()
estyle.theme_use(
    'clam')  # if not used then uncomment element_create and layout
# estyle.element_create("plain.field", "from", "clam") # "plain.field" is the cross reference
# follows the layout of "vista", need layout to enable configure with vista
'''
estyle.layout("EntryStyle.TEntry",
                   [('Entry.plain.field', {'children': [( # using the cross reference
                       'Entry.background', {'children': [(
                           'Entry.padding', {'children': [(
                               'Entry.textarea', {'sticky': 'nswe'})],
                      'sticky': 'nswe'})], 'sticky': 'nswe'})],
                      'border':'2', 'sticky': 'nswe'})])
'''
estyle.configure(
    "EntryStyle.TEntry",  # handle for style in Entry
    fieldbackground="light blue"  # Set colour here "EntryStyle.TEntry"
)  # font must be set in entry properties - not here

entry = Entry(root_window, style="EntryStyle.TEntry", font="Gigi 12")
entry.pack(padx=10, pady=10)
Beispiel #12
0
class MainDialog(tk.Frame):
    def __init__(self, master):
        tk.Frame.__init__(self, master)
        master.config(background=ctl.BACKGROUND_COLOR)
        toplevel = self.winfo_toplevel()
        toplevel.title('Corners Detector')
        toplevel.iconbitmap(os.path.abspath(os.path.join('resource', 'corners-icon.ico')))

        # Declare all of the instance attributes here, and initialize them in separate methods for code separation
        # Keep them as attributes so we will not have issues with garbage collection. Especially with the PhotoImage
        self.settings = Settings().load()
        self.__title_frame = None  # tk.Frame
        self.__action_frame = None  # tk.Frame
        self.__status_frame = None  # tk.Frame
        self.__figure_frame = None  # tk.Frame
        self.__title = None  # tk.Label
        self.__status_bar = None  # tk.Label
        self.__progress_bar = None  # tk.Progressbar
        self.__settings_button = None  # tk.Button
        self.__go_button = None  # tk.Button
        self.__open_file_button = None  # tk.Button
        self.__popup_image_button = None  # tk.Button
        self.__settings_button_tooltip = None  # view.tooltip.Tooltip
        self.__go_button_tooltip = None  # view.tooltip.Tooltip
        self.__open_file_button_tooltip = None  # view.tooltip.Tooltip
        self.__popup_image_button_tooltip = None  # view.tooltip.Tooltip
        self.__file_path_entry_tooltip = None  # view.tooltip.Tooltip
        self.__canny_check_var = None  # tk.IntVar  - to hold the value of the canny edge checkbox
        self.__canny_checkbutton = None  # tk.Checkbutton
        self.__gauss_check_var = None  # tk.IntVar  - to hold the value of the gaussian checkbox
        self.__gauss_checkbutton = None  # tk.Checkbutton
        self.__file_path_entry = None  # tk.Entry
        self.__magnifying_icon = None  # tk.PhotoImage
        self.__play_icon = None  # tk.PhotoImage
        self.__popout_icon = None  # tk.PhotoImage
        self.__settings_icon = None  # tk.PhotoImage
        self.__figure = None  # A reference to pyplot figure, so we can destroy it when there is a new input
        self.__style = None  # tk.ttk.Style
        self.__running = False  # Indication of when we wait for the Harris Detector worker to finish
        self.__image = None  # A reference to the input image. It is being set by the Harris Detector action
        self.__processed_image = None  # A reference to the processed image (outcome). It is being set by the Harris Detector action
        self.__error = False  # Indication for a failure during Harris Detector algorithm
        self.progress_text_format = '{0}%'

        self.__style = Style(master)
        self.__style.theme_use('clam')
        self.__style.configure("Horizontal.TProgressbar", foreground='#E0E0E0', background=ctl.ACCEPT_COLOR,
                               troughcolor=ctl.BACKGROUND_TOOLTIP_COLOR, bordercolor=ctl.ACCEPT_COLOR,
                               lightcolor=ctl.ACCEPT_COLOR, darkcolor=ctl.ACCEPT_COLOR)
        self.__style.configure('TButton', font=ctl.FONT_BUTTON, borderwidth='1', background=ctl.BACKGROUND_COLOR, relief='FLAT')
        self.__style.configure('TLabel', font=ctl.FONT_REGULAR)
        self.__style.map('TButton', background=[('active', '!disabled', '#4E6067')])
        self.__style.map('TCombobox', foreground=[('readonly', '!disabled', ctl.FOREGROUND_EDITOR_COLOR)])
        self.__style.map('TCombobox', background=[('readonly', '!disabled', ctl.BACKGROUND_EDITOR_COLOR)])
        self.__style.map('TCombobox', fieldbackground=[('readonly', '!disabled', ctl.BACKGROUND_EDITOR_COLOR)])
        self.__style.map('TCombobox', lightcolor=[('readonly', '!disabled', 'black')])
        self.__style.map('TCombobox', darkcolor=[('readonly', '!disabled', 'black')])
        self.__style.map('TCombobox', bordercolor=[('readonly', '!disabled', '#E0E0E0')])
        master.option_add("*TCombobox*Listbox*Background", ctl.BACKGROUND_EDITOR_COLOR)
        master.option_add("*TCombobox*Listbox*Foreground", ctl.FOREGROUND_EDITOR_COLOR)

        self.create_title_section(master)
        self.create_action_section(master)
        self.create_status_section(master)
        self.create_workarea_section(master)

        master.bind('<Return>', self.on_enter_pressed)
        master.geometry("800x600")

    def create_title_section(self, master):
        """
        Title area contains a frame with a label in it.
        :param master: Master dialog to add the frame to
        :return: None
        """
        self.__title_frame = ctl.create_frame(master, tk.X)
        self.__title = ctl.create_title(self.__title_frame, 'Corners Detector')
        self.__settings_icon = tk.PhotoImage(file=os.path.abspath(os.path.join('resource', 'settings-icon.png')))
        self.__settings_button = ttk.Button(master=self.__title_frame, image=self.__settings_icon, command=self.show_settings_dialog,
                                            style='TButton')
        self.__settings_button_tooltip = Tooltip(self.__settings_button, 'Settings')

        # First display the button and only then the label, so they will sit in one row
        self.__settings_button.pack(side=tk.RIGHT)
        self.__title.pack(fill=tk.X)

    def create_action_section(self, master):
        """
        Action area contains a frame with an entry (text edit for image path), open file dialog button and Go button.
        Open file dialog button will display an open file dialog to select image
        Go button will execute Harris Detector action on the selected image
        :param master: Master dialog to add the frame to
        :return: None
        """
        self.__action_frame = ctl.create_frame(master, tk.X)
        self.__magnifying_icon = tk.PhotoImage(file=os.path.abspath(os.path.join('resource', 'magnifying-icon.png')))
        self.__file_path_entry = ctl.create_entry(self.__action_frame)
        self.__file_path_entry.pack(fill=tk.BOTH, side=tk.LEFT, expand=True)
        self.__file_path_entry_tooltip = Tooltip(self.__file_path_entry, 'Click the magnifying icon in order to open an image')

        self.__open_file_button = ttk.Button(master=self.__action_frame, image=self.__magnifying_icon,
                                             command=self.open_file_action, style='TButton', width=4)
        self.__open_file_button.pack(side=tk.LEFT)
        self.__open_file_button_tooltip = Tooltip(self.__open_file_button, 'Open image or video')
        ctl.create_pad(self.__action_frame, tk.LEFT)

        self.__play_icon = tk.PhotoImage(file=os.path.abspath(os.path.join('resource', 'play-icon.png')))
        self.__go_button = ttk.Button(master=self.__action_frame, image=self.__play_icon,
                                      command=self.on_enter_pressed, style='TButton', width=4)
        self.__go_button_tooltip = Tooltip(self.__go_button, 'Execute corners detection')
        self.__go_button.pack(side=tk.RIGHT)

        # Get a second line in the actions area, so the checkbox will be under the entry
        helper_frame = ctl.create_frame(master, tk.X)
        self.__canny_checkbutton, self.__canny_check_var = ctl.create_checkbutton(helper_frame, 'Go through Canny Edge Detection', tk.LEFT)
        self.__gauss_checkbutton, self.__gauss_check_var = ctl.create_checkbutton(helper_frame, 'Apply Gaussian Blur', tk.LEFT)
        self.__gauss_checkbutton.select()

        self.__popout_icon = tk.PhotoImage(file=os.path.abspath(os.path.join('resource', 'pop-out-icon.png')))
        self.__popup_image_button = ttk.Button(master=helper_frame, image=self.__popout_icon, command=self.popup_image, style='TButton')
        self.__popup_image_button_tooltip = Tooltip(self.__popup_image_button, 'Pops out the image with marks as a pyplot dialog')
        self.__popup_image_button.pack(side=tk.RIGHT)
        self.__popup_image_button['state'] = 'disabled'

    def create_status_section(self, master):
        """
        Status area contains a progress bar which we put at the bottom of the frame, to show a progress indication when
        the algorithm is executing. (Can take some seconds)
        We also add a label into the progress bar to use it as a status bar as well
        :param master: Master dialog to add the frame to
        :return: None
        """
        self.__status_frame = ctl.create_frame(master, tk.X, 0, 0)
        self.__status_frame.pack(fill=tk.X, side=tk.BOTTOM, anchor=tk.S)
        # Add label into the layout
        self.__style.layout('text.Horizontal.TProgressbar',
                            [('Horizontal.Progressbar.trough',
                              {'children': [('Horizontal.Progressbar.pbar', {'side': 'left', 'sticky': 's'})], 'sticky': 'swe'}),
                             ('Horizontal.Progressbar.label', {'sticky': 'we'})])
        self.__style.configure('text.Horizontal.TProgressbar', font=ctl.FONT_REGULAR)
        self.__progress_bar = tk.ttk.Progressbar(master=self.__status_frame, orient=tk.HORIZONTAL, style='text.Horizontal.TProgressbar',
                                                 length=101, mode='determinate', value=0, maximum=101)
        self.__progress_bar.pack(fill=tk.X)
        self.update_status('Open an image using the magnifying button and click Play')

    def create_workarea_section(self, master):
        """
        Workarea contains a frame onto which we are displaying the plots when we finish executing Harris Detector algorithm
        :param master: Master dialog to add the frame to
        :return: None
        """
        self.__figure_frame = ctl.create_frame(master, tk.BOTH)
        self.__figure_frame.configure(background='white')  # Make it white because I could not modify the PyPlot background

    def update_status(self, text):
        """
        Updates the text of the progress bar (status bar) with the specified text
        :param text: The text to set into the status bar
        :return: None
        """
        self.__style.configure('text.Horizontal.TProgressbar', text=' ' + text)
        self.progress_text_format = ' ' + text + ' {0}%'
        print(text)

    def update_progress(self, progress):
        """
        Updates the progress bar with a progress, so user can see how much time remains
        :param progress: The progress sto set to the progressbar
        :return: None
        """
        progress = np.min([100, int(progress)])
        self.__progress_bar['value'] = progress
        self.__style.configure('text.Horizontal.TProgressbar', text=self.progress_text_format.format(progress))

    def start_progress(self):
        """
        Prepare for starting a progress in the progress bar, for visualizing process.
        We also start checking the job queue to detect if the algorithm has finished its execution so we can display the outcome
        :return: None
        """
        self.set_user_components_state('disabled')
        self.__image = self.__processed_image = None
        self.__running = True
        self.periodically_check_outcome()

        if self.__figure is not None:
            self.__figure.set_visible(False)
            self.__figure.clear()
            self.__figure = None

            # Remove all children so we will not have issues with pyplot's painting
            for child in self.__figure_frame.winfo_children():
                child.destroy()

    def stop_progress(self):
        """
        Stops the progress of the progress bar, and the periodic check of the job queue
        :return: None
        """
        # self.__progress_bar.stop()
        self.__progress_bar['value'] = 0
        self.__running = False
        self.set_user_components_state('normal')

    def set_user_components_state(self, new_state):
        """
        Sets the state of user components to 'normal' or 'disabled'.
        When the algorithm is running in background, we disable the user components so there won't be a mess
        :param new_state: The new state to set. Can be one of 'normal' or 'disabled'
        :return: None
        """
        self.__go_button['state'] = new_state
        self.__open_file_button['state'] = new_state
        self.__file_path_entry['state'] = new_state
        self.__canny_checkbutton['state'] = new_state
        self.__gauss_checkbutton['state'] = new_state
        self.__popup_image_button['state'] = new_state

    def open_file_action(self):
        """
        Displaying a file open dialog in image selecting mode, to select an image for executing the algorithm on
        :return: None
        """
        file_name = tkfiledialog.askopenfilename(filetypes=[("Image File", '.jpg .jpeg .png .bmp'), ("Video File", '.mp4 .avi .wmv')])
        self.__file_path_entry.delete(0, tk.END)
        self.__file_path_entry.insert(0, file_name)

    def show_settings_dialog(self):
        """
        Displaying Settings dialog so user can customize the algorithm settings
        :return: None
        """
        settings = SettingsDialog(self.master, self.settings).result
        if settings:
            self.settings = settings
            self.settings.save()

    def on_enter_pressed(self, event=None):
        """
        This event is raised whenever user presses the Go button or Enter
        In this case we are going to execute Harris Detector algorithm using the selected image, in case there is a valid selection.
        :param event: The keypress event (We register on the master frame)
        :return: None
        """
        file_path = self.__file_path_entry.get().strip()
        if file_path == '':
            messagebox.showerror('Illegal Input', 'Please select a file first')
            return None

        if not os.path.exists(file_path) or not os.path.isfile(file_path):
            messagebox.showerror('Illegal Input', 'Selected file is not a file or it does not exist:\n{}'.format(file_path))
            return None

        if not self.__running:
            if is_video(file_path):
                self.play_selected_video(file_path)
            else:
                self.start_progress()

                # Run it in background so the progress bar will not get blocked. (We cannot block te gui thread)
                t = Thread(target=self.execute_harris_detector, args=(file_path,))
                t.start()
        else:
            print('Already running. Cannot run multiple detections in parallel.')

    def execute_harris_detector(self, path):
        """
        The job of executing Harris Detector algorithm.
        It takes time so we have a specific action for that, such that we can run it using a background thread
        :param path: Path to the selected image
        :return: None
        """
        self.__image, self.__processed_image = corners_and_line_intersection_detector(cv2.imread(path),
                                                                                      lambda text: self.update_status(text),
                                                                                      lambda progress: self.update_progress(progress),
                                                                                      bool(self.__canny_check_var.get()),
                                                                                      bool(self.__gauss_check_var.get()),
                                                                                      self.settings)
        if self.__image is None or self.__processed_image is None:
            self.__error = True

    def show_images(self, img, processed_image):
        """
        When Harris Detector job has finished we display the results as embedded figure
        :param img: Original image
        :param processed_image: Image with corner marks
        :return: None
        """
        self.__figure = Figure(figsize=(5, 5), dpi=100)
        axes = self.__figure.add_subplot(121)
        axes.imshow(np.uint8(img[:, :, ::-1]))
        axes = self.__figure.add_subplot(122)
        axes.imshow(np.uint8(processed_image[:, :, ::-1]))
        self.__figure.subplots_adjust(0.05, 0.2, 0.95, 0.9, 0.2, 0.2)
        canvas = FigureCanvasTkAgg(self.__figure, self.__figure_frame)
        canvas.draw()
        canvas.get_tk_widget().pack(side=tk.BOTTOM, fill=tk.BOTH, expand=True)
        toolbar = NavigationToolbar2Tk(canvas, self.__figure_frame)
        toolbar.update()
        canvas._tkcanvas.pack(side=tk.TOP, fill=tk.BOTH, expand=True)

    def periodically_check_outcome(self):
        """
        Check every 200 ms if there is something new to show, which means a harris_detector worker has finished
        and we can pick the output and show it in the GUI
        """
        if self.__error:
            self.__error = False
            self.stop_progress()
            messagebox.showerror('Error', 'Error has occurred while trying to detect corners')
            self.__image = self.__processed_image = None
            return None

        if self.__image is not None and self.__processed_image is not None:
            self.stop_progress()
            # Plot the images, embedded within our dialog rather than popping up another dialog.
            self.show_images(self.__image, self.__processed_image)

        if self.__running:
            self.master.after(50, self.periodically_check_outcome)

    def popup_image(self):
        """
        Action corresponding to when user presses the popup button, to plot the outcome outside the main window
        :return: None
        """
        if self.__processed_image is not None:
            plt.figure('Corners Detector')
            plt.tight_layout(pad=0.5)
            plt.imshow(np.uint8(self.__processed_image[:, :, ::-1]))
            plt.subplots_adjust(0.05, 0.05, 0.95, 0.95, 0.1, 0.1)
            figure_manager = plt.get_current_fig_manager()
            figure_manager.window.iconbitmap(os.path.abspath(os.path.join('resource', 'corners-icon.ico')))
            try:
                # In case there would be an issue on Ubuntu or something like that, just catch the error and use resize
                figure_manager.window.state('zoomed')
            except Exception as e:
                print('Error has occurred while trying to show window as maximized. Fallback to resize strategy:', str(e))
                figure_manager.resize(*figure_manager.window.maxsize())
                figure_manager.window.wm_geometry("+0+0")

            plt.show()

    def play_selected_video(self, file_path):
        """
        This method will load a video from file and display it in cv2's window.
        We will execute corners detection, using the application settings, over the frames of the selected video and draw them live.
        :param file_path: Path to the video file to load
        :return: None
        """
        font = cv2.FONT_HERSHEY_COMPLEX
        bottom_left_corner_of_text = (10, 30)
        font_scale = 1
        font_color = (0, 255, 0)
        lineType = 1

        cap = cv2.VideoCapture(file_path)
        while cap.isOpened():
            ret, frame = cap.read()

            if frame is None:
                break

            # Don't send listeners while playing a video in order to avoid of flooding the console
            image, processed_image = corners_and_line_intersection_detector(frame,
                                                                            is_using_canny=bool(self.__canny_check_var.get()),
                                                                            is_applying_gauss=bool(self.__gauss_check_var.get()),
                                                                            settings=self.settings)
            self.__progress_bar['value'] = 0

            if processed_image is not None:
                cv2.putText(processed_image, 'Press q to stop', bottom_left_corner_of_text, font, font_scale, font_color, lineType)
                cv2.imshow('Corners Detector', processed_image)

            if cv2.waitKey(1) & 0xFF == ord('q'):
                break
        cap.release()
Beispiel #13
0
    def __init__(self):
        try:
            with open(r'C:\Users\barry\PycharmProjects\face_rec\labels.pickle',
                      'rb') as self.f:
                self.og_labels = pickle.load(self.f)
            print(self.og_labels)
        # error checking
        except FileNotFoundError:

            print(
                "No label.pickle file detected, will create required pickle files"
            )

        # this will be used to for selecting the photos
        self.current_id = 0
        # creating a blank ids dictionary
        self.labels_ids = {}
        # this is the directory where all the users are stored
        self.BASE_DIR = os.path.dirname(os.path.abspath(__file__))
        self.image_dir = os.path.join(self.BASE_DIR, 'images')
        for self.root, self.dirs, self.files in os.walk(self.image_dir):
            # checking each folder in the images directory
            for self.file in self.files:
                # looking for any png or jpg files of the users
                if self.file.endswith('png') or self.file.endswith('jpg'):
                    # getting the folder name, as the name of the folder will be the user
                    self.path = os.path.join(self.root, self.file)
                    self.label = os.path.basename(os.path.dirname(
                        self.path)).replace(' ', '-').lower()
                    if not self.label in self.labels_ids:
                        # adding the user into the labels_id dictionary
                        self.labels_ids[self.label] = self.current_id
                        self.current_id += 1
                        self.id = self.labels_ids[self.label]

        print(self.labels_ids)
        # this is compare the new label ids to the old label ids dictionary seeing if their has been any new users or old users
        # being added to the system, if there is no change then nothing will happen
        self.og_labels = 0
        toolbar_width = 40

        root = Tk()
        s = Style(root)
        # add the label to the progressbar style
        s.layout(
            "LabeledProgressbar",
            [(
                'LabeledProgressbar.trough',
                {
                    'children': [
                        ('LabeledProgressbar.pbar', {
                            'side': 'right',
                            'sticky': 'ns'
                        }),
                        (
                            "LabeledProgressbar.label",  # label inside the bar
                            {
                                "sticky": ""
                            })
                    ],
                    'sticky':
                    'nswe'
                })])

        p = Progressbar(root,
                        orient="horizontal",
                        length=300,
                        style="LabeledProgressbar")
        p.pack()

        # change the text of the progressbar,
        # the trailing spaces are here to properly center the text
        s.configure("LabeledProgressbar", text="0%")
        if self.labels_ids != self.og_labels:
            # if the dictionary change then the new dictionary will be dump into the pickle file
            with open('labels.pickle', 'wb') as self.file:
                pickle.dump(self.labels_ids, self.file)

            self.known_faces = []
            for self.i in self.labels_ids:

                noOfImgs = len([
                    filename
                    for filename in os.listdir('images/' + mssv.get() + self.i)
                    if os.path.isfile(
                        os.path.join('images/' + mssv.get() +
                                     self.i, filename))
                ])
                print("Dang load ", end='')
                print(noOfImgs, end='')
                print(" hinh cua ", end='')
                print(self.i)

                # setup toolbar
                sys.stdout.write("[%s]" % (" " * toolbar_width))
                sys.stdout.flush()
                sys.stdout.write(
                    "\b" *
                    (toolbar_width + 1))  # return to start of line, after '['

                for imgNo in range(1, (noOfImgs + 1)):
                    self.directory = os.path.join(self.image_dir, self.i,
                                                  str(imgNo) + '.png')
                    self.img = face_recognition.load_image_file(self.directory)
                    self.img_encoding = face_recognition.face_encodings(
                        self.img)[0]
                    self.known_faces.append([self.i, self.img_encoding])
                    #sf = self.directory.count(self.image_dir)
                    #sfd = self.directory.count(self.i)

                    #time.sleep(0.1)  # do real work here
                    # update the bar
                    percent = str(round((imgNo / noOfImgs) * 100))
                    #percent2 = str("Dang load " + str(imgNo) + "/" + str(noOfImgs) + "anh cua " + self.i)
                    #p.step((noOfImgs/imgNo)/1.22)
                    #s.configure("LabeledProgressbar", text="{0}".format(percent2))
                    #root.update()
                    sys.stdout.write(colored(percent + "% ", "green"))
                    sys.stdout.flush()

                sys.stdout.write("]\n")
            print(self.known_faces)

            print("No Of Imgs" + str(len(self.known_faces)))
            root.mainloop()
            with open('KnownFace.pickle', 'wb') as self.known_faces_file:
                pickle.dump(self.known_faces, self.known_faces_file)
        else:
            with open(
                    r'CC:\Users\barry\PycharmProjects\face_rec\KnownFace.pickle',
                    'rb') as self.faces_file:
                self.known_faces = pickle.load(self.faces_file)
            print(self.known_faces)
Beispiel #14
0
class EventScheduler(Tk):
    def __init__(self):
        Tk.__init__(self, className='Scheduler')
        logging.info('Start')
        self.protocol("WM_DELETE_WINDOW", self.hide)
        self._visible = BooleanVar(self, False)
        self.withdraw()

        self.icon_img = PhotoImage(master=self, file=ICON48)
        self.iconphoto(True, self.icon_img)

        # --- systray icon
        self.icon = TrayIcon(ICON, fallback_icon_path=ICON_FALLBACK)

        # --- menu
        self.menu_widgets = SubMenu(parent=self.icon.menu)
        self.menu_eyes = Eyes(self.icon.menu, self)
        self.icon.menu.add_checkbutton(label=_('Manager'),
                                       command=self.display_hide)
        self.icon.menu.add_cascade(label=_('Widgets'), menu=self.menu_widgets)
        self.icon.menu.add_cascade(label=_("Eyes' rest"), menu=self.menu_eyes)
        self.icon.menu.add_command(label=_('Settings'), command=self.settings)
        self.icon.menu.add_separator()
        self.icon.menu.add_command(label=_('About'),
                                   command=lambda: About(self))
        self.icon.menu.add_command(label=_('Quit'), command=self.exit)
        self.icon.bind_left_click(lambda: self.display_hide(toggle=True))

        add_trace(self._visible, 'write', self._visibility_trace)

        self.menu = Menu(self, tearoff=False)
        self.menu.add_command(label=_('Edit'), command=self._edit_menu)
        self.menu.add_command(label=_('Delete'), command=self._delete_menu)
        self.right_click_iid = None

        self.menu_task = Menu(self.menu, tearoff=False)
        self._task_var = StringVar(self)
        menu_in_progress = Menu(self.menu_task, tearoff=False)
        for i in range(0, 110, 10):
            prog = '{}%'.format(i)
            menu_in_progress.add_radiobutton(label=prog,
                                             value=prog,
                                             variable=self._task_var,
                                             command=self._set_progress)
        for state in ['Pending', 'Completed', 'Cancelled']:
            self.menu_task.add_radiobutton(label=_(state),
                                           value=state,
                                           variable=self._task_var,
                                           command=self._set_progress)
        self._img_dot = tkPhotoImage(master=self)
        self.menu_task.insert_cascade(1,
                                      menu=menu_in_progress,
                                      compound='left',
                                      label=_('In Progress'),
                                      image=self._img_dot)
        self.title('Scheduler')
        self.rowconfigure(1, weight=1)
        self.columnconfigure(0, weight=1)

        self.scheduler = BackgroundScheduler(coalesce=False,
                                             misfire_grace_time=86400)
        self.scheduler.add_jobstore('sqlalchemy',
                                    url='sqlite:///%s' % JOBSTORE)
        self.scheduler.add_jobstore('memory', alias='memo')
        # --- style
        self.style = Style(self)
        self.style.theme_use("clam")
        self.style.configure('title.TLabel', font='TkdefaultFont 10 bold')
        self.style.configure('title.TCheckbutton',
                             font='TkdefaultFont 10 bold')
        self.style.configure('subtitle.TLabel', font='TkdefaultFont 9 bold')
        self.style.configure('white.TLabel', background='white')
        self.style.configure('border.TFrame',
                             background='white',
                             border=1,
                             relief='sunken')
        self.style.configure("Treeview.Heading", font="TkDefaultFont")
        bgc = self.style.lookup("TButton", "background")
        fgc = self.style.lookup("TButton", "foreground")
        bga = self.style.lookup("TButton", "background", ("active", ))
        self.style.map('TCombobox',
                       fieldbackground=[('readonly', 'white'),
                                        ('readonly', 'focus', 'white')],
                       background=[("disabled", "active", "readonly", bgc),
                                   ("!disabled", "active", "readonly", bga)],
                       foreground=[('readonly', '!disabled', fgc),
                                   ('readonly', '!disabled', 'focus', fgc),
                                   ('readonly', 'disabled', 'gray40'),
                                   ('readonly', 'disabled', 'focus', 'gray40')
                                   ],
                       arrowcolor=[("disabled", "gray40")])
        self.style.configure('menu.TCombobox',
                             foreground=fgc,
                             background=bgc,
                             fieldbackground=bgc)
        self.style.map('menu.TCombobox',
                       fieldbackground=[('readonly', bgc),
                                        ('readonly', 'focus', bgc)],
                       background=[("disabled", "active", "readonly", bgc),
                                   ("!disabled", "active", "readonly", bga)],
                       foreground=[('readonly', '!disabled', fgc),
                                   ('readonly', '!disabled', 'focus', fgc),
                                   ('readonly', 'disabled', 'gray40'),
                                   ('readonly', 'disabled', 'focus', 'gray40')
                                   ],
                       arrowcolor=[("disabled", "gray40")])
        self.style.map('DateEntry', arrowcolor=[("disabled", "gray40")])
        self.style.configure('cal.TFrame', background='#424242')
        self.style.configure('month.TLabel',
                             background='#424242',
                             foreground='white')
        self.style.configure('R.TButton',
                             background='#424242',
                             arrowcolor='white',
                             bordercolor='#424242',
                             lightcolor='#424242',
                             darkcolor='#424242')
        self.style.configure('L.TButton',
                             background='#424242',
                             arrowcolor='white',
                             bordercolor='#424242',
                             lightcolor='#424242',
                             darkcolor='#424242')
        active_bg = self.style.lookup('TEntry', 'selectbackground',
                                      ('focus', ))
        self.style.map('R.TButton',
                       background=[('active', active_bg)],
                       bordercolor=[('active', active_bg)],
                       darkcolor=[('active', active_bg)],
                       lightcolor=[('active', active_bg)])
        self.style.map('L.TButton',
                       background=[('active', active_bg)],
                       bordercolor=[('active', active_bg)],
                       darkcolor=[('active', active_bg)],
                       lightcolor=[('active', active_bg)])
        self.style.configure('txt.TFrame', background='white')
        self.style.layout('down.TButton', [('down.TButton.downarrow', {
            'side': 'right',
            'sticky': 'ns'
        })])
        self.style.map('TRadiobutton',
                       indicatorforeground=[('disabled', 'gray40')])
        self.style.map('TCheckbutton',
                       indicatorforeground=[('disabled', 'gray40')],
                       indicatorbackground=[
                           ('pressed', '#dcdad5'),
                           ('!disabled', 'alternate', 'white'),
                           ('disabled', 'alternate', '#a0a0a0'),
                           ('disabled', '#dcdad5')
                       ])
        self.style.map('down.TButton', arrowcolor=[("disabled", "gray40")])

        self.style.map('TMenubutton',
                       arrowcolor=[('disabled',
                                    self.style.lookup('TMenubutton',
                                                      'foreground',
                                                      ['disabled']))])
        bg = self.style.lookup('TFrame', 'background', default='#ececec')
        self.configure(bg=bg)
        self.option_add('*Toplevel.background', bg)
        self.option_add('*Menu.background', bg)
        self.option_add('*Menu.tearOff', False)
        # toggle text
        self._open_image = PhotoImage(name='img_opened',
                                      file=IM_OPENED,
                                      master=self)
        self._closed_image = PhotoImage(name='img_closed',
                                        file=IM_CLOSED,
                                        master=self)
        self._open_image_sel = PhotoImage(name='img_opened_sel',
                                          file=IM_OPENED_SEL,
                                          master=self)
        self._closed_image_sel = PhotoImage(name='img_closed_sel',
                                            file=IM_CLOSED_SEL,
                                            master=self)
        self.style.element_create(
            "toggle",
            "image",
            "img_closed", ("selected", "!disabled", "img_opened"),
            ("active", "!selected", "!disabled", "img_closed_sel"),
            ("active", "selected", "!disabled", "img_opened_sel"),
            border=2,
            sticky='')
        self.style.map('Toggle', background=[])
        self.style.layout('Toggle', [('Toggle.border', {
            'children': [('Toggle.padding', {
                'children': [('Toggle.toggle', {
                    'sticky': 'nswe'
                })],
                'sticky': 'nswe'
            })],
            'sticky':
            'nswe'
        })])
        # toggle sound
        self._im_sound = PhotoImage(master=self, file=IM_SOUND)
        self._im_mute = PhotoImage(master=self, file=IM_MUTE)
        self._im_sound_dis = PhotoImage(master=self, file=IM_SOUND_DIS)
        self._im_mute_dis = PhotoImage(master=self, file=IM_MUTE_DIS)
        self.style.element_create(
            'mute',
            'image',
            self._im_sound, ('selected', '!disabled', self._im_mute),
            ('selected', 'disabled', self._im_mute_dis),
            ('!selected', 'disabled', self._im_sound_dis),
            border=2,
            sticky='')
        self.style.layout('Mute', [('Mute.border', {
            'children': [('Mute.padding', {
                'children': [('Mute.mute', {
                    'sticky': 'nswe'
                })],
                'sticky': 'nswe'
            })],
            'sticky':
            'nswe'
        })])
        self.style.configure('Mute', relief='raised')
        # widget scrollbar
        self._im_trough = {}
        self._im_slider_vert = {}
        self._im_slider_vert_prelight = {}
        self._im_slider_vert_active = {}
        self._slider_alpha = Image.open(IM_SCROLL_ALPHA)
        for widget in ['Events', 'Tasks']:
            bg = CONFIG.get(widget, 'background', fallback='gray10')
            fg = CONFIG.get(widget, 'foreground')

            widget_bg = self.winfo_rgb(bg)
            widget_fg = tuple(
                round(c * 255 / 65535) for c in self.winfo_rgb(fg))
            active_bg = active_color(*widget_bg)
            active_bg2 = active_color(*active_color(*widget_bg, 'RGB'))

            slider_vert = Image.new('RGBA', (13, 28), active_bg)
            slider_vert_active = Image.new('RGBA', (13, 28), widget_fg)
            slider_vert_prelight = Image.new('RGBA', (13, 28), active_bg2)

            self._im_trough[widget] = tkPhotoImage(width=15,
                                                   height=15,
                                                   master=self)
            self._im_trough[widget].put(" ".join(
                ["{" + " ".join([bg] * 15) + "}"] * 15))
            self._im_slider_vert_active[widget] = PhotoImage(
                slider_vert_active, master=self)
            self._im_slider_vert[widget] = PhotoImage(slider_vert, master=self)
            self._im_slider_vert_prelight[widget] = PhotoImage(
                slider_vert_prelight, master=self)
            self.style.element_create('%s.Vertical.Scrollbar.trough' % widget,
                                      'image', self._im_trough[widget])
            self.style.element_create(
                '%s.Vertical.Scrollbar.thumb' % widget,
                'image',
                self._im_slider_vert[widget],
                ('pressed', '!disabled', self._im_slider_vert_active[widget]),
                ('active', '!disabled', self._im_slider_vert_prelight[widget]),
                border=6,
                sticky='ns')
            self.style.layout(
                '%s.Vertical.TScrollbar' % widget,
                [('%s.Vertical.Scrollbar.trough' % widget, {
                    'children': [('%s.Vertical.Scrollbar.thumb' % widget, {
                        'expand': '1'
                    })],
                    'sticky':
                    'ns'
                })])
        # --- tree
        columns = {
            _('Summary'): ({
                'stretch': True,
                'width': 300
            }, lambda: self._sort_by_desc(_('Summary'), False)),
            _('Place'): ({
                'stretch': True,
                'width': 200
            }, lambda: self._sort_by_desc(_('Place'), False)),
            _('Start'): ({
                'stretch': False,
                'width': 150
            }, lambda: self._sort_by_date(_('Start'), False)),
            _('End'): ({
                'stretch': False,
                'width': 150
            }, lambda: self._sort_by_date(_("End"), False)),
            _('Category'): ({
                'stretch': False,
                'width': 100
            }, lambda: self._sort_by_desc(_('Category'), False))
        }
        self.tree = Treeview(self, show="headings", columns=list(columns))
        for label, (col_prop, cmd) in columns.items():
            self.tree.column(label, **col_prop)
            self.tree.heading(label, text=label, anchor="w", command=cmd)
        self.tree.tag_configure('0', background='#ececec')
        self.tree.tag_configure('1', background='white')
        self.tree.tag_configure('outdated', foreground='red')

        scroll = AutoScrollbar(self,
                               orient='vertical',
                               command=self.tree.yview)
        self.tree.configure(yscrollcommand=scroll.set)

        # --- toolbar
        toolbar = Frame(self)
        self.img_plus = PhotoImage(master=self, file=IM_ADD)
        Button(toolbar, image=self.img_plus, padding=1,
               command=self.add).pack(side="left", padx=4)
        Label(toolbar, text=_("Filter by")).pack(side="left", padx=4)
        # --- TODO: add filter by start date (after date)
        self.filter_col = Combobox(
            toolbar,
            state="readonly",
            # values=("",) + self.tree.cget('columns')[1:],
            values=("", _("Category")),
            exportselection=False)
        self.filter_col.pack(side="left", padx=4)
        self.filter_val = Combobox(toolbar,
                                   state="readonly",
                                   exportselection=False)
        self.filter_val.pack(side="left", padx=4)
        Button(toolbar,
               text=_('Delete All Outdated'),
               padding=1,
               command=self.delete_outdated_events).pack(side="right", padx=4)

        # --- grid
        toolbar.grid(row=0, columnspan=2, sticky='we', pady=4)
        self.tree.grid(row=1, column=0, sticky='eswn')
        scroll.grid(row=1, column=1, sticky='ns')

        # --- restore data
        data = {}
        self.events = {}
        self.nb = 0
        try:
            with open(DATA_PATH, 'rb') as file:
                dp = Unpickler(file)
                data = dp.load()
        except Exception:
            l = [
                f for f in os.listdir(os.path.dirname(BACKUP_PATH))
                if f.startswith('data.backup')
            ]
            if l:
                l.sort(key=lambda x: int(x[11:]))
                shutil.copy(os.path.join(os.path.dirname(BACKUP_PATH), l[-1]),
                            DATA_PATH)
                with open(DATA_PATH, 'rb') as file:
                    dp = Unpickler(file)
                    data = dp.load()
        self.nb = len(data)
        backup()
        now = datetime.now()
        for i, prop in enumerate(data):
            iid = str(i)
            self.events[iid] = Event(self.scheduler, iid=iid, **prop)
            self.tree.insert('',
                             'end',
                             iid,
                             values=self.events[str(i)].values())
            tags = [str(self.tree.index(iid) % 2)]
            self.tree.item(iid, tags=tags)
            if not prop['Repeat']:
                for rid, d in list(prop['Reminders'].items()):
                    if d < now:
                        del self.events[iid]['Reminders'][rid]
        self.after_id = self.after(15 * 60 * 1000, self.check_outdated)

        # --- bindings
        self.bind_class("TCombobox",
                        "<<ComboboxSelected>>",
                        self.clear_selection,
                        add=True)
        self.bind_class("TCombobox", "<Control-a>", self.select_all)
        self.bind_class("TEntry", "<Control-a>", self.select_all)
        self.tree.bind('<3>', self._post_menu)
        self.tree.bind('<1>', self._select)
        self.tree.bind('<Double-1>', self._edit_on_click)
        self.menu.bind('<FocusOut>', lambda e: self.menu.unpost())
        self.filter_col.bind("<<ComboboxSelected>>", self.update_filter_val)
        self.filter_val.bind("<<ComboboxSelected>>", self.apply_filter)

        # --- widgets
        self.widgets = {}
        prop = {
            op: CONFIG.get('Calendar', op)
            for op in CONFIG.options('Calendar')
        }
        self.widgets['Calendar'] = CalendarWidget(self,
                                                  locale=CONFIG.get(
                                                      'General', 'locale'),
                                                  **prop)
        self.widgets['Events'] = EventWidget(self)
        self.widgets['Tasks'] = TaskWidget(self)
        self.widgets['Timer'] = Timer(self)
        self.widgets['Pomodoro'] = Pomodoro(self)

        self._setup_style()

        for item, widget in self.widgets.items():
            self.menu_widgets.add_checkbutton(
                label=_(item),
                command=lambda i=item: self.display_hide_widget(i))
            self.menu_widgets.set_item_value(_(item), widget.variable.get())
            add_trace(widget.variable,
                      'write',
                      lambda *args, i=item: self._menu_widgets_trace(i))

        self.icon.loop(self)
        self.tk.eval("""
apply {name {
    set newmap {}
    foreach {opt lst} [ttk::style map $name] {
        if {($opt eq "-foreground") || ($opt eq "-background")} {
            set newlst {}
            foreach {st val} $lst {
                if {($st eq "disabled") || ($st eq "selected")} {
                    lappend newlst $st $val
                }
            }
            if {$newlst ne {}} {
                lappend newmap $opt $newlst
            }
        } else {
            lappend newmap $opt $lst
        }
    }
    ttk::style map $name {*}$newmap
}} Treeview
        """)

        # react to scheduler --update-date in command line
        signal.signal(signal.SIGUSR1, self.update_date)

        # update selected date in calendar and event list every day
        self.scheduler.add_job(self.update_date,
                               CronTrigger(hour=0, minute=0, second=1),
                               jobstore='memo')

        self.scheduler.start()

    def _setup_style(self):
        # scrollbars
        for widget in ['Events', 'Tasks']:
            bg = CONFIG.get(widget, 'background', fallback='gray10')
            fg = CONFIG.get(widget, 'foreground', fallback='white')

            widget_bg = self.winfo_rgb(bg)
            widget_fg = tuple(
                round(c * 255 / 65535) for c in self.winfo_rgb(fg))
            active_bg = active_color(*widget_bg)
            active_bg2 = active_color(*active_color(*widget_bg, 'RGB'))

            slider_vert = Image.new('RGBA', (13, 28), active_bg)
            slider_vert.putalpha(self._slider_alpha)
            slider_vert_active = Image.new('RGBA', (13, 28), widget_fg)
            slider_vert_active.putalpha(self._slider_alpha)
            slider_vert_prelight = Image.new('RGBA', (13, 28), active_bg2)
            slider_vert_prelight.putalpha(self._slider_alpha)

            self._im_trough[widget].put(" ".join(
                ["{" + " ".join([bg] * 15) + "}"] * 15))
            self._im_slider_vert_active[widget].paste(slider_vert_active)
            self._im_slider_vert[widget].paste(slider_vert)
            self._im_slider_vert_prelight[widget].paste(slider_vert_prelight)

        for widget in self.widgets.values():
            widget.update_style()

    def report_callback_exception(self, *args):
        err = ''.join(traceback.format_exception(*args))
        logging.error(err)
        showerror('Exception', str(args[1]), err, parent=self)

    def save(self):
        logging.info('Save event database')
        data = [ev.to_dict() for ev in self.events.values()]
        with open(DATA_PATH, 'wb') as file:
            pick = Pickler(file)
            pick.dump(data)

    def update_date(self, *args):
        """Update Calendar's selected day and Events' list."""
        self.widgets['Calendar'].update_date()
        self.widgets['Events'].display_evts()
        self.update_idletasks()

    # --- bindings
    def _select(self, event):
        if not self.tree.identify_row(event.y):
            self.tree.selection_remove(*self.tree.selection())

    def _edit_on_click(self, event):
        sel = self.tree.selection()
        if sel:
            sel = sel[0]
            self.edit(sel)

    # --- class bindings
    @staticmethod
    def clear_selection(event):
        combo = event.widget
        combo.selection_clear()

    @staticmethod
    def select_all(event):
        event.widget.selection_range(0, "end")
        return "break"

    # --- show / hide
    def _menu_widgets_trace(self, item):
        self.menu_widgets.set_item_value(_(item),
                                         self.widgets[item].variable.get())

    def display_hide_widget(self, item):
        value = self.menu_widgets.get_item_value(_(item))
        if value:
            self.widgets[item].show()
        else:
            self.widgets[item].hide()

    def hide(self):
        self._visible.set(False)
        self.withdraw()
        self.save()

    def show(self):
        self._visible.set(True)
        self.deiconify()

    def _visibility_trace(self, *args):
        self.icon.menu.set_item_value(_('Manager'), self._visible.get())

    def display_hide(self, toggle=False):
        value = self.icon.menu.get_item_value(_('Manager'))
        if toggle:
            value = not value
            self.icon.menu.set_item_value(_('Manager'), value)
        self._visible.set(value)
        if not value:
            self.withdraw()
            self.save()
        else:
            self.deiconify()

    # --- event management
    def event_add(self, event):
        self.nb += 1
        iid = str(self.nb)
        self.events[iid] = event
        self.tree.insert('', 'end', iid, values=event.values())
        self.tree.item(iid, tags=str(self.tree.index(iid) % 2))
        self.widgets['Calendar'].add_event(event)
        self.widgets['Events'].display_evts()
        self.widgets['Tasks'].display_tasks()
        self.save()

    def event_configure(self, iid):
        self.tree.item(iid, values=self.events[iid].values())
        self.widgets['Calendar'].add_event(self.events[iid])
        self.widgets['Events'].display_evts()
        self.widgets['Tasks'].display_tasks()
        self.save()

    def add(self, date=None):
        iid = str(self.nb + 1)
        if date is not None:
            event = Event(self.scheduler, iid=iid, Start=date)
        else:
            event = Event(self.scheduler, iid=iid)
        Form(self, event, new=True)

    def delete(self, iid):
        index = self.tree.index(iid)
        self.tree.delete(iid)
        for k, item in enumerate(self.tree.get_children('')[index:]):
            tags = [
                t for t in self.tree.item(item, 'tags') if t not in ['1', '0']
            ]
            tags.append(str((index + k) % 2))
            self.tree.item(item, tags=tags)

        self.events[iid].reminder_remove_all()
        self.widgets['Calendar'].remove_event(self.events[iid])
        del (self.events[iid])
        self.widgets['Events'].display_evts()
        self.widgets['Tasks'].display_tasks()
        self.save()

    def edit(self, iid):
        self.widgets['Calendar'].remove_event(self.events[iid])
        Form(self, self.events[iid])

    def check_outdated(self):
        """Check for outdated events every 15 min."""
        now = datetime.now()
        for iid, event in self.events.items():
            if not event['Repeat'] and event['Start'] < now:
                tags = list(self.tree.item(iid, 'tags'))
                if 'outdated' not in tags:
                    tags.append('outdated')
                self.tree.item(iid, tags=tags)
        self.after_id = self.after(15 * 60 * 1000, self.check_outdated)

    def delete_outdated_events(self):
        now = datetime.now()
        outdated = []
        for iid, prop in self.events.items():
            if prop['End'] < now:
                if not prop['Repeat']:
                    outdated.append(iid)
                elif prop['Repeat']['Limit'] != 'always':
                    end = prop['End']
                    enddate = datetime.fromordinal(
                        prop['Repeat']['EndDate'].toordinal())
                    enddate.replace(hour=end.hour, minute=end.minute)
                    if enddate < now:
                        outdated.append(iid)
        for item in outdated:
            self.delete(item)
        logging.info('Deleted outdated events')

    def refresh_reminders(self):
        """
        Reschedule all reminders.

        Required when APScheduler is updated.
        """
        for event in self.events.values():
            reminders = [date for date in event['Reminders'].values()]
            event.reminder_remove_all()
            for date in reminders:
                event.reminder_add(date)
        logging.info('Refreshed reminders')

    # --- sorting
    def _move_item(self, item, index):
        self.tree.move(item, "", index)
        tags = [t for t in self.tree.item(item, 'tags') if t not in ['1', '0']]
        tags.append(str(index % 2))
        self.tree.item(item, tags=tags)

    @staticmethod
    def to_datetime(date):
        date_format = get_date_format("short", CONFIG.get("General",
                                                          "locale")).pattern
        dayfirst = date_format.startswith("d")
        yearfirst = date_format.startswith("y")
        return parse(date, dayfirst=dayfirst, yearfirst=yearfirst)

    def _sort_by_date(self, col, reverse):
        l = [(self.to_datetime(self.tree.set(k, col)), k)
             for k in self.tree.get_children('')]
        l.sort(reverse=reverse)

        # rearrange items in sorted positions
        for index, (val, k) in enumerate(l):
            self._move_item(k, index)

        # reverse sort next time
        self.tree.heading(col,
                          command=lambda: self._sort_by_date(col, not reverse))

    def _sort_by_desc(self, col, reverse):
        l = [(self.tree.set(k, col), k) for k in self.tree.get_children('')]
        l.sort(reverse=reverse, key=lambda x: x[0].lower())

        # rearrange items in sorted positions
        for index, (val, k) in enumerate(l):
            self._move_item(k, index)

        # reverse sort next time
        self.tree.heading(col,
                          command=lambda: self._sort_by_desc(col, not reverse))

    # --- filter
    def update_filter_val(self, event):
        col = self.filter_col.get()
        self.filter_val.set("")
        if col:
            l = set()
            for k in self.events:
                l.add(self.tree.set(k, col))

            self.filter_val.configure(values=tuple(l))
        else:
            self.filter_val.configure(values=[])
            self.apply_filter(event)

    def apply_filter(self, event):
        col = self.filter_col.get()
        val = self.filter_val.get()
        items = list(self.events.keys())
        if not col:
            for item in items:
                self._move_item(item, int(item))
        else:
            i = 0
            for item in items:
                if self.tree.set(item, col) == val:
                    self._move_item(item, i)
                    i += 1
                else:
                    self.tree.detach(item)

    # --- manager's menu
    def _post_menu(self, event):
        self.right_click_iid = self.tree.identify_row(event.y)
        self.tree.selection_remove(*self.tree.selection())
        self.tree.selection_add(self.right_click_iid)
        if self.right_click_iid:
            try:
                self.menu.delete(_('Progress'))
            except TclError:
                pass
            state = self.events[self.right_click_iid]['Task']
            if state:
                self._task_var.set(state)
                if '%' in state:
                    self._img_dot = PhotoImage(master=self, file=IM_DOT)
                else:
                    self._img_dot = tkPhotoImage(master=self)
                self.menu_task.entryconfigure(1, image=self._img_dot)
                self.menu.insert_cascade(0,
                                         menu=self.menu_task,
                                         label=_('Progress'))
            self.menu.tk_popup(event.x_root, event.y_root)

    def _delete_menu(self):
        if self.right_click_iid:
            self.delete(self.right_click_iid)

    def _edit_menu(self):
        if self.right_click_iid:
            self.edit(self.right_click_iid)

    def _set_progress(self):
        if self.right_click_iid:
            self.events[self.right_click_iid]['Task'] = self._task_var.get()
            self.widgets['Tasks'].display_tasks()
            if '%' in self._task_var.get():
                self._img_dot = PhotoImage(master=self, file=IM_DOT)
            else:
                self._img_dot = tkPhotoImage(master=self)
            self.menu_task.entryconfigure(1, image=self._img_dot)

    # --- icon menu
    def exit(self):
        self.save()
        rep = self.widgets['Pomodoro'].stop(self.widgets['Pomodoro'].on)
        if not rep:
            return
        self.menu_eyes.quit()
        self.after_cancel(self.after_id)
        try:
            self.scheduler.shutdown()
        except SchedulerNotRunningError:
            pass
        self.destroy()

    def settings(self):
        splash_supp = CONFIG.get('General', 'splash_supported', fallback=True)
        dialog = Settings(self)
        self.wait_window(dialog)
        self._setup_style()
        if splash_supp != CONFIG.get('General', 'splash_supported'):
            for widget in self.widgets.values():
                widget.update_position()

    # --- week schedule
    def get_next_week_events(self):
        """Return events scheduled for the next 7 days """
        locale = CONFIG.get("General", "locale")
        next_ev = {}
        today = datetime.now().date()
        for d in range(7):
            day = today + timedelta(days=d)
            evts = self.widgets['Calendar'].get_events(day)
            if evts:
                evts = [self.events[iid] for iid in evts]
                evts.sort(key=lambda ev: ev.get_start_time())
                desc = []
                for ev in evts:
                    if ev["WholeDay"]:
                        date = ""
                    else:
                        date = "%s - %s " % (
                            format_time(ev['Start'], locale=locale),
                            format_time(ev['End'], locale=locale))
                    place = "(%s)" % ev['Place']
                    if place == "()":
                        place = ""
                    desc.append(("%s%s %s\n" % (date, ev['Summary'], place),
                                 ev['Description']))
                next_ev[day.strftime('%A')] = desc
        return next_ev

    # --- tasks
    def get_tasks(self):
        # TODO: find events with repetition in the week
        # TODO: better handling of events on several days
        tasks = []
        for event in self.events.values():
            if event['Task']:
                tasks.append(event)
        return tasks
Beispiel #15
0
    buttonPosition.configure(text='Left Window')
else:
    buttonPosition.configure(text='Right Window')

app.wm_attributes('-alpha', alpha)
app.wm_attributes('-topmost', 1)
app.resizable(0, 0)
app.overrideredirect(1)
app.protocol("WM_DELETE_WINDOW", on_closing)

s = Style(fr)
s.layout("LabeledProgressbar", [('LabeledProgressbar.trough', {
    'children': [('LabeledProgressbar.pbar', {
        'sticky': 'ns'
    }), ("LabeledProgressbar.label", {
        "sticky": ""
    })],
    'sticky':
    'nswe'
})])

l1 = tk.Label(fr, borderwidth=3, relief="ridge")
l1.place(x=int(ws * (24 / dw)), y=int(hs * (40 / dh)))
# Progress bar widget
progress = Progressbar(l1,
                       orient='horizontal',
                       length=int(ws * (220 / dw)),
                       mode='determinate',
                       style="LabeledProgressbar")
progress.pack()
s.configure("LabeledProgressbar",
Beispiel #16
0
class App:
    def __init__(self):
        self.root = Tk()
        self.s = Style()
        self.fr = Frame(self.root)
        self.fr.grid(sticky='nsew')
        self.img = PhotoImage("frameBorder", data="""
R0lGODlhPwA/APcAAAAAAJWVlby8vMTExAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAP8ALAAAAAA/AD8A
AAj/AP8JHEiwoMGDCBMqXMiwocOHECNKnEixokWGATJq3Mixo8ePF/9pDLlw48SRJB2iVBkgpcSM
LF2ebIlRJkWaCmHafIkTYc+dEH8aFAq0IVGBAnQWjRhAwMGkS086NQg1KtOpBatafdj06dGtPrES
1AoWo9iBZMvmPIv0q1qCXam6fSswbta5dO2OxftWL1q+av22pVuS7b+0hAsKPgy47GLEiQc+bgx2
cuSwXi8ftKxZsWHIlzl3lvyZ8lbRo0WWTk06M2vVrlmjHj27c23Nt0Ovfp07cu/EvwkH7zvZ9NKM
pY0XRf40qXKbyA0zfi6TOUIBznE3ld5WaV7rCbGbNQysETtD7M5XLi9v3iH6j/Djy4/OXSH69PPz
e0Qf8r7//wAG+J9LAxRo4IEIJqjggq81CFZAADs=
""")
        self.img1 = PhotoImage("frameFocusBorder", data="""
R0lGODlhPwA/APcAAAAAAP9jR5WVlby8vMTExAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAP8ALAAAAAA/AD8A
AAj/AP8JHEiwoMGDCBMqXMiwocOHECNKnEixokWGAjJq3Mixo8ePF/9pDECypMmTKFOm3DhxZICQ
C0tqhJiRJMyHJDM6rPnyJs4AOjHa9AkxJ0YBPYkWDZoQqdKJQBc6fRoxKsIBNalKBDrgINakWnEK
6Grwa9iqY71OPeuQq1qwbGOmLbs2rlyyBc3aZeiWLty9B/vmrQs48NzBfwsTFExQr2LDeBsTfjyQ
8UDHlBcflpyYsmWBmDML/PwvtGjSpjOjnqx682XWnl2Dhv14defaskvTVmxbdMHevivnTh078uvb
vIfvLgw8+L/mwaH7ln5aOXLm1p2Pzq6demvjs6/vaQWqfLld8uB1m4+L3ivW9WHRp1c/tHb7q+/r
A845dv5snsyRl1tj7/Ek3kX8ZTSAf5ctyJFKEEao0kYLMpiXgx9lqOGG/VmIH4YchvhRhSFVaOKJ
KKaoIok3EeDiizDGKOOMNGpno2IBAQA7
""")
        self.s.element_create("RoundedFrame", "image", "frameBorder",
            ("focus", "frameFocusBorder"), border=16, sticky="nsew")
        self.s.layout("RoundedFrame", [("RoundedFrame", {"sticky": "nsew"})])
        self.build()

    def build(self):
        self.rbs = []
        self.rbs1 = []
        self.lF0 = lF0 = LabelFrame(self.fr, text='Widget and Themes')
        lF0.grid(row=0, column=0, sticky='nw')
        self.fr1 = fr1 = Frame(lF0)
        fr1.grid(row=0, column=0, sticky='nw')
        # create check box to select reverse selection order
        self.lF12 = lF12 = LabelFrame(fr1, text='Select Widget before Theme')
        lF12.grid(row=0, column=0, sticky='nw')
        self.ord = ord = IntVar()
        ord.set(0)
        cbut3 = Checkbutton(lF12, text='Reverse selection order', variable=ord, 
                command=self.selord)
        cbut3.grid(row=0, column=0, padx=5, pady=5)
        cbut3.state(['!selected'])
        
        # create a Combobox to choose widgets
        widget_sel = ['Button', 'Checkbutton', 'Combobox', 'Entry', 'Frame',
                      'Label', 'LabelFrame', 'Menubutton', 'Notebook', 
                      'PanedWindow', 'Progressbar', 'Radiobutton', 'Scale', 
                      'Scrollbar', 'Separator', 'Sizegrip', 'Treeview']
        ord = self.ord

        self.lf6 = LabelFrame(self.fr1, text='Select Widget', style="RoundedFrame",
                               padding=(10,1,10,10))
        self.lf6.grid(row=1, column=0, sticky='nw')
        
        self.lf6.state([("focus" if self.ord.get() == 0 else "!focus")]) 
        self.widget_value = StringVar()
        self.cb = Combobox(self.lf6, values=widget_sel,
                           textvariable=self.widget_value,
                           state= ('disabled' if self.ord.get()==1 else 'active'))
        self.cb.grid(row=0, column=0, padx=5, pady=5, sticky='nw')
        self.cb.bind('<<ComboboxSelected>>', self.enabled)

        # create a Radio Buttons to choose orientation
        fr2 = Frame(self.lF0)
        fr2.grid(row=0, column=1, sticky='nw')        
        self.lF5 = lF5 = LabelFrame(fr2, style="RoundedFrame", padding=(10,1,10,10),
            text='Orientation of \nProgressbar \nScale \nScrollbar')
        lF5.grid(row=0, column=0, padx=5, pady=5, sticky='nw')
        self.orient = StringVar()
        orientT = ['Horizontal', 'Vertical']
        for ix, val in enumerate(orientT):
            rb = Radiobutton(lF5, text=val, value=val, command=self.orient_command,
                             variable=self.orient, state='disabled')
            rb.grid(row=ix, column=0, sticky='w')
            self.rbs.append(rb)
            
        # create Radio Buttons to choose themes
        themes = {"alt":  "alt - standard", 
            "clam":  "clam - standard", "classic":  "classic - standard",
            "default":  "default - standard"}
            
        self.lF1 = LabelFrame(self.fr1, text='Select Theme', style="RoundedFrame",
                              padding=(10,1,10,10))
        self.lF1.grid(row=2, column=0, sticky='n')
        self.theme_value = StringVar()
        for ix, val in enumerate(themes):
            rb1 = Radiobutton(self.lF1, text=themes[val], value=val, 
                state='disabled', variable=self.theme_value, command=self.theme_command)
            rb1.grid(row=ix, column=0, padx=10, sticky='nw')
            self.rbs1.append(rb1)
            
    def enabled(self, event):
        # from widget selection
        self.lf6.state(["!focus"]) 
        if self.ord.get() == 0:
            if self.widget_value.get() in ('Progressbar', 'Scale', 'Scrollbar'):
                self.lF5.state(["focus"])
                for opt in self.rbs:
                    opt.state(['!disabled'])
                for opt in self.rbs1:
                    opt.state(['disabled'])
            else:
                for opt in self.rbs1:
                    opt.state(['!disabled'])
                self.lF1.state(["focus"])    
                self.lF1['text'] = 'Select Theme'
                self.theme_value.set(None)
        if self.ord.get() == 1:
            self.lf6['text'] = 'Widget'
            if self.widget_value.get() in ('Progressbar', 'Scale', 'Scrollbar'):
                self.lF5.state(["focus"])
                for opt in self.rbs:
                    opt.state(['!disabled'])
                

    def orient_command(self):
        # from orient selection
        self.lF5.state(["!focus"])
        if self.ord.get() == 0:
            try:
                for opt in self.rbs1:
                    opt.state(['!disabled'])
                self.lF1.state(["focus"])
                self.theme_value.set(None)
                self.lF1['text'] = 'Select Theme'
            except (NameError, AttributeError):
                pass
    
    def theme_command(self):
        # from theme selection
        self.s.theme_use(self.theme_value.get())
        self.lF1.state(["!focus"])
        if self.ord.get() == 0:
            self.lF1['text'] = 'Theme'
        if self.ord.get() == 1:
            self.cb.state(['!disabled'])
            self.lF1['text'] = 'Theme'
            self.lf6.state(["focus"])
            
    def selord(self):
        # from select ord
        if self.ord.get() == 0:
            self.lf6.state(["focus"]) 
            self.lF12['text'] = 'Select widget before theme'
            self.theme_value.set(None)
            self.orient.set(None)
            self.cb.set('')
            self.lF1.state(["!focus"])
            self.lF5.state(["!focus"])
        if self.ord.get() == 1:
            self.lF12['text'] = 'Select theme before widget'
            self.cb.state(['disabled'])
            for opt in self.rbs1:
                opt.state(['!disabled'])
            self.lF1.state(["focus"])
            self.theme_value.set(None)
            self.orient.set(None)
            self.cb.set('')
            self.lf6.state(["!focus"])
            self.lF5.state(["!focus"])
Beispiel #17
0
class App(Tk):
    def __init__(self):
        Tk.__init__(self, className=cst.APP_NAME)
        self.protocol("WM_DELETE_WINDOW", self.quit)
        self.withdraw()

        logging.info('Starting %s', cst.APP_NAME)

        self.im_icon = PhotoImage(master=self, file=cst.IM_ICON_48)
        self.iconphoto(True, self.im_icon)

        # --- style
        self.style = Style(self)
        self.style.theme_use("clam")
        self.style.configure("TScale", sliderlength=20)
        self.style.map("TCombobox",
                       fieldbackground=[('readonly', 'white')],
                       selectbackground=[('readonly', 'white')],
                       selectforeground=[('readonly', 'black')])
        self.style.configure("title.TLabel", font="TkDefaultFont 9 bold")
        self.style.configure("white.TLabel", background="white")
        self.style.map("white.TLabel", background=[("active", "white")])
        self.style.configure('heading.TLabel',
                             relief='ridge',
                             borderwidth=1,
                             padding=(10, 4))
        self.style.configure('manager.TButton', padding=0)
        self.style.map('manager.Treeview', background=[], foreground=[])
        self.style.layout(
            'no_edit.TEntry',
            [('Entry.padding', {
                'children': [('Entry.textarea', {
                    'sticky': 'nswe'
                })],
                'sticky': 'nswe'
            })])
        self.style.configure('no_edit.TEntry',
                             background='white',
                             padding=[4, 0])
        self.style.configure('manager.TEntry', padding=[2, 1])
        self.style.layout('manager.Treeview.Row', [('Treeitem.row', {
            'sticky': 'nswe'
        }), ('Treeitem.image', {
            'side': 'right',
            'sticky': 'e'
        })])
        self.style.layout('manager.Treeview.Item', [('Treeitem.padding', {
            'children': [('Checkbutton.indicator', {
                'side': 'left',
                'sticky': ''
            }), ('Treeitem.text', {
                'side': 'left',
                'sticky': ''
            })],
            'sticky':
            'nswe'
        })])

        self._im_trough = tkPhotoImage(name='trough-scrollbar-vert',
                                       width=15,
                                       height=15,
                                       master=self)
        bg = CONFIG.get("Widget", 'background', fallback='gray10')
        widget_bg = (0, 0, 0)
        widget_fg = (255, 255, 255)
        vmax = self.winfo_rgb('white')[0]
        color = tuple(int(val / vmax * 255) for val in widget_bg)
        active_bg = cst.active_color(color)
        active_bg2 = cst.active_color(cst.active_color(color, 'RGB'))
        slider_vert_insens = Image.new('RGBA', (13, 28), widget_bg)
        slider_vert = Image.new('RGBA', (13, 28), active_bg)
        slider_vert_active = Image.new('RGBA', (13, 28), widget_fg)
        slider_vert_prelight = Image.new('RGBA', (13, 28), active_bg2)
        self._im_trough.put(" ".join(["{" + " ".join([bg] * 15) + "}"] * 15))
        self._im_slider_vert_active = PhotoImage(slider_vert_active,
                                                 name='slider-vert-active',
                                                 master=self)
        self._im_slider_vert = PhotoImage(slider_vert,
                                          name='slider-vert',
                                          master=self)
        self._im_slider_vert_prelight = PhotoImage(slider_vert_prelight,
                                                   name='slider-vert-prelight',
                                                   master=self)
        self._im_slider_vert_insens = PhotoImage(slider_vert_insens,
                                                 name='slider-vert-insens',
                                                 master=self)
        self.style.element_create('widget.Vertical.Scrollbar.trough', 'image',
                                  'trough-scrollbar-vert')
        self.style.element_create(
            'widget.Vertical.Scrollbar.thumb',
            'image',
            'slider-vert', ('pressed', '!disabled', 'slider-vert-active'),
            ('active', '!disabled', 'slider-vert-prelight'),
            ('disabled', 'slider-vert-insens'),
            border=6,
            sticky='ns')
        self.style.layout('widget.Vertical.TScrollbar', [
            ('widget.Vertical.Scrollbar.trough', {
                'children': [('widget.Vertical.Scrollbar.thumb', {
                    'expand': '1'
                })],
                'sticky': 'ns'
            })
        ])

        hide = Image.new('RGBA', (12, 12), active_bg2)
        hide_active = Image.new('RGBA', (12, 12), widget_fg)
        hide_pressed = Image.new('RGBA', (12, 12), (150, 0, 0))
        toggle_open = Image.new('RGBA', (9, 9), widget_fg)
        toggle_open_active = Image.new('RGBA', (9, 9), active_bg2)
        toggle_close = Image.new('RGBA', (9, 9), widget_fg)
        toggle_close_active = Image.new('RGBA', (9, 9), active_bg2)
        self._im_hide = PhotoImage(hide, master=self)
        self._im_hide_active = PhotoImage(hide_active, master=self)
        self._im_hide_pressed = PhotoImage(hide_pressed, master=self)
        self._im_open = PhotoImage(toggle_open, master=self)
        self._im_open_active = PhotoImage(toggle_open_active, master=self)
        self._im_close = PhotoImage(toggle_close, master=self)
        self._im_close_active = PhotoImage(toggle_close_active, master=self)

        self.style.element_create(
            "toggle",
            "image",
            self._im_close, ("!hover", "selected", "!disabled", self._im_open),
            ("hover", "!selected", "!disabled", self._im_close_active),
            ("hover", "selected", "!disabled", self._im_open_active),
            border=2,
            sticky='')
        self.style.layout('Toggle', [('Toggle.border', {
            'children': [('Toggle.padding', {
                'children': [('Toggle.toggle', {
                    'sticky': 'nswe'
                })],
                'sticky': 'nswe'
            })],
            'sticky':
            'nswe'
        })])
        self.style.configure('widget.close.TButton',
                             background=bg,
                             relief='flat',
                             image=self._im_hide,
                             padding=0)
        self.style.map('widget.close.TButton',
                       background=[],
                       relief=[],
                       image=[('active', '!pressed', self._im_hide_active),
                              ('active', 'pressed', self._im_hide_pressed)])
        self.option_add('*Toplevel.background',
                        self.style.lookup('TFrame', 'background'))
        self.option_add('*{app_name}.background'.format(app_name=cst.APP_NAME),
                        self.style.lookup('TFrame', 'background'))
        self.widget_style_init()

        # --- tray icon menu
        self.icon = TrayIcon(cst.ICON)
        self.menu_widgets = SubMenu(parent=self.icon.menu)

        self.menu_categories = SubMenu(parent=self.menu_widgets)
        self.menu_categories.add_command(label=_('Hide all'),
                                         command=self.hide_all_cats)
        self.menu_categories.add_command(label=_('Show all'),
                                         command=self.hide_all_cats)
        self.menu_categories.add_separator()

        self.menu_feeds = SubMenu(parent=self.menu_widgets)
        self.menu_feeds.add_command(label=_('Hide all'),
                                    command=self.hide_all_feeds)
        self.menu_feeds.add_command(label=_('Show all'),
                                    command=self.show_all_feeds)
        self.menu_feeds.add_separator()

        self.menu_widgets.add_command(label=_('Hide all'),
                                      command=self.hide_all)
        self.menu_widgets.add_command(label=_('Show all'),
                                      command=self.show_all)
        self.menu_widgets.add_separator()
        self.menu_widgets.add_cascade(label=_('Categories'),
                                      menu=self.menu_categories)
        self.menu_widgets.add_cascade(label=_('Feeds'), menu=self.menu_feeds)

        self.icon.menu.add_cascade(label=_('Widgets'), menu=self.menu_widgets)
        self.icon.menu.add_command(label=_('Add feed'), command=self.add)
        self.icon.menu.add_command(label=_('Update feeds'),
                                   command=self.feed_update)
        self.icon.menu.add_command(label=_('Manage feeds'),
                                   command=self.feed_manage)
        self.icon.menu.add_command(label=_("Suspend"), command=self.start_stop)
        self.icon.menu.add_separator()
        self.icon.menu.add_command(label=_('Settings'), command=self.settings)
        self.icon.menu.add_command(label=_("Check for updates"),
                                   command=lambda: UpdateChecker(self, True))
        self.icon.menu.add_command(label=_("Help"), command=lambda: Help(self))
        self.icon.menu.add_command(label=_("About"),
                                   command=lambda: About(self))
        self.icon.menu.add_command(label=_('Quit'), command=self.quit)
        self.icon.loop(self)

        self._notify_no_internet = True

        self._internet_id = ""
        self._update_id = ""
        self._check_add_id = ""
        self._check_end_update_id = ""
        self._check_result_update_id = {}
        self._check_result_init_id = {}
        self.queues = {}
        self.threads = {}

        # --- category widgets
        self.cat_widgets = {}
        self.cat_widgets['All'] = CatWidget(self, 'All')
        self.cat_widgets['All'].event_generate('<Configure>')
        self.menu_widgets.add_checkbutton(label=_('Latests'),
                                          command=self.toggle_latests_widget)
        cst.add_trace(self.cat_widgets['All'].variable, 'write',
                      self.latests_widget_trace)
        self.cat_widgets['All'].variable.set(
            LATESTS.getboolean('All', 'visible'))
        cats = LATESTS.sections()

        cats.remove('All')
        for category in cats:
            self.cat_widgets[category] = CatWidget(self, category)
            self.cat_widgets[category].event_generate('<Configure>')
            self.menu_categories.add_checkbutton(
                label=category,
                command=lambda c=category: self.toggle_category_widget(c))
            cst.add_trace(self.cat_widgets[category].variable,
                          'write',
                          lambda *args, c=category: self.cat_widget_trace(c))
            self.cat_widgets[category].variable.set(
                LATESTS.getboolean(category, 'visible'))

        # --- feed widgets
        self.feed_widgets = {}
        for title in FEEDS.sections():
            self._check_result_update_id[title] = ''
            self._check_result_init_id[title] = ''
            self.queues[title] = Queue(1)
            self.threads[title] = None
            self.menu_feeds.add_checkbutton(
                label=title,
                command=lambda t=title: self.toggle_feed_widget(t))
            self.feed_widgets[title] = FeedWidget(self, title)
            cst.add_trace(self.feed_widgets[title].variable,
                          'write',
                          lambda *args, t=title: self.feed_widget_trace(t))
            self.feed_widgets[title].variable.set(
                FEEDS.getboolean(title, 'visible', fallback=True))
        self.feed_init()

        # --- check for updates
        if CONFIG.getboolean("General", "check_update"):
            UpdateChecker(self)

        self.bind_class('TEntry', '<Control-a>', self.entry_select_all)

    def widget_style_init(self):
        """Init widgets style."""
        bg = CONFIG.get('Widget', 'background', fallback='gray10')
        feed_bg = CONFIG.get('Widget', 'feed_background', fallback='gray20')
        fg = CONFIG.get('Widget', 'foreground')
        vmax = self.winfo_rgb('white')[0]
        widget_bg = tuple(int(val / vmax * 255) for val in self.winfo_rgb(bg))
        widget_fg = tuple(int(val / vmax * 255) for val in self.winfo_rgb(fg))
        active_bg = cst.active_color(widget_bg)
        active_bg2 = cst.active_color(cst.active_color(widget_bg, 'RGB'))
        slider_alpha = Image.open(cst.IM_SCROLL_ALPHA)
        slider_vert_insens = Image.new('RGBA', (13, 28), widget_bg)
        slider_vert = Image.new('RGBA', (13, 28), active_bg)
        slider_vert.putalpha(slider_alpha)
        slider_vert_active = Image.new('RGBA', (13, 28), widget_fg)
        slider_vert_active.putalpha(slider_alpha)
        slider_vert_prelight = Image.new('RGBA', (13, 28), active_bg2)
        slider_vert_prelight.putalpha(slider_alpha)

        self._im_slider_vert_active.paste(slider_vert_active)
        self._im_slider_vert.paste(slider_vert)
        self._im_slider_vert_prelight.paste(slider_vert_prelight)
        self._im_slider_vert_insens.paste(slider_vert_insens)
        self._im_trough.put(" ".join(["{" + " ".join([bg] * 15) + "}"] * 15))

        hide_alpha = Image.open(cst.IM_HIDE_ALPHA)
        hide = Image.new('RGBA', (12, 12), active_bg)
        hide.putalpha(hide_alpha)
        hide_active = Image.new('RGBA', (12, 12), active_bg2)
        hide_active.putalpha(hide_alpha)
        hide_pressed = Image.new('RGBA', (12, 12), widget_fg)
        hide_pressed.putalpha(hide_alpha)
        toggle_open_alpha = Image.open(cst.IM_OPENED_ALPHA)
        toggle_open = Image.new('RGBA', (9, 9), widget_fg)
        toggle_open.putalpha(toggle_open_alpha)
        toggle_open_active = Image.new('RGBA', (9, 9), active_bg2)
        toggle_open_active.putalpha(toggle_open_alpha)
        toggle_close_alpha = Image.open(cst.IM_CLOSED_ALPHA)
        toggle_close = Image.new('RGBA', (9, 9), widget_fg)
        toggle_close.putalpha(toggle_close_alpha)
        toggle_close_active = Image.new('RGBA', (9, 9), active_bg2)
        toggle_close_active.putalpha(toggle_close_alpha)
        self._im_hide.paste(hide)
        self._im_hide_active.paste(hide_active)
        self._im_hide_pressed.paste(hide_pressed)
        self._im_open.paste(toggle_open)
        self._im_open_active.paste(toggle_open_active)
        self._im_close.paste(toggle_close)
        self._im_close_active.paste(toggle_close_active)

        self.style.configure('widget.TFrame', background=bg)
        self.style.configure('widget.close.TButton', background=bg)
        #                             relief='flat', image=self._im_hide, padding=0)
        #        self.style.map('widget.close.TButton', background=[], relief=[],
        #                       image=[('active', '!pressed', self._im_hide_active),
        #                              ('active', 'pressed', self._im_hide_pressed)])
        self.style.configure('widget.interior.TFrame', background=feed_bg)
        self.style.configure('widget.TSizegrip', background=bg)
        self.style.configure('widget.Horizontal.TSeparator', background=bg)
        self.style.configure('widget.TLabel',
                             background=bg,
                             foreground=fg,
                             font=CONFIG.get('Widget', 'font'))
        self.style.configure('widget.title.TLabel',
                             background=bg,
                             foreground=fg,
                             font=CONFIG.get('Widget', 'font_title'))
        self.style.configure('widget.TButton',
                             background=bg,
                             foreground=fg,
                             padding=1,
                             relief='flat')
        self.style.map('widget.TButton',
                       background=[('disabled', active_bg), ('pressed', fg),
                                   ('active', active_bg)],
                       foreground=[('pressed', bg)])
        #                       relief=[('pressed', 'sunken')])
        #                       bordercolor=[('pressed', active_bg)],
        #                       darkcolor=[('pressed', bg)],
        #                       lightcolor=[('pressed', fg)])

        self.update_idletasks()

    def hide_all(self):
        """Withdraw all widgets."""
        for widget in self.cat_widgets.values():
            widget.withdraw()
        for widget in self.feed_widgets.values():
            widget.withdraw()

    def show_all(self):
        """Deiconify all widgets."""
        for widget in self.cat_widgets.values():
            widget.deiconify()
        for widget in self.feed_widgets.values():
            widget.deiconify()

    def hide_all_feeds(self):
        """Withdraw all feed widgets."""
        for widget in self.feed_widgets.values():
            widget.withdraw()

    def show_all_feeds(self):
        """Deiconify all feed widgets."""
        for widget in self.feed_widgets.values():
            widget.deiconify()

    def hide_all_cats(self):
        """Withdraw all category widgets."""
        for cat, widget in self.cat_widgets.items():
            if cat != 'All':
                widget.withdraw()

    def show_all_cats(self):
        """Deiconify all category widgets."""
        for cat, widget in self.cat_widgets.items():
            if cat != 'All':
                widget.deiconify()

    def start_stop(self):
        """Suspend / restart update checks."""
        if self.icon.menu.get_item_label(4) == _("Suspend"):
            after_ids = [
                self._update_id, self._check_add_id, self._internet_id,
                self._check_end_update_id, self._update_id
            ]
            after_ids.extend(self._check_result_update_id.values())
            after_ids.extend(self._check_result_init_id.values())
            for after_id in after_ids:
                try:
                    self.after_cancel(after_id)
                except ValueError:
                    pass
            self.icon.menu.set_item_label(4, _("Restart"))
            self.icon.menu.disable_item(1)
            self.icon.menu.disable_item(2)
            self.icon.change_icon(cst.ICON_DISABLED, 'feedagregator suspended')
        else:
            self.icon.menu.set_item_label(4, _("Suspend"))
            self.icon.menu.enable_item(1)
            self.icon.menu.enable_item(2)
            self.icon.change_icon(cst.ICON, 'feedagregator')
            for widget in self.feed_widgets.values():
                widget.clear()
            self.feed_init()

    @staticmethod
    def entry_select_all(event):
        event.widget.selection_clear()
        event.widget.selection_range(0, 'end')

    def test_connection(self):
        """
        Launch update check if there is an internet connection otherwise
        check again for an internet connection after 30s.
        """
        if cst.internet_on():
            logging.info('Connected to Internet')
            self._notify_no_internet = True
            for widget in self.feed_widgets.values():
                widget.clear()
            self.feed_init()
        else:
            self._internet_id = self.after(30000, self.test_connection)

    def quit(self):
        for after_id in self.tk.call('after', 'info'):
            try:
                self.after_cancel(after_id)
            except ValueError:
                pass
        for thread in self.threads.values():
            try:
                thread.terminate()
            except AttributeError:
                pass
        for title, widget in self.feed_widgets.items():
            FEEDS.set(title, 'visible', str(widget.variable.get()))
        for cat, widget in self.cat_widgets.items():
            LATESTS.set(cat, 'visible', str(widget.variable.get()))
        try:
            self.destroy()
        except TclError:
            logging.error("Error on quit")
            self.after(500, self.quit)

    def feed_widget_trace(self, title):
        value = self.feed_widgets[title].variable.get()
        self.menu_feeds.set_item_value(title, value)
        FEEDS.set(title, 'visible', str(value))
        cst.save_feeds()

    def cat_widget_trace(self, category):
        value = self.cat_widgets[category].variable.get()
        self.menu_categories.set_item_value(category, value)
        LATESTS.set(category, 'visible', str(value))
        cst.save_latests()

    def latests_widget_trace(self, *args):
        value = self.cat_widgets['All'].variable.get()
        self.menu_widgets.set_item_value(_('Latests'), value)
        LATESTS.set('All', 'visible', str(value))
        cst.save_latests()

    def toggle_category_widget(self, category):
        value = self.menu_categories.get_item_value(category)
        if value:
            self.cat_widgets[category].deiconify()
        else:
            self.cat_widgets[category].withdraw()
        self.update_idletasks()

    def toggle_latests_widget(self):
        value = self.menu_widgets.get_item_value(_('Latests'))
        if value:
            self.cat_widgets['All'].deiconify()
        else:
            self.cat_widgets['All'].withdraw()
        self.update_idletasks()

    def toggle_feed_widget(self, title):
        value = self.menu_feeds.get_item_value(title)
        if value:
            self.feed_widgets[title].deiconify()
        else:
            self.feed_widgets[title].withdraw()
        self.update_idletasks()

    def report_callback_exception(self, *args):
        """Log exceptions."""
        err = "".join(traceback.format_exception(*args))
        logging.error(err)
        showerror(_("Error"), str(args[1]), err, True)

    def settings(self):
        update_delay = CONFIG.get('General', 'update_delay')
        splash_supp = CONFIG.get('General', 'splash_supported', fallback=True)
        dialog = Config(self)
        self.wait_window(dialog)
        cst.save_config()
        self.widget_style_init()
        splash_change = splash_supp != CONFIG.get('General',
                                                  'splash_supported')
        for widget in self.cat_widgets.values():
            widget.update_style()
            if splash_change:
                widget.update_position()
        for widget in self.feed_widgets.values():
            widget.update_style()
            if splash_change:
                widget.update_position()
        if update_delay != CONFIG.get('General', 'update_delay'):
            self.feed_update()

    def add(self):
        dialog = Add(self)
        self.wait_window(dialog)
        url = dialog.url
        self.feed_add(url)

    def category_remove(self, category):
        self.cat_widgets[category].destroy()
        del self.cat_widgets[category]
        self.menu_categories.delete(category)
        LATESTS.remove_section(category)
        cst.save_feeds()
        cst.save_latests()

    @staticmethod
    def feed_get_info(url, queue, mode='latest'):
        feed = feedparser.parse(url)
        feed_title = feed['feed'].get('title', '')
        entries = feed['entries']
        today = datetime.now().strftime('%Y-%m-%d %H:%M')
        if entries:
            entry_title = entries[0].get('title', '')
            summary = entries[0].get('summary', '')
            link = entries[0].get('link', '')
            latest = """<p id=title>{}</p>\n{}""".format(entry_title, summary)
            if 'updated' in entries[0]:
                updated = entries[0].get('updated')
            else:
                updated = entries[0].get('published', today)
            updated = dateutil.parser.parse(
                updated, tzinfos=cst.TZINFOS).strftime('%Y-%m-%d %H:%M')
        else:
            entry_title = ""
            summary = ""
            link = ""
            latest = ""
            updated = today

        if mode == 'all':
            data = []
            for entry in entries:
                title = entry.get('title', '')
                summary = entry.get('summary', '')
                if 'updated' in entry:
                    date = entry.get('updated')
                else:
                    date = entry.get('published', today)
                date = dateutil.parser.parse(
                    date, tzinfos=cst.TZINFOS).strftime('%Y-%m-%d %H:%M')
                link = entry.get('link', '')
                data.append((title, date, summary, link))
            queue.put((feed_title, latest, updated, data))
        else:
            queue.put(
                (feed_title, latest, updated, entry_title, summary, link))

    def _check_result_add(self, thread, queue, url, manager_queue=None):
        if thread.is_alive():
            self._check_add_id = self.after(1000, self._check_result_add,
                                            thread, queue, url, manager_queue)
        else:
            title, latest, date, data = queue.get(False)
            if title:
                try:
                    # check if feed's title already exists
                    FEEDS.add_section(title)
                except configparser.DuplicateSectionError:
                    i = 2
                    duplicate = True
                    while duplicate:
                        # increment i until title~#i does not already exist
                        try:
                            FEEDS.add_section("{}~#{}".format(title, i))
                        except configparser.DuplicateSectionError:
                            i += 1
                        else:
                            duplicate = False
                            name = "{}~#{}".format(title, i)
                else:
                    name = title
                if manager_queue is not None:
                    manager_queue.put(name)
                logging.info("Added feed '%s' %s", name, url)
                if CONFIG.getboolean("General", "notifications",
                                     fallback=True):
                    run([
                        "notify-send", "-i", cst.IM_ICON_SVG, name,
                        cst.html2text(latest)
                    ])
                self.cat_widgets['All'].entry_add(name, date, latest, url)
                filename = cst.new_data_file()
                cst.save_data(filename, latest, data)
                FEEDS.set(name, 'url', url)
                FEEDS.set(name, 'updated', date)
                FEEDS.set(name, 'data', filename)
                FEEDS.set(name, 'visible', 'True')
                FEEDS.set(name, 'geometry', '')
                FEEDS.set(name, 'position', 'normal')
                FEEDS.set(name, 'category', '')
                FEEDS.set(name, 'sort_is_reversed', 'False')
                FEEDS.set(name, 'active', 'True')
                cst.save_feeds()
                self.queues[name] = queue
                self.feed_widgets[name] = FeedWidget(self, name)
                self.menu_feeds.add_checkbutton(
                    label=name, command=lambda: self.toggle_feed_widget(name))
                cst.add_trace(self.feed_widgets[name].variable, 'write',
                              lambda *args: self.feed_widget_trace(name))
                self.feed_widgets[name].variable.set(True)
                for entry_title, date, summary, link in data:
                    self.feed_widgets[name].entry_add(entry_title, date,
                                                      summary, link, -1)
            else:
                if manager_queue is not None:
                    manager_queue.put('')
                if cst.internet_on():
                    logging.error('%s is not a valid feed.', url)
                    showerror(_('Error'),
                              _('{url} is not a valid feed.').format(url=url))
                else:
                    logging.warning('No Internet connection.')
                    showerror(_('Error'), _('No Internet connection.'))

    def feed_add(self, url, manager=False):
        """
        Add feed with given url.

        manager: whether this command is run from the feed manager.
        """
        if url:
            queue = Queue(1)
            manager_queue = Queue(1) if manager else None
            thread = Process(target=self.feed_get_info,
                             args=(url, queue, 'all'),
                             daemon=True)
            thread.start()
            self._check_result_add(thread, queue, url, manager_queue)
            if manager:
                return manager_queue

    def feed_set_active(self, title, active):
        FEEDS.set(title, 'active', str(active))
        cst.save_feeds()
        cat = FEEDS.get(title, 'category', fallback='')
        if active:
            self.menu_feeds.enable_item(title)
            if FEEDS.getboolean(title, 'visible'):
                self.feed_widgets[title].deiconify()
            if cat != '':
                self.cat_widgets[cat].show_feed(title)
            self.cat_widgets['All'].show_feed(title)
            self._feed_update(title)
        else:
            self.menu_feeds.disable_item(title)
            self.feed_widgets[title].withdraw()
            if cat != '':
                self.cat_widgets[cat].hide_feed(title)
            self.cat_widgets['All'].hide_feed(title)

    def feed_change_cat(self, title, old_cat, new_cat):
        if old_cat != new_cat:
            FEEDS.set(title, 'category', new_cat)
            if old_cat != '':
                self.cat_widgets[old_cat].remove_feed(title)
            if new_cat != '':
                if new_cat not in LATESTS.sections():
                    LATESTS.add_section(new_cat)
                    LATESTS.set(new_cat, 'visible', 'True')
                    LATESTS.set(new_cat, 'geometry', '')
                    LATESTS.set(new_cat, 'position', 'normal')
                    LATESTS.set(new_cat, 'sort_order', 'A-Z')
                    self.cat_widgets[new_cat] = CatWidget(self, new_cat)
                    self.cat_widgets[new_cat].event_generate('<Configure>')
                    self.menu_categories.add_checkbutton(
                        label=new_cat,
                        command=lambda: self.toggle_category_widget(new_cat))
                    cst.add_trace(self.cat_widgets[new_cat].variable, 'write',
                                  lambda *args: self.cat_widget_trace(new_cat))
                    self.cat_widgets[new_cat].variable.set(True)
                else:
                    try:
                        filename = FEEDS.get(title, 'data')
                        latest = cst.feed_get_latest(filename)
                    except (configparser.NoOptionError,
                            pickle.UnpicklingError):
                        latest = ''
                    self.cat_widgets[new_cat].entry_add(
                        title, FEEDS.get(title, 'updated'), latest,
                        FEEDS.get(title, 'url'))

    def feed_rename(self, old_name, new_name):
        options = {
            opt: FEEDS.get(old_name, opt)
            for opt in FEEDS.options(old_name)
        }
        FEEDS.remove_section(old_name)
        try:
            # check if feed's title already exists
            FEEDS.add_section(new_name)
        except configparser.DuplicateSectionError:
            i = 2
            duplicate = True
            while duplicate:
                # increment i until new_name~#i does not already exist
                try:
                    FEEDS.add_section("{}~#{}".format(new_name, i))
                except configparser.DuplicateSectionError:
                    i += 1
                else:
                    duplicate = False
                    name = "{}~#{}".format(new_name, i)
        else:
            name = new_name
        logging.info("Renamed feed '%s' to '%s'", old_name, name)
        for opt, val in options.items():
            FEEDS.set(name, opt, val)
        self._check_result_init_id[name] = self._check_result_init_id.pop(
            old_name, '')
        self._check_result_update_id[name] = self._check_result_update_id.pop(
            old_name, '')
        self.threads[name] = self.threads.pop(old_name, None)
        self.queues[name] = self.queues.pop(old_name)
        self.feed_widgets[name] = self.feed_widgets.pop(old_name)
        self.feed_widgets[name].rename_feed(name)
        self.cat_widgets['All'].rename_feed(old_name, name)
        category = FEEDS.get(name, 'category', fallback='')
        if category != '':
            self.cat_widgets[category].rename_feed(old_name, name)
        self.menu_feeds.delete(old_name)
        self.menu_feeds.add_checkbutton(
            label=name, command=lambda: self.toggle_feed_widget(name))
        trace_info = cst.info_trace(self.feed_widgets[name].variable)
        if trace_info:
            cst.remove_trace(self.feed_widgets[name].variable, 'write',
                             trace_info[0][1])
        cst.add_trace(self.feed_widgets[name].variable, 'write',
                      lambda *args: self.feed_widget_trace(name))
        self.menu_feeds.set_item_value(name,
                                       self.feed_widgets[name].variable.get())

        cst.save_feeds()
        return name

    def feed_remove(self, title):
        self.feed_widgets[title].destroy()
        del self.queues[title]
        try:
            del self.threads[title]
        except KeyError:
            pass
        del self.feed_widgets[title]
        try:
            del self._check_result_init_id[title]
        except KeyError:
            pass
        try:
            del self._check_result_update_id[title]
        except KeyError:
            pass
        try:
            os.remove(os.path.join(cst.PATH_DATA, FEEDS.get(title, 'data')))
        except FileNotFoundError:
            pass
        self.menu_feeds.delete(title)
        logging.info("Removed feed '%s' %s", title, FEEDS.get(title, 'url'))
        category = FEEDS.get(title, 'category', fallback='')
        self.cat_widgets['All'].remove_feed(title)
        if category != '':
            self.cat_widgets[category].remove_feed(title)
        FEEDS.remove_section(title)

    def feed_manage(self):
        dialog = Manager(self)
        self.wait_window(dialog)
        self.update_idletasks()
        cst.save_latests()
        if dialog.change_made:
            cst.save_feeds()
            self.feed_update()

    def feed_init(self):
        """Update feeds."""
        for title in FEEDS.sections():
            if FEEDS.getboolean(title, 'active', fallback=True):
                logging.info("Updating feed '%s'", title)
                self.threads[title] = Process(target=self.feed_get_info,
                                              args=(FEEDS.get(title, 'url'),
                                                    self.queues[title], 'all'),
                                              daemon=True)
                self.threads[title].start()
                self._check_result_init(title)
        self._check_end_update_id = self.after(2000, self._check_end_update)

    def _check_result_init(self, title):
        if self.threads[title].is_alive():
            self._check_result_init_id[title] = self.after(
                1000, self._check_result_init, title)
        else:
            t, latest, updated, data = self.queues[title].get()
            if not t:
                if cst.internet_on():
                    run([
                        "notify-send", "-i", "dialog-error",
                        _("Error"),
                        _('{url} is not a valid feed.').format(
                            url=FEEDS.get(title, 'url'))
                    ])
                    logging.error('%s is not a valid feed.',
                                  FEEDS.get(title, 'url'))
                else:
                    if self._notify_no_internet:
                        run([
                            "notify-send", "-i", "dialog-error",
                            _("Error"),
                            _('No Internet connection.')
                        ])
                        logging.warning('No Internet connection')
                        self._notify_no_internet = False
                        self._internet_id = self.after(30000,
                                                       self.test_connection)
                    after_ids = [
                        self._update_id, self._check_add_id,
                        self._check_end_update_id, self._update_id
                    ]
                    after_ids.extend(self._check_result_update_id.values())
                    after_ids.extend(self._check_result_init_id.values())
                    for after_id in after_ids:
                        try:
                            self.after_cancel(after_id)
                        except ValueError:
                            pass
            else:
                date = datetime.strptime(updated, '%Y-%m-%d %H:%M')
                if (date > datetime.strptime(FEEDS.get(title, 'updated'),
                                             '%Y-%m-%d %H:%M')
                        or not FEEDS.has_option(title, 'data')):
                    if CONFIG.getboolean("General",
                                         "notifications",
                                         fallback=True):
                        run([
                            "notify-send", "-i", cst.IM_ICON_SVG, title,
                            cst.html2text(latest)
                        ])
                    FEEDS.set(title, 'updated', updated)
                    category = FEEDS.get(title, 'category', fallback='')
                    self.cat_widgets['All'].update_display(
                        title, latest, updated)
                    if category != '':
                        self.cat_widgets[category].update_display(
                            title, latest, updated)
                    logging.info("Updated feed '%s'", title)
                    self.feed_widgets[title].clear()
                    for entry_title, date, summary, link in data:
                        self.feed_widgets[title].entry_add(
                            entry_title, date, summary, link, -1)
                    logging.info("Populated widget for feed '%s'", title)
                    self.feed_widgets[title].event_generate('<Configure>')
                    self.feed_widgets[title].sort_by_date()
                    try:
                        filename = FEEDS.get(title, 'data')
                    except configparser.NoOptionError:
                        filename = cst.new_data_file()
                        FEEDS.set(title, 'data', filename)
                        cst.save_feeds()
                    cst.save_data(filename, latest, data)
                else:
                    logging.info("Feed '%s' is up-to-date", title)

    def _feed_update(self, title):
        """Update feed with given title."""
        logging.info("Updating feed '%s'", title)
        self.threads[title] = Process(target=self.feed_get_info,
                                      args=(FEEDS.get(title, 'url'),
                                            self.queues[title]),
                                      daemon=True)
        self.threads[title].start()
        self._check_result_update(title)

    def feed_update(self):
        """Update all feeds."""
        try:
            self.after_cancel(self._update_id)
        except ValueError:
            pass
        for thread in self.threads.values():
            try:
                thread.terminate()
            except AttributeError:
                pass
        self.threads.clear()
        for title in FEEDS.sections():
            if FEEDS.getboolean(title, 'active', fallback=True):
                self._feed_update(title)
        self._check_end_update_id = self.after(2000, self._check_end_update)

    def _check_result_update(self, title):
        if self.threads[title].is_alive():
            self._check_result_update_id[title] = self.after(
                1000, self._check_result_update, title)
        else:
            t, latest, updated, entry_title, summary, link = self.queues[
                title].get(False)
            if not t:
                if cst.internet_on():
                    run([
                        "notify-send", "-i", "dialog-error",
                        _("Error"),
                        _('{url} is not a valid feed.').format(
                            url=FEEDS.get(title, 'url'))
                    ])
                    logging.error('%s is not a valid feed.',
                                  FEEDS.get(title, 'url'))
                else:
                    if self._notify_no_internet:
                        run([
                            "notify-send", "-i", "dialog-error",
                            _("Error"),
                            _('No Internet connection.')
                        ])
                        logging.warning('No Internet connection')
                        self._notify_no_internet = False
                        self._internet_id = self.after(30000,
                                                       self.test_connection)
                    after_ids = [
                        self._update_id, self._check_add_id,
                        self._check_end_update_id, self._update_id
                    ]
                    after_ids.extend(self._check_result_update_id.values())
                    after_ids.extend(self._check_result_init_id.values())
                    for after_id in after_ids:
                        try:
                            self.after_cancel(after_id)
                        except ValueError:
                            pass
            else:
                date = datetime.strptime(updated, '%Y-%m-%d %H:%M')
                if date > datetime.strptime(FEEDS.get(title, 'updated'),
                                            '%Y-%m-%d %H:%M'):
                    logging.info("Updated feed '%s'", title)
                    if CONFIG.getboolean("General",
                                         "notifications",
                                         fallback=True):
                        run([
                            "notify-send", "-i", cst.IM_ICON_SVG, title,
                            cst.html2text(latest)
                        ])
                    FEEDS.set(title, 'updated', updated)
                    category = FEEDS.get(title, 'category', fallback='')
                    self.cat_widgets['All'].update_display(
                        title, latest, updated)
                    if category != '':
                        self.cat_widgets[category].update_display(
                            title, latest, updated)
                    self.feed_widgets[title].entry_add(entry_title, updated,
                                                       summary, link, 0)
                    self.feed_widgets[title].sort_by_date()
                    try:
                        filename = FEEDS.get(title, 'data')
                        old, data = cst.load_data(filename)
                    except pickle.UnpicklingError:
                        cst.save_data(filename, latest,
                                      [(entry_title, updated, summary, link)])
                    except configparser.NoOptionError:
                        filename = cst.new_data_file()
                        FEEDS.set(title, 'data', filename)
                        cst.save_data(filename, latest,
                                      [(entry_title, updated, summary, link)])
                    else:
                        data.insert(0, (entry_title, updated, summary, link))
                        cst.save_data(filename, latest, data)
                else:
                    logging.info("Feed '%s' is up-to-date", title)

    def _check_end_update(self):
        b = [t.is_alive() for t in self.threads.values() if t is not None]
        if sum(b):
            self._check_end_update_id = self.after(1000,
                                                   self._check_end_update)
        else:
            cst.save_feeds()
            for widget in self.cat_widgets.values():
                widget.sort()
            self._update_id = self.after(
                CONFIG.getint("General", "update_delay"), self.feed_update)
Beispiel #18
0
class Application(Frame):
    def __init__(self, master=None):
        super().__init__(master)
        self.master = master
        self.master.geometry("200x150")
        self.master.pack_propagate(0)
        self.master.resizable(0, 0)
        self.working_directory = str()

        self.s = Style(master)
        self.s.layout("LabeledProgressbar", [('LabeledProgressbar.trough', {
            'children': [('LabeledProgressbar.pbar', {
                'side': 'left',
                'sticky': 'ns'
            }), ("LabeledProgressbar.label", {
                "sticky": ""
            })],
            'sticky':
            'nswe'
        })])
        self.s.configure("LabeledProgressbar", background='green')

        self.extract_button = Button(self)

        self.get_dir_button = Button(self)

        self.progress_bar = Progressbar(self.master,
                                        orient=HORIZONTAL,
                                        length=180,
                                        mode='determinate',
                                        style="LabeledProgressbar")

        self.configure_widgets()

        self.pack()

    def wire_extract_function(self, extract):
        self.extract_button["command"] = extract

    def update_progressbar(self, value, max_value):
        progress = round(value / max_value * 100, 2)
        self.progress_bar["value"] = progress
        self.s.configure("LabeledProgressbar",
                         text="{0} %      ".format(progress))
        self.master.update_idletasks()

    def configure_widgets(self):

        self.get_dir_button["text"] = "SELECT DIRECTORY"
        self.get_dir_button["command"] = self.ask_dir
        self.get_dir_button.pack(fill=BOTH, pady=10)

        self.extract_button["text"] = "EXTRACT"
        self.extract_button.pack(fill=BOTH, pady=10)

        self.progress_bar.pack(side=BOTTOM, pady=20)
        self.s.configure("LabeledProgressbar", text="0 %      ")

    def ask_dir(self):
        tmp = filedialog.askdirectory()
        self.working_directory = tmp.replace('\\', '/')
Beispiel #19
0
#*************************************************************************************************************************
# Initilizing progress bars

# progressbar with text inside it
s = Style(root)
# add the label to the progressbar style
s.layout(
    "LabeledProgressbar",
    [(
        'LabeledProgressbar.trough',
        {
            'children': [
                ('LabeledProgressbar.pbar', {
                    'side': 'left',
                    'sticky': 'ns'
                }),
                (
                    "LabeledProgressbar.label",  # label inside the bar
                    {
                        "sticky": ""
                    })
            ],
            'sticky':
            'nswe'
        })])

progress = Progressbar(commandframe,
                       orient="horizontal",
                       length=300,
                       style="LabeledProgressbar")
progress.pack(side=TOP, padx=10, pady=10)
Beispiel #20
0
    def add_fram_search(self):
        self.frame = Frame(self.window, width=850, height=385, bg="#ef5151")
        self.frame.place(x=77, y=20)

        self.l1 = Label(self.frame,
                        text="Enter Reg_N/Blood_G:",
                        font="Times 16 bold")
        self.l1.place(x=50, y=43)

        self.Entry_reg = Entry(self.frame, font="courior 14 bold")
        self.Entry_reg.place(x=280, y=43, height=30)

        # search-Button
        self.b1 = Button(self.frame, text="Search-RN", font="Times 12 bold")
        self.b1.place(x=510, y=40, height=37)
        self.b1.bind('<Button-1>', self.regno)

        self.b1 = Button(self.frame, text="Search-BG", font="Times 12 bold")
        self.b1.place(x=599, y=40, height=37)
        self.b1.bind('<Button-1>', self.bg)

        # Back-Buton
        self.b1 = Button(self.frame, text="Back", font="Times 12 bold")
        self.b1.place(x=690, y=40, height=37)
        self.b1.bind('<Button-1>', self.back)

        # for Styling Table
        style = Style()
        style.configure("mystyle.Treeview",
                        highlightthickness=0,
                        bd=0,
                        font=('Calibri 11'))  # Modify the font of the body
        style.configure(
            "mystyle.Treeview.Heading",
            font=('Calibri 13 bold'))  # Modify the font of the headings
        style.layout("mystyle.Treeview", [('mystyle.Treeview.treearea', {
            'sticky': 'nswe'
        })])  # Remove the borders

        # import TreeViewe
        self.tr = Treeview(self.frame,
                           columns=('A', 'B', 'C', 'D', 'E', 'F'),
                           selectmode="extended",
                           style="mystyle.Treeview")
        # heading key+text

        self.tr.heading("#0", text="Sr_No")
        self.tr.column("#0", minwidth=0, width=100, stretch=NO)

        self.tr.heading("#1", text="Name")
        self.tr.column("#1", minwidth=0, width=100, stretch=NO)

        self.tr.heading("#2", text="Reg_No")
        self.tr.column("#2", minwidth=0, width=100, stretch=NO)

        self.tr.heading("#3", text="Blood_Group")
        self.tr.column("#3", minwidth=0, width=100, stretch=NO)

        self.tr.heading("#4", text="Phone_No")
        self.tr.column("#4", minwidth=0, width=100, stretch=NO)

        self.tr.heading("#5", text="update")
        self.tr.column("#5", minwidth=0, width=100, stretch=NO)

        self.tr.heading("#6", text="delete")
        self.tr.column("#6", minwidth=0, width=100, stretch=NO)

        self.sb = Scrollbar(self.tr)
        self.sb.place(x=673, y=2, height=223, width=20, bordermode=OUTSIDE)
        self.sb.config(command=self.tr.yview)
        self.tr.config(yscrollcommand=self.sb.set)

        self.tr.place(x=50, y=100, width=691)
        # Remove All ROW
        self.Entry_reg.bind('<KeyRelease>', self.remove)

        self.tr.bind('<Double-Button-1>', self.action)

        self.window.mainloop()
Beispiel #21
0
from tkinter.ttk import Separator, Style, Combobox, Treeview
from time import sleep
from snapFood import *

mydb = SnapFoodDB()

style = Style()
style.configure("mystyle.Treeview",
                highlightthickness=0,
                bd=0,
                font=('Calibri', 11))  # Modify the font of the body
style.configure("mystyle.Treeview.Heading",
                font=('Calibri', 13,
                      'bold'))  # Modify the font of the headings
style.layout("mystyle.Treeview", [('mystyle.Treeview.treearea', {
    'sticky': 'nswe'
})])  # Remove the borders


class Application:
    def __init__(self, master):
        self.username = ""
        self.password = ""
        # self.db_cursor = mydb.cursor()
        self.master = master
        master.title("Snapp Food")

        #Bring the window to the center of screen
        windowWidth = master.winfo_reqwidth()
        windowHeight = master.winfo_reqheight()
        # print("Width",windowWidth,"Height",windowHeight)
Frame with Image

replace the image with your own image, if the screen size
is large enough, about 1000 wide by 350 high.
'''

from tkinter import Tk, PhotoImage
from tkinter.ttk import Frame, Style, Label, Entry
from PIL import Image, ImageTk

root = Tk()
s = Style()

im = Image.open('../images/BountyMoorea.jpg') # change to your own file
tkim = ImageTk.PhotoImage(im)
width,height = im.size

s.element_create("ship", "image", tkim)
s.layout("ship", [("ship", {"sticky": "nsew"})])

fr=Frame(root, style="ship", height=height,width=width) 
fr.grid(column=0, row=1, sticky='nsew')

il = Label(fr, text= 'Label')
il.place(relx=0.1, rely=0.1, anchor='center') # using place to position widget

en = Entry(fr, width=15)
en.place(relx=0.1, rely=0.15, anchor='center')

root.mainloop()
Beispiel #23
0
5pguUnClehS4tuMEDARQgH8FBMBBBExGwIGdAxywXAUBKHCZkAIoEEAFp33W
QGl47ZgBAwZEwKigE1SQgAUCUDCXiwtQIIAFCTQwgaCrZeCABAzIleIGHDD/
oIAHGUznmXABGMABT4xpmBYBHGgAKGq1ZbppThgAG8EEAW61KwYMSOBAApdy
pNp/BkhAAQLcEqCTt+ACJW645I5rLrgEeOsTBtwiQIEElRZg61sTNBBethSw
CwEA/Pbr778ABywwABBAgAAG7xpAq6mGUUTdAPZ6YIACsRKAAbvtZqzxxhxn
jDG3ybbKFHf36ZVYpuE5oIGhHMTqcqswvyxzzDS/HDMHEiiggQMLDxCZXh8k
BnEBCQTggAUGGKCB0ktr0PTTTEfttNRQT22ABR4EkEABDXgnGUEn31ZABglE
EEAAWaeN9tpqt832221HEEECW6M3wc+Hga3SBgtMODBABw00UEEBgxdO+OGG
J4744oZzXUEDHQxwN7F5G7QRdXxPoPkAnHfu+eeghw665n1vIKhJBQUEADs=""")

style = Style()
# img1 is frameFocusBorder, img2 is frameBorder - cross reference
style.element_create("RoundedFrame", "image", "frameBorder",
    ("focus", "frameFocusBorder"), border=16, sticky="nsew")

style.layout("RoundedFrame", [("RoundedFrame", {"sticky": "nsew"})])
style.configure("TEntry", borderwidth=0) # general handle widget class Entry

frame = Frame(style="RoundedFrame", padding=10)
frame.pack(fill='x')

frame2 = Frame(style="RoundedFrame", padding=10)
frame2.pack(fill='both', expand=1)

entry = Entry(frame, text='Test')
entry.pack(fill='x')
entry.bind("<FocusIn>", lambda evt: frame.state(["focus"]))
entry.bind("<FocusOut>", lambda evt: frame.state(["!focus"]))

text = Text(frame2, borderwidth=0, bg="white", highlightthickness=0)
text.pack(fill='both', expand=1)
RRRWENHwRQEBADs="""

# the images are combined gif data
s1 = PhotoImage("search1", data=data, format="gif -index 0")
s2 = PhotoImage("search2", data=data, format="gif -index 1")

style = Style()
style.theme_use('default')

style.element_create("Search.field", "image", "search1",
    ("focus", "search2"), border=[22, 7, 14], sticky="ew")

style.layout("Search.entry", [
    ("Search.field", {"sticky": "nswe", "border": 1, "children":
        [("Entry.padding", {"sticky": "nswe", "children":
            [("Entry.textarea", {"sticky": "nswe"})]
        })]
    })]
)

style.configure("Search.entry", background="#b2b2b2",
                font=font.nametofont("TkDefaultFont"))

root.configure(background="#b2b2b2")

e1 = Entry(style="Search.entry", width=20)
e1.grid(padx=10, pady=10)

e2 = Entry(style="Search.entry", width=20)
e2.grid(padx=10, pady=10)