Esempio n. 1
1
class OptionWindow(Toplevel):
    def __call__(self, options=[], display=True):
        self.options = options

        self.listbox.delete(0, END)
        for key, value in options:
            self.listbox.insert(END, key)

        if display:
            self.display()

    def __init__(self):
        Toplevel.__init__(self, master=root)
        self.options = None
        self.title('Matches')

        self.listbox = Listbox(master=self)

        self.listbox.pack(expand=True, fill=BOTH, side=TOP)
        self.listbox.focus_set()
        self.listbox.activate(0)
        self.listbox.selection_set(0)

        self.listbox.config(width=50)

        self.listbox.bind('<Key-h>',
                          lambda event: self.listbox.event_generate('<Left>'))

        self.listbox.bind('<Key-l>',
                          lambda event: self.listbox.event_generate('<Right>'))

        self.listbox.bind('<Key-k>',
                          lambda event: self.listbox.event_generate('<Up>'))

        self.listbox.bind('<Key-j>',
                          lambda event: self.listbox.event_generate('<Down>'))

        self.listbox.bind('<Escape>', lambda event: self.close())
        self.protocol("WM_DELETE_WINDOW", self.close)
        self.transient(root)
        self.withdraw()

    def display(self):
        self.grab_set()
        self.deiconify()
        self.listbox.focus_set()
        # self.wait_window(self)

    def close(self):
        # When calling destroy or withdraw without
        # self.deoiconify it doesnt give back
        # the focus to the parent window.

        self.deiconify()
        self.grab_release()
        self.withdraw()
Esempio n. 2
0
def openStats(handler):
    statsApi = get(
        "https://raw.githubusercontent.com/revoxhere/duco-statistics/master/api.json",
        data=None)
    if statsApi.status_code == 200:  #Check for reponse
        statsApi = (statsApi.json())
        print(statsApi)

    statsWindow = Toplevel()
    statsWindow.resizable(False, False)
    statsWindow.title("Duino-Coin Wallet - Stats")
    statsWindow.configure(background=backgroundColor)
    statsWindow.transient([root])

    textFont3 = Font(statsWindow, size=14, weight="bold")
    textFont = Font(statsWindow, size=12, weight="normal")

    Label(statsWindow,
          text="Duco Statistics - WIP",
          background=backgroundColor,
          foreground=foregroundColor,
          font=textFont3).grid(row=0, column=0)

    Active_workers_listbox = Listbox(statsWindow,
                                     exportselection=False,
                                     background=backgroundColor,
                                     foreground=foregroundColor,
                                     selectbackground="#7bed9f",
                                     border="0",
                                     font=textFont,
                                     width="20",
                                     height="13")
    Active_workers_listbox.grid(row=1, column=0, sticky=W)
    i = 0
    for worker in statsApi['Active workers']:
        Active_workers_listbox.insert(i, worker)
        i += 1

    Active_workers_listbox.select_set(32)
    Active_workers_listbox.event_generate("<<ListboxSelect>>")

    Top_10_listbox = Listbox(statsWindow,
                             exportselection=False,
                             background=backgroundColor,
                             foreground=foregroundColor,
                             selectbackground="#7bed9f",
                             border="0",
                             font=textFont,
                             width="33",
                             height="13")
    Top_10_listbox.grid(row=1, column=1, sticky=W)
    i = 0
    for rich in statsApi['Top 10 richest miners']:
        Top_10_listbox.insert(i, statsApi['Top 10 richest miners'][i])
        i += 1

    Top_10_listbox.select_set(32)
    Top_10_listbox.event_generate("<<ListboxSelect>>")

    statsWindow.mainloop()
Esempio n. 3
0
class SelectMultiple(TwoCells):
    def __init__(self, parent, text, values, **kwargs):
        super().__init__(parent, **kwargs)
        self.label = Label(self.frame, text=text)
        self.label.grid(column=0, row=0, padx=5, pady=5, sticky=W)
        self.selected_options = StringVar(self.frame)
        self.selected_options.set(values)
        self.listbox = Listbox(self.frame,
                               listvariable=self.selected_options,
                               selectmode=MULTIPLE)
        self.listbox.grid(column=1, row=0, padx=5, pady=5, sticky=E)

    def disable(self):
        self.listbox.configure(state=DISABLED)
        return self

    def enable(self):
        self.listbox.configure(state=NORMAL)
        return self

    def set(self, values):
        if values:
            self.enable()
        else:
            self.disable()
        self.listbox.selection_clear(0, self.listbox.size())
        for value in values:
            for index in range(self.listbox.size()):
                if value == self.listbox.get(index):
                    self.listbox.selection_set(index)
                    self.listbox.event_generate("<<ListboxSelect>>")

    def get(self):
        return [self.listbox.get(i) for i in self.listbox.curselection()]
class model_select(Frame):
    def __init__(self,controller,model_list,current_model,master,*args,**kwargs):
        self.controller = controller
        self.model_list = model_list
        self.current_model = current_model

        # Dibujar widget
        super().__init__(master, *args, **kwargs)
        self.listbox = Listbox(self, exportselection=False)
        self.listbox.bind('<<ListboxSelect>>', self.selection)
        self.listbox.pack()

        for item in self.model_list:
            self.listbox.insert(END, item)

        self.listbox.select_set(0)
        self.listbox.event_generate("<<ListboxSelect>>")

    def selection(self,x):
        w = x.widget
        index = int(w.curselection()[0])
        value = w.get(index)
        print(value)

        # Send message to interface to load another model
        f_path = os.path.join(config_folder, value)
        self.current_model.change_model(f_path)
        self.controller.event_change_model(self.current_model)
        pass
class mask_select(Frame):
    def __init__(self, controller, current_model : model_manager_obj, master, *args, **kwargs):
        self.controller = controller


        super().__init__(master, *args, **kwargs)
        self.listbox = Listbox(self, exportselection=False)
        self.listbox.pack(fill="both", expand=True)
        self.listbox.bind("<<ListboxSelect>>",self.selection)
        Label(self,text="New mask file: ").pack()
        self.entry_text = StringVar()
        Entry(self,textvariable=self.entry_text).pack()
        Button(self,text='Create',command=self.add_new).pack()

        self.update_model(current_model)


    def update_model(self, current_model):
        self.model = current_model
        self.mask_file_list = self.model.get_mask_file_list()
        self.current_mask_file=self.model.get_current_mask_file()

        self.listbox.delete(0, END)
        for item in self.mask_file_list:
            self.listbox.insert(END, item)
        self.listbox.select_set(0)
        self.listbox.event_generate("<<ListboxSelect>>")

    def selection(self,event):
        w = event.widget
        index = int(w.curselection()[0])
        value = w.get(index)
        selected = value
        self.controller.event_change_mask_file(selected)
        pass

    def add_new(self):
        new = self.entry_text.get()
        self.controller.event_add_mask_file(new)
        pass
Esempio n. 6
0
class Controller:
    SNAP_RADIUS = 5

    def __init__(self, tk: Tk):
        tk.title("Layered Polygons")

        menubar = Menu(tk)

        menu_file = Menu(menubar, tearoff=0)
        menu_file.add_command(label="New...", command=self._new_scene)
        menu_file.add_command(label="Open...", command=self._open_scene)
        menu_file.add_separator()
        menu_file.add_command(label="Save", command=self._save_scene)
        menu_file.add_command(label="Save As...", command=self._save_scene_as)
        menu_file.add_separator()
        menu_export = Menu(menu_file, tearoff=0)
        menu_export.add_command(label="Wavefront (.obj)...",
                                command=self._export_obj)
        menu_file.add_cascade(label="Export As", menu=menu_export)
        menu_file.add_separator()
        menu_file.add_command(label="Quit", command=self._quit_app)
        menubar.add_cascade(label="File", menu=menu_file)

        tk.config(menu=menubar)

        paned = PanedWindow(tk, relief=RAISED)
        paned.pack(fill=BOTH, expand=1)

        frame = Frame(paned)
        paned.add(frame)
        self._canvas = LayPolyCanvas(frame)
        bar_x = Scrollbar(frame, orient=HORIZONTAL)
        bar_x.pack(side=BOTTOM, fill=X)
        bar_x.config(command=self._canvas.xview)
        bar_y = Scrollbar(frame, orient=VERTICAL)
        bar_y.pack(side=RIGHT, fill=Y)
        bar_y.config(command=self._canvas.yview)
        self._canvas.config(xscrollcommand=bar_x.set, yscrollcommand=bar_y.set)
        self._canvas.pack(side=LEFT, expand=True, fill=BOTH)
        # Thanks to the two guys on Stack Overflow for that!
        # ( http://stackoverflow.com/a/7734187 )

        self._layer_list = Listbox(paned, selectmode=SINGLE)
        paned.add(self._layer_list)

        self._scene = None
        self._current_layer = None
        self._is_drawing_polygon = False
        self._tk = tk

        self._canvas.bind("<Button-1>", self._canvas_left_click)
        self._canvas.bind("<Button-3>", self._canvas_right_click)
        self._canvas.bind("<Motion>", self._canvas_mouse_moved)
        self._layer_list.bind("<<ListboxSelect>>", self._layer_change)

        self._current_path = None

    def _canvas_left_click(self, event):
        if not self._scene or not self._current_layer:
            return
        x, y = self._canvas.window_to_canvas_coords(event.x, event.y)

        if self._is_drawing_polygon:
            polygon = self._current_layer.get_polygon_at(-1)

            # Move vtx away from mouse to not interfere with search for closest
            polygon.get_vertex_at(-1).\
                set_coords(x-self.SNAP_RADIUS, y-self.SNAP_RADIUS)

            closest_vertex = self._current_layer.get_closest_vertex(
                x, y, self.SNAP_RADIUS)

            if closest_vertex:
                polygon.remove_vertex_at(-1)
                if closest_vertex is polygon.get_vertex_at(0):
                    self._is_drawing_polygon = False
                else:
                    polygon.add_vertex(closest_vertex)
                    polygon.add_vertex(Vertex(x, y))
            else:
                polygon.get_vertex_at(-1)\
                    .set_coords(x, y)
                polygon.add_vertex(Vertex(x, y))

            self._canvas.notify_polygon_change(self._current_layer
                                               .get_polygon_count()-1)
        else:
            # Create start vertex or use already existing one
            start_vertex = self._current_layer\
                .get_closest_vertex(x, y, self.SNAP_RADIUS)
            if not start_vertex:
                start_vertex = Vertex(x, y)

            # Vertex for mouse cursor
            next_vertex = Vertex(x, y)

            self._current_layer.add_polygon(
                Polygon([start_vertex, next_vertex]))

            self._is_drawing_polygon = True

            self._canvas.notify_layer_change()

    def _canvas_right_click(self, event):
        if not self._current_layer:
            return

        if self._is_drawing_polygon:
            self._current_layer.remove_polygon_at(-1)
            self._is_drawing_polygon = False
        else:
            x, y = self._canvas.window_to_canvas_coords(event.x, event.y)
            for i in range(0, self._current_layer.get_polygon_count()):
                if self._current_layer.get_polygon_at(i).contains(x, y):
                    self._current_layer.remove_polygon_at(i)
                    break

        self._canvas.notify_layer_change()

    def _canvas_mouse_moved(self, event):
        if self._is_drawing_polygon:
            x, y = self._canvas.window_to_canvas_coords(event.x, event.y)
            self._current_layer.get_polygon_at(-1).get_vertex_at(-1)\
                .set_coords(x, y)
            self._canvas.notify_polygon_change(self._current_layer
                                               .get_polygon_count()-1)

    def _layer_change(self, event):
        selection = self._layer_list.curselection()
        if len(selection) > 0 and self._scene:
            layer = self._scene.get_layer_at(selection[0])
            if layer:
                self._is_drawing_polygon = False
                self._current_layer = layer
                self._canvas.notify_new_layer(self._current_layer)

    def _set_scene(self, scene: Scene) -> bool:
        if scene.get_layer_count() <= 0:
            messagebox.showerror("Error!", "Scene has no layers!")
            return False

        self._scene = scene

        # Prepare canvas
        # TODO Extra 10px padding for canvas
        width, height = self._scene.get_size()
        self._canvas.config(scrollregion=(0, 0, width, height))

        # Empty listbox, fill it, select first entry
        self._layer_list.delete(0, self._layer_list.size()-1)
        for i in range(0, self._scene.get_layer_count()):
            self._layer_list.insert(i, self._scene.get_layer_at(i).get_name())
        self._layer_list.selection_set(0)
        self._layer_list.event_generate("<<ListboxSelect>>")

        return True

    def _set_current_path(self, path):
        self._current_path = path
        if path:
            self._tk.title(path + " - Layered Polygons")
        else:
            self._tk.title("Untitled - Layered Polygons")

    def _new_scene(self):
        path = filedialog.askopenfilename(defaultextension=".ora",
                                          filetypes=[("OpenRaster files",
                                                      ".ora")])
        if not path:
            return

        scene = ora.read(path)
        if not scene:
            messagebox.showerror("Error!", "File could not be opened!")
            return

        if self._set_scene(scene):
            self._set_current_path(None)

    def _open_scene(self):
        path = filedialog.askopenfilename(defaultextension=".lp",
                                          filetypes=[("Layered polygons"
                                                      " files", ".lp")])
        if not path:
            return

        scene = lp.read(path)
        if not scene:
            messagebox.showerror("Error!", "File could not be opened!")
            return

        if self._set_scene(scene):
            self._set_current_path(path)

    def _save_scene_help(self, path):
        if lp.save(path, self._scene):
            self._set_current_path(path)
        else:
            messagebox.showerror("Error!", "File could not be saved!")

    def _save_scene(self):
        if not self._current_path:
            self._save_scene_as()
            return
        self._save_scene_help(self._current_path)

    def _save_scene_as(self):
        if not self._scene:
            return
        path = filedialog.asksaveasfilename(defaultextension=".lp",
                                            filetypes=[("Layered polygons"
                                                        " files", ".lp")])
        if path:
            self._save_scene_help(path)

    def _export_obj(self):
        if not self._scene:
            return

        path_obj = filedialog.asksaveasfilename(defaultextension=".obj",
                                                filetypes=[("Wavefront object"
                                                            " files",
                                                            ".obj")])
        if not path_obj:
            return
        path_obj, path_mtl, path_data = obj.get_paths(path_obj)
        obj.save(path_obj, path_mtl, path_data, self._scene)

    def _quit_app(self):
        self._tk.quit()
        exit()
Esempio n. 7
0
class Application(tk.Frame):
    def __init__(self, parent, *args, **kwargs):
        self.entrys = []
        self.textboxes = []
        self.asterisks = 1
        self.selected_index = 0
        self.previous_index = None
        self.update_flag = False
        self.action_flag = 0
        self.previous_key = ''
        self.new_key = ''
        #init frame
        print('INITIALISING FRAME')
        tk.Frame.__init__(self, parent, *args, **kwargs)
        self.parent = parent
        #Set window name, size
        parent.title('SwiftPass')
        parent.geometry('700x700')
        #on mouse1 click, deselect listbox
        parent.bind('<ButtonPress-1>', self.deselect_lb_item)
        self.generate_widgets()
        self.populate_data()

    def generate_widgets(self):
        print('GENERATING WIDGETS')

        #Service ID
        self.serviceid_text = StringVar()
        self.serviceid_label = Label(self.parent,
                                     text='Service ID',
                                     font=(
                                         'bold',
                                         14,
                                     ),
                                     pady=20,
                                     padx=5)
        self.serviceid_label.grid(row=0, column=0, sticky=W)
        self.serviceid_entry = Entry(self.parent,
                                     textvariable=self.serviceid_text)
        self.serviceid_entry.grid(row=0, column=1)
        self.entrys.append(self.serviceid_entry)
        self.textboxes.append(self.serviceid_text)

        #Service Name
        self.service_text = StringVar()
        self.service_label = Label(self.parent,
                                   text='Service Name',
                                   font=('bold', 14),
                                   pady=20,
                                   padx=5)
        self.service_label.grid(row=1, column=0, sticky=W)
        self.service_entry = Entry(self.parent, textvariable=self.service_text)
        self.service_entry.grid(row=1, column=1)
        self.entrys.append(self.service_entry)
        self.textboxes.append(self.service_text)

        #URL
        self.url_text = StringVar()
        self.url_label = Label(self.parent,
                               text='URL',
                               font=('bold', 14),
                               pady=20,
                               padx=5)
        self.url_label.grid(row=2, column=0, sticky=W)
        self.url_entry = Entry(self.parent, textvariable=self.url_text)
        self.url_entry.grid(row=2, column=1)
        self.entrys.append(self.url_entry)
        self.textboxes.append(self.url_text)

        #Username
        self.username_text = StringVar()
        self.username_label = Label(self.parent,
                                    text='Username',
                                    font=('bold,', 14),
                                    pady=20,
                                    padx=5)
        self.username_label.grid(row=3, column=0, stick=W)
        self.username_entry = Entry(self.parent,
                                    textvariable=self.username_text)
        self.username_entry.grid(row=3, column=1)
        self.entrys.append(self.username_entry)
        self.textboxes.append(self.username_text)

        #Password
        self.password_text = StringVar()
        self.password_label = Label(self.parent,
                                    text='Password',
                                    font=('bold', 14),
                                    pady=20,
                                    padx=5)
        self.password_label.grid(row=4, column=0, sticky=W)
        self.password_entry = Entry(self.parent,
                                    textvariable=self.password_text)
        self.password_entry.grid(row=4, column=1)
        self.entrys.append(self.password_entry)
        self.textboxes.append(self.password_text)

        #Listbox
        self.password_list = Listbox(self.parent,
                                     height=20,
                                     width=50,
                                     border=1)
        self.password_list.grid(row=5,
                                column=0,
                                padx=5,
                                columnspan=3,
                                rowspan=6)
        self.password_list.bind('<<ListboxSelect>>', self.select)
        #self.scrollbar = tk.Scrollbar(self.parent)
        #self.scrollbar.grid(row=3, column=2)

        #self.password_list.config(yscrollcommand=self.scrollbar.set)
        #self.scrollbar.config(command=self.password_list.yview)

        #Add button
        self.add_btn = Button(self.parent,
                              text='Add Service',
                              width=12,
                              command=self.add_service,
                              fg='black',
                              foreground='black',
                              highlightbackground='black')
        self.add_btn.grid(row=0, column=3, pady=20, padx=5)

        #Remove button
        self.remove_btn = Button(self.parent,
                                 text='Remove Service',
                                 width=12,
                                 command=self.remove_service,
                                 fg='black',
                                 foreground='black',
                                 highlightbackground='black')
        self.remove_btn.grid(row=0, column=4, pady=20, padx=5)

        #Edit button
        self.edit_btn = Button(self.parent,
                               text='Edit Service',
                               width=12,
                               command=self.edit_service,
                               fg='black',
                               foreground='black',
                               highlightbackground='black')
        self.edit_btn.grid(row=1, column=3, pady=20, padx=5)

        #Show Password button
        self.show_passwords_btn = Button(self.parent,
                                         text='Show Passwords',
                                         width=12,
                                         command=self.toggle_show_passwords,
                                         fg='black',
                                         foreground='black',
                                         highlightbackground='black')
        self.show_passwords_btn.grid(row=1, column=4, pady=20, padx=5)

        #Save button
        self.save_btn = Button(self.parent,
                               text='Save',
                               width=12,
                               command=self.save,
                               state='disabled',
                               fg='black',
                               foreground='black',
                               highlightbackground='black')
        self.save_btn.grid(row=2, column=3, pady=20, padx=5)

        #Cancel button
        self.cancel_btn = Button(self.parent,
                                 text='Cancel',
                                 width=12,
                                 command=self.cancel,
                                 state='disabled',
                                 fg='black',
                                 foreground='black',
                                 highlightbackground='black')
        self.cancel_btn.grid(row=2, column=4, pady=20, padx=5)

        #Copy URL button
        self.copy_url_btn = Button(
            self.parent,
            text='Copy',
            width=12,
            command=lambda: self.clipboard(self.url_entry.get()),
            fg='black',
            foreground='black',
            highlightbackground='black')
        self.copy_url_btn.grid(row=2, column=2)

        #Copy Username button
        self.copy_uname_btn = Button(
            self.parent,
            text='Copy',
            width=12,
            command=lambda: self.clipboard(self.username_entry.get()),
            fg='black',
            foreground='black',
            highlightbackground='black')
        self.copy_uname_btn.grid(row=3, column=2)

        #Copy Password button
        self.copy_pass_btn = Button(
            self.parent,
            text='Copy',
            width=12,
            command=lambda: self.clipboard(
                db.get_password(self.serviceid_entry.get())),
            fg='black',
            foreground='black',
            highlightbackground='black')
        self.copy_pass_btn.grid(row=4, column=2)
        #self.toggle_tb(1)

        self.generate_secure_password_32_btn = Button(
            self.parent,
            text='Generate (32)',
            width=12,
            fg='black',
            foreground='black',
            highlightbackground='black',
            command=lambda: self.password_text.set(self.generate_password(32)),
            state='disabled')
        self.generate_secure_password_32_btn.grid(row=4, column=3)

        self.generate_secure_password_64_btn = Button(
            self.parent,
            text='Generate (64)',
            width=12,
            fg='black',
            foreground='black',
            highlightbackground='black',
            command=lambda: self.password_text.set(self.generate_password(64)),
            state='disabled')
        self.generate_secure_password_64_btn.grid(row=4, column=4)

    #Deselect currently selected listbox item
    def deselect_lb_item(self, event):
        print('DESELECTED LISTBOX')
        if self.selected_index == self.previous_index:
            self.password_list.selection_clear(0, tk.END)
        self.previous_index = self.password_list.curselection()

    def populate_data(self):
        #clear listbox
        print('POPULATING DATA')
        self.password_list.delete(0, END)

        if self.asterisks == 1:
            for row in db.fetch():
                #anonyimise password
                self.anonyimise_listbox(row)
        if self.asterisks == 0:
            for row in db.fetch():
                #insert row to listbox
                self.password_list.insert(END, row)

        self.password_list.select_set(self.selected_index)
        self.password_list.event_generate("<<ListboxSelect>>")

    def anonyimise_listbox(self, data):
        print('ANONYIMISING DATA')
        #anonyimise password
        pwd = self.anonymise(str(data[4]))
        data_list = list(data)
        data_list[4] = pwd
        new_row = tuple(data_list)
        #insert password
        self.password_list.insert(END, new_row)

    def unan_listbox(self):
        print('UNANYMISING DATA')
        #reinit data
        self.populate_data()

    def toggle_show_passwords(self):
        print('TOGGLING SHOW PASSWORDS')
        changed_flag = False
        if self.asterisks == 1:
            self.asterisks = 0
            #reinit data
            self.populate_data()
            changed_flag = True
        if self.asterisks == 0 and changed_flag is False:
            self.asterisks = 1
            #clear listbox
            self.password_list.delete(0, END)

            for row in db.fetch():
                #anonymise password
                self.anonyimise_listbox(row)
        self.password_list.select_set(self.selected_index)
        self.password_list.event_generate("<<ListboxSelect>>")

    def anonymise(self, password):
        #return anonyimised password
        return "*" * len(password)

    def add_service(self):
        print('BEGIN ADD SERVICE')
        self.clear()
        self.toggle_tb(0)
        self.action_flag = 'add'
        self.add_btn["state"] = "disabled"
        self.remove_btn["state"] = "disabled"
        self.edit_btn["state"] = "disabled"
        self.show_passwords_btn["state"] = "disabled"
        self.password_list["state"] = "disabled"
        self.save_btn["state"] = "active"
        self.cancel_btn["state"] = "active"
        self.generate_secure_password_32_btn["state"] = "active"
        self.generate_secure_password_64_btn["state"] = "active"

    def cancel(self):
        print('CANCEL ACTION')
        self.toggle_tb(1)
        self.save_btn["state"] = "disabled"
        self.cancel_btn["state"] = "disabled"
        self.add_btn["state"] = "active"
        self.remove_btn["state"] = "active"
        self.edit_btn["state"] = "active"
        self.password_list["state"] = "normal"
        self.show_passwords_btn["state"] = "active"
        self.generate_secure_password_32_btn["state"] = "disabled"
        self.generate_secure_password_64_btn["state"] = "disabled"
        return

    def save(self):
        print('SAVING ACTION')
        allow = False
        if self.action_flag == 'add':
            if self.insert_service() != -1:
                allow = True

        if self.action_flag == 'edit':
            if self.commit_edit() != -1:
                allow = True
        if allow is True:
            self.toggle_tb(1)
            self.save_btn["state"] = "disabled"
            self.cancel_btn["state"] = "disabled"
            self.add_btn["state"] = "active"
            self.remove_btn["state"] = "active"
            self.edit_btn["state"] = "active"
            self.show_passwords_btn["state"] = "active"
            self.password_list["state"] = "normal"
            self.generate_secure_password_32_btn["state"] = "disabled"
            self.generate_secure_password_64_btn["state"] = "disabled"

            self.populate_data()

    def insert_service(self):
        print('ATTEMPTING INSERT TO DATABASE')
        if self.check() == -1: return -1
        #insert data to be database
        print('INSERT SUCCESSFUL')
        db.insert(self.service_entry.get(), self.url_entry.get(),
                  str(self.username_entry.get()), self.password_entry.get())
        self.populate_data()

    def check(self):
        #length check
        if len(self.service_entry.get()) == 0 or len(
                self.username_entry.get()) == 0 or len(
                    self.url_entry.get()) == 0 or len(
                        self.password_entry.get()) == 0:
            #show message box
            mb.showerror("Error", "Please ensure all fields contain data")
            return -1
        return 1

    def edit_service(self):

        self.toggle_tb(0)
        self.add_btn["state"] = "disabled"
        self.remove_btn["state"] = "disabled"
        self.edit_btn["state"] = "disabled"
        self.show_passwords_btn["state"] = "disabled"
        self.password_list["state"] = "disabled"
        self.save_btn["state"] = "active"
        self.cancel_btn["state"] = "active"
        self.action_flag = 'edit'
        self.generate_secure_password_32_btn["state"] = "active"
        self.generate_secure_password_64_btn["state"] = "active"

    def commit_edit(self):
        if self.check() == -1: return
        #update database
        db.update(self.serviceid_entry.get(), self.service_entry.get(),
                  self.url_entry.get(), str(self.username_entry.get()),
                  self.password_entry.get())
        self.populate_data()

    def remove_service(self):
        id = self.serviceid_entry.get()
        db.remove(id)
        self.populate_data()

    def clear(self):
        #clear textboxes
        for tb in self.textboxes:
            tb.set('')
        return

    def toggle_tb(self, flag):
        #enable/disable textboxes
        if flag == 1:
            for tb in self.entrys:
                tb.config(state='disabled')
            return
        for tb in self.entrys:
            tb.config(state='normal')
        self.serviceid_entry.config(state='disabled')

    def select(self, event):
        #insert selected listbox item into textboxes
        sel = self.password_list.get(self.password_list.curselection())
        self.selected_index = self.password_list.curselection()
        service_id = sel[0]
        service_name = sel[1]
        url = sel[2]
        username = sel[3]
        password = sel[4]
        self.serviceid_text.set(service_id)
        self.service_text.set(service_name)
        self.url_text.set(url)
        self.username_text.set(username)
        #check if we need to anonymise
        if self.asterisks == 1:
            password = self.anonymise(password)
        self.password_text.set(password)

    def clipboard(self, arg):
        #copy to clipboard
        cbl.copy(arg)

    def generate_password(self, len):
        return ''.join(random.choice(string.ascii_letters) for i in range(len))
Esempio n. 8
0
class Controller:
    SNAP_RADIUS = 5

    def __init__(self, tk: Tk):
        tk.title("Layered Polygons")

        menubar = Menu(tk)

        menu_file = Menu(menubar, tearoff=0)
        menu_file.add_command(label="New...", command=self._new_scene)
        menu_file.add_command(label="Open...", command=self._open_scene)
        menu_file.add_separator()
        menu_file.add_command(label="Save", command=self._save_scene)
        menu_file.add_command(label="Save As...", command=self._save_scene_as)
        menu_file.add_separator()
        menu_export = Menu(menu_file, tearoff=0)
        menu_export.add_command(label="Wavefront (.obj)...",
                                command=self._export_obj)
        menu_file.add_cascade(label="Export As", menu=menu_export)
        menu_file.add_separator()
        menu_file.add_command(label="Quit", command=self._quit_app)
        menubar.add_cascade(label="File", menu=menu_file)

        tk.config(menu=menubar)

        paned = PanedWindow(tk, relief=RAISED)
        paned.pack(fill=BOTH, expand=1)

        frame = Frame(paned)
        paned.add(frame)
        self._canvas = LayPolyCanvas(frame)
        bar_x = Scrollbar(frame, orient=HORIZONTAL)
        bar_x.pack(side=BOTTOM, fill=X)
        bar_x.config(command=self._canvas.xview)
        bar_y = Scrollbar(frame, orient=VERTICAL)
        bar_y.pack(side=RIGHT, fill=Y)
        bar_y.config(command=self._canvas.yview)
        self._canvas.config(xscrollcommand=bar_x.set, yscrollcommand=bar_y.set)
        self._canvas.pack(side=LEFT, expand=True, fill=BOTH)
        # Thanks to the two guys on Stack Overflow for that!
        # ( http://stackoverflow.com/a/7734187 )

        self._layer_list = Listbox(paned, selectmode=SINGLE)
        paned.add(self._layer_list)

        self._scene = None
        self._current_layer = None
        self._is_drawing_polygon = False
        self._tk = tk

        self._canvas.bind("<Button-1>", self._canvas_left_click)
        self._canvas.bind("<Button-3>", self._canvas_right_click)
        self._canvas.bind("<Motion>", self._canvas_mouse_moved)
        self._layer_list.bind("<<ListboxSelect>>", self._layer_change)

        self._current_path = None

    def _canvas_left_click(self, event):
        if not self._scene or not self._current_layer:
            return
        x, y = self._canvas.window_to_canvas_coords(event.x, event.y)

        if self._is_drawing_polygon:
            polygon = self._current_layer.get_polygon_at(-1)

            # Move vtx away from mouse to not interfere with search for closest
            polygon.get_vertex_at(-1).\
                set_coords(x-self.SNAP_RADIUS, y-self.SNAP_RADIUS)

            closest_vertex = self._current_layer.get_closest_vertex(
                x, y, self.SNAP_RADIUS)

            if closest_vertex:
                polygon.remove_vertex_at(-1)
                if closest_vertex is polygon.get_vertex_at(0):
                    self._is_drawing_polygon = False
                else:
                    polygon.add_vertex(closest_vertex)
                    polygon.add_vertex(Vertex(x, y))
            else:
                polygon.get_vertex_at(-1)\
                    .set_coords(x, y)
                polygon.add_vertex(Vertex(x, y))

            self._canvas.notify_polygon_change(
                self._current_layer.get_polygon_count() - 1)
        else:
            # Create start vertex or use already existing one
            start_vertex = self._current_layer\
                .get_closest_vertex(x, y, self.SNAP_RADIUS)
            if not start_vertex:
                start_vertex = Vertex(x, y)

            # Vertex for mouse cursor
            next_vertex = Vertex(x, y)

            self._current_layer.add_polygon(
                Polygon([start_vertex, next_vertex]))

            self._is_drawing_polygon = True

            self._canvas.notify_layer_change()

    def _canvas_right_click(self, event):
        if not self._current_layer:
            return

        if self._is_drawing_polygon:
            self._current_layer.remove_polygon_at(-1)
            self._is_drawing_polygon = False
        else:
            x, y = self._canvas.window_to_canvas_coords(event.x, event.y)
            for i in range(0, self._current_layer.get_polygon_count()):
                if self._current_layer.get_polygon_at(i).contains(x, y):
                    self._current_layer.remove_polygon_at(i)
                    break

        self._canvas.notify_layer_change()

    def _canvas_mouse_moved(self, event):
        if self._is_drawing_polygon:
            x, y = self._canvas.window_to_canvas_coords(event.x, event.y)
            self._current_layer.get_polygon_at(-1).get_vertex_at(-1)\
                .set_coords(x, y)
            self._canvas.notify_polygon_change(
                self._current_layer.get_polygon_count() - 1)

    def _layer_change(self, event):
        selection = self._layer_list.curselection()
        if len(selection) > 0 and self._scene:
            layer = self._scene.get_layer_at(selection[0])
            if layer:
                self._is_drawing_polygon = False
                self._current_layer = layer
                self._canvas.notify_new_layer(self._current_layer)

    def _set_scene(self, scene: Scene) -> bool:
        if scene.get_layer_count() <= 0:
            messagebox.showerror("Error!", "Scene has no layers!")
            return False

        self._scene = scene

        # Prepare canvas
        # TODO Extra 10px padding for canvas
        width, height = self._scene.get_size()
        self._canvas.config(scrollregion=(0, 0, width, height))

        # Empty listbox, fill it, select first entry
        self._layer_list.delete(0, self._layer_list.size() - 1)
        for i in range(0, self._scene.get_layer_count()):
            self._layer_list.insert(i, self._scene.get_layer_at(i).get_name())
        self._layer_list.selection_set(0)
        self._layer_list.event_generate("<<ListboxSelect>>")

        return True

    def _set_current_path(self, path):
        self._current_path = path
        if path:
            self._tk.title(path + " - Layered Polygons")
        else:
            self._tk.title("Untitled - Layered Polygons")

    def _new_scene(self):
        path = filedialog.askopenfilename(defaultextension=".ora",
                                          filetypes=[("OpenRaster files",
                                                      ".ora")])
        if not path:
            return

        scene = ora.read(path)
        if not scene:
            messagebox.showerror("Error!", "File could not be opened!")
            return

        if self._set_scene(scene):
            self._set_current_path(None)

    def _open_scene(self):
        path = filedialog.askopenfilename(defaultextension=".lp",
                                          filetypes=[("Layered polygons"
                                                      " files", ".lp")])
        if not path:
            return

        scene = lp.read(path)
        if not scene:
            messagebox.showerror("Error!", "File could not be opened!")
            return

        if self._set_scene(scene):
            self._set_current_path(path)

    def _save_scene_help(self, path):
        if lp.save(path, self._scene):
            self._set_current_path(path)
        else:
            messagebox.showerror("Error!", "File could not be saved!")

    def _save_scene(self):
        if not self._current_path:
            self._save_scene_as()
            return
        self._save_scene_help(self._current_path)

    def _save_scene_as(self):
        if not self._scene:
            return
        path = filedialog.asksaveasfilename(defaultextension=".lp",
                                            filetypes=[("Layered polygons"
                                                        " files", ".lp")])
        if path:
            self._save_scene_help(path)

    def _export_obj(self):
        if not self._scene:
            return

        path_obj = filedialog.asksaveasfilename(defaultextension=".obj",
                                                filetypes=[("Wavefront object"
                                                            " files", ".obj")])
        if not path_obj:
            return
        path_obj, path_mtl, path_data = obj.get_paths(path_obj)
        obj.save(path_obj, path_mtl, path_data, self._scene)

    def _quit_app(self):
        self._tk.quit()
        exit()
class DMselector(ttk.Frame):
    """Listbox for DM Creation, Selection, and Sorting."""
    def __init__(self, master, conflict):
        """Initialize DM selection/creation Widget."""
        ttk.Frame.__init__(self, master)
        self.conflict = conflict
        self.dms = conflict.decisionMakers
        # variables
        self.listVariable = StringVar(
            value=tuple(['Double Click to Add Item']))
        self.selIdx = None
        self.selectedDM = None

        # widgets
        self.label = ttk.Label(self, text="Decision Makers")
        self.dmListDisp = Listbox(self, listvariable=self.listVariable)
        self.scrollY = ttk.Scrollbar(self,
                                     orient=VERTICAL,
                                     command=self.dmListDisp.yview)
        self.upBtn = ttk.Button(self, width=10, text='Up', command=self.upCmd)
        self.downBtn = ttk.Button(self,
                                  width=10,
                                  text='Down',
                                  command=self.downCmd)
        self.delBtn = ttk.Button(self,
                                 width=10,
                                 text='Delete',
                                 command=self.delCmd)

        # configuration
        self.dmListDisp.configure(yscrollcommand=self.scrollY.set)
        self.columnconfigure(0, weight=1)
        self.rowconfigure(1, weight=1)

        self.label.grid(column=0, row=0, columnspan=5, sticky=NSEW)
        self.dmListDisp.grid(column=0, row=1, columnspan=5, sticky=NSEW)
        self.scrollY.grid(column=5, row=1, sticky=NSEW)
        self.upBtn.grid(column=2, row=2, sticky=NSEW)
        self.downBtn.grid(column=3, row=2, sticky=NSEW)
        self.delBtn.grid(column=4, row=2, sticky=NSEW)

        self.dmListDisp.bind('<<ListboxSelect>>', self.selChgCmd)
        self.dmListDisp.bind('<Double-1>', self.editCmd)
        self.dmListDisp.bind('<Delete>', self.delCmd)
        self.dmListDisp.bind('<Return>', self.editCmd)

    def refresh(self, event=None):
        """Refresh widget contents."""
        self.updateList()
        for idx in range(len(self.dms)):
            self.dmListDisp.itemconfigure(idx, foreground='black')
        self.dmListDisp.itemconfigure(len(self.dms), foreground='#A0A0A0')

    def updateList(self, event=None):
        """Update the value in the displayed listVariable."""
        self.listVariable.set(
            tuple(self.dms.names() + ['Double Click to Add Item']))

    def moveEntry(self, idx, idx2):
        """Move an item from idx to idx2."""
        self.dms.insert(idx2, self.dms.pop(idx))
        self.updateList()
        self.dmListDisp.selection_clear(idx)
        self.dmListDisp.selection_set(idx2)
        self.selChgCmd()
        self.event_generate("<<dmOptChg>>")

    def upCmd(self, event=None):
        """Move the selected element up one space in the list."""
        idx = self.selIdx
        # check that there is an entry selected, and it isn't the first entry.
        if idx not in [-1, 0, len(self.dms)]:
            self.moveEntry(idx, idx - 1)

    def downCmd(self, event=None):
        """Move the selected element down one space in the list."""
        idx = self.selIdx
        # check that there is an entry selected, and it isn't the last entry
        if idx not in [-1, len(self.dms) - 1, len(self.dms)]:
            self.moveEntry(idx, idx + 1)

    def delCmd(self, *args):
        """Delete the selected element from the list."""
        idx = self.selIdx
        if idx != len(self.dms):  # check that a valid entry is selected
            del self.dms[idx]
            self.refresh()
            self.event_generate("<<dmOptChg>>")

    def selChgCmd(self, *args):
        """Called when the selection changes."""
        self.selIdx = int(self.dmListDisp.curselection()[0])
        if self.selIdx != len(self.conflict.decisionMakers):
            self.selectedDM = self.conflict.decisionMakers[self.selIdx]
        else:
            self.selectedDM = None
        self.event_generate('<<DMselected>>')

    def editCmd(self, *args):
        """Called when a list entry is selected for editing."""
        self.event_generate('<<EditDM>>')

    def reselect(self, event=None):
        """Return selection focus to a dm after an action is completed."""
        if self.selIdx is not None:
            self.dmListDisp.selection_set(self.selIdx)
            self.dmListDisp.event_generate('<<ListboxSelect>>')
Esempio n. 10
0
class SettingsFrame(Frame):
    """
    Frame inheritance class for application settings and controls.
    """
    def __init__(self, app, *args, **kwargs):
        """
        Constructor
        """

        self.__app = app  # Reference to main application class
        self.__master = self.__app.get_master()  # Reference to root class (Tk)
        Frame.__init__(self, self.__master, *args, **kwargs)

        #  Initialise up key variables
        self._image_num = 0
        self._image_name = "image"
        self._settype = StringVar()
        self._zoom = DoubleVar()
        self._radius = DoubleVar()
        self._exponent = IntVar()
        self._zx_off = DoubleVar()
        self._zy_off = DoubleVar()
        self._cx_off = DoubleVar()
        self._cy_off = DoubleVar()
        self._maxiter = IntVar()
        self._zx_coord = DoubleVar()
        self._zy_coord = DoubleVar()
        self._theme = StringVar()
        self._shift = IntVar()
        self._themes = None
        self._filename = StringVar()
        self._filepath = None
        self._frames = IntVar()
        self._zoominc = DoubleVar()
        self._autoiter = IntVar()
        self._autosave = IntVar()
        self._validsettings = True

        self.body()

    def body(self):
        """
        Set up frame and widgets.
        """

        # Create settings panel widgets
        # pylint: disable=W0108
        self.lbl_settype = Label(self, text=LBLMODE)
        self.spn_settype = Spinbox(
            self,
            values=("BurningShip", "Tricorn", "Julia", "Mandelbrot"),
            width=8,
            bg=GOOD,
            wrap=True,
            textvariable=self._settype,
        )
        self.lbl_zoom = Label(self, text=LBLZOOM)
        self.ent_zoom = Entry(
            self,
            border=2,
            relief="sunken",
            width=12,
            bg=GOOD,
            justify=RIGHT,
            textvariable=self._zoom,
        )
        self.lbl_zoominc = Label(self, text=LBLZOOMINC, justify=LEFT)
        self.ent_zoominc = Entry(self,
                                 width=5,
                                 border=2,
                                 bg=GOOD,
                                 justify=RIGHT,
                                 textvariable=self._zoominc)
        self.lbl_zx_off = Label(self, text=LBLZXOFF)
        self.ent_zx_off = Entry(
            self,
            border=2,
            relief="sunken",
            width=12,
            bg=GOOD,
            justify=RIGHT,
            textvariable=self._zx_off,
        )
        self.lbl_zy_off = Label(self, text=LBLZYOFF)
        self.ent_zy_off = Entry(
            self,
            border=2,
            relief="sunken",
            width=12,
            bg=GOOD,
            justify=RIGHT,
            textvariable=self._zy_off,
        )
        self.lbl_cx_off = Label(self, text=LBLCX)
        self.ent_cx_off = Entry(
            self,
            border=2,
            relief="sunken",
            width=12,
            bg=GOOD,
            justify=RIGHT,
            textvariable=self._cx_off,
            state=DISABLED,
        )
        self.lbl_cy_off = Label(self, text=LBLCY)
        self.ent_cy_off = Entry(
            self,
            border=2,
            relief="sunken",
            width=12,
            bg=GOOD,
            justify=RIGHT,
            textvariable=self._cy_off,
            state=DISABLED,
        )
        self.lbl_niter = Label(self, text=LBLITER, justify=LEFT)
        self.ent_maxiter = Entry(
            self,
            border=2,
            relief="sunken",
            bg=GOOD,
            width=8,
            justify=RIGHT,
            textvariable=self._maxiter,
        )
        self.chk_autoiter = Checkbutton(self,
                                        text="Auto",
                                        variable=self._autoiter,
                                        onvalue=1,
                                        offvalue=0)
        self.lbl_theme = Label(self, text=LBLTHEME, justify=LEFT)
        self.lbl_radius = Label(self, text=LBLRAD, justify=LEFT)
        self.ent_radius = Entry(
            self,
            border=2,
            relief="sunken",
            bg=GOOD,
            width=8,
            justify=RIGHT,
            textvariable=self._radius,
        )
        self.lbl_exp = Label(self, text=LBLEXP)
        self.spn_exp = Spinbox(
            self,
            border=2,
            relief="sunken",
            bg=GOOD,
            width=4,
            from_=2,
            to=20,
            wrap=True,
            textvariable=self._exponent,
        )
        self.sep_1 = ttk.Separator(
            self,
            orient=HORIZONTAL,
        )
        self.lbx_theme = Listbox(
            self,
            border=2,
            relief="sunken",
            bg=GOOD,
            width=6,
            height=5,
            justify=LEFT,
            exportselection=False,
        )
        self.lbl_shift = Label(self, text=LBLSHIFT, justify=LEFT)
        self.scl_shift = Scale(
            self,
            from_=0,
            to=100,
            orient=HORIZONTAL,
            variable=self._shift,
            border=2,
            relief="sunken",
            sliderlength=20,
            troughcolor=GOOD,
        )
        self.scrollbar = Scrollbar(self, orient=VERTICAL)
        self.lbx_theme.config(yscrollcommand=self.scrollbar.set)
        self.scrollbar.config(command=self.lbx_theme.yview)
        self.lbx_theme.select_set(0)
        self.lbx_theme.event_generate("<<ListboxSelect>>")
        self.lbl_coords = Label(self, text="Re, Im", fg="grey")
        self.btn_plot = Button(
            self,
            text=BTNPLOT,
            width=8,
            fg="green",
            command=lambda: self.__app.frm_fractal.plot(),
        )
        self.btn_cancel = Button(
            self,
            text=BTNCAN,
            width=8,
            command=lambda: self.__app.frm_fractal.cancel_press(),
        )
        self.btn_reset = Button(self, text=BTNRST, width=8, command=self.reset)
        self.ent_save = Entry(
            self,
            textvariable=self._filename,
            width=6,
            border=2,
            relief="sunken",
            bg=GOOD,
            justify=LEFT,
        )
        self._filename.set(self._image_name + str(self._image_num))
        self.btn_save = Button(self,
                               text=BTNSAVE,
                               width=8,
                               command=self.save_image)
        self.lbl_auto = Label(self, text=LBLAUTO, justify=LEFT)
        self.btn_autozoom = Button(
            self,
            text=BTNZOOM,
            width=8,
            command=lambda: self.__app.frm_fractal.animate_zoom(),
        )
        self.btn_autospin = Button(
            self,
            text=BTNSPIN,
            width=8,
            command=lambda: self.__app.frm_fractal.animate_spin(),
            state=DISABLED,
        )
        self.chk_autosave = Checkbutton(self,
                                        text=BTNSAVE,
                                        variable=self._autosave,
                                        onvalue=1,
                                        offvalue=0)
        self.lbl_frames = Label(self, text=FRMSTXT)
        self.ent_frames = Entry(self,
                                width=5,
                                border=2,
                                bg=GOOD,
                                justify=RIGHT,
                                textvariable=self._frames)

        # Get list of available themes
        for idx, theme in enumerate(THEMES):
            self.lbx_theme.insert(idx, theme)

        self.body_arrange()  # Position all widgets in frame

        self.reset()  # Reset all settings to their defaults

        self.set_traces(
        )  # Trace entry variables for validation and event handling

    def body_arrange(self):
        """
        Position widgets in frame
        """

        # Position all widgets in their parent frames
        self.btn_plot.grid(column=0,
                           row=1,
                           ipadx=3,
                           ipady=3,
                           sticky=(W),
                           padx=3,
                           pady=3)
        self.btn_cancel.grid(column=1,
                             row=1,
                             ipadx=3,
                             ipady=3,
                             sticky=(W),
                             padx=3,
                             pady=3)
        self.btn_reset.grid(column=2,
                            row=1,
                            ipadx=3,
                            ipady=3,
                            sticky=(W),
                            padx=3,
                            pady=3)
        self.ent_save.grid(column=0,
                           row=2,
                           columnspan=2,
                           sticky=(W, E),
                           padx=3,
                           pady=3)
        self.btn_save.grid(column=2,
                           row=2,
                           ipadx=3,
                           ipady=3,
                           sticky=(W),
                           padx=3,
                           pady=3)
        self.lbl_auto.grid(column=0, row=3, sticky=(W))
        self.btn_autozoom.grid(column=1,
                               row=3,
                               ipadx=3,
                               ipady=3,
                               sticky=(W),
                               padx=3,
                               pady=3)
        self.btn_autospin.grid(column=2,
                               row=3,
                               ipadx=3,
                               ipady=3,
                               sticky=(W),
                               padx=3,
                               pady=3)
        self.lbl_frames.grid(column=0, row=4, sticky=(W))
        self.ent_frames.grid(column=1, row=4, sticky=(W), padx=3, pady=3)
        self.chk_autosave.grid(column=2, row=4, sticky=(W), padx=3, pady=3)
        self.sep_1.grid(column=0, row=5, columnspan=3, pady=5, sticky=(W, E))
        self.lbl_settype.grid(column=0, row=6, sticky=(W))
        self.spn_settype.grid(column=1,
                              row=6,
                              columnspan=2,
                              sticky=(W, E),
                              padx=3,
                              pady=3)
        self.lbl_zoom.grid(column=0, row=7, sticky=(W))
        self.ent_zoom.grid(column=1,
                           row=7,
                           columnspan=2,
                           sticky=(W, E),
                           padx=3,
                           pady=3)
        self.lbl_zoominc.grid(column=0, row=8, sticky=(W))
        self.ent_zoominc.grid(column=1, row=8, sticky=(W), padx=3, pady=3)
        self.lbl_zx_off.grid(column=0, row=9, sticky=(W))
        self.ent_zx_off.grid(column=1,
                             row=9,
                             columnspan=2,
                             sticky=(W, E),
                             padx=3,
                             pady=3)
        self.lbl_zy_off.grid(column=0, row=10, sticky=(W))
        self.ent_zy_off.grid(column=1,
                             row=10,
                             columnspan=2,
                             sticky=(W, E),
                             padx=3,
                             pady=3)
        self.lbl_cx_off.grid(column=0, row=11, sticky=(W))
        self.ent_cx_off.grid(column=1,
                             row=11,
                             columnspan=2,
                             sticky=(W, E),
                             padx=3,
                             pady=3)
        self.lbl_cy_off.grid(column=0, row=12, sticky=(W))
        self.ent_cy_off.grid(column=1,
                             row=12,
                             columnspan=2,
                             sticky=(W, E),
                             padx=3,
                             pady=3)
        self.lbl_niter.grid(column=0, row=13, sticky=(W))
        self.ent_maxiter.grid(column=1, row=13, sticky=(W), padx=3, pady=3)
        self.chk_autoiter.grid(column=2, row=13, sticky=(W), padx=3, pady=3)
        self.lbl_radius.grid(column=0, row=14, sticky=(W))
        self.ent_radius.grid(column=1, row=14, sticky=(W), padx=3, pady=3)
        self.lbl_exp.grid(column=0, row=15, sticky=(W))
        self.spn_exp.grid(column=1, row=15, sticky=(W), padx=3, pady=3)
        self.lbl_theme.grid(column=0, row=16, sticky=(W))
        self.lbx_theme.grid(column=1,
                            row=16,
                            padx=3,
                            pady=3,
                            columnspan=2,
                            sticky=(N, S, W, E))
        self.scrollbar.grid(column=2, row=16, sticky=(N, S, E))
        self.lbl_shift.grid(column=0, row=17, sticky=(W))
        self.scl_shift.grid(column=1,
                            row=17,
                            columnspan=2,
                            padx=3,
                            pady=3,
                            sticky=(W, E))
        self.lbx_theme.bind("<<ListboxSelect>>", self.get_sel_theme)

    def set_traces(self):
        """
        Set up entry variable traces for validation and event handling
        """

        self._validsettings = True
        self._settype.trace("w", self.val_settings)
        self._zoom.trace("w", self.val_settings)
        self._zx_off.trace("w", self.val_settings)
        self._zy_off.trace("w", self.val_settings)
        self._cx_off.trace("w", self.val_settings)
        self._cy_off.trace("w", self.val_settings)
        self._maxiter.trace("w", self.val_settings)
        self._radius.trace("w", self.val_settings)
        self._exponent.trace("w", self.val_settings)
        self._filename.trace("w", self.val_settings)
        self._frames.trace("w", self.val_settings)
        self._zoominc.trace("w", self.val_settings)

    def val_settings(self, *args, **kwargs):
        """
        Validate all user-entered settings.
        (A personal choice but I find this user experience more intuitive
        than the standard validatecommand method for Entry widgets)
        """

        self._validsettings = True
        self.__app.set_status("")

        if self.is_float(self.ent_zoom.get()) and self._zoom.get() > 0:
            flg = GOOD
        else:
            flg = BAD
        self.flag_entry(self.ent_zoom, flg)

        if self.is_float(self.ent_zx_off.get()):
            flg = GOOD
        else:
            flg = BAD
        self.flag_entry(self.ent_zx_off, flg)

        if self.is_float(self.ent_zy_off.get()):
            flg = GOOD
        else:
            flg = BAD
        self.flag_entry(self.ent_zy_off, flg)

        if self.is_float(self.ent_cx_off.get()):
            flg = GOOD
        else:
            flg = BAD
        self.flag_entry(self.ent_cx_off, flg)

        if self.is_float(self.ent_cy_off.get()):
            flg = GOOD
        else:
            flg = BAD
        self.flag_entry(self.ent_cy_off, flg)

        if self.is_integer(self.ent_maxiter.get()) and self._maxiter.get() > 0:
            flg = GOOD
        else:
            flg = BAD
        self.flag_entry(self.ent_maxiter, flg)

        if self.is_float(self.ent_radius.get()) and self._radius.get() > 0:
            flg = GOOD
        else:
            flg = BAD
        self.flag_entry(self.ent_radius, flg)

        if self.is_integer(self.spn_exp.get()) and self._exponent.get() > 1:
            flg = GOOD
        else:
            flg = BAD
        self.flag_entry(self.spn_exp, flg)

        if self.is_integer(self.ent_frames.get()) and self._frames.get() > 0:
            flg = GOOD
        else:
            flg = BAD
        self.flag_entry(self.ent_frames, flg)

        if self.is_float(self.ent_zoominc.get()) and self._zoominc.get() > 0:
            flg = GOOD
        else:
            flg = BAD
        self.flag_entry(self.ent_zoominc, flg)

        if self.is_filename(self.ent_save.get()):
            flg = GOOD
        else:
            flg = BAD
        self.flag_entry(self.ent_save, flg)

        if self.spn_settype.get() in {"Mandelbrot", "Tricorn", "BurningShip"}:
            self.btn_autospin.config(state=DISABLED)
            self.ent_cx_off.config(state=DISABLED)
            self.ent_cy_off.config(state=DISABLED)
            self._cx_off.set(0)
            self._cy_off.set(0)
            flg = GOOD
        elif self.spn_settype.get() == "Julia":
            self.btn_autospin.config(state=NORMAL)
            self.ent_cx_off.config(state=NORMAL)
            self.ent_cy_off.config(state=NORMAL)
            flg = GOOD
        else:
            flg = BAD
        self.flag_entry(self.spn_settype, flg)

    def flag_entry(self, ent, flag):
        """
        Flag entry field as valid or invalid and set global validity status flag.
        This flag is used throughout to determine whether functions can proceed
        or not.
        """

        ent.config(bg=flag)
        if flag == BAD:
            self._validsettings = False
            self.__app.set_status(VALERROR, "red")

    def is_float(self, flag):
        """
        Validate if entry is a float.
        """

        try:
            float(flag)
            return True
        except ValueError:
            return False

    def is_integer(self, flag):
        """
        Validate if entry is a positive integer.
        """

        try:
            int(flag)
            if int(flag) > 0:
                return True
            return False
        except ValueError:
            return False

    def is_filename(self, flag):
        """
        Validate if entry represents a valid filename using a regexp.
        """

        return match("^[\w\-. ]+$", flag) and flag != ""

    def reset(self):
        """
        Reset settings to defaults.
        """

        self._settype.set("Mandelbrot")
        self._zoom.set(0.75)
        self._zx_off.set(-0.5)
        self._zy_off.set(0.0)
        self._cx_off.set(0.0)
        self._cy_off.set(0.0)
        self._maxiter.set(128)
        self._radius.set(2.0)
        self._exponent.set(2)
        self._frames.set(10)
        self._zoominc.set(2.0)
        self._autoiter.set(1)
        self._autosave.set(0)
        self._theme.set("Default")
        self._filename.set("image0")
        self._shift.set(0)
        self.set_sel_theme()

        self.__app.set_status(SETINITTXT)

    def get_sel_theme(self, *args, **kwargs):
        """
        Get selected theme from listbox and set global variable.
        """

        idx = self.lbx_theme.curselection()
        if idx == "":
            idx = 0
        self._theme.set(self.lbx_theme.get(idx))

    def set_sel_theme(self):
        """
        Lookup index of selected theme and highlight that listbox position.
        NB: this requires 'exportselection=False' option to be set on listbox to
        work properly.
        """

        for idx, theme in enumerate(THEMES):
            if theme == self._theme.get():
                self.lbx_theme.activate(idx)
                self.lbx_theme.see(idx)
                break

    def get_settings(self):
        """
        Return all current settings as a dict.
        """

        if not self._validsettings:
            settings = {"valid": self._validsettings}
            return settings

        settings = {
            "settype": self._settype.get(),
            "zoom": self._zoom.get(),
            "zxoffset": self._zx_off.get(),
            "zyoffset": self._zy_off.get(),
            "cxoffset": self._cx_off.get(),
            "cyoffset": self._cy_off.get(),
            "maxiter": self._maxiter.get(),
            "autoiter": self._autoiter.get(),
            "autosave": self._autosave.get(),
            "radius": self._radius.get(),
            "exponent": self._exponent.get(),
            "theme": self._theme.get(),
            "shift": self._shift.get(),
            "filepath": self._filepath,
            "filename": self._filename.get(),
            "frames": self._frames.get(),
            "zoominc": self._zoominc.get(),
            "valid": self._validsettings,
        }
        return settings

    def update_settings(self, **kwargs):
        """
        Update settings from keyword parms.
        """

        if "settype" in kwargs:
            self._settype.set(kwargs["settype"])
        if "zoom" in kwargs:
            self._zoom.set(kwargs["zoom"])
        if "zxoffset" in kwargs:
            self._zx_off.set(kwargs["zxoffset"])
        if "zyoffset" in kwargs:
            self._zy_off.set(kwargs["zyoffset"])
        if "cxoffset" in kwargs:
            self._cx_off.set(kwargs["cxoffset"])
        if "cyoffset" in kwargs:
            self._cy_off.set(kwargs["cyoffset"])
        if "maxiter" in kwargs:
            self._maxiter.set(kwargs["maxiter"])
        if "autoiter" in kwargs:
            self._autoiter.set(kwargs["autoiter"])
        if "autosave" in kwargs:
            self._autosave.set(kwargs["autosave"])
        if "radius" in kwargs:
            self._radius.set(kwargs["radius"])
        if "exponent" in kwargs:
            self._exponent.set(kwargs["exponent"])
        if "filepath" in kwargs:
            self._filepath.set(kwargs["filepath"])
        if "filename" in kwargs:
            self._filename.set(kwargs["filename"])
        if "frames" in kwargs:
            self._frames.set(kwargs["frames"])
        if "zoominc" in kwargs:
            self._zoominc.set(kwargs["zoominc"])
        if "theme" in kwargs:
            self._theme.set(kwargs["theme"])
            self.set_sel_theme()
        if "shift" in kwargs:
            self._shift.set(kwargs["shift"])

    def set_filepath(self):
        """
        Sets filepath for saved files for the duration of this session.
        """

        default = os.getcwd()  # Default _filepath is current working directory
        if self._filepath is None:
            self._filepath = filedialog.askdirectory(title=SAVETITLE,
                                                     initialdir=default,
                                                     mustexist=True)
            if self._filepath == "":
                self._filepath = None  # User cancelled

        return self._filepath

    def save_image(self):
        """
        Save image as PNG file to selected filepath and automatically increment default
        image name. NB: currently this will overwrite any existing file of the same
        name without warning.
        """

        # Bug out if the settings are invalid
        settings = self.__app.frm_settings.get_settings()
        if not settings["valid"]:
            return

        # Check if image has been created
        image = self.__app.frm_fractal.mandelbrot.get_image()
        if image is None:
            self.__app.set_status(NOIMGERROR, "red")
            return

        # Set _filename and path
        if self.set_filepath() is None:  # User cancelled
            return
        fname = self._filename.get()
        fqname = self._filepath + "/" + fname

        # Save the image along with its metadata
        try:
            # image.write(fqname + ".png", format="png")
            image.save(fqname + ".png", format="png")
            self.save_metadata()
        except OSError:
            self.__app.set_status(SAVEERROR, "red")
            self._filepath = None
            return

        self._image_num += 1
        self._filename.set(self._image_name + str(self._image_num))
        self.__app.set_status(IMGSAVETXT + fqname + ".png", "green")

        # Return focus to image frame
        self.__app.frm_fractal.focus_set()

    def save_metadata(self):
        """
        Save json file containing meta data associated with image,
        allowing it to be imported and reproduced.
        """

        if self._filepath is None:
            if self.set_filepath() is None:  # User cancelled
                return

        fname = self._filename.get()
        fqname = self._filepath + "/" + fname
        filename = fqname + ".json"
        createtime = strftime("%b %d %Y %H:%M:%S %Z", gmtime())

        jsondata = {
            MODULENAME: {
                "filename": fqname + ".png",
                "created": createtime,
                "settype": self._settype.get(),
                "zoom": self._zoom.get(),
                "zoominc": self._zoominc.get(),
                "frames": self._frames.get(),
                "escradius": self._radius.get(),
                "exponent": self._exponent.get(),
                "maxiter": self._maxiter.get(),
                "zxoffset": self._zx_off.get(),
                "zyoffset": self._zy_off.get(),
                "cxoffset": self._cx_off.get(),
                "cyoffset": self._cy_off.get(),
                "theme": self._theme.get(),
                "shift": self._shift.get(),
            }
        }

        try:
            with open(filename, "w") as outfile:
                dump(jsondata, outfile)
        except OSError:
            self.__app.set_status(METASAVEERROR, "red")
            self._filepath = None

        # Return focus to image frame
        self.__app.frm_fractal.focus_set()

    def import_metadata(self):
        """
        Update settings from imported json metadata file.
        """

        # Select and read file
        try:
            default = os.getcwd()
            filepath = filedialog.askopenfilename(
                initialdir=default,
                title=SELTITLE,
                filetypes=(("json files", "*.json"), ("all files", "*.*")),
            )
            if filepath == "":  # User cancelled
                return
            with open(filepath, "r") as infile:
                jsondata = infile.read()
        except OSError:
            self.__app.set_status(OPENFILEERROR, "red")
            return

        # Parse file
        try:

            settings = loads(jsondata).get(MODULENAME)

            # Set plot parameters
            self._settype.set(settings.get("settype", "Mandelbrot"))
            self._zoom.set(settings.get("zoom", 1))
            self._zoominc.set(settings.get("zoominc", 2.0))
            self._frames.set(settings.get("frames", 10))
            self._radius.set(settings.get("escradius", 2.0))
            self._exponent.set(settings.get("exponent", 2))
            self._maxiter.set(settings.get("maxiter", 256))
            self._zx_off.set(settings.get("zxoffset", 0))
            self._zy_off.set(settings.get("zyoffset", 0))
            self._cx_off.set(settings.get("cxoffset", 0))
            self._cy_off.set(settings.get("cyoffset", 0))
            self._theme.set(settings.get("theme", "Default"))
            self._shift.set(settings.get("shift", 0))

        except OSError:
            self.__app.set_status(BADJSONERROR, "red")
            return

        self.set_sel_theme()

        fbase = os.path.basename(filepath)
        filename, fileext = os.path.splitext(fbase)
        self.__app.set_status(
            "Metadata file " + filename + fileext + METAPROMPTTXT, "green")

        # Return focus to image frame
        self.__app.frm_fractal.focus_set()
Esempio n. 11
0
def openCalculator(handler):
	global conversionresulttext, fromCurrencyInput, toCurrencyInput, amountInput, calculatorWindow

	currencyapi = get("https://api.exchangeratesapi.io/latest", data=None)
	if currencyapi.status_code == 200: #Check for reponse
		exchangerates = loads(currencyapi.content.decode())
		exchangerates["rates"]["DUCO"] = float(ducofiat)

	calculatorWindow = Toplevel()
	calculatorWindow.resizable(False, False)
	calculatorWindow.title("Duino-Coin Wallet - Calculator")
	calculatorWindow.configure(background = backgroundColor)
	calculatorWindow.transient([root])

	textFont2 = Font(calculatorWindow, size=12,weight="bold")
	textFont3 = Font(calculatorWindow, size=14,weight="bold")
	textFont = Font(calculatorWindow, size=12,weight="normal")

	Label(calculatorWindow, text="CURRENCY CONVERTER",
		background = backgroundColor,
		foreground = foregroundColor,
		font = textFont3).grid(row=0, column=0)

	Label(calculatorWindow, text="FROM",
		background = backgroundColor,
		foreground = foregroundColor,
		font = textFont2).grid(row=1, column=0)

	fromCurrencyInput = Listbox(calculatorWindow,
								exportselection=False,
								background = backgroundColor,
								foreground = foregroundColor,
								selectbackground = "#7bed9f",
								border="0", font=textFont,
								width="20", height="13")
	fromCurrencyInput.grid(row=2, column=0)
	i=0
	for currency in exchangerates["rates"]:
		fromCurrencyInput.insert(i, currency)
		i = i+1

	Label(calculatorWindow, text="TO",
		background = backgroundColor,
		foreground = foregroundColor,
		font = textFont2).grid(row=1, column=1)

	toCurrencyInput = Listbox(calculatorWindow,
								exportselection=False,
								foreground = foregroundColor,
								background = backgroundColor,
								selectbackground = "#7bed9f",
								border="0", font=textFont,
								width="20", height="13")
	toCurrencyInput.grid(row=2, column=1)
	i=0
	for currency in exchangerates["rates"]:
		toCurrencyInput.insert(i, currency)
		i = i+1

	toCurrencyInput.select_set(0)
	toCurrencyInput.event_generate("<<ListboxSelect>>")
	fromCurrencyInput.select_set(32)
	fromCurrencyInput.event_generate("<<ListboxSelect>>")

	Label(calculatorWindow, text="AMOUNT",
		background = backgroundColor,
		foreground = foregroundColor,
		font = textFont2).grid(row=3, column=0)

	def clear_ccamount_placeholder(self):
			amountInput.delete("0", "100")

	amountInput = Entry(calculatorWindow,
						background = "#7bed9f", foreground=foregroundColor,
						border="0", font=textFont,
						width="20")
	amountInput.grid(row=4, column=0)
	amountInput.insert("0", str(getBalance()))
	amountInput.bind("<FocusIn>", clear_ccamount_placeholder)

	Button(calculatorWindow, text="Convert",
			background = "#FEEEDA", foreground=foregroundColor,
			command=currencyConvert, width="22").grid(row=3, column=1, pady=(5, 0))

	conversionresulttext = StringVar(calculatorWindow)
	conversionresulttext.set("RESULT: 0.0")
	conversionresultLabel = Label(calculatorWindow,
								textvariable=conversionresulttext,
								background = backgroundColor,
								foreground = foregroundColor,
								font = textFont2)
	conversionresultLabel.grid(row=4, column=1)

	Label(calculatorWindow, text=" ",
		background = backgroundColor,
		foreground = foregroundColor,
		font = textFont2).grid(row=5, column=0)

	calculatorWindow.mainloop()
Esempio n. 12
0
class AlbumsPanel(Frame):

    def __init__(self, parent, albumsController: IAlbumsController):
        super().__init__(parent)
        self.albumsController = albumsController

        self.albumList: List[AlbumDb] = []
        self.selectedAlbumName: str = None

        self.musicFromDisc: List[Music] = []

        self.displayedMusicOnComputer = None
        self.displayedMusicInAlbum = None

        self.__initView()

    def __initView(self):
        self.grid_columnconfigure(0, weight=1)
        self.grid_rowconfigure(3, weight=1)

        self.albumsListBox = Listbox(self, exportselection=0)
        self.albumsListBox.grid(row=0, column=0, sticky='WE', padx=(10, 0), pady=10)
        self.albumsListBox.bind('<Double-1>', self.__albumDoubleClicked)
        self.albumsListBox.bind("<<ListboxSelect>>", self.__albumSelected)

        albumsScrollbar = Scrollbar(self, command=self.albumsListBox.yview)
        albumsScrollbar.grid(row=0, column=1, sticky='NS', padx=(0, 10), pady=10)

        self.albumsListBox.configure(yscrollcommand=albumsScrollbar.set)

        ######################################################################################################

        buttonsFrame = Frame(self)
        buttonsFrame.grid(row=1, column=0, sticky='W', padx=10)

        self.albumDeleteButton = Button(buttonsFrame, text=ALBUM_DELETE_TEXT, command=self.__deleteAlbum)
        self.albumDeleteButton.grid(row=0, column=0, padx=5)

        self.albumExportButton = Button(buttonsFrame, text=ALBUM_EXPORT_TEXT, command=self.__exportAlbumClicked)
        self.albumExportButton.grid(row=0, column=1, padx=5)

        self.albumImportButton = Button(buttonsFrame, text=ALBUM_IMPORT_TEXT, command=self.__importAlbumClicked)
        self.albumImportButton.grid(row=0, column=2, padx=5)

        ######################################################################################################

        createFrame = Frame(self)
        createFrame.grid(row=2, column=0, sticky='W', padx=10)

        label = Label(createFrame, text=ALBUM_CREATE_LABEL_TEXT)
        label.grid(row=0, column=0)

        self.createAlbumNameEntry = Entry(createFrame)
        self.createAlbumNameEntry.grid(row=0, column=1)

        self.createAlbumButton = Button(createFrame, text=ALBUM_CREATE_BUTTON_TEXT, command=self.__createAlbum)
        self.createAlbumButton.grid(row=0, column=2)

        ######################################################################################################
        # Music on computer

        musicFrame = Frame(self, padx=10, pady=10)
        musicFrame.grid(row=3, column=0, columnspan=2, sticky='WENS')
        musicFrame.grid_columnconfigure(0, weight=1)
        musicFrame.grid_columnconfigure(3, weight=1)
        musicFrame.grid_rowconfigure(1, weight=1)

        label = Label(musicFrame, text=MUSIC_ON_COMPUTER_TEXT)
        label.grid(row=0, column=0, sticky='W')

        self.musicOnComputerListBox = Listbox(musicFrame)
        self.musicOnComputerListBox.grid(row=1, column=0, sticky='WENS')

        musicOnComputerScrollbar = Scrollbar(musicFrame, command=self.musicOnComputerListBox.yview)
        musicOnComputerScrollbar.grid(row=1, column=1, sticky='NS')

        self.musicOnComputerListBox.configure(yscrollcommand=musicOnComputerScrollbar.set)

        ######################################################################################################

        buttonFrame = Frame(musicFrame, padx=10)
        buttonFrame.grid(row=1, column=2)

        self.removeFromAlbumButton = Button(buttonFrame, text='<<', command=self.__removeMusicFromAlbumClicked)
        self.removeFromAlbumButton.grid(row=0, column=0)

        self.addToAlbumButton = Button(buttonFrame, text='>>', command=self.__addMusicToAlbumClicked)
        self.addToAlbumButton.grid(row=1, column=0)

        ######################################################################################################
        #Music in album

        label = Label(musicFrame, text=MUSIC_IN_ALBUM_TEXT)
        label.grid(row=0, column=3, sticky='W')

        self.musicInAlbumListBox = Listbox(musicFrame)
        self.musicInAlbumListBox.grid(row=1, column=3, sticky='WENS')

        musicInAlbumScrollbar = Scrollbar(musicFrame, command=self.musicInAlbumListBox.yview)
        musicInAlbumScrollbar.grid(row=1, column=4, sticky='NS')

        self.musicInAlbumListBox.configure(yscrollcommand=musicInAlbumScrollbar.set)

        ######################################################################################################

    def displayAlbums(self, albums: List[AlbumDb], musicFromDisc: List[Music]):
        self.albumList = albums
        self.musicFromDisc = musicFromDisc

        self.albumsListBox.delete(0, 'end')
        for i in range(len(self.albumList)):
            a = self.albumList[i]
            self.albumsListBox.insert(i, a.name)

        if self.selectedAlbumName is not None:
            selectedIndex = -1
            for i in range(len(self.albumList)):
                if self.albumList[i].name == self.selectedAlbumName:
                    selectedIndex = i
                    break

            if selectedIndex >= 0:
                self.albumsListBox.select_set(selectedIndex)
                self.albumsListBox.event_generate("<<ListboxSelect>>")

    def __deleteAlbum(self):
        selection = self.albumsListBox.curselection()

        if len(selection) <= 0:
            messagebox.showwarning('Warning', DELETE_ALBUM_SELECT_TEXT)
            return

        self.albumsListBox.selection_clear(0, END)
        self.albumsListBox.event_generate("<<ListboxSelect>>")

        album = self.albumList[selection[0]]
        self.albumsController.deleteAlbum(album.name)

    def __createAlbum(self):
        name = self.createAlbumNameEntry.get()

        if name is None or name == '':
            messagebox.showwarning('Warning', CRATE_ALBUM_INSERT_NAME_TEXT)
            return

        self.albumsController.createAlbum(name)

    def __albumSelected(self, event):
        self.musicOnComputerListBox.delete(0, 'end')
        self.musicInAlbumListBox.delete(0, 'end')

        selection = self.albumsListBox.curselection()
        if len(selection) <= 0:
            return

        selectedAlbum = self.albumList[selection[0]]
        self.selectedAlbumName = selectedAlbum.name

        self.__lisMusicOnComputer(selectedAlbum)
        self.__lisMusicInAlbum(selectedAlbum)

    def __lisMusicOnComputer(self, album):
        musicInAlbum = set()
        for m in album.music:
            musicInAlbum.add(m.path)

        if self.musicFromDisc is None:
            return

        music = self.musicFromDisc.copy()
        music = filter(lambda m: m.path not in musicInAlbum, music)
        self.displayedMusicOnComputer = list(music)

        i = 0
        for m in self.displayedMusicOnComputer:
            self.musicOnComputerListBox.insert(i, m.filename)
            i = i + 1

    def __lisMusicInAlbum(self, album):
        musicOnDisc = set()
        if self.musicFromDisc is not None:
            for m in self.musicFromDisc:
                musicOnDisc.add(m.path)

        self.displayedMusicInAlbum = list(album.music)

        i = 0
        for m in self.displayedMusicInAlbum:
            description = os.path.basename(m.path)
            if m.path not in musicOnDisc:
                description = '<missing> ' + m.path

            self.musicInAlbumListBox.insert(i, description)
            i = i + 1

    def __addMusicToAlbumClicked(self):
        selection = self.albumsListBox.curselection()
        if len(selection) <= 0:
            return

        selectedAlbum = self.albumList[selection[0]]

        selection = self.musicOnComputerListBox.curselection()
        if len(selection) <= 0:
            messagebox.showwarning('Warning', ADD_TO_ALBUM_SELECT_TEXT)
            return

        selectedMusic = self.displayedMusicOnComputer[selection[0]]

        self.albumsController.addMusicToAlbum(selectedAlbum.name, selectedMusic.path)

    def __removeMusicFromAlbumClicked(self):
        selection = self.albumsListBox.curselection()
        if len(selection) <= 0:
            return

        selectedAlbum = self.albumList[selection[0]]

        selection = self.musicInAlbumListBox.curselection()
        if len(selection) <= 0:
            messagebox.showwarning('Warning', REMOVE_FROM_ALBUM_SELECT_TEXT)
            return

        selectedMusic = self.displayedMusicInAlbum[selection[0]]

        self.albumsController.removeMusicFromAlbum(selectedAlbum.name, selectedMusic.path)

    def __exportAlbumClicked(self):
        selection = self.albumsListBox.curselection()
        if len(selection) <= 0:
            messagebox.showwarning('Warning', EXPORT_ALBUM_SELECT_TEXT)
            return

        selectedAlbum = self.albumList[selection[0]]
        self.albumsController.exportAlbum(selectedAlbum.name)

    def __importAlbumClicked(self):
        self.albumsController.importAlbum()

    def __albumDoubleClicked(self, event):
        album = self.albumList[self.albumsListBox.curselection()[0]]
        self.albumsController.addAlbumToQueue(album)
Esempio n. 13
0
class PiScreen(tkinter.Frame):
    def __init__(self, master: 'tkinter.Tk'):
        global client, status, theme
        # host = '192.168.1.120'
        host = 'localhost'
        if sys.platform.startswith('linux'):
            host = 'localhost'
        client.connect(host, 6600)
        tkinter.Frame.__init__(self, master, padx=0, pady=0)
        self.pack()
        self.place(height=240, width=320, x=0, y=0)
        status = client.status()
        self.volume = int(status["volume"])

        self.screen_data = {
            "1": [
                "QUEUE", "PLAYLISTS", "LIBRARY", "SETUP", "CLEAR PLAYLIST",
                "RANDOM " + status['random'], "REPEAT " + status['repeat'],
                "SINGLE " + status['single'], "CONSUME " + status['consume']
            ],
            "1.1": {
                "ACTION": "QUEUE"
            },
            "1.2": {
                "ACTION": "PLAYLISTS"
            },
            "1.3": ["ARTISTS", "ALBUMS", "GENRES"],
            "1.3.1": {
                "ACTION": "ARTISTS"
            },
            "1.3.2": {
                "ACTION": "ALBUMS"
            },
            "1.3.3": {
                "ACTION": "GENRES"
            },
            "1.4": ["UPDATE LIBRARY", "THEMES"],
            "1.4.1": {
                "ACTION": "UPDATE_LIBRARY"
            },
            "1.4.2": {
                "ACTION": "THEMES"
            },
            "1.5": {
                "ACTION": "CLEAR"
            },
            "1.6": {
                "ACTION": "RANDOM"
            },
            "1.7": {
                "ACTION": "REPEAT"
            },
            "1.8": {
                "ACTION": "SINGLE"
            },
            "1.9": {
                "ACTION": "CONSUME"
            }
        }

        self.screen_format = {"1.Q": "SONG", "1.P": "PLAYLIST"}

        self.current_song_var = tkinter.StringVar()
        self.footer_text_var = tkinter.StringVar()

        # Screens
        self.playerScreen = Canvas(self,
                                   width=320,
                                   height=240,
                                   bg=theme['PLAYER']['background'],
                                   borderwidth=0,
                                   highlightthickness=0)

        self.menuScreen = Frame(self, width=320, height=240, bg="white")
        self.menuScreen.place(height=240, width=320, x=0, y=0)

        # Menu Screen items
        self.headerFrame = Frame(self.menuScreen,
                                 width=320,
                                 height=20,
                                 bg=theme['HEADER']['background'])
        self.headerFrame.pack(side=tkinter.TOP, fill=X)

        self.currentSongLabel = Label(self.headerFrame,
                                      font=(theme['HEADER']['font'], 12,
                                            'bold'),
                                      bg=theme['HEADER']['background'],
                                      foreground=theme['HEADER']['foreground'],
                                      textvariable=self.current_song_var,
                                      justify=tkinter.LEFT,
                                      anchor=tkinter.W)
        self.currentSongLabel.place(x=0,
                                    y=0,
                                    width=300,
                                    height=20,
                                    anchor=tkinter.NW)

        self.volumeLabel = Label(self.headerFrame,
                                 font=(theme['HEADER']['font'], 10, 'bold'),
                                 bg=theme['HEADER']['background'],
                                 foreground=theme['HEADER']['foreground'],
                                 text='')
        self.volumeLabel.place(x=300, y=0, anchor=tkinter.NW)

        self.mainFrame = Frame(self.menuScreen, width=320, height=200)
        self.mainFrame.pack(side=tkinter.TOP, fill=Y)

        self.listbox = Listbox(self.mainFrame,
                               selectmode=tkinter.SINGLE,
                               font=(theme['MAIN']['font'], 11),
                               bg=theme['MAIN']['background'],
                               fg=theme['MAIN']['foreground'],
                               height=10,
                               activestyle="none",
                               borderwidth=0,
                               highlightthickness=0,
                               selectbackground=theme['MAIN']['selected'],
                               selectforeground=theme['MAIN']['foreground'])
        self.listbox.bind("<Key>", self.handle_keys)
        self.listbox.configure(width=320, height=11)
        self.listbox.pack(side=tkinter.TOP,
                          expand=1,
                          ipadx=0,
                          ipady=0,
                          padx=0,
                          pady=0)
        self.listbox.focus_set()

        self.footer = Label(self.menuScreen,
                            textvariable=self.footer_text_var,
                            font=(theme['FOOTER']['font'], 10, 'bold'),
                            bg=theme['FOOTER']['background'],
                            foreground=theme['FOOTER']['foreground'],
                            justify=tkinter.LEFT,
                            anchor=tkinter.W)
        self.footer.configure(width=320, height=1)
        self.footer.pack(side=tkinter.BOTTOM)

        self.focus_set()
        self.bind("<Key>", self.handle_keys)
        self.screen = "1"
        self.show_screen()
        self.tick()

    def tick(self):
        global awayCount, keyMode, footerMessage, footerMessageCount
        self.update_header()
        if keyMode != 'PLAYER':
            awayCount += 1
            if awayCount > 120:
                awayCount = 0
                self.screen = ''
                self.show_screen()
        else:
            awayCount = 0

        if footerMessage == self.footer_text_var.get():
            footerMessageCount += 1
            if footerMessageCount > 8:
                footerMessageCount = 0
                self.footer_text_var.set("")
        else:
            footerMessage = self.footer_text_var.get()
            footerMessageCount = 0

        self.after(800, self.tick)

    def update_header(self):
        global status, keyMode, songChanged, currentSong, songName, songTicker, minTickerLength, songTickerCount
        status = client.status()
        self.volume = int(status["volume"])
        self.volumeLabel.configure(text=status["volume"])
        if status["state"] == "play":
            currentSong = client.currentsong()
            song = currentSong["artist"] + " - " + currentSong["title"]
            if songName != song:
                songChanged = True
                songName = song
                if keyMode != 'PLAYER':  # song changed, refresh ui
                    if len(songName) >= minTickerLength:
                        songTicker = True
                        songTickerCount = -1
                    else:
                        songTicker = False
                        songTickerCount = 0
            if keyMode != 'PLAYER':
                if songTicker:
                    songTickerCount += 1
                    if songTickerCount == len(songName) + 5:
                        songTickerCount = 0
                song = songName + "     "
                new_song = song[songTickerCount:] + song[:songTickerCount]
                self.current_song_var.set(new_song)
            elif keyMode == 'PLAYER':
                self.show_player()
        else:
            if songName != '':
                self.current_song_var.set('')
                songName = ''
                songChanged = True
                if keyMode == 'PLAYER':
                    self.show_player()

    def show_screen(self):
        global keyMode
        if self.screen == '':
            keyMode = 'PLAYER'
            self.menuScreen.place_forget()
            self.playerScreen.place(height=240, width=320, x=0, y=0)
            self.show_player()
            self.update()
            self.screen = '1'
            return
        self.listbox.delete(0, self.listbox.size() - 1)
        format_name = "string"
        if self.screen in self.screen_format:
            format_name = self.screen_format[self.screen]
        if isinstance(self.screen_data[self.screen], list):
            for item in self.screen_data[self.screen]:
                if format_name == "string":
                    if not item:
                        self.listbox.insert(tkinter.END, "")
                    else:
                        self.listbox.insert(tkinter.END, item[:36])
                if format_name == "SONG":
                    songname = ''
                    if 'artist' in item:
                        songname = item['artist'][:18]
                    songname += " - "
                    if 'title' in item:
                        max = 36 - len(songname)
                        songname += item['title'][:max]
                    self.listbox.insert(tkinter.END, songname)
                if format_name == "PLAYLIST":
                    playlist_name = ''
                    if isinstance(item, str):
                        playlist_name = item
                    else:
                        playlist_name = item['playlist']
                    self.listbox.insert(tkinter.END, playlist_name)

        self.listbox.select_set(0)  # This only sets focus on the first item.
        self.listbox.event_generate("<<ListboxSelect>>")
        self.update()
        return

    def show_player(self):
        global image, bg, songChanged, volumeChanged
        if songChanged or image is None:
            if sys.platform.startswith('linux'):
                process = subprocess.Popen(
                    "./coverart.sh", shell=True,
                    stdout=subprocess.PIPE).stdout.read()
            else:
                process = "./icons/ic_album_white_48dp.png"
            image = ImageTk.PhotoImage(
                Image.open(process).resize((136, 136), Image.ANTIALIAS))
        if bg is None:
            process = "./icons/bg.png"
            if 'img_background' in theme['PLAYER']:
                process = theme['PLAYER']['img_background']
            bg = ImageTk.PhotoImage(
                Image.open(process).resize((320, 240), Image.ANTIALIAS))
        if icon_random is None:
            self.load_icons()

        if status["state"] == "play":
            if songChanged:
                self.playerScreen.delete(tkinter.ALL)
                self.playerScreen.create_image(160, 120, image=bg)

                self.playerScreen.create_rectangle(
                    10, 10, 150, 150, fill=theme['PLAYER']['foreground'])
                self.playerScreen.create_image(80, 80, image=image)

                self.playerScreen.create_image(178, 132, image=icon_random)
                self.playerScreen.create_image(224, 132, image=icon_repeat)
                self.playerScreen.create_image(270, 132, image=icon_single)
                self.playerScreen.create_rectangle(
                    298,
                    146,
                    308,
                    92,
                    fill=theme['PLAYER']['background'],
                    outline=theme['PLAYER']['foreground'],
                    width=1)
                self.playerScreen.create_line(
                    303,
                    144,
                    303,
                    144 - int(self.volume / 2),
                    fill=theme['PLAYER']['foreground'],
                    width=7)

                self.playerScreen.create_text(
                    10,
                    160,
                    text=currentSong['artist'],
                    anchor=tkinter.NW,
                    fill=theme['PLAYER']['foreground'],
                    font=(theme['PLAYER']['font'], 14, 'bold'))
                self.playerScreen.create_text(
                    10,
                    185,
                    text=currentSong['title'],
                    anchor=tkinter.NW,
                    fill=theme['PLAYER']['foreground'],
                    font=(theme['PLAYER']['font'], 12, 'bold'))
                self.playerScreen.create_text(
                    10,
                    210,
                    text=currentSong['album'],
                    anchor=tkinter.NW,
                    fill=theme['PLAYER']['foreground'],
                    font=(theme['PLAYER']['font'], 10, 'bold'))
            else:
                time = str(status['time']).split(":")
                played = int((float(time[0]) / float(time[1])) * 320)
                if played < 3:  # bug
                    self.playerScreen.create_rectangle(
                        0, 236, 320, 240, fill=theme['PLAYER']['background'])
                self.playerScreen.create_rectangle(
                    0, 236, played, 240, fill=theme['PLAYER']['foreground'])
            if volumeChanged:
                volumeChanged = False
                self.playerScreen.create_rectangle(
                    298,
                    146,
                    308,
                    92,
                    fill=theme['PLAYER']['background'],
                    outline=theme['PLAYER']['foreground'],
                    width=1)
                self.playerScreen.create_line(
                    303,
                    144,
                    303,
                    144 - int(self.volume / 2),
                    fill=theme['PLAYER']['foreground'],
                    width=7)
        else:  # Blank Screen
            self.playerScreen.delete(tkinter.ALL)
            self.playerScreen.create_image(160, 120, image=bg)
            self.playerScreen.create_text(
                20,
                20,
                text=theme['PLAYER']['default_message'],
                anchor=tkinter.NW,
                fill=theme['PLAYER']['foreground'],
                font=(theme['PLAYER']['font'], 20, 'bold'))
        songChanged = False
        return

    def handle_keys(self, event):
        global config, client, selectedAlbum, selectedArtist, selectedGenre
        global keyMode, textEntry, textBackAction, textSaveAction, awayCount, theme_name
        global albums, artists, queue, songs, playlists, status, genres, songChanged, volumeChanged

        awayCount = 0
        keycode = str(event.keycode)
        # self.footer_text_var.set(str("Key Pressed : "+keycode))
        if keyMode == 'PLAYER' and keycode != config["PISCREEN_KEYS"]["vol_up"] \
                and keycode != config["PISCREEN_KEYS"]["vol_down"] \
                and keycode != config["PISCREEN_KEYS"]["play"] \
                and keycode != config["PISCREEN_KEYS"]["next"] \
                and keycode != config["PISCREEN_KEYS"]["prev"] \
                and keycode != config["PISCREEN_KEYS"]["power"] \
                and keycode != config["PISCREEN_KEYS"]["left"]:
            keyMode = 'MENU'
            self.playerScreen.place_forget()
            self.menuScreen.place(height=240, width=320, x=0, y=0)
            self.show_screen()
            self.update()
            return
        if keyMode == 'TEXT':
            if keycode == config["PISCREEN_KEYS"]["back"]:  # back
                keyMode = 'MENU'
                self.run_command(textBackAction)
            if keycode == config["PISCREEN_KEYS"]["ok"]:  # ok
                keyMode = 'MENU'
                self.run_command(textSaveAction)
            if event.keysym in '0123456789-abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ':
                textEntry += event.keysym
                self.footer_text_var.set(str("Entry : " + textEntry))
            return
        # self.footer.configure(text=str('Key Pressed ' + str(event.keycode)))
        if keycode == config["PISCREEN_KEYS"]["menu"]:
            if self.screen == "1.P":
                selection = int(self.listbox.curselection()[0]) + 1
                if selection > 1:
                    self.footer_text_var.set(
                        str("Press 1 + OK to Delete Playlist"))
                    keyMode = 'TEXT'
                    textBackAction = "PLAYLISTS"
                    textSaveAction = "DELETE_PLAYLIST"
            if self.screen == "1.Q":
                self.footer_text_var.set(str("Press OK to remove Song"))
                keyMode = 'TEXT'
                textBackAction = "QUEUE"
                textSaveAction = "DELETE_SONG"
            return
        if keycode == config["PISCREEN_KEYS"]["down"]:  # down
            if self.listbox.size() > 0:
                selection = int(self.listbox.curselection()[0])
                count = self.listbox.size()
                if selection < (count - 1):
                    self.listbox.select_clear(selection)
                    self.listbox.selection_set(selection + 1)
                    self.listbox.event_generate("<<ListboxSelect>>")
            return
        if keycode == config["PISCREEN_KEYS"]["up"]:  # up
            if self.listbox.size() > 0:
                selection = int(self.listbox.curselection()[0])
                if selection > 0:
                    self.listbox.select_clear(selection)
                    self.listbox.selection_set(selection - 1)
                    self.listbox.event_generate("<<ListboxSelect>>")
            return
        if keycode == config["PISCREEN_KEYS"]["left"] or keycode == config[
                "PISCREEN_KEYS"]["back"]:  # left or escape
            if self.screen != "1":
                menu = self.screen.rsplit(".", maxsplit=1)
                new_screen = menu[0]
                self.screen = new_screen
                self.show_screen()
            else:
                self.screen = ''
                songChanged = True
                self.show_screen()
            return
        if keycode == config["PISCREEN_KEYS"]["right"] or keycode == config[
                "PISCREEN_KEYS"]["ok"]:  # right or return
            if self.listbox.size() > 0:
                selection = int(self.listbox.curselection()[0]) + 1
                new_screen = self.screen + "." + str(selection)
                if new_screen in self.screen_data:
                    if type(self.screen_data[new_screen]) is list:
                        self.screen = new_screen
                        self.show_screen()
                    else:
                        self.run_command(
                            self.screen_data[new_screen]["ACTION"])
                else:
                    if str(new_screen).startswith("1.Q."):
                        menu = new_screen.rsplit(".", maxsplit=1)
                        client.playid(int(queue[int(menu[1]) - 1]["id"]))
                        return
                    if str(new_screen).startswith("1.P."):
                        menu = new_screen.rsplit(".", maxsplit=1)
                        if menu[1] == "1":
                            keyMode = 'TEXT'
                            textBackAction = 'PLAYLISTS'
                            textSaveAction = 'SAVE_PLAYLIST'
                            textEntry = ''
                            self.footer_text_var.set(
                                'Back to Cancel, Ok to Save')
                        else:
                            playlist = playlists[int(menu[1]) - 1]['playlist']
                            client.clear()
                            client.load(playlist)
                            client.play()
                        return
                    if str(new_screen).startswith("1.3.A"):
                        if new_screen.count(".") == 3:
                            menu = new_screen.rsplit(".", maxsplit=1)
                            selectedArtist = artists[int(menu[1]) - 1]
                            albums = []
                            albums = client.list("album", selectedArtist)
                            albums[:0] = ["Add All"]
                            self.footer_text_var.set("SELECTED Artist " +
                                                     selectedArtist)
                            self.screen = new_screen
                            self.screen_data[new_screen] = albums
                            self.show_screen()
                            return
                        elif new_screen.count(".") == 4:
                            menu = new_screen.rsplit(".", maxsplit=1)
                            if menu[1] == "1":  # add all
                                client.findadd("artist", selectedArtist)
                                self.footer_text_var.set("Added All for " +
                                                         selectedArtist)
                                self.screen = menu[0].rsplit(".",
                                                             maxsplit=1)[0]
                                self.show_screen()
                            else:
                                selectedAlbum = albums[int(menu[1]) - 1]
                                songs = client.list("title", "album",
                                                    selectedAlbum, "artist",
                                                    selectedArtist)
                                songs[:0] = ["Add All"]
                                self.screen = new_screen
                                self.screen_data[new_screen] = songs
                                self.show_screen()
                                self.footer_text_var.set("Album Selected " +
                                                         selectedAlbum)
                            return
                        elif new_screen.count(".") == 5:
                            menu = new_screen.rsplit(".", maxsplit=1)
                            if menu[1] == "1":  # add all
                                client.findadd("album", selectedAlbum,
                                               "artist", selectedArtist)
                                self.footer_text_var.set("Added All for " +
                                                         selectedAlbum + "/" +
                                                         selectedArtist)
                                self.screen = menu[0].rsplit(".",
                                                             maxsplit=1)[0]
                                self.show_screen()
                            else:
                                selected_song = songs[int(menu[1]) - 1]
                                client.findadd("title", selected_song, "album",
                                               selectedAlbum, "artist",
                                               selectedArtist)
                                self.footer_text_var.set("Added " +
                                                         selected_song + "/" +
                                                         selectedAlbum + "/" +
                                                         selectedArtist)
                            return
                    if str(new_screen).startswith("1.3.B"):
                        menu = new_screen.rsplit(".", maxsplit=1)
                        if new_screen.count(".") == 3:
                            selectedAlbum = albums[int(menu[1]) - 1]
                            songs = client.list("title", "album",
                                                selectedAlbum)
                            songs[:0] = ["Add All"]
                            self.screen = new_screen
                            self.screen_data[new_screen] = songs
                            self.show_screen()
                            self.footer_text_var.set("Album Selected " +
                                                     selectedAlbum)
                        if new_screen.count(".") == 4:
                            if menu[1] == "1":  # add all
                                client.findadd("album", selectedAlbum)
                                self.footer_text_var.set(
                                    "Added All for album " + selectedAlbum)
                                self.screen = menu[0].rsplit(".",
                                                             maxsplit=1)[0]
                                self.show_screen()
                            else:
                                selected_song = songs[int(menu[1]) - 1]
                                client.findadd("title", selected_song, "album",
                                               selectedAlbum)
                                self.footer_text_var.set("Added " +
                                                         selected_song + "/" +
                                                         selectedAlbum)
                        return
                    if str(new_screen).startswith("1.3.C"):
                        menu = new_screen.rsplit(".", maxsplit=1)
                        if new_screen.count(".") == 3:
                            selectedGenre = genres[int(menu[1]) - 1]
                            songs = client.list("title", "genre",
                                                selectedGenre)
                            self.screen = new_screen
                            self.screen_data[new_screen] = songs
                            self.show_screen()
                            self.footer_text_var.set("Genre Selected " +
                                                     selectedAlbum)
                        if new_screen.count(".") == 4:
                            selected_song = songs[int(menu[1]) - 1]
                            client.findadd("title", selected_song, "genre",
                                           selectedGenre)
                            self.footer_text_var.set("Added " + selected_song +
                                                     selectedGenre)
                        return
                    if str(new_screen).startswith("1.4.T"):
                        menu = new_screen.rsplit(".", maxsplit=1)
                        theme_name = themes[int(menu[1]) - 1]
                        self.footer_text_var.set("Applying Theme " +
                                                 theme_name)
                        self.apply_theme()
            return
        if keycode == config["PISCREEN_KEYS"]["vol_up"]:
            if self.volume < 100:
                self.volume += 1
                client.setvol(self.volume)
                volumeChanged = True
                self.footer_text_var.set("Volume Up")
            else:
                self.footer_text_var.set("Volume Max!!")
            return
        if keycode == config["PISCREEN_KEYS"]["vol_down"]:
            if self.volume > 0:
                self.volume -= 1
                client.setvol(self.volume)
                volumeChanged = True
                self.footer_text_var.set("Volume Down")
            else:
                self.footer_text_var.set("Volume Zero!!")
            return
        if keycode == config["PISCREEN_KEYS"]["play"]:
            if status["state"] == "play":
                client.pause()
                self.footer_text_var.set("Paused")
            else:
                client.play()
                self.footer_text_var.set("Playing")
            return
        if keycode == config["PISCREEN_KEYS"]["next"]:
            client.next()
            self.footer_text_var.set("Next Song")
            return
        if keycode == config["PISCREEN_KEYS"]["prev"]:
            client.previous()
            self.footer_text_var.set("Previous Song")
            return
        if keycode == config["PISCREEN_KEYS"]["home"]:
            self.screen = ''
            self.show_screen()
            return
        if keycode == config["PISCREEN_KEYS"]["power"]:
            if sys.platform.startswith('linux'):
                call("sudo nohup shutdown -h now", shell=True)
            else:
                self.footer_text_var.set("Can't PowerOff from remote")
            return
        self.footer_text_var.set("UNKNOWN " + keycode)

    def run_command(self, action):
        global client, keyMode, textEntry, status
        global albums, artists, queue, songs, playlists, genres, themes
        if action == "QUEUE":
            local_queue = client.playlistinfo()
            queue.clear()
            for item in local_queue:
                queue.append(item)
            self.screen = "1.Q"
            self.screen_data["1.Q"] = queue
            self.footer_text_var.set("Right to play Song, Menu to delete")
            self.show_screen()
        elif action == "PLAYLISTS":
            playlists = client.listplaylists()
            playlists[:0] = ["SAVE PLAYLIST"]
            self.screen = "1.P"
            self.screen_data["1.P"] = playlists
            self.footer_text_var.set("Right to play Playlist, Menu to delete")
            self.show_screen()
        elif action == "ARTISTS":
            artists = client.list("artist")
            self.screen = "1.3.A"
            self.screen_data["1.3.A"] = artists
            self.show_screen()
        elif action == "ALBUMS":
            albums = client.list("album")
            self.screen = "1.3.B"
            self.screen_data["1.3.B"] = albums
            self.show_screen()
        elif action == "GENRES":
            genres = client.list("genre")
            self.screen = "1.3.C"
            self.screen_data["1.3.C"] = genres
            self.show_screen()
        elif action == "UPDATE_LIBRARY":
            self.footer_text_var.set("Updating library")
            client.update()
        elif action == "THEMES":
            self.footer_text_var.set("Select Theme")
            themes = ["default", "foofighters", "light"]
            self.screen = "1.4.T"
            self.screen_data["1.4.T"] = themes
            self.show_screen()
        elif action == "SAVE_PLAYLIST":
            keyMode = 'MENU'
            found = False
            if textEntry == '':
                self.footer_text_var.set("Name Empty!!")
                return
            for playlist in playlists:
                if isinstance(
                        playlist,
                        str) is False and textEntry == playlist['playlist']:
                    found = True
            if found:
                client.rm(textEntry)
                client.save(textEntry)
            else:
                client.save(textEntry)
            self.footer_text_var.set("Saved Playlist " + textEntry)
            textEntry = ''
            self.run_command("PLAYLISTS")
        elif action == "DELETE_PLAYLIST":
            keyMode = 'MENU'
            if textEntry == '1':
                selection = int(self.listbox.curselection()[0])
                client.rm(playlists[selection]['playlist'])
            textEntry = ''
            self.run_command("PLAYLISTS")
        elif action == "DELETE_SONG":
            keyMode = 'MENU'
            client.delete(int(self.listbox.curselection()[0]))
            textEntry = ''
            self.run_command("QUEUE")
        elif action == "CLEAR":
            self.footer_text_var.set("Clearing Queue")
            client.clear()
        elif action == "RANDOM":
            if status['random'] == '0':
                client.random('1')
            else:
                client.random('0')
            status = client.status()
            self.screen_data['1'][5] = "RANDOM " + status['random']
            self.update_random()
            self.show_screen()
        elif action == "REPEAT":
            if status['repeat'] == '0':
                client.repeat('1')
            else:
                client.repeat('0')
            status = client.status()
            self.screen_data['1'][6] = "REPEAT " + status['repeat']
            self.update_repeat()
            self.show_screen()
        elif action == "SINGLE":
            if status['single'] == '0':
                client.single('1')
            else:
                client.single('0')
            status = client.status()
            self.screen_data['1'][7] = "SINGLE " + status['single']
            self.update_single()
            self.show_screen()
        elif action == "CONSUME":
            if status['consume'] == '0':
                client.consume('1')
            else:
                client.consume('0')
            status = client.status()
            self.screen_data['1'][8] = "CONSUME " + status['consume']
            self.show_screen()
        self.update()
        return

    def load_icons(self):
        self.update_random()
        self.update_repeat()
        self.update_single()

    def update_random(self):
        global status, theme, icon_random
        fgcolor = ImageColor.getrgb(theme['PLAYER']['foreground'])
        bgcolor = ImageColor.getrgb(theme['PLAYER']['background'])
        fgcolor += (255, )
        bgcolor += (255, )
        icon_random = Image.open('./icons/ic_shuffle_white_36dp.png')
        if icon_random.mode != 'RGBA':
            icon_random = icon_random.convert('RGBA')
        data = list(icon_random.getdata())
        newData = list()
        for pixel in data:
            if pixel[3] != 0:
                if status['random'] == '1':
                    newData.append(fgcolor)
                else:
                    newData.append(bgcolor)
            else:
                newData.append(pixel)
        icon_random.putdata(newData)
        icon_random = ImageTk.PhotoImage(
            icon_random.resize((36, 36), Image.ANTIALIAS))

    def update_single(self):
        global status, theme, icon_single
        fgcolor = ImageColor.getrgb(theme['PLAYER']['foreground'])
        bgcolor = ImageColor.getrgb(theme['PLAYER']['background'])
        fgcolor += (255, )
        bgcolor += (255, )
        icon_single = Image.open('./icons/ic_repeat_one_white_36dp.png')
        if icon_single.mode != 'RGBA':
            icon_single = icon_single.convert('RGBA')
        data = list(icon_single.getdata())
        newData = list()
        for pixel in data:
            if pixel[3] != 0:
                if status['single'] == '1':
                    newData.append(fgcolor)
                else:
                    newData.append(bgcolor)
            else:
                newData.append(pixel)
        icon_single.putdata(newData)
        icon_single = ImageTk.PhotoImage(
            icon_single.resize((36, 36), Image.ANTIALIAS))

    def update_repeat(self):
        global status, theme, icon_repeat
        fgcolor = ImageColor.getrgb(theme['PLAYER']['foreground'])
        bgcolor = ImageColor.getrgb(theme['PLAYER']['background'])
        fgcolor += (255, )
        bgcolor += (255, )
        icon_repeat = Image.open('./icons/ic_repeat_white_36dp.png')
        if icon_repeat.mode != 'RGBA':
            icon_repeat = icon_repeat.convert('RGBA')
        data = list(icon_repeat.getdata())
        newData = list()
        for pixel in data:
            if pixel[3] != 0:
                if status['repeat'] == '1':
                    newData.append(fgcolor)
                else:
                    newData.append(bgcolor)
            else:
                newData.append(pixel)
        icon_repeat.putdata(newData)
        icon_repeat = ImageTk.PhotoImage(
            icon_repeat.resize((36, 36), Image.ANTIALIAS))

    def apply_theme(self):
        global theme_name, theme, config, bg
        my_file = Path('./theme/' + theme_name + '/theme.ini')
        if my_file.is_file():
            theme = configparser.ConfigParser()
            theme.read('./theme/' + theme_name + '/theme.ini')
            # player related settings
            bg = None
            self.playerScreen.configure(bg=theme['PLAYER']['background'])
            self.load_icons()
            # menu related settings
            self.headerFrame.configure(bg=theme['HEADER']['background'])
            self.currentSongLabel.configure(
                font=(theme['HEADER']['font'], 12, 'bold'),
                bg=theme['HEADER']['background'],
                foreground=theme['HEADER']['foreground'])
            self.volumeLabel.configure(
                font=(theme['HEADER']['font'], 10, 'bold'),
                bg=theme['HEADER']['background'],
                foreground=theme['HEADER']['foreground'])
            self.listbox.configure(
                font=(theme['MAIN']['font'], 11),
                bg=theme['MAIN']['background'],
                fg=theme['MAIN']['foreground'],
                selectbackground=theme['MAIN']['selected'],
                selectforeground=theme['MAIN']['foreground'])
            self.footer.configure(font=(theme['FOOTER']['font'], 10, 'bold'),
                                  bg=theme['FOOTER']['background'],
                                  foreground=theme['FOOTER']['foreground'])

            # write theme to config.ini
            config["THEME"]["theme"] = theme_name
            with open('config.ini', 'w') as configfile:
                config.write(configfile)
        else:
            self.footer_text_var.set("Theme Not Found")
            theme_name = config["THEME"]["theme"]
Esempio n. 14
0
def openStats(handler):
    statsApi = get(
        "https://raw.githubusercontent.com/revoxhere/duco-statistics/master/api.json",
        data=None)
    if statsApi.status_code == 200:  #Check for reponse
        statsApi = (statsApi.json())
        print(statsApi)

    statsWindow = Toplevel()
    statsWindow.resizable(False, False)
    statsWindow.title("Duino-Coin Wallet - Stats")
    statsWindow.configure(background=backgroundColor)
    statsWindow.transient([root])

    textFont3 = Font(statsWindow, size=14, weight="bold")
    textFont = Font(statsWindow, size=12, weight="normal")

    Label(statsWindow,
          text="Duco Statistics",
          background=backgroundColor,
          foreground=foregroundColor,
          font=textFont3).grid(row=0, column=0)

    i = 3
    i2 = 3
    for key in statsApi.keys():
        if str(key) == 'Active workers' or str(
                key) == 'Top 10 richest miners' or str(
                    key) == 'Total supply' or str(
                        key) == 'Full last block hash' or str(
                            key) == 'GitHub API file update count' or str(
                                key) == 'Diff increases per':
            pass
        else:
            if len(statsApi.get(str(key))) > 8:
                Label(statsWindow,
                      text=f"{key}: {statsApi.get(str(key))}",
                      background=backgroundColor,
                      foreground=foregroundColor,
                      font=textFont).grid(row=i2, column=1, sticky=W)
                i2 += 1
            else:
                Label(statsWindow,
                      text=f"{key}: {statsApi.get(str(key))}",
                      background=backgroundColor,
                      foreground=foregroundColor,
                      font=textFont).grid(row=i, column=0, sticky=W)
                i += 1

    Active_workers_listbox = Listbox(statsWindow,
                                     exportselection=False,
                                     background=backgroundColor,
                                     foreground=foregroundColor,
                                     selectbackground="#7bed9f",
                                     border="0",
                                     font=textFont,
                                     width="20",
                                     height="13")
    Active_workers_listbox.grid(row=1, column=0, sticky=W)
    i = 0
    for worker in (statsApi['Active workers']).split(', '):
        Active_workers_listbox.insert(i, worker)
        i = i + 1

    Active_workers_listbox.select_set(32)
    Active_workers_listbox.event_generate("<<ListboxSelect>>")

    Top_10_listbox = Listbox(statsWindow,
                             exportselection=False,
                             background=backgroundColor,
                             foreground=foregroundColor,
                             selectbackground="#7bed9f",
                             border="0",
                             font=textFont,
                             width="33",
                             height="13")
    Top_10_listbox.grid(row=1, column=1, sticky=W)
    i = 0
    for rich in (statsApi['Top 10 richest miners']).split(', '):
        Top_10_listbox.insert(i, rich)
        i = i + 1

    Top_10_listbox.select_set(32)
    Top_10_listbox.event_generate("<<ListboxSelect>>")

    statsWindow.mainloop()
Esempio n. 15
0
class MusicPanel(Frame):
    def __init__(self, parent, musicController: IMusicController):
        super().__init__(parent)
        self.musicController = musicController
        self.musicList: List[Music] = []

        self.selectedMusicPath: str = None

        self.__initView()

    def __initView(self):
        self.grid_columnconfigure(0, weight=1)

        self.musicListBox = Listbox(self)
        self.musicListBox.grid(row=0,
                               column=0,
                               sticky='WE',
                               padx=(10, 0),
                               pady=10)
        self.musicListBox.bind('<Double-1>', self.musicDoubleClicked)
        self.musicListBox.bind("<<ListboxSelect>>", self.musicSelected)

        musicScrollbar = Scrollbar(self, command=self.musicListBox.yview)
        musicScrollbar.grid(row=0,
                            column=1,
                            sticky='NS',
                            padx=(0, 10),
                            pady=10)

        self.musicListBox.configure(yscrollcommand=musicScrollbar.set)

        ################################################################################

        skipLabel = Label(self, text=SKIP_TEXT)
        skipLabel.grid(row=1, column=0)

        self.skipListBox = Listbox(self, exportselection=0)
        self.skipListBox.grid(row=2,
                              column=0,
                              sticky='WE',
                              padx=(10, 0),
                              pady=10)

        skipScrollbar = Scrollbar(self, command=self.skipListBox.yview)
        skipScrollbar.grid(row=2, column=1, sticky='NS', padx=(0, 10), pady=10)

        self.skipListBox.configure(yscrollcommand=skipScrollbar.set)

        self.deleteSkipButton = Button(self,
                                       text=DELETE_SKIP_TEXT,
                                       command=self.onSkipDelete)
        self.deleteSkipButton.grid(row=3, column=0, sticky='W', padx=10)

        ################################################################################

        self.addSkipFrame = Frame(self)
        self.addSkipFrame.grid(row=4, column=0, padx=10, sticky='W')

        self.addSkipLabel = Label(self.addSkipFrame, text=ADD_SKIP_LABEL_TEXT)
        self.addSkipLabel.grid(row=0, column=0)

        self.addSkipStartMinutesTE = Entry(self.addSkipFrame,
                                           width=5,
                                           exportselection=0)
        self.addSkipStartMinutesTE.insert(END, '0')
        self.addSkipStartMinutesTE.grid(row=0, column=1)

        label = Label(self.addSkipFrame, text=':')
        label.grid(row=0, column=2)

        self.addSkipStartSecondsTE = Entry(self.addSkipFrame,
                                           width=5,
                                           exportselection=0)
        self.addSkipStartSecondsTE.insert(END, '0')
        self.addSkipStartSecondsTE.grid(row=0, column=3)

        label = Label(self.addSkipFrame, text=ADD_SKIP_TO_LABEL_TEXT)
        label.grid(row=0, column=4)

        self.addSkipEndMinutesTE = Entry(self.addSkipFrame,
                                         width=5,
                                         exportselection=0)
        self.addSkipEndMinutesTE.insert(END, '0')
        self.addSkipEndMinutesTE.grid(row=0, column=5)

        label = Label(self.addSkipFrame, text=':')
        label.grid(row=0, column=6)

        self.addSkipEndSecondsTE = Entry(self.addSkipFrame,
                                         width=5,
                                         exportselection=0)
        self.addSkipEndSecondsTE.insert(END, '0')
        self.addSkipEndSecondsTE.grid(row=0, column=7)

        self.addSkipButton = Button(self.addSkipFrame,
                                    text=ADD_SKIP_BUTTON_TEXT,
                                    command=self.__addSkip)
        self.addSkipButton.grid(row=0, column=8, padx=2)

    def displayMusic(self, music: List[Music]):
        self.musicList = music

        self.musicListBox.delete(0, 'end')
        for i in range(len(music)):
            m = music[i]
            self.musicListBox.insert(i, m)

        if self.selectedMusicPath is not None:
            selectedIndex = -1
            for i in range(len(self.musicList)):
                if self.musicList[i].path == self.selectedMusicPath:
                    selectedIndex = i
                    break

            if selectedIndex >= 0:
                self.musicListBox.select_set(selectedIndex)
                self.musicListBox.event_generate("<<ListboxSelect>>")

    def musicDoubleClicked(self, event):
        music = self.musicList[self.musicListBox.curselection()[0]]
        self.musicController.onMusicDoubleClicked(music)

    def onSkipDelete(self):
        musicSelection = self.musicListBox.curselection()
        skipSelection = self.skipListBox.curselection()

        if len(skipSelection) <= 0 or len(musicSelection) <= 0:
            messagebox.showwarning('Warning', DELETE_SKIP_SELECT_MUSIC)
            return

        music = self.musicList[musicSelection[0]]
        self.musicController.onSkipDeleteClicked(music.skips[skipSelection[0]])

    def musicSelected(self, event):
        self.skipListBox.delete(0, 'end')

        selection = self.musicListBox.curselection()
        if len(selection) <= 0:
            return

        selectedMusic = self.musicList[selection[0]]
        self.selectedMusicPath = selectedMusic.path

        if selectedMusic.skips is not None:
            for i in range(len(selectedMusic.skips)):
                s = selectedMusic.skips[i]

                startMinute = int(s.start / 60)
                startSecond = s.start % 60
                stopMinute = int(s.end / 60)
                stopSecond = s.end % 60

                text = f'Skip from {startMinute:02d}:{startSecond:02d} to {stopMinute:02d}:{stopSecond:02d}'
                self.skipListBox.insert(i, text)

    def __addSkip(self):
        selection = self.musicListBox.curselection()

        if len(selection) <= 0:
            messagebox.showwarning('Warning', ADD_SKIP_SELECT_MUSIC)
            return

        music = self.musicList[selection[0]]

        try:
            startMinutes = int(self.addSkipStartMinutesTE.get())
            startSeconds = int(self.addSkipStartSecondsTE.get())
            endMinutes = int(self.addSkipEndMinutesTE.get())
            endSeconds = int(self.addSkipEndSecondsTE.get())
        except:
            messagebox.showwarning('Warning', ADD_SKIP_PARSE_ERROR_TEXT)
            return

        start = startMinutes * 60 + startSeconds
        end = endMinutes * 60 + endSeconds

        if end <= start:
            messagebox.showwarning('Warning', ADD_SKIP_END_LOWER_THAN_START)
            return

        self.musicController.onSkipAddClicked(music.path, start, end)
class index_select(Frame):
    def __init__(self,controller,current_model,master,*args,**kwargs):
        self.controller = controller
        self.current_model = current_model
        self.filtered_list = None
        self.saved_selection = None

        from tkinter import EXTENDED,Scrollbar,Y

        #dibujar widget
        super().__init__(master, *args, **kwargs)

        f_st=Frame(self)
        Label(f_st,text="Current_index: ").pack()
        Label(f_st, text="Current_filter: ").pack()
        f_st.pack()

        frame_index_listbox = Frame(self)
        self.listbox = Listbox(frame_index_listbox, exportselection=False,selectmode=EXTENDED)
        self.listbox.pack(side=LEFT)

        scrollbar = Scrollbar(frame_index_listbox)
        scrollbar.pack(side=LEFT, fill=Y)
        frame_index_listbox.pack()


        # attach listbox to scrollbar
        self.listbox.config(yscrollcommand=scrollbar.set)
        scrollbar.config(command=self.listbox.yview)

        f=Frame(self)
        Label(f,text="Filtro: ").pack(side=LEFT)
        self.entry_w = Entry(f)
        self.entry_w.pack(side=LEFT)
        f.pack()

        f2=Frame(self)
        Button(f2, text='Filter',command=self.filter_indexs).pack(side=LEFT)
        Button(f2,text='Clean Filter',command=self.clean_filter).pack(side=LEFT)
        Button(f2, text='Export sel for gen',command=self.export_selection).pack(side=LEFT)
        f2.pack()

        f3=Frame(self)
        Button(self, text='<<',command=self.next_prev(-1)).pack(side=LEFT)
        Button(self, text='>>',command=self.next_prev(1)).pack(side=LEFT)
        f3.pack()

        self.update_model(current_model)
        self.listbox.select_set(0)
        self.listbox.event_generate("<<ListboxSelect>>")
        self.listbox.bind('<<ListboxSelect>>', self.selection)

    def filter_indexs(self):
        import random
        path_filter = self.entry_w.get()
        with open(path_filter,'r') as f:
            indexs_list_str = f.read().strip()
        random.seed(3)
        indexs_list = list(set(indexs_list_str.split('\n')))
        print(len(indexs_list))
        random.shuffle(indexs_list)

        self.filtered_list = indexs_list
        self.listbox.delete(0, END)
        for item in indexs_list:
            self.listbox.insert(END, item)

    def clean_filter(self):
        self.filtered_list = None
        self.update_model(self.current_model)
        self.listbox.delete(0, END)
        for item in sorted(self.index_list):
            self.listbox.insert(END, item)
        self.saved_selection = None

    def export_selection(self):
        sel_files_folder = os.path.join('config_files','select_files')
        os.makedirs(sel_files_folder,exist_ok=True)

        sel_list = self.listbox.curselection()
        index_list = [self.listbox.get(ind) for ind in sel_list]
        print("Exporting list for image generator. List: {0}".format(index_list))
        now_s = now_string()
        out_selection_file = {'index_list' : index_list,
                              'train_result_path': self.current_model.current_config_file,
                              'details' : '',
                              'mask_file' : self.current_model.current_mask_file}
        sel_file_name = "{0}_{1}_{2}_selection.json".format(self.current_model.classifier_key,self.current_model.dataset_key,now_s)
        sel_path = os.path.join(sel_files_folder,sel_file_name)
        with open(sel_path,'w') as f:
            json.dump(out_selection_file,f)
        print("Select in {0}".format(sel_path))

    def update_model(self, current_model):
        self.model = current_model
        self.index_list = self.model.get_index_list()
        self.current_index = self.model.get_current_index()
        self.mask_list = self.model.get_current_mask_index_list()

        indexs_list = self.filtered_list if self.filtered_list else sorted(self.index_list)

        self.listbox.delete(0, END)
        for item in indexs_list:
            self.listbox.insert(END, item)

        if self.saved_selection:
            ind,ypos = self.saved_selection
            self.listbox.selection_set(ind)
            self.listbox.yview_moveto(ypos[0])  # go back to that position

    def next_prev(self,x):
        def selection():
            ind_l = self.index_list.index(self.current_index)
            n = len(self.index_list)
            n_ind_l = (ind_l+x) % n
            next = self.index_list[n_ind_l]
            self.current_index = next
            self.listbox.selection_clear(0, END)
            self.listbox.select_set(n_ind_l)
            self.controller.event_change_index(next)

        return selection

    def selection(self,event):
        w = event.widget
        index = int(w.curselection()[0])
        value = w.get(index)
        print("v: {0}".format(value))
        selected_index = value
        self.current_index = selected_index
        self.controller.event_change_index(selected_index)
        self.saved_selection = (index,self.listbox.yview())

        pass
Esempio n. 17
0
class AutoCompleteEntryListbox(Frame):
    def __init__(self,
                 master=None,
                 completevalues=[],
                 allow_other_values=False,
                 **kwargs):
        """
        Create a Entry + Listbox with autocompletion.

        Keyword arguments:
         - allow_other_values (boolean): whether the user is allowed to enter values not in the list
        """
        exportselection = kwargs.pop('exportselection', False)
        width = kwargs.pop('width', None)
        justify = kwargs.pop('justify', None)
        font = kwargs.pop('font', None)
        Frame.__init__(self, master, padding=4, **kwargs)
        self.columnconfigure(0, weight=1)
        self.rowconfigure(1, weight=1)
        self._allow_other_values = allow_other_values
        self._completevalues = completevalues
        self._validate = self.register(self.validate)
        self.entry = Entry(self,
                           width=width,
                           justify=justify,
                           font=font,
                           validate='key',
                           exportselection=exportselection,
                           validatecommand=(self._validate, "%d", "%S", "%i",
                                            "%s", "%P"))
        f = Frame(self, style='border.TFrame', padding=1)
        self.listbox = Listbox(f,
                               width=width,
                               justify=justify,
                               font=font,
                               exportselection=exportselection,
                               selectmode="browse",
                               highlightthickness=0,
                               relief='flat')
        self.listbox.pack(fill='both', expand=True)
        scroll = AutoHideScrollbar(self,
                                   orient='vertical',
                                   command=self.listbox.yview)
        self.listbox.configure(yscrollcommand=scroll.set)
        self.entry.grid(sticky='ew')
        f.grid(sticky='nsew')
        scroll.grid(row=1, column=1, sticky='ns')
        for c in self._completevalues:
            self.listbox.insert('end', c)

        self.listbox.bind('<<ListboxSelect>>', self.update_entry)
        self.listbox.bind("<KeyPress>", self.keypress)
        self.entry.bind("<Tab>", self.tab)
        self.entry.bind("<Down>", self.down)
        self.entry.bind("<Up>", self.up)
        self.entry.focus_set()

    def tab(self, event):
        """Move at the end of selected text on tab press."""
        self.entry = event.widget
        self.entry.selection_clear()
        self.entry.icursor("end")
        return "break"

    def keypress(self, event):
        """Select the first item which name begin by the key pressed."""
        key = event.char.lower()
        l = [i for i in self._completevalues if i[0].lower() == key]
        if l:
            i = self._completevalues.index(l[0])
            self.listbox.selection_clear(0, "end")
            self.listbox.selection_set(i)
            self.listbox.see(i)
            self.update_entry()

    def up(self, event):
        """Navigate in the listbox with up key."""
        try:
            i = self.listbox.curselection()[0]
            self.listbox.selection_clear(0, "end")
            if i <= 0:
                i = len(self._completevalues)
            self.listbox.see(i - 1)
            self.listbox.select_set(i - 1)
        except (TclError, IndexError):
            self.listbox.selection_clear(0, "end")
            i = len(self._completevalues)
            self.listbox.see(i - 1)
            self.listbox.select_set(i - 1)
        self.listbox.event_generate('<<ListboxSelect>>')

    def down(self, event):
        """Navigate in the listbox with down key."""
        try:
            i = self.listbox.curselection()[0]
            self.listbox.selection_clear(0, "end")
            if i >= len(self._completevalues):
                i = -1
            self.listbox.see(i + 1)
            self.listbox.select_set(i + 1)
        except (TclError, IndexError):
            self.listbox.selection_clear(0, "end")
            self.listbox.see(0)
            self.listbox.select_set(0)
        self.listbox.event_generate('<<ListboxSelect>>')

    def validate(self, action, modif, pos, prev_txt, new_txt):
        """Complete the text in the entry with values."""
        try:
            sel = self.entry.selection_get()
            txt = prev_txt.replace(sel, '')
        except TclError:
            txt = prev_txt
        if action == "0":
            txt = txt[:int(pos)] + txt[int(pos) + 1:]
            return True
        else:
            txt = txt[:int(pos)] + modif + txt[int(pos):]
            l = [i for i in self._completevalues if i[:len(txt)] == txt]
            if l:
                i = self._completevalues.index(l[0])
                self.listbox.selection_clear(0, "end")
                self.listbox.selection_set(i)
                self.listbox.see(i)
                index = self.entry.index("insert")
                self.entry.delete(0, "end")
                self.entry.insert(0, l[0].replace("\ ", " "))
                self.entry.selection_range(index + 1, "end")
                self.entry.icursor(index + 1)
                return True
            else:
                return self._allow_other_values

    def __getitem__(self, key):
        return self.cget(key)

    def update_entry(self, event=None):
        """Update entry when an item is selected in the listbox."""
        try:
            sel = self.listbox.get(self.listbox.curselection()[0])
        except (TclError, IndexError):
            return
        self.entry.delete(0, "end")
        self.entry.insert(0, sel)
        self.entry.selection_clear()
        self.entry.icursor("end")
        self.event_generate('<<ItemSelect>>')

    def keys(self):
        keys = Combobox.keys(self)
        keys.append('allow_other_values')
        return keys

    def get(self):
        return self.entry.get()

    def cget(self, key):
        if key == 'allow_other_values':
            return self._allow_other_values
        elif key == 'completevalues':
            return self._completevalues
        else:
            return self.cget(self, key)

    def config(self, dic={}, **kwargs):
        self.configure(dic={}, **kwargs)

    def configure(self, dic={}, **kwargs):
        dic2 = {}
        dic2.update(dic)
        dic2.update(kwargs)
        self._allow_other_values = dic2.pop('allow_other_values',
                                            self._allow_other_values)
        self._completevalues = dic2.pop('completevalues', self._completevalues)
        self.config(self, dic2)
Esempio n. 18
0
class FontChooser(Toplevel):
    """Font chooser dialog."""

    def __init__(self, master, font_dict={}, text="Abcd", title="Font Chooser",
                 **kwargs):
        """
        Create a new FontChooser instance.
        Arguments:
            master : Tk or Toplevel instance
                master window
            font_dict : dict
                dictionnary, like the one returned by the ``actual`` method of a ``Font`` object:
                ::
                    {'family': str,
                     'size': int,
                     'weight': 'bold'/'normal',
                     'slant': 'italic'/'roman',
                     'underline': bool,
                     'overstrike': bool}
            text : str
                text to be displayed in the preview label
            title : str
                window title
            kwargs : dict
                additional keyword arguments to be passed to ``Toplevel.__init__``
        """
        Toplevel.__init__(self, master, **kwargs)
        self.title(title)
        self.resizable(False, False)
        self.protocol("WM_DELETE_WINDOW", self.quit)
        self._validate_family = self.register(self.validate_font_family)
        self._validate_size = self.register(self.validate_font_size)

        # --- variable storing the chosen font
        self.res = ""

        style = Style(self)
        style.configure("prev.TLabel", background="white")
        bg = style.lookup("TLabel", "background")
        self.configure(bg=bg)

        # --- family list
        self.fonts = list(set(families()))
        self.fonts.append("TkDefaultFont")
        self.fonts.sort()
        for i in range(len(self.fonts)):
            self.fonts[i] = self.fonts[i].replace(" ", "\ ")
        max_length = int(2.5 * max([len(font) for font in self.fonts])) // 3
        self.sizes = ["%i" % i for i in (list(range(6, 17)) + list(range(18, 32, 2)))]
        # --- font default
        font_dict["weight"] = font_dict.get("weight", "normal")
        font_dict["slant"] = font_dict.get("slant", "roman")
        font_dict["underline"] = font_dict.get("underline", False)
        font_dict["overstrike"] = font_dict.get("overstrike", False)
        font_dict["family"] = font_dict.get("family",
                                            self.fonts[0].replace('\ ', ' '))
        font_dict["size"] = font_dict.get("size", 10)

        # --- creation of the widgets
        # ------ style parameters (bold, italic ...)
        options_frame = Frame(self, relief='groove', borderwidth=2)
        self.font_family = StringVar(self, " ".join(self.fonts))
        self.font_size = StringVar(self, " ".join(self.sizes))
        self.var_bold = BooleanVar(self, font_dict["weight"] == "bold")
        b_bold = Checkbutton(options_frame, text=TR["Bold"],
                             command=self.toggle_bold,
                             variable=self.var_bold)
        b_bold.grid(row=0, sticky="w", padx=4, pady=(4, 2))
        self.var_italic = BooleanVar(self, font_dict["slant"] == "italic")
        b_italic = Checkbutton(options_frame, text=TR["Italic"],
                               command=self.toggle_italic,
                               variable=self.var_italic)
        b_italic.grid(row=1, sticky="w", padx=4, pady=2)
        self.var_underline = BooleanVar(self, font_dict["underline"])
        b_underline = Checkbutton(options_frame, text=TR["Underline"],
                                  command=self.toggle_underline,
                                  variable=self.var_underline)
        b_underline.grid(row=2, sticky="w", padx=4, pady=2)
        self.var_overstrike = BooleanVar(self, font_dict["overstrike"])
        b_overstrike = Checkbutton(options_frame, text=TR["Overstrike"],
                                   variable=self.var_overstrike,
                                   command=self.toggle_overstrike)
        b_overstrike.grid(row=3, sticky="w", padx=4, pady=(2, 4))
        # ------ Size and family
        self.var_size = StringVar(self)
        self.entry_family = Entry(self, width=max_length, validate="key",
                                  validatecommand=(self._validate_family, "%d", "%S",
                                                   "%i", "%s", "%V"))
        self.entry_size = Entry(self, width=4, validate="key",
                                textvariable=self.var_size,
                                validatecommand=(self._validate_size, "%d", "%P", "%V"))
        self.list_family = Listbox(self, selectmode="browse",
                                   listvariable=self.font_family,
                                   highlightthickness=0,
                                   exportselection=False,
                                   width=max_length)
        self.list_size = Listbox(self, selectmode="browse",
                                 listvariable=self.font_size,
                                 highlightthickness=0,
                                 exportselection=False,
                                 width=4)
        scroll_family = Scrollbar(self, orient='vertical',
                                  command=self.list_family.yview)
        scroll_size = Scrollbar(self, orient='vertical',
                                command=self.list_size.yview)
        self.preview_font = Font(self, **font_dict)
        if len(text) > 30:
            text = text[:30]
        self.preview = Label(self, relief="groove", style="prev.TLabel",
                             text=text, font=self.preview_font,
                             anchor="center")

        # --- widget configuration
        self.list_family.configure(yscrollcommand=scroll_family.set)
        self.list_size.configure(yscrollcommand=scroll_size.set)

        self.entry_family.insert(0, font_dict["family"])
        self.entry_family.selection_clear()
        self.entry_family.icursor("end")
        self.entry_size.insert(0, font_dict["size"])

        try:
            i = self.fonts.index(self.entry_family.get().replace(" ", "\ "))
        except ValueError:
            # unknown font
            i = 0
        self.list_family.selection_clear(0, "end")
        self.list_family.selection_set(i)
        self.list_family.see(i)
        try:
            i = self.sizes.index(self.entry_size.get())
            self.list_size.selection_clear(0, "end")
            self.list_size.selection_set(i)
            self.list_size.see(i)
        except ValueError:
            # size not in list
            pass

        self.entry_family.grid(row=0, column=0, sticky="ew",
                               pady=(10, 1), padx=(10, 0))
        self.entry_size.grid(row=0, column=2, sticky="ew",
                             pady=(10, 1), padx=(10, 0))
        self.list_family.grid(row=1, column=0, sticky="nsew",
                              pady=(1, 10), padx=(10, 0))
        self.list_size.grid(row=1, column=2, sticky="nsew",
                            pady=(1, 10), padx=(10, 0))
        scroll_family.grid(row=1, column=1, sticky='ns', pady=(1, 10))
        scroll_size.grid(row=1, column=3, sticky='ns', pady=(1, 10))
        options_frame.grid(row=0, column=4, rowspan=2,
                           padx=10, pady=10, ipadx=10)

        self.preview.grid(row=2, column=0, columnspan=5, sticky="eswn",
                          padx=10, pady=(0, 10), ipadx=4, ipady=4)

        button_frame = Frame(self)
        button_frame.grid(row=3, column=0, columnspan=5, pady=(0, 10), padx=10)

        Button(button_frame, text="Ok",
               command=self.ok).grid(row=0, column=0, padx=4, sticky='ew')
        Button(button_frame, text=TR["Cancel"],
               command=self.quit).grid(row=0, column=1, padx=4, sticky='ew')
        self.list_family.bind('<<ListboxSelect>>', self.update_entry_family)
        self.list_size.bind('<<ListboxSelect>>', self.update_entry_size,
                            add=True)
        self.list_family.bind("<KeyPress>", self.keypress)
        self.entry_family.bind("<Return>", self.change_font_family)
        self.entry_family.bind("<Tab>", self.tab)
        self.entry_size.bind("<Return>", self.change_font_size)

        self.entry_family.bind("<Down>", self.down_family)
        self.entry_size.bind("<Down>", self.down_size)

        self.entry_family.bind("<Up>", self.up_family)
        self.entry_size.bind("<Up>", self.up_size)

        # bind Ctrl+A to select all instead of go to beginning
        self.bind_class("TEntry", "<Control-a>", self.select_all)

        self.wait_visibility(self)
        self.grab_set()
        self.entry_family.focus_set()
        self.lift()

    def select_all(self, event):
        """Select all entry content."""
        event.widget.selection_range(0, "end")

    def keypress(self, event):
        """Select the first font whose name begin by the key pressed."""
        key = event.char.lower()
        l = [i for i in self.fonts if i[0].lower() == key]
        if l:
            i = self.fonts.index(l[0])
            self.list_family.selection_clear(0, "end")
            self.list_family.selection_set(i)
            self.list_family.see(i)
            self.update_entry_family()

    def up_family(self, event):
        """Navigate in the family listbox with up key."""
        try:
            i = self.list_family.curselection()[0]
            self.list_family.selection_clear(0, "end")
            if i <= 0:
                i = len(self.fonts)
            self.list_family.see(i - 1)
            self.list_family.select_set(i - 1)
        except TclError:
            self.list_family.selection_clear(0, "end")
            i = len(self.fonts)
            self.list_family.see(i - 1)
            self.list_family.select_set(i - 1)
        self.list_family.event_generate('<<ListboxSelect>>')

    def up_size(self, event):
        """Navigate in the size listbox with up key."""
        try:
            s = self.var_size.get()
            if s in self.sizes:
                i = self.sizes.index(s)
            elif s:
                sizes = list(self.sizes)
                sizes.append(s)
                sizes.sort(key=lambda x: int(x))
                i = sizes.index(s)
            else:
                i = 0
            self.list_size.selection_clear(0, "end")
            if i <= 0:
                i = len(self.sizes)
            self.list_size.see(i - 1)
            self.list_size.select_set(i - 1)
        except TclError:
            i = len(self.sizes)
            self.list_size.see(i - 1)
            self.list_size.select_set(i - 1)
        self.list_size.event_generate('<<ListboxSelect>>')

    def down_family(self, event):
        """Navigate in the family listbox with down key."""
        try:
            i = self.list_family.curselection()[0]
            self.list_family.selection_clear(0, "end")
            if i >= len(self.fonts):
                i = -1
            self.list_family.see(i + 1)
            self.list_family.select_set(i + 1)
        except TclError:
            self.list_family.selection_clear(0, "end")
            self.list_family.see(0)
            self.list_family.select_set(0)
        self.list_family.event_generate('<<ListboxSelect>>')

    def down_size(self, event):
        """Navigate in the size listbox with down key."""
        try:
            s = self.var_size.get()
            if s in self.sizes:
                i = self.sizes.index(s)
            elif s:
                sizes = list(self.sizes)
                sizes.append(s)
                sizes.sort(key=lambda x: int(x))
                i = sizes.index(s) - 1
            else:
                s = len(self.sizes) - 1
            self.list_size.selection_clear(0, "end")
            if i < len(self.sizes) - 1:
                self.list_size.selection_set(i + 1)
                self.list_size.see(i + 1)
            else:
                self.list_size.see(0)
                self.list_size.select_set(0)
        except TclError:
            self.list_size.selection_set(0)
        self.list_size.event_generate('<<ListboxSelect>>')

    def toggle_bold(self):
        """Update font preview weight."""
        b = self.var_bold.get()
        self.preview_font.configure(weight=["normal", "bold"][b])

    def toggle_italic(self):
        """Update font preview slant."""
        b = self.var_italic.get()
        self.preview_font.configure(slant=["roman", "italic"][b])

    def toggle_underline(self):
        """Update font preview underline."""
        b = self.var_underline.get()
        self.preview_font.configure(underline=b)

    def toggle_overstrike(self):
        """Update font preview overstrike."""
        b = self.var_overstrike.get()
        self.preview_font.configure(overstrike=b)

    def change_font_family(self, event=None):
        """Update font preview family."""
        family = self.entry_family.get()
        if family.replace(" ", "\ ") in self.fonts:
            self.preview_font.configure(family=family)

    def change_font_size(self, event=None):
        """Update font preview size."""
        size = int(self.var_size.get())
        self.preview_font.configure(size=size)

    def validate_font_size(self, d, ch, V):
        """Validation of the size entry content."""
        l = [i for i in self.sizes if i[:len(ch)] == ch]
        i = None
        if l:
            i = self.sizes.index(l[0])
        elif ch.isdigit():
            sizes = list(self.sizes)
            sizes.append(ch)
            sizes.sort(key=lambda x: int(x))
            i = min(sizes.index(ch), len(self.sizes))
        if i is not None:
            self.list_size.selection_clear(0, "end")
            self.list_size.selection_set(i)
            deb = self.list_size.nearest(0)
            fin = self.list_size.nearest(self.list_size.winfo_height())
            if V != "forced":
                if i < deb or i > fin:
                    self.list_size.see(i)
                return True
        if d == '1':
            return ch.isdigit()
        else:
            return True

    def tab(self, event):
        """Move at the end of selected text on tab press."""
        self.entry_family = event.widget
        self.entry_family.selection_clear()
        self.entry_family.icursor("end")
        return "break"

    def validate_font_family(self, action, modif, pos, prev_txt, V):
        """Completion of the text in the entry with existing font names."""
        if self.entry_family.selection_present():
            sel = self.entry_family.selection_get()
            txt = prev_txt.replace(sel, '')
        else:
            txt = prev_txt
        if action == "0":
            txt = txt[:int(pos)] + txt[int(pos) + 1:]
            return True
        else:
            txt = txt[:int(pos)] + modif + txt[int(pos):]
            ch = txt.replace(" ", "\ ")
            l = [i for i in self.fonts if i[:len(ch)] == ch]
            if l:
                i = self.fonts.index(l[0])
                self.list_family.selection_clear(0, "end")
                self.list_family.selection_set(i)
                deb = self.list_family.nearest(0)
                fin = self.list_family.nearest(self.list_family.winfo_height())
                index = self.entry_family.index("insert")
                self.entry_family.delete(0, "end")
                self.entry_family.insert(0, l[0].replace("\ ", " "))
                self.entry_family.selection_range(index + 1, "end")
                self.entry_family.icursor(index + 1)
                if V != "forced":
                    if i < deb or i > fin:
                        self.list_family.see(i)
                return True
            else:
                return False

    def update_entry_family(self, event=None):
        """Update family entry when an item is selected in the family listbox."""
        #  family = self.list_family.get("@%i,%i" % (event.x , event.y))
        family = self.list_family.get(self.list_family.curselection()[0])
        self.entry_family.delete(0, "end")
        self.entry_family.insert(0, family)
        self.entry_family.selection_clear()
        self.entry_family.icursor("end")
        self.change_font_family()

    def update_entry_size(self, event):
        """Update size entry when an item is selected in the size listbox."""
        #  size = self.list_size.get("@%i,%i" % (event.x , event.y))
        size = self.list_size.get(self.list_size.curselection()[0])
        self.var_size.set(size)
        self.change_font_size()

    def ok(self):
        """Validate choice."""
        self.res = self.preview_font.actual()
        self.quit()

    def get_res(self):
        """Return chosen font."""
        return self.res

    def quit(self):
        self.destroy()
Esempio n. 19
0
class myListBox(Frame):
    def __init__(self,
                 root,
                 items=[],
                 id='',
                 item_select_handler=default_item_select_handler,
                 smode=tki.EXTENDED):
        self.item_count = 0
        self.root = root
        self.item_select_handler = item_select_handler
        Frame.__init__(self, self.root)
        self.id = id
        vscrollbar = Scrollbar(self, orient=tki.VERTICAL)
        vscrollbar.pack(side=tki.RIGHT, fill=tki.Y)
        hscrollbar = Scrollbar(self, orient=tki.HORIZONTAL)
        hscrollbar.pack(side=tki.BOTTOM, fill=tki.X)
        ## mode can be: SINGLE, BROWSE, MULTIPLE, EXTENDED
        ##        selectmode
        ##
        ## Determines how many items can be selected, and how mouse drags affect the selection −
        ##
        ##    BROWSE − Normally, you can only select one line out of a listbox. If you click on an item and then drag to a different line, the selection will follow the mouse. This is the default.
        ##    SINGLE − You can only select one line, and you can't drag the mouse.wherever you click button 1, that line is selected.
        ##    MULTIPLE − You can select any number of lines at once. Clicking on any line toggles whether or not it is selected.
        ##    EXTENDED − You can select any adjacent group of lines at once by clicking on the first line and dragging to the last line.

        self.list = Listbox(self,
                            selectmode=smode,
                            exportselection=0,
                            xscrollcommand=hscrollbar.set,
                            yscrollcommand=vscrollbar.set)
        for i in items:
            assert (type(i) is str)
            self.list.insert(items.index(i), i)
        self.list.pack(fill=tki.BOTH, expand=1)
        self.list.bind('<Double-Button-1>', self.item_select_handler)
        self.list.bind('<1>', self.item_select_handler)
        self.list.bind('<Return>', self.item_select_handler)
        ## DO NOT catch ListboxSelect event, because:
        ##        a) it is not associated with (x_root, y_root) and (x,y) coordinates, so the popup appears always at (0,0) of the main root window
        ##        b) it duplicates the click event catching  self.list.bind( '<1>', self.item_select_handler ) and generates a second event
        ## self.list.bind( '<<ListboxSelect>>', self.item_select_handler )
        hscrollbar.config(command=self.list.xview)
        vscrollbar.config(command=self.list.yview)
        self.pack(side=tki.LEFT, fill=tki.BOTH, expand=1)
        self.current = self.list.curselection()

    def insert_item(self, pos, item):
        self.list.insert(pos, item)
        self.item_count += 1
        self.activate(pos)
        self.index(pos)

    def delete(self, start, end=None):
        assert (type(start) is int)
        if (end is None):
            self.list.delete(start)
            self.item_count -= 1
        else:
            assert ((type(end) is int) or (end == tki.END))
            if (type(end) is str):
                self.list.delete(start, (self.item_count - 1))
                self.item_count -= (self.item_count - start)
            else:
                self.list.delete(start, end)
                self.item_count -= (end - start) + 1

    def select_set(self, i):
        self.list.selection_clear(0, tki.END)
        self.list.select_set(i)

    def activate(self, i):
        self.list.activate(i)

    def index(self, i):
        self.list.index(i)

    def generate_select_event(self, pos=None):
        assert (pos is not None)
        if (pos is not None):
            self.activate(pos)
            self.index(pos)
            self.select_set(pos)
            self.list.event_generate("<<ListboxSelect>>")

##    def poll(self):
##        now = self.list.curselection()
##        if now != self.current:
##            self.list_has_changed( now )
##            self.current = now
##        self.after( 250, self.poll )

    def list_has_changed(self, selection):
        print('widget {0} selection is {1}'.format(self.id, selection))
Esempio n. 20
0
class FilePane:
    def __init__(self,
                 root,
                 items=list(),
                 on_selection=list(),
                 on_close=list()):
        self.items = items
        self.item_count = len(items)
        self.on_selection = on_selection
        self.on_close = on_close

        self.window = Toplevel()
        self.window.title('Files')
        self.window.transient(root)
        self.window.protocol("WM_DELETE_WINDOW", self.on_window_close)

        self.menubar = Menu(self.window)
        self.menubar.add_command(label='Previous', command=self.previous)
        self.menubar.add_command(label='Next', command=self.next)

        # Display the menu
        self.window.config(menu=self.menubar)

        self.scrollbar = Scrollbar(self.window, orient='vertical')
        self.listbox = Listbox(self.window,
                               yscrollcommand=self.scrollbar.set,
                               exportselection=False)
        self.set_items(items)
        self.scrollbar.config(command=self.listbox.yview)
        self.scrollbar.pack(side='right', fill='y')
        self.listbox.pack(side='left', fill='both', expand=1)

        self.listbox.bind('<<ListboxSelect>>', self.on_select)

    def on_window_close(self):
        for callback in self.on_close:
            callback()
        self.window.withdraw()

    def hide(self):
        self.window.withdraw()

    def show(self):
        self.window.deiconify()

    def selected_item(self):
        return self.items[self.listbox.curselection()[0]]

    def select_index(self, index):
        self.listbox.selection_clear(0, END)

        # From https://stackoverflow.com/a/25451279/11628429
        self.listbox.select_set(
            index)  #This only sets focus on the first item.
        self.listbox.event_generate("<<ListboxSelect>>")

    def set_items(self, items):
        self.items = items
        self.item_count = len(items)
        self.listbox.delete(0, END)

        for item in items:
            item = path.split(item)[1]
            self.listbox.insert(END, item)

        self.select_index(0)

    def previous(self):
        index = self.listbox.curselection()[0] - 1
        if index < 0:
            index = self.item_count - 1
        self.select_index(index)

    def next(self):
        index = self.listbox.curselection()[0] + 1
        if index >= self.item_count:
            index = 0
        self.select_index(index)

    def on_select(self, event):
        if self.on_selection:
            for callback in self.on_selection:
                callback(self.selected_item())
Esempio n. 21
0
class FontChooser(Toplevel):
    """ Font chooser toplevel """
    def __init__(self,
                 master,
                 font_dict={},
                 text="Abcd",
                 title="Font Chooser",
                 **kwargs):
        """
            Create a new FontChooser instance.

            font: dictionnary, like the one returned by the .actual
                  method of a Font object

                    {'family': 'DejaVu Sans',
                     'overstrike':False,
                     'size': 12,
                     'slant': 'italic' or 'roman',
                     'underline': False,
                     'weight': 'bold' or 'normal'}

            text: text to be displayed in the preview label

            title: window title

            **kwargs: additional keyword arguments to be passed to
                      Toplevel.__init__
        """
        Toplevel.__init__(self, master, **kwargs)
        self.title(title)
        self.resizable(False, False)
        self.protocol("WM_DELETE_WINDOW", self.quit)
        self._validate_family = self.register(self.validate_font_family)
        self._validate_size = self.register(self.validate_font_size)

        # variable storing the chosen font
        self.res = ""

        style = Style(self)
        style.configure("prev.TLabel", background="white")
        bg = style.lookup("TLabel", "background")
        self.configure(bg=bg)

        # family list
        self.fonts = list(set(families()))
        self.fonts.append("TkDefaultFont")
        self.fonts.sort()
        for i in range(len(self.fonts)):
            self.fonts[i] = self.fonts[i].replace(" ", "\ ")
        max_length = int(2.5 * max([len(font) for font in self.fonts])) // 3
        self.sizes = [
            "%i" % i for i in (list(range(6, 17)) + list(range(18, 32, 2)))
        ]
        # font default
        font_dict["weight"] = font_dict.get("weight", "normal")
        font_dict["slant"] = font_dict.get("slant", "roman")
        font_dict["family"] = font_dict.get("family",
                                            self.fonts[0].replace('\ ', ' '))
        font_dict["size"] = font_dict.get("size", 10)

        # Widgets creation
        options_frame = Frame(self, relief='groove', borderwidth=2)
        self.font_family = StringVar(self, " ".join(self.fonts))
        self.font_size = StringVar(self, " ".join(self.sizes))
        self.var_bold = BooleanVar(self, font_dict["weight"] == "bold")
        b_bold = Checkbutton(options_frame,
                             text=TR["Bold"],
                             command=self.toggle_bold,
                             variable=self.var_bold)
        b_bold.grid(row=0, sticky="w", padx=4, pady=(4, 2))
        self.var_italic = BooleanVar(self, font_dict["slant"] == "italic")
        b_italic = Checkbutton(options_frame,
                               text=TR["Italic"],
                               command=self.toggle_italic,
                               variable=self.var_italic)
        b_italic.grid(row=1, sticky="w", padx=4, pady=2)
        self.var_size = StringVar(self)
        self.entry_family = Entry(self,
                                  width=max_length,
                                  validate="key",
                                  validatecommand=(self._validate_family, "%d",
                                                   "%S", "%i", "%s", "%V"))
        entry_size = Entry(self,
                           width=4,
                           validate="key",
                           textvariable=self.var_size,
                           validatecommand=(self._validate_size, "%d", "%P",
                                            "%V"))
        self.list_family = Listbox(self,
                                   selectmode="browse",
                                   listvariable=self.font_family,
                                   highlightthickness=0,
                                   exportselection=False,
                                   width=max_length)
        self.list_size = Listbox(self,
                                 selectmode="browse",
                                 listvariable=self.font_size,
                                 highlightthickness=0,
                                 exportselection=False,
                                 width=4)
        scroll_family = Scrollbar(self,
                                  orient='vertical',
                                  command=self.list_family.yview)
        scroll_size = Scrollbar(self,
                                orient='vertical',
                                command=self.list_size.yview)
        self.preview_font = Font(self, **font_dict)
        if len(text) > 30:
            text = text[:30]
        self.preview = Label(self,
                             relief="groove",
                             style="prev.TLabel",
                             text=text,
                             font=self.preview_font,
                             anchor="center")

        # Widget configuration
        self.list_family.configure(yscrollcommand=scroll_family.set)
        self.list_size.configure(yscrollcommand=scroll_size.set)

        self.entry_family.insert(0, font_dict["family"])
        self.entry_family.selection_clear()
        self.entry_family.icursor("end")
        entry_size.insert(0, font_dict["size"])

        i = self.fonts.index(self.entry_family.get().replace(" ", "\ "))
        self.list_family.selection_clear(0, "end")
        self.list_family.selection_set(i)
        self.list_family.see(i)
        i = self.sizes.index(entry_size.get())
        self.list_size.selection_clear(0, "end")
        self.list_size.selection_set(i)
        self.list_size.see(i)

        self.entry_family.grid(row=0,
                               column=0,
                               sticky="ew",
                               pady=(10, 1),
                               padx=(10, 0))
        entry_size.grid(row=0,
                        column=2,
                        sticky="ew",
                        pady=(10, 1),
                        padx=(10, 0))
        self.list_family.grid(row=1,
                              column=0,
                              sticky="nsew",
                              pady=(1, 10),
                              padx=(10, 0))
        self.list_size.grid(row=1,
                            column=2,
                            sticky="nsew",
                            pady=(1, 10),
                            padx=(10, 0))
        scroll_family.grid(row=1, column=1, sticky='ns', pady=(1, 10))
        scroll_size.grid(row=1, column=3, sticky='ns', pady=(1, 10))
        options_frame.grid(row=0,
                           column=4,
                           rowspan=2,
                           padx=10,
                           pady=10,
                           ipadx=10)

        self.preview.grid(row=2,
                          column=0,
                          columnspan=5,
                          sticky="eswn",
                          padx=10,
                          pady=(0, 10),
                          ipadx=4,
                          ipady=4)

        button_frame = Frame(self)
        button_frame.grid(row=3, column=0, columnspan=5, pady=(0, 10), padx=10)

        Button(button_frame, text="Ok", command=self.ok).grid(row=0,
                                                              column=0,
                                                              padx=4,
                                                              sticky='ew')
        Button(button_frame, text=TR["Cancel"],
               command=self.quit).grid(row=0, column=1, padx=4, sticky='ew')
        self.list_family.bind('<<ListboxSelect>>', self.update_entry_family)
        self.list_size.bind('<<ListboxSelect>>',
                            self.update_entry_size,
                            add=True)
        self.list_family.bind("<KeyPress>", self.keypress)
        self.entry_family.bind("<Return>", self.change_font_family)
        self.entry_family.bind("<Tab>", self.tab)
        entry_size.bind("<Return>", self.change_font_size)

        self.entry_family.bind("<Down>", self.down_family)
        entry_size.bind("<Down>", self.down_size)

        self.entry_family.bind("<Up>", self.up_family)
        entry_size.bind("<Up>", self.up_size)

        # bind Ctrl+A to select all instead of go to beginning
        self.bind_class("TEntry", "<Control-a>", self.select_all)

        self.update_idletasks()
        self.grab_set()
        self.entry_family.focus_set()
        self.lift()

    def select_all(self, event):
        event.widget.selection_range(0, "end")

    def keypress(self, event):
        key = event.char.lower()
        l = [i for i in self.fonts if i[0].lower() == key]
        if l:
            i = self.fonts.index(l[0])
            self.list_family.selection_clear(0, "end")
            self.list_family.selection_set(i)
            self.list_family.see(i)
            self.update_entry_family()

    def up_family(self, event):
        try:
            txt = self.entry_family.get().replace(" ", "\ ")
            l = [i for i in self.fonts if i[:len(txt)] == txt]
            if l:
                self.list_family.selection_clear(0, "end")
                i = self.fonts.index(l[0])
                if i > 0:
                    self.list_family.selection_set(i - 1)
                    self.list_family.see(i - 1)
                else:
                    i = len(self.fonts)
                    self.list_family.see(i - 1)
                    self.list_family.select_set(i - 1)

        except TclError:
            i = len(self.fonts)
            self.list_family.see(i - 1)
            self.list_family.select_set(i - 1)
        self.list_family.event_generate('<<ListboxSelect>>')

    def up_size(self, event):
        try:
            s = self.var_size.get()
            i = self.sizes.index(s)
            self.list_size.selection_clear(0, "end")
            if i > 0:
                self.list_size.selection_set(i - 1)
                self.list_size.see(i - 1)
            else:
                i = len(self.sizes)
                self.list_size.see(i - 1)
                self.list_size.select_set(i - 1)
        except TclError:
            i = len(self.sizes)
            self.list_size.see(i - 1)
            self.list_size.select_set(i - 1)
        self.list_size.event_generate('<<ListboxSelect>>')

    def down_family(self, event):
        try:
            txt = self.entry_family.get().replace(" ", "\ ")
            l = [i for i in self.fonts if i[:len(txt)] == txt]
            if l:
                self.list_family.selection_clear(0, "end")
                i = self.fonts.index(l[0])
                if i < len(self.fonts) - 1:
                    self.list_family.selection_set(i + 1)
                    self.list_family.see(i + 1)
                else:
                    self.list_family.see(0)
                    self.list_family.select_set(0)

        except TclError:
            self.list_family.selection_set(0)
        self.list_family.event_generate('<<ListboxSelect>>')

    def down_size(self, event):
        try:
            s = self.var_size.get()
            i = self.sizes.index(s)
            self.list_size.selection_clear(0, "end")
            if i < len(self.sizes) - 1:
                self.list_size.selection_set(i + 1)
                self.list_size.see(i + 1)
            else:
                self.list_size.see(0)
                self.list_size.select_set(0)
        except TclError:
            self.list_size.selection_set(0)
        self.list_size.event_generate('<<ListboxSelect>>')

    def toggle_bold(self):
        b = self.var_bold.get()
        self.preview_font.configure(weight=["normal", "bold"][b])

    def toggle_italic(self):
        b = self.var_italic.get()
        self.preview_font.configure(slant=["roman", "italic"][b])

    def toggle_underline(self):
        b = self.var_underline.get()
        self.preview_font.configure(underline=b)

    def toggle_overstrike(self):
        b = self.var_overstrike.get()
        self.preview_font.configure(overstrike=b)

    def change_font_family(self, event=None):
        family = self.entry_family.get()
        if family.replace(" ", "\ ") in self.fonts:
            self.preview_font.configure(family=family)

    def change_font_size(self, event=None):
        size = int(self.var_size.get())
        self.preview_font.configure(size=size)

    def validate_font_size(self, d, ch, V):
        ''' Validation of the size entry content '''
        l = [i for i in self.sizes if i[:len(ch)] == ch]
        if l:
            i = self.sizes.index(l[0])
            self.list_size.selection_clear(0, "end")
            self.list_size.selection_set(i)
            deb = self.list_size.nearest(0)
            fin = self.list_size.nearest(self.list_size.winfo_height())
            if V != "forced":
                if i < deb or i > fin:
                    self.list_size.see(i)
                return True
        if d == '1':
            return ch.isdigit()
        else:
            return True

    def tab(self, event):
        self.entry_family = event.widget
        self.entry_family.selection_clear()
        self.entry_family.icursor("end")
        return "break"

    def validate_font_family(self, action, modif, pos, prev_txt, V):
        """ completion of the text in the path entry with existing
            folder/file names """
        if self.entry_family.selection_present():
            sel = self.entry_family.selection_get()
            txt = prev_txt.replace(sel, '')
        else:
            txt = prev_txt
        if action == "0":
            txt = txt[:int(pos)] + txt[int(pos) + 1:]
            return True
        else:
            txt = txt[:int(pos)] + modif + txt[int(pos):]
            ch = txt.replace(" ", "\ ")
            l = [i for i in self.fonts if i[:len(ch)] == ch]
            if l:
                i = self.fonts.index(l[0])
                self.list_family.selection_clear(0, "end")
                self.list_family.selection_set(i)
                deb = self.list_family.nearest(0)
                fin = self.list_family.nearest(self.list_family.winfo_height())
                index = self.entry_family.index("insert")
                self.entry_family.delete(0, "end")
                self.entry_family.insert(0, l[0].replace("\ ", " "))
                self.entry_family.selection_range(index + 1, "end")
                self.entry_family.icursor(index + 1)
                if V != "forced":
                    if i < deb or i > fin:
                        self.list_family.see(i)
                return True
            else:
                return False

    def update_entry_family(self, event=None):
        #  family = self.list_family.get("@%i,%i" % (event.x , event.y))
        family = self.list_family.get(self.list_family.curselection()[0])
        self.entry_family.delete(0, "end")
        self.entry_family.insert(0, family)
        self.entry_family.selection_clear()
        self.entry_family.icursor("end")
        self.change_font_family()

    def update_entry_size(self, event):
        #  size = self.list_size.get("@%i,%i" % (event.x , event.y))
        size = self.list_size.get(self.list_size.curselection()[0])
        self.var_size.set(size)
        self.change_font_size()

    def ok(self):
        self.res = self.preview_font.actual()
        self.quit()

    def get_res(self):
        return self.res

    def quit(self):
        self.destroy()