Esempio n. 1
0
class CustomSpinbox(Frame):
    def __init__(self,
                 master,
                 *args,
                 label="",
                 minimum=0,
                 maximum=9999,
                 **kwargs):
        super(CustomSpinbox, self).__init__(master, *args, **kwargs)
        self.minimum = minimum
        self.maximum = maximum if maximum > minimum else minimum + 1
        self.create_spinbox(label)
        self.register_filter()

    def create_spinbox(self, label):
        from tkinter import Label

        self.label = Label(self, text=label, width=LABEL_WIDTH)
        self.spinbox = Spinbox(self, from_=self.minimum, to=self.maximum)

        self.label.pack(side="left")
        self.spinbox.pack(side="left", fill="x", expand=True)

    def register_filter(self):
        tk = self.get_instance_tk(self)
        if tk:
            new_register = tk.register(self.filter_spinbox)
            self.spinbox.config(validate="key",
                                validatecommand=(new_register, "%P"))

    def filter_spinbox(self, value):
        if value.isdigit() and int(value) in range(self.minimum,
                                                   self.maximum + 1):
            return True
        if value == "":
            return True
        return False

    def get_instance_tk(self, widget):
        from tkinter import Tk

        if isinstance(widget, Tk):
            return widget
        else:
            master = self.get_instance_tk(widget.master)
            return master

    def set_label(self, label):
        self.label.config(text=label)

    def get_value(self):
        return int(self.spinbox.get())

    def set_value(self, value):
        if value in range(self.minimum, self.maximum + 1):
            self.spinbox.delete(0, "end")
            self.spinbox.insert("end", str(value))
Esempio n. 2
0
class TimeChooser(Frame):
    '''
    classdocs
    '''
    def __init__(self, parent, initialTime=None):
        super().__init__(parent)

        if initialTime is None:
            initialTime = datetime.now().time()

        self.hour = Spinbox(self, from_=1, to=12, width=3)
        self.hour.grid(column=0, row=0)
        Label(self, text=":").grid(column=1, row=0)
        self.minute = Spinbox(self, from_=00, to=59, format="%02.0f", width=3)
        self.minute.grid(column=2, row=0)
        self.ampm = Spinbox(self, values=("AM", "PM"), width=4)
        self.ampm.grid(column=3, row=0)

        # set AM/PM
        self.ampm.delete(0, "end")
        self.ampm.insert(0, "AM" if initialTime.hour < 12 else "PM")

        # set hour, 12-hour display
        self.hour.delete(0, "end")
        if initialTime.hour == 0:
            self.hour.insert(0, "12")
        elif initialTime.hour <= 12:
            self.hour.insert(0, str(initialTime.hour))
        else:
            self.hour.insert(0, str(initialTime.hour - 12))

        # set minute
        self.minute.delete(0, "end")
        self.minute.insert(0, "{:0>2d}".format(initialTime.minute))

        # readonly the entry widgets
        self.hour.config(state="readonly")
        self.minute.config(state="readonly")
        self.ampm.config(state="readonly")

    def getTime(self):
        hour = int(self.hour.get())
        if self.ampm.get() == "AM":
            hour %= 12
        elif hour < 12:
            hour += 12

        return time(hour=int(hour), minute=int(self.minute.get()))
Esempio n. 3
0
 def __init__(self,master=None):
     Frame.__init__(self,master)
     #Sides of Dice
     labelSides=Label(self,text="Sides")
     labelSides.grid(row=0,column=0)
     self.sides=StringVar()
     self.sides.set(20)
     spinboxSides=Spinbox(self,from_=1,to=20,increment=1,width=4)
     spinboxSides.config(textvariable=self.sides, font="sans 24", justify="center")
     spinboxSides.grid(row=0,column=1)
     #Number of Dices
     labelNumber=Label(self,text="Number")
     labelNumber.grid(row=1,column=0)
     self.number=StringVar()
     self.number.set(1)
     spinboxNumber=Spinbox(self,from_=1,to=30,increment=1,width=4)
     spinboxNumber.config(textvariable=self.number, font="sans 24", justify="center")
     spinboxNumber.grid(row=1,column=1)
     #Modifier
     labelModifier=Label(self,text="Modifier")
     labelModifier.grid(row=2,column=0)
     self.modifier=StringVar()
     self.modifier.set(0)
     spinboxModifier=Spinbox(self,from_=-5,to=5,increment=1,width=4)
     spinboxModifier.config(textvariable=self.modifier, font="sans 24", justify="center")
     spinboxModifier.grid(row=2,column=1)
     #Hide Checkbox
     labelHide=Label(self, text="Hide")
     labelHide.grid(row=2, column=2)
     self.hide=IntVar()
     self.hide.set(0)
     checkbuttonHide=Checkbutton(self,variable=self.hide)
     checkbuttonHide.grid(row=2,column=3)
     #Result display
     self.result=StringVar()
     self.result.set("")
     labelResult1=Label(self,text="Result")
     labelResult1.grid(row=1, column=4)
     labelResult2=Label(self,text=self.result.get(),relief=SUNKEN,width=4)
     labelResult2.grid(row=1,column=5)
     #Button to roll
     buttonRoll=Button(self,text="Roll!", command=self.roll)
     buttonRoll.grid(row=2,column=5)
Esempio n. 4
0
class ResizeImageDialog(CustomDialog):
    def __init__(self,
                 root,
                 width,
                 height,
                 maintain_aspect_ratio=False,
                 primary_dimension='width',
                 title="Resize",
                 on_change=list(),
                 on_cancel=list(),
                 on_confirm=list(),
                 **kwargs):
        self.init_width = width
        self.init_height = height
        self.init_maintain_aspect_ratio = maintain_aspect_ratio
        self.init_primary_dimension = primary_dimension
        self.on_change = on_change
        self.on_confirm = on_confirm
        self.on_cancel = on_cancel

        self.window = Toplevel()
        self.window.title(title)
        self.window.transient(root)
        self.window.grab_set()

        self.primary_dimension = StringVar()
        self.primary_dimension.set(primary_dimension)

        self.resize_mode = StringVar()
        self.resize_mode.set('percentage')

        self.resize_percentage = IntVar()
        self.resize_percentage.set(100.0)

        self.resize_width = IntVar()
        self.resize_width.set(width)
        self.resize_height = IntVar()
        self.resize_height.set(height)

        self.maintain_aspect_ratio = IntVar()

        # See https://stackoverflow.com/a/4140988/11628429
        self.vcmd_is_float = (self.window.register(self.is_float), '%P')
        self.vcmd_is_int = (self.window.register(self.is_int), '%P')

        self.percentage_radiobutton = Radiobutton(self.window,
                                                  text='By percentage',
                                                  value='percentage',
                                                  variable=self.resize_mode,
                                                  command=self.set_mode)
        self.percentage_radiobutton.grid(row=0, column=0)

        self.percentage_entry = Spinbox(self.window,
                                        from_=0,
                                        to=float('inf'),
                                        textvariable=self.resize_percentage,
                                        validate='all',
                                        validatecommand=self.vcmd_is_float)
        self.percentage_entry.grid(row=0, column=1)

        self.absolute_radiobutton = Radiobutton(self.window,
                                                text='By absolute value',
                                                value='absolute',
                                                variable=self.resize_mode,
                                                command=self.set_mode)
        self.absolute_radiobutton.grid(row=2, column=0)

        self.ratio_checkbox = Checkbutton(self.window,
                                          text='Maintain aspect ratio',
                                          variable=self.maintain_aspect_ratio,
                                          command=self.ratio_change)
        self.ratio_checkbox.grid(row=3, column=0)

        self.width_label = Label(self.window, text='Width')
        self.width_label.grid(row=5, column=0)

        self.width_entry = Spinbox(
            self.window,
            from_=0,
            to=float('inf'),
            textvariable=self.resize_width,
            validate='all',
            validatecommand=self.vcmd_is_int
        )  # needs a command to respect aspect ratio on change
        self.width_entry.grid(row=5, column=1)

        self.height_label = Label(self.window, text='Height')
        self.height_label.grid(row=6, column=0)

        self.height_entry = Spinbox(self.window,
                                    from_=0,
                                    to=float('inf'),
                                    textvariable=self.resize_height,
                                    validate='all',
                                    validatecommand=self.vcmd_is_int)
        self.height_entry.grid(row=6, column=1)

        self.cancel_button = Button(self.window,
                                    text='Cancel',
                                    command=self.cancel)
        self.cancel_button.grid(row=9, column=0)

        self.reset_button = Button(self.window,
                                   text='Reset',
                                   command=self.reset)
        self.reset_button.grid(row=9, column=1)

        self.confirm_button = Button(self.window,
                                     text='Confirm',
                                     command=self.confirm)
        self.confirm_button.grid(row=9, column=2)

        self.resize_percentage.trace('w', self.on_percentage_change)
        self.resize_width_trace_id = self.resize_width.trace(
            'w', self.on_width_change)
        self.resize_height_trace_id = self.resize_height.trace(
            'w', self.on_height_change)
        self.set_mode()

    def set_resize_width_without_trace(self, value):
        if not isinstance(value, int):
            raise TypeError('height should be an int')
        self.resize_width.trace_vdelete("w", self.resize_width_trace_id)
        self.resize_width.set(value)
        self.resize_width_trace_id = self.resize_width.trace(
            'w', self.on_width_change)

    def set_resize_height_without_trace(self, value):
        if not isinstance(value, int):
            raise TypeError('width should be an int')
        self.resize_height.trace_vdelete("w", self.resize_height_trace_id)
        self.resize_height.set(value)
        self.resize_height_trace_id = self.resize_height.trace(
            'w', self.on_height_change)

    def on_update(self, *args):
        mode = self.resize_mode.get()
        for callback in self.on_change:
            if mode == 'percentage':
                percentage = self.resize_percentage.get() / 100
                callback(percentage, percentage,
                         self.maintain_aspect_ratio.get(),
                         self.primary_dimension.get())
            else:
                callback(self.resize_width.get(), self.resize_height.get(),
                         self.maintain_aspect_ratio.get(),
                         self.primary_dimension.get())

    def on_percentage_change(self, *args):
        self.on_update()

    def on_width_change(self, *args):
        self.primary_dimension.set('width')
        if self.maintain_aspect_ratio.get():
            self.set_resize_height_without_trace(
                round(self.init_height *
                      (self.resize_width.get() / self.init_width)))
        self.on_update()

    def on_height_change(self, *args):
        self.primary_dimension.set('height')
        if self.maintain_aspect_ratio.get():
            self.set_resize_width_without_trace(
                round(self.init_width *
                      (self.resize_height.get() / self.init_height)))
        self.on_update()

    def reset(self):
        self.resize_percentage.set(100.0)
        self.set_resize_width_without_trace(self.init_width)
        self.set_resize_height_without_trace(self.init_height)
        self.maintain_aspect_ratio.set(self.init_maintain_aspect_ratio)
        self.primary_dimension.set(self.init_primary_dimension)
        self.on_update()

    def set_mode(self):
        mode = self.resize_mode.get()
        if mode == 'percentage':
            self.percentage_entry.config(state='normal')
            self.ratio_checkbox.config(state='disabled')
            self.width_label.config(state='disabled')
            self.width_entry.config(state='disabled')
            self.height_label.config(state='disabled')
            self.height_entry.config(state='disabled')
        else:
            self.percentage_entry.config(state='disabled')
            self.ratio_checkbox.config(state='normal')
            self.width_label.config(state='normal')
            self.width_entry.config(state='normal')
            self.height_label.config(state='normal')
            self.height_entry.config(state='normal')

    def is_float(self, P):
        try:
            float(P)
            return True
        except ValueError:
            return False

    def is_int(self, P):
        return str.isdecimal(P)

    def ratio_change(self):
        if self.maintain_aspect_ratio.get():
            if self.primary_dimension.get() == 'width':
                self.set_resize_height_without_trace(
                    round(self.init_height *
                          (self.resize_width.get() / self.init_width)))
            else:
                self.set_resize_width_without_trace(
                    round(self.init_width *
                          (self.resize_height.get() / self.init_height)))
            self.on_update()
        print(self.maintain_aspect_ratio.get())

        print('w', self.resize_width.get())
        print('h', self.resize_height.get())
Esempio n. 5
0
from tkinter import Tk, DoubleVar, Label, Spinbox
from functools import partial


def update_label(spinbox, label, var):
    """
    Écrit 'min' ou 'max' dans label en fonction de la valeur
    du textvariable de spinbox
    """
    value = var.get()
    if value == spinbox.cget('from'):
        label.config(text='Min')
    elif value == spinbox.cget('to'):
        label.config(text='Max')


root = Tk()
value = DoubleVar(root)
label = Label(text=4)
spinbox = Spinbox(root, textvariable=value, from_=4, to=8, increment=0.5)
spinbox.config(command=partial(update_label, spinbox, label, value))

spinbox.grid(row=0, column=0)
label.grid(row=1, column=0)

root.mainloop()
    class ResizeAndCompressingWindow:
        def __init__(self, parent):
            self.parent = parent
            self.frame0 = Frame(self.parent)
            self.title = Label(self.frame0,
                               text='Resize and compressing',
                               font='arial 20')
            self.BackButton = Button(self.title,
                                     text='<< Back',
                                     background='#888',
                                     foreground='#000',
                                     padx='2',
                                     pady='0',
                                     command=self.parent.init_menu_window)
            self.frame1 = Frame(self.parent)
            self.DirectoryLabel = Label(self.frame1, text='Directory', width=6)
            self.directory = StringVar()
            self.directory.set(os.getcwd())
            self.DirectoryEntry = Entry(self.frame1,
                                        textvariable=self.directory)
            self.BrowseButton = Button(
                self.frame1,
                text='Browse',
                background='#888',
                foreground='#000',
                padx='2',
                pady='0',
                width='10',
                command=lambda: self.directory.set(
                    filedialog.askdirectory(
                        parent=self.parent,
                        initialdir=self.directory.get,
                        title='Please select a folder with images:')))
            self.frame2 = Frame(self.parent)
            self.MethodLabel = Label(self.frame2, text='Resizing method')
            self.method_listbox = Listbox(self.frame2, exportselection=False)
            methods = ['Scale', 'Fit', 'Cover', 'Thumb']
            for method in methods:
                self.method_listbox.insert('end', method)
            self.method_listbox.bind('<<ListboxSelect>>', self.on_select)
            self.frame3 = Frame(self.parent)
            self.SizeLabelText = StringVar()
            self.SizeLabelText.set('Change resize method!')
            self.SizeLabel = Label(self.frame3,
                                   textvariable=self.SizeLabelText,
                                   justify='left')
            self.HeightFrame = Frame(self.frame3)
            self.HeightLabel = Label(self.HeightFrame,
                                     justify='left',
                                     text='Height:')
            listvalues = ['']
            listvalues.extend(range(1, 9999 + 1, 1))
            validate_int_val = (self.parent.register(Window.validate_int_val),
                                '%d', '%i', '%P', '%s', '%S', '%v', '%V', '%W')
            self.HeightSpinbox = Spinbox(self.HeightFrame,
                                         values=listvalues,
                                         state='disabled',
                                         validate='all',
                                         validatecommand=validate_int_val)
            self.WidthFrame = Frame(self.frame3)
            self.WidthLabel = Label(self.WidthFrame,
                                    justify='left',
                                    text='Width:')
            self.WidthSpinbox = Spinbox(self.WidthFrame,
                                        values=listvalues,
                                        state='disabled',
                                        validate='all',
                                        validatecommand=validate_int_val)
            self.StartButton = Button(
                self.frame3,
                text='Start',
                background='#888',
                foreground='#000',
                padx='2',
                pady='0',
                width='10',
                command=self.start_resize_and_compressing,
                state='disabled')

        def show(self):
            self.frame0.pack(fill='x')
            self.BackButton.pack(side='left')
            self.title.pack(fill='x', pady=5, ipady=4)
            self.frame1.pack(fill='x')
            self.DirectoryLabel.pack(side='left', padx=5, pady=5)
            self.DirectoryEntry.pack(side='left',
                                     padx=5,
                                     expand=True,
                                     fill='x')
            self.BrowseButton.pack(side='left')
            self.frame2.pack(side='left', padx=3, pady=10)
            self.MethodLabel.pack()
            self.method_listbox.pack()
            self.frame3.pack(fill='x', padx=3, pady=10)
            self.SizeLabel.pack(fill='x', ipady=10)
            self.HeightFrame.pack(fill='x')
            self.HeightLabel.pack(side='left', padx=5)
            self.HeightSpinbox.pack(side='left', padx=6)
            self.WidthFrame.pack(fill='x')
            self.WidthLabel.pack(side='left', padx=5)
            self.WidthSpinbox.pack(side='left', padx=10)
            self.StartButton.pack(fill='x',
                                  pady=10,
                                  ipady=10,
                                  side='bottom',
                                  expand=True)

        def on_select(self, event):
            widget = event.widget
            selection = widget.curselection()
            try:
                value = widget.get(selection[0])
            except IndexError:
                return
            if value == 'Scale':
                self.SizeLabelText.set(
                    'You must provide either a target width or a target height,\nbut not both.'
                )
            else:
                self.SizeLabelText.set(
                    'You must provide both a width and a height.')
            self.HeightSpinbox.config(state='normal')
            self.WidthSpinbox.config(state='normal')
            self.StartButton.config(state='normal')

        def start_resize_and_compressing(self):
            try:
                method = self.method_listbox.get(
                    self.method_listbox.curselection())
            except TclError:
                messagebox.showerror('Error!', 'Change resize Method.')
                return
            height = self.HeightSpinbox.get()
            width = self.WidthSpinbox.get()
            processing_thread = threading.Thread(target=tPNG.start_compressing,
                                                 args=(self.parent,
                                                       self.directory.get(),
                                                       method, height, width))
            processing_thread.daemon = True
            message = 'Start resize and compressing process?\n\nParameters:\nMethod : ' + method
            if height != '':
                message += '\nHeight: ' + height
            if width != '':
                message += '\nWidth: ' + width
            if height == '' or width == '':
                if method != 'Scale':
                    Window.error_message('need_width_and_height')
                elif height == '' and width == '':
                    Window.error_message('need_width_or_height')
                elif messagebox.askyesno(title='Start?', message=message):
                    processing_thread.start()
            elif method == 'Scale':
                Window.error_message('need_width_or_height')
            elif messagebox.askyesno(title='Start?', message=message):
                processing_thread.start()
Esempio n. 7
0
class NavigationForTableFrame(Frame):
    ''' This class is responsible for navigation over the table object.
        Table rows are displayed page by page.
        This class provides buttons that allow to navigate from page
        to page.

        Attributes:
            table (TableFrame or any object that has attribute nb_rows and
                implements display_data method): table that should be navigated.
            goto_spin (Spinbox): Spinbox widget that allows to enter page
                number and to switch between pages.
            text_var_nb_pages (StringVar): text variable that shows total
                number of pages.
            current_page_str (StringVar): text variable that stores
                currently displayed page.

        Args:
            parent (Tk object): parent for this frame.
            table (TableFrameWithInputOutputBox): table with multiple pages that
                will be navigated by this frame.
    '''
    def __init__(self, parent, table, *args, **kw):
        super().__init__(parent, *args, **kw)
        self.table = table
        self.goto_spin = None
        self.text_var_nb_pages = StringVar()
        self.current_page_str = StringVar()
        self.create_widgets()

    def create_widgets(self):
        ''' Creates all necessary widgets for navigation.
        '''
        prev_btn = Button(self,
                          text='<<',
                          width=5,
                          command=self.show_prev_page)
        prev_btn.grid(row=0, column=0, sticky=N, padx=3)
        next_btn = Button(self,
                          text='>>',
                          width=5,
                          command=self.show_next_page)
        next_btn.grid(row=0, column=1, sticky=N)
        goto_lbl = Label(self, text='Go to')
        goto_lbl.grid(row=0, column=3, sticky=N, padx=5)

        self.goto_spin = Spinbox(self,
                                 width=7,
                                 from_=1,
                                 to=1,
                                 textvariable=self.current_page_str,
                                 command=self.on_page_change)

        self.goto_spin.bind('<Return>', self.on_page_change)
        self.goto_spin.grid(row=0, column=4, sticky=N, padx=5)
        nb_pages_lb = Label(self, textvariable=self.text_var_nb_pages)
        nb_pages_lb.grid(row=0, column=5, sticky=W + N, padx=5)
        self.reset_navigation()

    def show_prev_page(self):
        ''' Displays previous page.

            This method is called when user presses button '<<'.
            If the first page is currently displayed and the method is called,
            then the call to this method is ignored.
        '''
        prev_page_index = int(self.current_page_str.get()) - 1
        if prev_page_index > 0:
            self.current_page_str.set(prev_page_index)
            self.on_page_change()

    def show_next_page(self):
        ''' Displays next page.

            This method is called when user presses button '>>'.
            If the last page is currently displayed and the method is called,
            then the call to this method is ignored.
        '''
        next_page_index = int(self.current_page_str.get()) + 1
        if next_page_index <= int(self.goto_spin.cget('to')):
            self.current_page_str.set(next_page_index)
            self.on_page_change()

    def on_page_change(self, *args):
        ''' Displays a page which number is currently stored in
            current_page_str.

            This method is called in show_next_page(), show_prev_page() and
            when the user enters data and presses Enter.
            args are supplied by Return event.
            If the entered value is invalid, then the first page is displayed.
            If the entered value is zero or negative, then the first page is
            isplayed.
            If the entered value is larger than the total number of pages,
            then the last page is displayed.
        '''
        try:
            curr_page = int(self.current_page_str.get())
        except ValueError:
            curr_page = 1
            self.current_page_str.set(curr_page)

        max_page = int(self.goto_spin.cget('to'))
        if curr_page > max_page:
            curr_page = max_page
            self.current_page_str.set(curr_page)
        if curr_page <= 0:
            curr_page = 1
            self.current_page_str.set(curr_page)
        # second -1 because row indeces start with 0
        row_index = calculate_start_row_index(curr_page, self.table.nb_rows)

        self.table.display_data(row_index)

    def reset_navigation(self):
        ''' Resets navigation parameters.

            Sets current page number to 1 and total number of pages to zero.
        '''
        self.current_page_str.set('1')
        self.text_var_nb_pages.set('1 pages')
        self.goto_spin.config(to=1)

    def set_navigation(self, nb_data_pages, reset_curr_page=True):
        ''' Sets navigation parameters.

            Sets current page number to 1 and total number of pages
            to nb_data_pages.

            Args:
                nb_data_pages (int): new value for the total number of pages.
                reset_curr_page (bool): True is current page must be reset to 1,
                    False otherwise.
        '''
        self.goto_spin.config(to=nb_data_pages)
        if reset_curr_page:
            self.current_page_str.set('1')
        self.text_var_nb_pages.set('{0} pages'.format(nb_data_pages))
class NavigationForTableFrame(Frame):
    ''' This class is responsible for navigation over the table object.
        Table rows are displayed page by page.
        This class provides buttons that allow to navigate from page
        to page.

        Attributes:
            table (TableFrame or any object that has attribute nb_rows and
                implements display_data method): table that should be navigated.
            goto_spin (Spinbox): Spinbox widget that allows to enter page
                number and to switch between pages.
            text_var_nb_pages (StringVar): text variable that shows total
                number of pages.
            current_page_str (StringVar): text variable that stores
                currently displayed page.

        Args:
            parent (Tk object): parent for this frame.
            table (TableFrameWithInputOutputBox): table with multiple pages that
                will be navigated by this frame.
    '''
    def __init__(self, parent, table, *args, **kw):
        super().__init__(parent, *args, **kw)
        self.table = table
        self.goto_spin = None
        self.text_var_nb_pages = StringVar()
        self.current_page_str = StringVar()
        self.create_widgets()

    def create_widgets(self):
        ''' Creates all necessary widgets for navigation.
        '''
        prev_btn = Button(self, text='<<', width=5,
                          command=self.show_prev_page)
        prev_btn.grid(row=0, column=0, sticky=N, padx=3)
        next_btn = Button(self, text='>>', width=5,
                          command=self.show_next_page)
        next_btn.grid(row=0, column=1, sticky=N)
        goto_lbl = Label(self, text='Go to')
        goto_lbl.grid(row=0, column=3, sticky=N, padx=5)

        self.goto_spin = Spinbox(self, width=7, from_=1, to=1,
                                 textvariable=self.current_page_str,
                                 command=self.on_page_change)

        self.goto_spin.bind('<Return>', self.on_page_change)
        self.goto_spin.grid(row=0, column=4, sticky=N, padx=5)
        nb_pages_lb = Label(self, textvariable=self.text_var_nb_pages)
        nb_pages_lb.grid(row=0, column=5, sticky=W+N, padx=5)
        self.reset_navigation()

    def show_prev_page(self):
        ''' Displays previous page.

            This method is called when user presses button '<<'.
            If the first page is currently displayed and the method is called,
            then the call to this method is ignored.
        '''
        prev_page_index = int(self.current_page_str.get()) - 1
        if prev_page_index > 0:
            self.current_page_str.set(prev_page_index)
            self.on_page_change()

    def show_next_page(self):
        ''' Displays next page.

            This method is called when user presses button '>>'.
            If the last page is currently displayed and the method is called,
            then the call to this method is ignored.
        '''
        next_page_index = int(self.current_page_str.get()) + 1
        if next_page_index <= int(self.goto_spin.cget('to')):
            self.current_page_str.set(next_page_index)
            self.on_page_change()

    def on_page_change(self, *args):
        ''' Displays a page which number is currently stored in
            current_page_str.

            This method is called in show_next_page(), show_prev_page() and
            when the user enters data and presses Enter.
            args are supplied by Return event.
            If the entered value is invalid, then the first page is displayed.
            If the entered value is zero or negative, then the first page is
            isplayed.
            If the entered value is larger than the total number of pages,
            then the last page is displayed.
        '''
        try:
            curr_page = int(self.current_page_str.get())
        except ValueError:
            curr_page = 1
            self.current_page_str.set(curr_page)

        max_page = int(self.goto_spin.cget('to'))
        if curr_page > max_page:
            curr_page = max_page
            self.current_page_str.set(curr_page)
        if curr_page <= 0:
            curr_page = 1
            self.current_page_str.set(curr_page)
        # second -1 because row indeces start with 0
        row_index = calculate_start_row_index(curr_page, self.table.nb_rows)

        self.table.display_data(row_index)

    def reset_navigation(self):
        ''' Resets navigation parameters.

            Sets current page number to 1 and total number of pages to zero.
        '''
        self.current_page_str.set('1')
        self.text_var_nb_pages.set('1 pages')
        self.goto_spin.config(to=1)

    def set_navigation(self, nb_data_pages, reset_curr_page=True):
        ''' Sets navigation parameters.

            Sets current page number to 1 and total number of pages
            to nb_data_pages.

            Args:
                nb_data_pages (int): new value for the total number of pages.
                reset_curr_page (bool): True is current page must be reset to 1,
                    False otherwise.
        '''
        self.goto_spin.config(to=nb_data_pages)
        if reset_curr_page:
            self.current_page_str.set('1')
        self.text_var_nb_pages.set('{0} pages'.format(nb_data_pages))
class SettingsFrame(Frame):
    """
    Settings frame class.
    """
    def __init__(self, app, *args, **kwargs):
        """
        Constructor.

        :param Frame app: reference to main tkinter application
        :param args: optional args to pass to Frame parent class
        :param kwargs: optional kwargs to pass to Frame parent class
        """

        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)

        self._protocol = IntVar()
        self._raw = IntVar()
        self._autoscroll = IntVar()
        self._maxlines = IntVar()
        self._webmap = IntVar()
        self._mapzoom = IntVar()
        self._units = StringVar()
        self._format = StringVar()
        self._datalog = IntVar()
        self._logformat = StringVar()
        self._record_track = IntVar()
        self._show_zerosig = IntVar()
        self._show_legend = IntVar()
        self._validsettings = True
        self._in_filepath = None
        self._logpath = None
        self._trackpath = None
        self._img_conn = ImageTk.PhotoImage(Image.open(ICON_CONN))
        self._img_disconn = ImageTk.PhotoImage(Image.open(ICON_DISCONN))
        self._img_ubxconfig = ImageTk.PhotoImage(Image.open(ICON_UBXCONFIG))
        self._img_dataread = ImageTk.PhotoImage(Image.open(ICON_LOGREAD))

        self._body()
        self._do_layout()
        self._reset()

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

        for i in range(4):
            self.grid_columnconfigure(i, weight=1)
        self.grid_rowconfigure(0, weight=1)

        self.option_add("*Font", self.__app.font_sm)

        # serial port configuration panel
        self._frm_serial = SerialConfigFrame(self,
                                             preselect=KNOWNGPS,
                                             timeouts=TIMEOUTS,
                                             bpsrates=BPSRATES)

        # connection buttons
        self._frm_buttons = Frame(self)
        self._btn_connect = Button(
            self._frm_buttons,
            width=45,
            height=35,
            image=self._img_conn,
            command=lambda: self.__app.serial_handler.connect(),
        )
        self._btn_disconnect = Button(
            self._frm_buttons,
            width=45,
            height=35,
            image=self._img_disconn,
            command=lambda: self.__app.serial_handler.disconnect(),
            state=DISABLED,
        )
        self._btn_connect_file = Button(
            self._frm_buttons,
            width=45,
            height=35,
            image=self._img_dataread,
            command=lambda: self._on_data_stream(),
        )
        self._lbl_status_preset = Label(self._frm_buttons,
                                        font=self.__app.font_md2,
                                        text="")

        # Other configuration options
        self._frm_options = Frame(self)
        self._lbl_protocol = Label(self._frm_options, text=LBLPROTDISP)
        self._rad_nmea = Radiobutton(self._frm_options,
                                     text="NMEA",
                                     variable=self._protocol,
                                     value=NMEA_PROTOCOL)
        self._rad_ubx = Radiobutton(self._frm_options,
                                    text="UBX",
                                    variable=self._protocol,
                                    value=UBX_PROTOCOL)
        self._rad_all = Radiobutton(self._frm_options,
                                    text="ALL",
                                    variable=self._protocol,
                                    value=MIXED_PROTOCOL)
        self._lbl_consoledisplay = Label(self._frm_options, text=LBLDATADISP)
        self._rad_parsed = Radiobutton(self._frm_options,
                                       text="Parsed",
                                       variable=self._raw,
                                       value=0)
        self._rad_raw = Radiobutton(self._frm_options,
                                    text="Raw",
                                    variable=self._raw,
                                    value=1)
        self._lbl_format = Label(self._frm_options, text="Degrees Format")
        self._spn_format = Spinbox(
            self._frm_options,
            values=(DDD, DMS, DMM),
            width=6,
            state=READONLY,
            readonlybackground=ENTCOL,
            wrap=True,
            textvariable=self._format,
        )
        self._lbl_units = Label(self._frm_options, text="Units")
        self._spn_units = Spinbox(
            self._frm_options,
            values=(UMM, UIK, UI, UMK),
            width=13,
            state=READONLY,
            readonlybackground=ENTCOL,
            wrap=True,
            textvariable=self._units,
        )
        self._chk_scroll = Checkbutton(self._frm_options,
                                       text="Autoscroll",
                                       variable=self._autoscroll)
        self._spn_maxlines = Spinbox(
            self._frm_options,
            values=("100", "200", "500", "1000", "2000"),
            width=6,
            readonlybackground=ENTCOL,
            wrap=True,
            textvariable=self._maxlines,
            state=READONLY,
        )
        self._chk_webmap = Checkbutton(
            self._frm_options,
            text="Web Map    Zoom",
            variable=self._webmap,
            command=lambda: self._on_webmap(),
        )
        self._scl_mapzoom = Scale(
            self._frm_options,
            from_=1,
            to=20,
            orient=HORIZONTAL,
            relief="sunken",
            bg=ENTCOL,
            variable=self._mapzoom,
        )
        self._chk_zerosig = Checkbutton(self._frm_options,
                                        text=LBLSHOWNULL,
                                        variable=self._show_zerosig)
        self._chk_legend = Checkbutton(self._frm_options,
                                       text=LBLLEGEND,
                                       variable=self._show_legend)
        self._chk_datalog = Checkbutton(
            self._frm_options,
            text=LBLDATALOG,
            variable=self._datalog,
            command=lambda: self._on_data_log(),
        )
        self._spn_datalog = Spinbox(
            self._frm_options,
            values=("Raw", "Parsed", "Both"),
            width=7,
            readonlybackground=ENTCOL,
            wrap=True,
            textvariable=self._logformat,
            state=READONLY,
        )
        self._chk_recordtrack = Checkbutton(
            self._frm_options,
            text=LBLTRACKRECORD,
            variable=self._record_track,
            command=lambda: self._on_record_track(),
        )
        self._lbl_ubxconfig = Label(self._frm_options, text=LBLUBXCONFIG)
        self._btn_ubxconfig = Button(
            self._frm_options,
            width=45,
            height=35,
            text="UBX",
            image=self._img_ubxconfig,
            command=lambda: self._on_ubx_config(),
            state=DISABLED,
        )

    def _do_layout(self):
        """
        Position widgets in frame.
        """

        self._frm_serial.grid(column=0,
                              row=1,
                              columnspan=4,
                              padx=3,
                              pady=3,
                              sticky=(W, E))
        ttk.Separator(self).grid(column=0,
                                 row=2,
                                 columnspan=4,
                                 padx=3,
                                 pady=3,
                                 sticky=(W, E))

        self._frm_buttons.grid(column=0, row=3, columnspan=4, sticky=(W, E))
        self._btn_connect.grid(column=0, row=0, padx=3, pady=3)
        self._btn_connect_file.grid(column=1, row=0, padx=3, pady=3)
        self._btn_disconnect.grid(column=3, row=0, padx=3, pady=3)

        ttk.Separator(self).grid(column=0,
                                 row=7,
                                 columnspan=4,
                                 padx=3,
                                 pady=3,
                                 sticky=(W, E))

        self._frm_options.grid(column=0, row=8, columnspan=4, sticky=(W, E))
        self._lbl_protocol.grid(column=0, row=0, padx=3, pady=3, sticky=(W))
        self._rad_nmea.grid(column=1, row=0, padx=0, pady=0, sticky=(W))
        self._rad_ubx.grid(column=2, row=0, padx=0, pady=0, sticky=(W))
        self._rad_all.grid(column=3, row=0, padx=0, pady=0, sticky=(W))
        self._lbl_consoledisplay.grid(column=0,
                                      row=1,
                                      padx=2,
                                      pady=3,
                                      sticky=(W))
        self._rad_parsed.grid(column=1, row=1, padx=1, pady=3, sticky=(W))
        self._rad_raw.grid(column=2, row=1, padx=2, pady=3, sticky=(W))
        self._lbl_format.grid(column=0, row=2, padx=3, pady=3, sticky=(W))
        self._spn_format.grid(column=1, row=2, padx=2, pady=3, sticky=(W))
        self._lbl_units.grid(column=0, row=3, padx=3, pady=3, sticky=(W))
        self._spn_units.grid(column=1,
                             row=3,
                             columnspan=3,
                             padx=2,
                             pady=3,
                             sticky=(W))
        self._chk_scroll.grid(column=0, row=4, padx=3, pady=3, sticky=(W))
        self._spn_maxlines.grid(column=1,
                                row=4,
                                columnspan=3,
                                padx=3,
                                pady=3,
                                sticky=(W))
        self._chk_webmap.grid(column=0, row=5, padx=3, pady=3, sticky=(W))
        self._scl_mapzoom.grid(column=1, row=5, columnspan=3, sticky=(W))
        self._chk_legend.grid(column=0, row=6, padx=3, pady=3, sticky=(W))
        self._chk_zerosig.grid(column=1,
                               row=6,
                               columnspan=2,
                               padx=3,
                               pady=3,
                               sticky=(W))
        self._chk_datalog.grid(column=0, row=7, padx=3, pady=3, sticky=(W))
        self._spn_datalog.grid(column=1, row=7, padx=3, pady=3, sticky=(W))
        self._chk_recordtrack.grid(column=0,
                                   row=8,
                                   columnspan=2,
                                   padx=3,
                                   pady=3,
                                   sticky=(W))

        ttk.Separator(self._frm_options).grid(column=0,
                                              row=9,
                                              columnspan=4,
                                              padx=3,
                                              pady=3,
                                              sticky=(W, E))
        self._lbl_ubxconfig.grid(column=0, row=10, padx=3, pady=3, sticky=(W))
        self._btn_ubxconfig.grid(column=1, row=10, padx=3, pady=3, sticky=(W))

    def _on_ubx_config(self, *args, **kwargs):  # pylint: disable=unused-argument
        """
        Open UBX configuration dialog panel.
        """

        self.__app.ubxconfig()

    def _on_webmap(self):
        """
        Reset webmap refresh timer
        """

        self.__app.frm_mapview.reset_map_refresh()

    def _on_data_log(self):
        """
        Start or stop data logger
        """

        if self._datalog.get() == 1:
            self._logpath = self.__app.file_handler.set_logfile_path()
            if self._logpath is not None:
                self.__app.set_status("Data logging enabled: " + self._logpath,
                                      "green")
            else:
                self._datalog.set(False)
        else:
            self._logpath = None
            self._datalog.set(False)
            #             self.__app.file_handler.close_logfile()
            self.__app.set_status("Data logging disabled", "blue")

    def _on_record_track(self):
        """
        Start or stop track recorder
        """

        if self._record_track.get() == 1:
            self._trackpath = self.__app.file_handler.set_trackfile_path()
            if self._trackpath is not None:
                self.__app.set_status(
                    "Track recording enabled: " + self._trackpath, "green")
            else:
                self._record_track.set(False)
        else:
            self._trackpath = None
            self._record_track.set(False)
            #             self.__app.file_handler.close_trackfile()
            self.__app.set_status("Track recording disabled", "blue")

    def _on_data_stream(self):
        """
        Start data file streamer
        """

        self._in_filepath = self.__app.file_handler.open_infile()
        if self._in_filepath is not None:
            self.__app.set_status("")
            self.__app.serial_handler.connect_file()

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

        self._protocol.set(MIXED_PROTOCOL)
        self._format.set(DDD)
        self._units.set(UMM)
        self._autoscroll.set(1)
        self._maxlines.set(300)
        self._raw.set(False)
        self._webmap.set(False)
        self._mapzoom.set(10)
        self._show_legend.set(True)
        self._show_zerosig.set(False)
        self._datalog.set(False)
        self._record_track.set(False)

    def enable_controls(self, status: int):
        """
        Public method to enable and disable those controls
        which depend on connection status.

        :param int status: connection status as integer
               (0=Disconnected, 1=Connected to serial,
               2=Connected to file, 3=No serial ports available)

        """

        self._frm_serial.set_status(status)

        self._btn_connect.config(
            state=(DISABLED if status in (CONNECTED, CONNECTED_FILE,
                                          NOPORTS) else NORMAL))
        self._btn_disconnect.config(
            state=(DISABLED if status in (DISCONNECTED, NOPORTS) else NORMAL))
        self._chk_datalog.config(
            state=(DISABLED if status in (CONNECTED, CONNECTED_FILE,
                                          NOPORTS) else NORMAL))
        self._spn_datalog.config(
            state=(DISABLED if status in (CONNECTED, CONNECTED_FILE,
                                          NOPORTS) else READONLY))
        self._chk_recordtrack.config(
            state=(DISABLED if status in (CONNECTED,
                                          CONNECTED_FILE) else NORMAL))
        self._btn_connect_file.config(
            state=(DISABLED if status in (CONNECTED,
                                          CONNECTED_FILE) else NORMAL))
        self._btn_ubxconfig.config(
            state=(DISABLED if status in (DISCONNECTED, CONNECTED_FILE,
                                          NOPORTS) else NORMAL))
        self.__app.menu.options_menu.entryconfig(
            0,
            state=(DISABLED if status in (CONNECTED_FILE, DISCONNECTED,
                                          NOPORTS) else NORMAL),
        )

    def get_size(self) -> (int, int):
        """
        Get current frame size.

        :return: (width, height)
        :rtype: tuple

        """

        self.update_idletasks()  # Make sure we know about any resizing
        return (self.winfo_width(), self.winfo_height())

    def serial_settings(self) -> Frame:
        """
        Return reference to common serial configuration panel

        :return: reference to serial form
        :rtype: Frame
        """

        return self._frm_serial

    @property
    def protocol(self) -> int:
        """
        Getter for displayed protocols

        :return: protocol displayed (0=NMEA, 1=UBX, 2=BOTH)
        :rtype: int
        """

        return self._protocol.get()

    @property
    def raw(self) -> int:
        """
        Getter for console display format

        :return: display format (0 - parsed, 1 = raw)
        :rtype: int
        """

        return self._raw.get()

    @property
    def autoscroll(self) -> int:
        """
        Getter for autoscroll flag

        :return: scroll setting (0 = no scroll, 1 = auto)
        :rtype: int
        """

        return self._autoscroll.get()

    @property
    def maxlines(self) -> int:
        """
        Getter for max console display lines

        :return: max lines in console display (default=300)
        :rtype: int
        """

        return self._maxlines.get()

    @property
    def webmap(self) -> int:
        """
        Getter for webmap flag

        :return: map type (0 = static map, 1 = dynamic web map)
        :rtype: int
        """

        return self._webmap.get()

    @property
    def mapzoom(self) -> int:
        """
        Getter for webmap zoom level

        :return: webmap zoom level (1-20)
        :rtype: int
        """

        return self._mapzoom.get()

    @property
    def units(self) -> int:
        """
        Getter for display units

        :return: "UMM" = metric m/s, "UMK" = metric kmph,
                 "UI" = imperial mph, "UIK" = imperial knots
        :rtype: int
        """

        return self._units.get()

    @property
    def format(self) -> str:
        """
        Getter for degrees format

        :return: "DD.D" = decimal degrees, "DM.M" = degrees, decimal minutes,
                 "D.M.S" = degrees, minutes, seconds
        :rtype: str
        """

        return self._format.get()

    @property
    def infilepath(self) -> str:
        """
        Getter for input file path

        :return: input file path
        :rtype: str
        """

        return self._in_filepath

    @property
    def outfilepath(self) -> str:
        """
        Getter for output file path

        :return: output file path
        :rtype: str
        """

        return self._logpath

    @property
    def datalogging(self) -> int:
        """
        Getter for datalogging flag

        :return: 0 = no log, 1 = record datalog
        :rtype: int
        """

        return self._datalog.get()

    @property
    def logformat(self) -> str:
        """
        Getter for datalogging format

        :return: "Raw", "Parsed", "Both"
        :rtype: str
        """

        return self._logformat.get()

    @property
    def record_track(self) -> int:
        """
        Getter for record track flag

        :return: 0 = no track, 1 = record track
        :rtype: int
        """

        return self._record_track.get()

    @property
    def show_zero(self) -> int:
        """
        Getter for zero signal flag

        :return: 0 = exclude, 1 = include
        :rtype: int
        """

        return self._show_zerosig.get()

    @property
    def show_legend(self) -> int:
        """
        Getter for graph legend flag

        :return: 0 = hide, 1 = show
        :rtype: int
        """

        return self._show_legend.get()
Esempio n. 10
0
class Application(Frame):
    def __init__(self, master=None):
        """ Main GUI."""
        Frame.__init__(self, master)
        Frame.grid(self, padx=(40, 40), pady=(10, 10))

        self.path1 = StringVar()
        path1_lbl = ttk.Label(self, text='Path:')
        path1_lbl.grid(column=1, columnspan=4, row=1, sticky=W)
        path1_entry = ttk.Entry(self, width=30, textvariable=self.path1)
        path1_entry.grid(column=1, columnspan=4, row=2, sticky=(W, E))
        path1_btn = ttk.Button(self, text="Browse", command=self.open1)
        path1_btn.grid(column=1, row=3, sticky=W, padx=(0, 0))

        self.graph1_btn = ttk.Button(self,
                                     text="Graph",
                                     state=DISABLED,
                                     command=lambda: self.graph1(self.C, 1))
        self.graph1_btn.grid(column=2, row=3, sticky=W)

        self.info1_lbl = ttk.Label(self, text='Scan Info/Comments:')
        self.info1_lbl.grid(column=1,
                            columnspan=4,
                            row=5,
                            sticky=W,
                            pady=(10, 0))
        self.info1_Entry = Text(self, width=30, height=12)
        self.info1_Entry.grid(column=1, columnspan=4, row=6, sticky=(N, W, E))

        in_C = StringVar()
        self.input_entry = ttk.Entry(self, width=10, textvariable=in_C)
        self.input_entry.grid(column=4, row=3, sticky=(W, E))
        self.int_btn = ttk.Button(self,
                                  text="Input Array",
                                  command=lambda: self.Input_C())
        self.int_btn.grid(column=4, row=5, sticky=W)

        self.int_lbl = ttk.Label(self,
                                 text="Inverse Distance "
                                 "Weighting Interpolation",
                                 font='bold')
        self.int_lbl.grid(column=1,
                          columnspan=4,
                          row=7,
                          sticky=W,
                          pady=(10, 2))

        self.int_btn = ttk.Button(self,
                                  text="Interpolate",
                                  state=DISABLED,
                                  command=lambda: self.interpolation(self.C))
        self.int_btn.grid(column=1, row=8, sticky=W)

        self.NP1 = IntVar()
        self.NP1.set(5)
        n_lbl = ttk.Label(self, text='No. pts')
        n_lbl.grid(column=1, row=9, sticky=(N, W))
        self.n_box = Spinbox(self,
                             format='%.0f',
                             from_=0,
                             to=self.NP1.get(),
                             width=5,
                             increment=1)  #1E10
        self.n_box.grid(column=1, row=10, sticky=(N, W))
        self.n_box.insert(1, 5)

        p_lbl = ttk.Label(self, text='Power')
        p_lbl.grid(column=2, row=9, sticky=(N, W))
        self.p_box = Spinbox(self,
                             format='%.0f',
                             from_=0,
                             to=1E10,
                             width=5,
                             increment=1)
        self.p_box.grid(column=2, row=10, sticky=(N, W))
        self.p_box.insert(1, 2)

        self.transpose_chk = IntVar()
        self.trans_btn = Checkbutton(self,
                                     text="Tranpose",
                                     variable=self.transpose_chk,
                                     state=DISABLED,
                                     command=lambda: self.check_tr(self.C))
        self.trans_btn.grid(column=3, row=10, sticky=(N, W))

        self.Refl_x = IntVar()
        self.Refl_x.set(1)
        self.Refl_x_btn = Checkbutton(self,
                                      text="Reflect_x",
                                      variable=self.Refl_x,
                                      state=DISABLED,
                                      command=lambda: self.check_tr(self.C))
        self.Refl_x_btn.grid(column=3, row=9, sticky=(N, W))
        self.info1_Entry.insert(END, "Reflect x = %s" % (self.Refl_x.get()))
        self.N_out_btn = ttk.Button(self,
                                    text="Save-Grid",
                                    state=DISABLED,
                                    command=lambda: self.N_out(self.N))
        self.N_out_btn.grid(column=1, row=12, sticky=W)
        self.M_out_btn = ttk.Button(self,
                                    text="Save-xyz",
                                    state=DISABLED,
                                    command=lambda: self.N_out(self.M))
        self.M_out_btn.grid(column=2, row=12, sticky=W)
        self.plot_btn = ttk.Button(self,
                                   text="Plot",
                                   state=DISABLED,
                                   command=lambda: self.plot(self.C, self.N))
        self.plot_btn.grid(column=3, row=12, sticky=(N, W))

        # Default values for the interpolated grid
        self.x01_ = StringVar()
        self.y01_ = StringVar()
        self.x01_.set(0.600001)  #default
        self.y01_.set(0.600001)  #default

        self.dx1_ = DoubleVar()  # from file
        self.dy1_ = DoubleVar()  # from file

        self.y02_ = StringVar()
        self.x02_ = StringVar()
        self.x02_.set(0.60)  #default
        self.y02_.set(0.60)  #default

        self.dx2_ = StringVar()
        self.dy2_ = StringVar()
        self.dx2_.set(0.5)  #default
        self.dy2_.set(0.5)  #default

        self.np_x2_ = StringVar()
        self.np_y2_ = StringVar()
        self.np_x2_.set(13)  #default
        self.np_y2_.set(13)  #default

        self.grid2_lbl = ttk.Label(self, text="Interpolated Grid")
        self.grid2_lbl.grid(column=1,
                            columnspan=4,
                            row=22,
                            sticky=(W, E),
                            pady=(5, 2))

        x01_entry = ttk.Entry(self, width=6, textvariable=self.x01_)
        x01_entry.grid(column=2, row=17, sticky=W)
        x01_lbl = ttk.Label(self, text='x0')
        x01_lbl.grid(column=1, row=17, sticky=(N, W), padx=(40, 0))

        y01_entry = ttk.Entry(self, width=6, textvariable=self.y01_)
        y01_entry.grid(column=4, row=17, sticky=W)
        y01_lbl = ttk.Label(self, text='y0')
        y01_lbl.grid(column=3, row=17, sticky=(N, W), padx=(40, 0))

        dx1_entry = ttk.Entry(self, width=6, textvariable=self.dx1_)
        dx1_entry.grid(column=2, row=18, sticky=W)
        dx1_lbl = ttk.Label(self, text='dx1')
        dx1_lbl.grid(column=1, row=18, sticky=(N, W), padx=(40, 0))

        dy1_entry = ttk.Entry(self, width=6, textvariable=self.dy1_)
        dy1_entry.grid(column=4, row=18, sticky=W)
        dy1_lbl = ttk.Label(self, text='dy1')
        dy1_lbl.grid(column=3, row=18, sticky=(N, W), padx=(40, 0))

        x02_entry = ttk.Entry(self, width=6, textvariable=self.x02_)
        x02_entry.grid(column=2, row=23, sticky=W)
        x02_lbl = ttk.Label(self, text='x0 (Int)')
        x02_lbl.grid(column=1, row=23, sticky=(N, W), padx=(40, 0))

        y02_entry = ttk.Entry(self, width=6, textvariable=self.y02_)
        y02_entry.grid(column=4, row=23, sticky=W)
        y02_lbl = ttk.Label(self, text='y0 (Int)')
        y02_lbl.grid(column=3, row=23, sticky=(N, W), padx=(40, 0))

        dx2_entry = ttk.Entry(self, width=6, textvariable=self.dx2_)
        dx2_entry.grid(column=2, row=24, sticky=W)
        dx2_lbl = ttk.Label(self, text='dx2')
        dx2_lbl.grid(column=1, row=24, sticky=(N, W), padx=(40, 0))

        dy2_entry = ttk.Entry(self, width=6, textvariable=self.dy2_)
        dy2_entry.grid(column=4, row=24, sticky=W)
        dy2_lbl = ttk.Label(self, text='dy2')
        dy2_lbl.grid(column=3, row=24, sticky=(N, W), padx=(40, 0))

        np_x2_entry = ttk.Entry(self, width=6, textvariable=self.np_x2_)
        np_x2_entry.grid(column=2, row=25, sticky=W)
        np_x2_lbl = ttk.Label(self, text='np_x2')
        np_x2_lbl.grid(column=1, row=25, sticky=(N, W), padx=(40, 0))

        np_y2_entry = ttk.Entry(self, width=6, textvariable=self.np_y2_)
        np_y2_entry.grid(column=4, row=25, sticky=W)
        np_y2_lbl = ttk.Label(self, text='np_y2')
        np_y2_lbl.grid(column=3, row=25, sticky=(N, W), padx=(40, 0))

        self.tipwf = DoubleVar()
        self.tipwf.set(4220)
        self.tip = IntVar()
        self.tip_btn = Checkbutton(self,
                                   text="Tip correction (mV)",
                                   variable=self.tip,
                                   state=DISABLED,
                                   command=lambda: self.workfunction(self.C))
        self.tip_btn.grid(column=3,
                          columnspan=2,
                          row=26,
                          sticky=(N, W),
                          pady=(15, 0))

        self.tip_entry = ttk.Entry(self, width=6, textvariable=self.tipwf)
        self.tip_entry.grid(column=2, row=26, sticky=E, pady=(15, 0))

        minmax_lbl = ttk.Label(self, text='Min and Max x/y')
        minmax_lbl.grid(column=2, columnspan=3, row=19, sticky=(N, W))

        self.xi = IntVar()
        self.xi.set(0)
        self.xf = IntVar()
        self.xf.set(0)
        xdata_lbl = ttk.Label(self, text='x-data_subset')
        xdata_lbl.grid(column=1, row=20, sticky=(N, W))
        self.xidata_box = Spinbox(self,
                                  format='%.0f',
                                  from_=0,
                                  to=self.xf.get(),
                                  width=5,
                                  increment=1)
        self.xidata_box.grid(column=2, row=20, sticky=(N, W), padx=(15, 0))
        self.xidata_box.insert(1, 0)
        self.xfdata_box = Spinbox(self,
                                  format='%.0f',
                                  from_=0,
                                  to=self.xf.get(),
                                  width=5,
                                  increment=1)
        self.xfdata_box.grid(column=3, row=20, sticky=(N, W))
        self.xfdata_box.insert(1, 0)

        self.yi = IntVar()
        self.yi.set(0)
        self.yf = IntVar()
        self.yf.set(0)
        ydata_lbl = ttk.Label(self, text='y-data_subset')
        ydata_lbl.grid(column=1, row=21, sticky=(N, W))
        self.yidata_box = Spinbox(self,
                                  format='%.0f',
                                  from_=0,
                                  to=self.yf.get(),
                                  width=5,
                                  increment=1)
        self.yidata_box.grid(column=2, row=21, sticky=(N, W), padx=(15, 0))
        self.yidata_box.insert(1, 0)
        self.yfdata_box = Spinbox(self,
                                  format='%.0f',
                                  from_=0,
                                  to=self.yf.get(),
                                  width=5,
                                  increment=1)
        self.yfdata_box.grid(column=3, row=21, sticky=(N, W))
        self.yfdata_box.insert(1, 0)

    def enable_btn(self):
        self.graph1_btn.config(state='ENABLED')
        self.int_btn.config(state='ENABLED')
        self.trans_btn.config(state='normal')
        self.Refl_x_btn.config(state='normal')
        self.N_out_btn.config(state='ENABLED')
        self.M_out_btn.config(state='ENABLED')
        self.tip_btn.config(state='normal')

    def Input_C(self):
        """"Loads tab-delimited data from the corresponding text-box"""
        A = self.input_entry.get()
        self.info1_Entry.delete(1.0, END)

        B = []
        reader = csv.reader(A.split('\n'), delimiter='\t')
        for row in reader:
            row = row[:]
            B.append(row)
        B = B[0:len(B) - 1][0:len(B[0])]
        for i in range(0, len(B)):
            for j in range(0, len(B[i])):
                B[i][j] = float(B[i][j])
        B = asarray(B)
        print(B)
        self.dx1_.set(0.18)
        self.dy1_.set(0.18)
        self.NP1.set(len(B[0]) * len(B) - 1)
        self.n_box.config(to=self.NP1.get())

        self.xf.set(len(B[0]))
        self.xfdata_box.delete(0, "end")
        self.xfdata_box.insert(1, self.xf.get())
        self.xidata_box.config(to=self.xf.get())
        self.xfdata_box.config(to=self.xf.get())

        self.yf.set(len(B))
        self.yfdata_box.delete(0, "end")
        self.yfdata_box.insert(1, self.yf.get())
        self.yidata_box.config(to=self.yf.get())
        self.yfdata_box.config(to=self.yf.get())

        self.C = B
        self.enable_btn()
        self.graph1(B, 1)
        return self.C

    def open1(self):
        """"Loads data from file and displays footer information"""
        fileName = filedialog.askopenfilename(title="Open CPD file")
        try:
            f = open(fileName, 'r')
        except IOError:
            pass

        i = f.readline().strip()
        if i == "Work Function data":
            pass
        else:
            i = messagebox.askyesno(title="Open file?",
                                    message="CPD file header not present!\n"
                                    "Proceed to open file?",
                                    default='no')
            if i == 1:
                pass
            else:
                pass
        self.path1.set(fileName)
        g = f.read()
        f.close()

        # Only CPD data is loaded but there are other measurements
        Tracking = g.find('Tracking')
        Grad = g.find('Grad')
        # Time = g.find('Time')
        # User = g.find('User')
        Footer = g.find('/') - 2
        # Footer = Footer - 2

        CPD_data = g[0:Tracking]
        # Tracking_data = g[Tracking:Grad]
        # Grad_data = g[Grad:Time]
        # Time_data = g[Time:User]
        # User_data = g[User:Footer]
        Footer_data = g[Footer:]

        a = Footer_data.split("\n")
        Date = a[0]
        Grad = [int(i) for i in a[-10].split() if i.isdigit()]
        DAS_Averages = [int(i) for i in a[-18].split() if i.isdigit()]
        WF_Averages = [int(i) for i in a[-14].split() if i.isdigit()]
        Xpoints = [int(i) for i in a[-5].split() if i.isdigit()]
        Ypoints = [int(i) for i in a[-4].split() if i.isdigit()]
        Xsteps = [int(i) for i in a[-3].split() if i.isdigit()]
        Ysteps = [int(i) for i in a[-2].split() if i.isdigit()]
        Xstepscm = Xsteps[0] * 0.0015  #xyscale
        Ystepscm = Ysteps[0] * 0.0015

        # C is the array used for the raw data
        C = []
        reader = csv.reader(CPD_data.split('\n'), delimiter=',')
        for row in reader:
            row = row[:-1]
            C.append(row)
        C = C[0:len(C) - 1][0:len(C[0])]
        for i in range(0, len(C)):
            for j in range(0, len(C[i])):
                C[i][j] = float(C[i][j])
        C = asarray(C)

        # Clear the textbox before putting in data for new file
        self.info1_Entry.delete(1.0, END)
        info_0 = "%s\n%s\n" % (fileName, Date)
        info_1 = ("Xpoints = %s\nYpoints = %s\nXsteps = %s (%s cm)\n"
                  "Ysteps= %s (%s cm)" \
            % (Xpoints[0], Ypoints[0], Xsteps[0], Xstepscm, Ysteps[0],
               Ystepscm))
        info_2 = "\nDAS_Aves = %s\nWF_Averages = %s\nGrad = %s"\
            % (DAS_Averages[0],WF_Averages[0],Grad[0])
        self.info1_Entry.insert(END, info_0)
        self.info1_Entry.insert(END, info_1)
        self.info1_Entry.insert(END, info_2)
        if self.Refl_x.get() == 1:
            info_3 = "\nReflect x = %s" % (self.Refl_x.get())
            self.info1_Entry.insert(END, info_3)

        if self.transpose_chk.get() == 1:
            info_4 = "\nTranspose = %s" % (self.transpose_chk.get())
            self.info1_Entry.insert(END, info_4)

        self.enable_btn()

        # To prevent divide by 0 issue 1E-8 is added
        if Xpoints[0] == len(C[0]):
            self.dx1_.set(Xstepscm + 1E-8)
            self.dy1_.set(Ystepscm + 1E-8)
        else:
            self.dy1_.set(Xstepscm + 1E-8)
            self.dx1_.set(Ystepscm + 1E-8)

        self.NP1.set(len(C[0]) * len(C) - 1)
        self.n_box.config(to=self.NP1.get())

        self.xf.set(len(C[0]))
        self.xfdata_box.delete(0, "end")
        self.xfdata_box.insert(1, self.xf.get())
        self.xidata_box.config(to=self.xf.get())
        self.xfdata_box.config(to=self.xf.get())

        self.yf.set(len(C))
        self.yfdata_box.delete(0, "end")
        self.yfdata_box.insert(1, self.yf.get())
        self.yidata_box.config(to=self.yf.get())
        self.yfdata_box.config(to=self.yf.get())

        self.tip.set(0)

        self.C = C
        self.Cr = C
        return self.C, self.Cr

    def graph1(self, data, row_a):
        """Graphs the raw CPD data"""
        plt.close()
        plt.figure(figsize=(3.5, 3.5), dpi=100, frameon=False)
        im = plt.imshow(data, cmap='jet')
        plt.colorbar(im, orientation='vertical', fraction=0.046, pad=0.05)

        plt.tight_layout()
        plt.savefig(path.join(tmpdir, im_name1), dpi=100, bbox_inches='tight')

        c = Canvas(self, width=350, height=350, bg='white')
        c.grid(row=row_a,
               column=5,
               columnspan=2,
               rowspan=50,
               sticky=(W, N),
               padx=50)
        c.background = PhotoImage(file=path.join(tmpdir, im_name1))
        c.create_image(1, 20, image=c.background, anchor=NW)

    def interpolation(self, C):
        """Performs inverse distance interpolation"""
        temp = []
        for j in range(int(self.yidata_box.get()), int(self.yfdata_box.get())):
            temp.append([])
            for i in range(int(self.xidata_box.get()),
                           int(self.xfdata_box.get())):
                temp[j - int(self.yidata_box.get())].append(C[j, i])
        # Sub-array of raw data defined by the min and max x/y value
        C = temp
        C = asarray(C)

        n = self.n_box.get()
        n = int(n)

        p = self.p_box.get()
        p = int(p)

        x01 = float(self.x01_.get())
        y01 = float(self.y01_.get())

        dx1 = float(self.dx1_.get())
        dy1 = float(self.dy1_.get())

        y02 = float(self.y02_.get())
        x02 = float(self.x02_.get())

        dx2 = float(self.dx2_.get())
        dy2 = float(self.dy2_.get())

        np_x2 = int(self.np_x2_.get())
        np_y2 = int(self.np_y2_.get())

        if self.transpose_chk.get() == 1:
            C = transpose(C)

        # Define the dimensions of the raw data grid
        np_x1 = len(C[0])
        np_y1 = len(C)

        NP1 = np_x1 * np_y1

        x1 = ones(np_x1)
        for i in range(0, np_x1):
            x1[i] = x01 + dx1 * i

        y1 = ones(np_y1)
        for i in range(0, np_y1):
            y1[i] = y01 + dy1 * i

        if self.Refl_x.get() == 1:
            x1_ = ones(np_x1)
            for i in range(0, len(x1)):
                x1_[i] = x1[-1 - i]
            x1 = x1_

        data_1d = C.flatten()

        # Define the dimensions of interpolated data grid
        NP2 = np_x2 * np_y2

        x2 = ones(np_x2)
        for i in range(0, np_x2):
            x2[i] = x02 + dx2 * i

        y2 = ones(np_y2)
        for i in range(0, np_y2):
            y2[i] = y02 + dy2 * i

        # Intperolation calculation
        k2 = 0
        int_data = ones(NP2)
        dist = [0] * (NP1)
        index = [0] * (NP1)
        for j2 in range(0, np_y2):
            for i2 in range(0, np_x2):
                dist_2d = []
                dist_1d = []
                for j in range(0, np_y1):
                    dist_2d.append([])
                    for i in range(0, np_x1):
                        dist_2d[j].append(
                            sqrt((x2[i2] - x1[i])**2 + (y2[j2] - y1[j])**2))
                        dist_1d.append(
                            sqrt((x2[i2] - x1[i])**2 + (y2[j2] - y1[j])**2))

                index = sorted(range(len(dist_1d)), key=lambda x: dist_1d[x])
                dist = sorted(dist_1d)
                up = min(n, NP1)
                temp = 0
                lamb = ones(up)
                if dist[0] > 0:
                    for i in range(0, up):
                        lamb[i] = (1/(dist[i]**p))\
                            /sum(ones(up)/power_(dist[0:up],p))
                        temp = temp + data_1d[index[i]] * lamb[i]
                else:
                    temp = data_1d[index[i]]
                int_data[k2] = temp
                k2 = k2 + 1

        M1 = []
        N = []
        k2 = 0
        for j2 in range(0, np_y2):
            N.append([])
            for i2 in range(0, np_x2):
                M1.append([x02 + i2 * dx2, y02 + j2 * dy2, int_data[k2]])
                N[j2].append(int_data[k2])
                k2 = k2 + 1
        M1 = asarray(M1)
        N = asarray(N)

        # Generate a xyz equivalent array
        if np_x2 == np_y2:
            Mt = []
            for j2 in range(0, np_y2):
                for i2 in range(0, np_x2):
                    Mt.append([y02 + j2 * dy2, x02 + i2 * dx2, N[i2, j2]])
                    k2 = k2 + 1
            M = append(Mt, M1, axis=1)
        else:
            M = M1

        self.N = N
        self.M1 = M1
        self.M = M

        self.graph1(self.N, 8)

        self.plot_btn.config(state='ENABLED')
        return (self.N, self.M1, self.M)

    def check_tr(self, C):
        self.info1_Entry.delete(10.0, END)
        if self.Refl_x.get() == 1:
            info_3 = "\nReflect x = %s" % (self.Refl_x.get())
            self.info1_Entry.insert(END, info_3)

        if self.transpose_chk.get() == 1:
            info_4 = "\nTranspose = %s" % (self.transpose_chk.get())
            self.info1_Entry.insert(END, info_4)
        self.interpolation(C)

    def plot(self, C, N):
        """Produces images of the raw and interpolated data plots"""
        plt.close('all')
        fig_ext = plt.figure(dpi=200)
        ax1 = fig_ext.add_subplot(121)
        ax1_im = plt.imshow(C,
                            vmin=amin([amin(C), amin(N)]),
                            vmax=amax([amax(C), amax(N)]),
                            cmap='jet')

        cbar = plt.colorbar(ax1_im,
                            orientation='vertical',
                            fraction=0.046,
                            pad=0.05)  # aspect='auto')
        if self.tip.get() == 1:
            cbar.set_label('Work Function (meV)')
        else:
            cbar.set_label('CPD (mV)')
        plt.xlabel('x-axis')
        plt.ylabel('y-axis')

        ax2 = fig_ext.add_subplot(122)
        ax2_im = plt.imshow(N,
                            vmin=amin([amin(C), amin(N)]),
                            vmax=amax([amax(C), amax(N)]),
                            cmap='jet')
        cbar = plt.colorbar(ax2_im,
                            orientation='vertical',
                            fraction=0.046,
                            pad=0.05)  #, aspect='auto')
        if self.tip.get() == 1:
            cbar.set_label('Work Function (meV)')
        else:
            cbar.set_label('CPD (mV)')
        plt.xlabel('x-axis')
        plt.ylabel('y-axis')

        plt.tight_layout()
        fig_ext = plt.gcf()
        plt.show()

    def N_out(self, N):
        """Exports the data as a csv file via dialogue box"""
        file_opt = options = {}
        options['filetypes'] = [('all files', '.*'),
                                ('CSV (Comma Delimited)', '.csv')]
        options['initialfile'] = '.csv'
        options['title'] = 'Save Array as CSV'

        try:
            fo1 = filedialog.asksaveasfile(mode='wb', **file_opt)
            savetxt(fo1,
                    N,
                    delimiter=',',
                    footer=self.info1_Entry.get(1.0, END))
            fo1.close()
        except IOError:
            messagebox.showinfo(title="Output file",
                                message="Output file issue")

    def workfunction(self, C):
        """Applies linear offset to CPD, useful for correcing 
        for the tip's workfunction and converting CPD into 
        workfunction"""
        if self.tip.get() == 1:
            self.C = C + float(self.tipwf.get())
            self.tip_entry.config(state='disabled')
        else:
            self.C = (C - float(self.tipwf.get()))
            self.tip_entry.config(state="normal")
        self.graph1(self.C, 1)
        return self.C
Esempio n. 11
0
def Spinbox(root, **options):
    s = TKSpinbox(root)

    s.config(**options)
    s.pack()
Esempio n. 12
0
class MyGUI():
    def __init__(self, root, frame):

        self.root = root
        self.root.title("ClockPy")
        #self.root.resizable(0,0)
        self.root.maxsize(width=385, height=550)
        self.root.minsize(width=385, height=550)
        self.root.iconbitmap("./icons/clock.ico")
        self.frame = frame

        # -----------  Function Refresh Clock  -----------

        def tick():
            time_string = time.strftime("%I:%M")
            time_string2 = time.strftime(":%S")
            time_day = time.strftime("%a, %d %B")
            time_m = time.strftime("%p")
            self.clock.config(text=time_string)
            self.clock_s.config(text=time_string2)
            self.clock_d.config(text=time_day)
            self.clock_m.config(text=time_m)
            self.clock.after(200, tick)

        # -----------  Function DataBASE  -----------
        #Load database
        db_name = 'database.db'
        # Operation database
        query = 'SELECT * FROM color'
        query_alarm = 'SELECT * FROM alarm'
        query2 = 'UPDATE color SET hexa=?'
        query_alarm2 = 'UPDATE alarm SET state=?'
        query_alarm3 = 'UPDATE alarm SET hours=?, minutes=?, meridiam=?'

        # Database Consult Update
        def db_query(query, parameters=(), alarm=None):
            with sqlite3.connect(db_name) as conn:
                cursor = conn.cursor()
                result = cursor.execute(query, parameters)
                conn.commit()
                if (parameters == ()):
                    if (alarm == None):
                        for row in result:
                            return row[1]
                    else:
                        for row in result:
                            return row[1:5]

        hexa_c = db_query(query)
        self.frame.config(width="385", height="550", bg=hexa_c)

        # -----------  Function Check Status Alarm  -----------

        def check_alarm():
            self.data_alarm_check = db_query(query_alarm, alarm="Y")
            time_check_h = time.strftime("%I")
            time_check_m = time.strftime("%M")
            time_check_mr = time.strftime("%p")
            time_check_s = time.strftime("%S")

            if (self.data_alarm_check[0] < 10):
                hours_check = "0" + str(self.data_alarm_check[0])
            else:
                hours_check = str(self.data_alarm_check[0])

            if (self.data_alarm_check[1] < 10):
                minutes_check = "0" + str(self.data_alarm_check[1])
            else:
                minutes_check = str(self.data_alarm_check[1])

            # Check Alarm and playsound
            if (self.data_alarm_check[3] == "on"):
                if (time_check_s == "00"):
                    if (time_check_h == hours_check):
                        if (time_check_m == minutes_check):
                            if (time_check_mr == self.data_alarm_check[2]):
                                playsound("./sound/alarm_sound.mp3")
                                self.root.deiconify()
                                self.root.focus_set()

            self.root.after(1000, check_alarm)

        # -----------  Windows Clock Alarm  -----------

        def windows():

            hexa_c = db_query(query)
            self.main_wn = Toplevel(self.root, takefocus=True, bg=hexa_c)
            self.main_wn.focus_force()
            self.main_wn.title("ClockPy Alarm")
            self.main_wn.geometry("320x158")
            self.main_wn.resizable(0, 0)
            self.main_wn.iconbitmap("./icons/clock.ico")
            self.main_wn.grab_set()

            self.date_alarm = db_query(query_alarm, alarm="Y")
            self.img_on = PhotoImage(file="./icons/on.png")
            self.img_off = PhotoImage(file="./icons/off.png")
            self.img_menu = PhotoImage(file="./icons/menu.png")

            self.switch = self.date_alarm[3]

            def check_state_alarm():

                if (self.date_alarm[0] < 10):
                    self.lb_hours.config(text="0" + str(self.date_alarm[0]))
                else:
                    self.lb_hours.config(text=self.date_alarm[0])

                if (self.date_alarm[1] < 10):
                    self.lb_minutes.config(text=":0" + str(self.date_alarm[1]))
                else:
                    self.lb_minutes.config(text=":" + str(self.date_alarm[1]))

                self.lb_meridiam.config(text=self.date_alarm[2])
                if (self.switch == "on"):
                    self.bt_switch.config(image=self.img_on)
                else:
                    self.bt_switch.config(image=self.img_off)

            def change_switch():
                if (self.switch == "off"):
                    self.bt_switch.config(image=self.img_on)
                    self.switch = "on"
                    db_query(query_alarm2, ("on", ))
                else:
                    self.bt_switch.config(image=self.img_off)
                    self.switch = "off"
                    db_query(query_alarm2, ("off", ))

            self.space_alarm = Frame(self.main_wn,
                                     width=300,
                                     height=100,
                                     bg="white")
            self.space_alarm.place(x=10, y=20)

            self.lb_hours = Label(self.space_alarm,
                                  font=("Roboto Light", 54),
                                  bg="white")
            self.lb_hours.place(x=10, y=0)

            self.lb_minutes = Label(self.space_alarm,
                                    font=("Roboto Light", 54),
                                    bg="white")
            self.lb_minutes.place(x=90, y=0)

            self.lb_meridiam = Label(self.space_alarm,
                                     font=("Roboto Light", 14),
                                     bg="white")
            self.lb_meridiam.place(x=190, y=15)

            self.bt_switch = Button(self.space_alarm,
                                    activebackground="white",
                                    command=lambda: change_switch())
            self.bt_switch.config(bg="white",
                                  bd=0,
                                  highlightthickness=0,
                                  relief='flat')
            self.bt_switch.place(x=245, y=10)

            self.bt_config_alarm = Button(self.space_alarm,
                                          image=self.img_menu,
                                          activebackground="white")
            self.bt_config_alarm.config(bg="white",
                                        bd=0,
                                        highlightthickness=0,
                                        relief='flat',
                                        command=lambda: setting_alarm())
            self.bt_config_alarm.place(x=250, y=55)
            check_state_alarm()

            # -----------  Windows Settings Alarm  -----------

            def setting_alarm():

                self.settings_wn = Toplevel(self.main_wn,
                                            bg=hexa_c,
                                            takefocus=True)
                self.settings_wn.focus_force()
                self.settings_wn.geometry("470x165")
                self.settings_wn.iconbitmap("./icons/clock.ico")
                self.settings_wn.grab_set()
                self.settings_wn.resizable(0, 0)
                self.settings_wn.title("ClockPy Alarm")

                self.space_alarm2 = Frame(self.settings_wn,
                                          width=450,
                                          height=100,
                                          bg="white")
                self.space_alarm2.place(x=10, y=20)

                self.select_hours = Spinbox(self.space_alarm2,
                                            from_=1,
                                            to=12,
                                            width=2,
                                            font=("Roboto Light", 50),
                                            bd=0,
                                            relief='flat',
                                            activebackground="white",
                                            textvariable=2,
                                            state="readonly")
                self.select_hours.config(buttondownrelief="flat",
                                         readonlybackground="white")
                self.select_hours.place(x=10, y=5)

                self.select_minutes = Spinbox(self.space_alarm2,
                                              from_=00,
                                              to=59,
                                              format="%02.0f",
                                              width=2,
                                              font=("Roboto Light", 50),
                                              bd=0,
                                              relief='flat',
                                              activebackground="white")
                self.select_minutes.config(buttondownrelief="flat",
                                           readonlybackground="white",
                                           state="readonly")
                self.select_minutes.place(x=150, y=5)

                self.select_meridiam = Spinbox(self.space_alarm2,
                                               values=("AM", "PM"),
                                               width=3,
                                               font=("Roboto Light", 50),
                                               bd=0,
                                               relief='flat',
                                               activebackground="white")
                self.select_meridiam.config(buttondownrelief="flat",
                                            readonlybackground="white",
                                            state="readonly")
                self.select_meridiam.place(x=285, y=5)

                self.bt_save_sttg = Button(self.settings_wn,
                                           text="Save",
                                           font=("Roboto Light", 12),
                                           bd=0,
                                           relief="flat",
                                           bg="white",
                                           command=lambda: save_sttg())
                self.bt_save_sttg.place(x=415, y=125)

                def save_sttg():
                    h = self.select_hours.get()
                    m = self.select_minutes.get()
                    md = self.select_meridiam.get()
                    db_query(query_alarm3, (
                        h,
                        m,
                        md,
                    ))
                    self.date_alarm = db_query(query_alarm, alarm="Y")
                    check_state_alarm()
                    self.settings_wn.destroy()

        # -----------  Function Change Color  -----------

        def change_color():
            rgb, hexa = askcolor()
            self.frame.config(bg=hexa)
            self.clock.config(bg=hexa)
            self.clock_s.config(bg=hexa)
            self.clock_m.config(bg=hexa)
            self.clock_d.config(bg=hexa)
            self.button1.config(bg=hexa, activebackground=hexa)
            self.button2.config(bg=hexa, activebackground=hexa)
            #self.lb.config(bg=hexa)
            # Update Value color database
            if (hexa != None):
                db_query(query2, (hexa, ))

        # -----------  Clock Configure  -----------

        # Clock Hours Minutes
        self.clock = Label(self.frame,
                           font=("Roboto Light", 64),
                           bg=hexa_c,
                           foreground="white")
        self.clock.place(x=65, y=150)
        # Clock Seconds
        self.clock_s = Label(self.frame,
                             font=("Roboto Light", 22),
                             bg=hexa_c,
                             foreground="white")
        self.clock_s.place(x=272, y=200)
        # Clock Meridiem
        self.clock_m = Label(self.frame,
                             font=("Roboto Light", 22),
                             bg=hexa_c,
                             foreground="white")
        self.clock_m.place(x=272, y=165)
        # Day Month
        self.clock_d = Label(self.frame,
                             font=("Roboto Light", 14),
                             bg=hexa_c,
                             foreground="white")
        self.clock_d.place(x=80, y=240)
        tick()
        check_alarm()

        # -----------  Button Change Color  -----------

        self.img = PhotoImage(file="./icons/color.png")
        self.img2 = PhotoImage(file="./icons/alarm.png")

        # Button Pallete Colors
        self.button1 = Button(self.frame,
                              image=self.img,
                              activebackground=hexa_c,
                              command=lambda: change_color())
        self.button1.config(bg=hexa_c,
                            bd=0,
                            highlightthickness=0,
                            relief='flat')
        self.button1.place(x=5, y=505)

        # Button Settings
        self.button2 = Button(self.frame,
                              image=self.img2,
                              activebackground=hexa_c,
                              command=lambda: windows())
        self.button2.config(bg=hexa_c,
                            bd=0,
                            highlightthickness=0,
                            relief='flat')
        self.button2.place(x=340, y=505)
        self.frame.pack()
class NewMorphLineWindow(Toplevel):
    def __init__(self, master=None):
        super().__init__(master=master)
        self.set_basic()
        self.set_widgets()

    def set_basic(self):
        self.minsize(600, 400)
        self.maxsize(600, 400)
        self.title("Ekstrakcja linii")
        self.protocol("WM_DELETE_WINDOW", lambda: self.cancel())

        self.handleBorder = {
            "Bez zmian (isolated)": 0,
            "Odbicie lustrzane (reflect)": 1,
            "Powielenie skrajnego piksela (replicate)": 2
        }

    def set_widgets(self):
        self.horizontalSizeW = StringVar(self, value="3")
        self.horizontalSizeH = StringVar(self, value="1")
        self.verticalSizeW = StringVar(self, value="3")
        self.verticalSizeH = StringVar(self, value="1")
        self.borderType = StringVar(self, list(self.handleBorder.keys())[0])
        self.cbVarHorizontal = IntVar(value=1)
        self.cbVarVertical = IntVar(value=1)
        self.cbVarOuter = IntVar(value=1)
        self.cbVarNegate = IntVar(value=0)

        self.sizeHorizontalWSpin = Spinbox(self,
                                           justify='center',
                                           font=("Helvetica", 15),
                                           from_=1,
                                           to=9999,
                                           textvariable=self.horizontalSizeW,
                                           command=self.update_preview,
                                           state='readonly',
                                           increment=2)
        self.sizeHorizontalHSpin = Spinbox(self,
                                           justify='center',
                                           font=("Helvetica", 15),
                                           from_=1,
                                           to=9999,
                                           textvariable=self.horizontalSizeH,
                                           command=self.update_preview,
                                           state='readonly',
                                           increment=2)
        self.sizeVerticalWSpin = Spinbox(self,
                                         justify='center',
                                         font=("Helvetica", 15),
                                         from_=1,
                                         to=9999,
                                         textvariable=self.verticalSizeW,
                                         command=self.update_preview,
                                         state='readonly',
                                         increment=2)
        self.sizeVerticalHSpin = Spinbox(self,
                                         justify='center',
                                         font=("Helvetica", 15),
                                         from_=1,
                                         to=9999,
                                         textvariable=self.verticalSizeH,
                                         command=self.update_preview,
                                         state='readonly',
                                         increment=2)

        self.horizontalSizeW.trace("w", self.update_preview)
        self.horizontalSizeH.trace("w", self.update_preview)
        self.verticalSizeW.trace("w", self.update_preview)
        self.verticalSizeH.trace("w", self.update_preview)
        self.borderType.trace("w", self.update_preview)
        self.cbVarHorizontal.trace("w", self.update_preview)
        self.cbVarVertical.trace("w", self.update_preview)
        self.cbVarOuter.trace("w", self.update_preview)
        self.cbVarNegate.trace("w", self.update_preview)

        self.cbHorizontal = Checkbutton(self,
                                        width=0,
                                        variable=self.cbVarHorizontal)
        self.cbVertical = Checkbutton(self,
                                      width=0,
                                      variable=self.cbVarVertical)
        self.cbOuterOnly = Checkbutton(self, width=0, variable=self.cbVarOuter)
        self.cbNegateFirst = Checkbutton(self,
                                         width=0,
                                         variable=self.cbVarNegate)

        self.borderList = OptionMenu(self, self.borderType)

        for border in self.handleBorder:
            self.borderList['menu'].add_command(
                label=border, command=lambda v=border: self.borderType.set(v))

        self.saveButton = Button(self,
                                 image=saveIcon,
                                 command=self.update_image)
        self.cancelButton = Button(self, image=closeIcon, command=self.cancel)

        self.update_preview()
        self.place_widgets()

    def update_image(self):
        self.master.image.cv2Image = copy.deepcopy(self.master.image.copy)
        self.master.image.morph_line(int(self.horizontalSizeW.get()),
                                     int(self.horizontalSizeH.get()),
                                     int(self.verticalSizeW.get()),
                                     int(self.verticalSizeH.get()),
                                     self.cbVarHorizontal.get(),
                                     self.cbVarVertical.get(),
                                     self.handleBorder[self.borderType.get()],
                                     self.cbVarOuter.get(),
                                     self.cbVarNegate.get())
        self.master.image.copy = copy.deepcopy(self.master.image.cv2Image)
        self.master.manager.new_state(self.master.image.cv2Image)
        self.master.update_visible_image()
        self.master.update_child_windows()
        self.destroy()

    def update_preview(self, *args):
        self.sizeHorizontalWSpin.config(from_=int(self.horizontalSizeH.get()) +
                                        2)
        self.sizeHorizontalHSpin.config(to=int(self.horizontalSizeW.get()) - 2)
        self.sizeVerticalWSpin.config(from_=int(self.verticalSizeH.get()) + 2)
        self.sizeVerticalHSpin.config(to=int(self.verticalSizeW.get()) - 2)
        self.master.image.cv2Image = copy.deepcopy(self.master.image.copy)
        self.master.image.morph_line(int(self.horizontalSizeW.get()),
                                     int(self.horizontalSizeH.get()),
                                     int(self.verticalSizeW.get()),
                                     int(self.verticalSizeH.get()),
                                     self.cbVarHorizontal.get(),
                                     self.cbVarVertical.get(),
                                     self.handleBorder[self.borderType.get()],
                                     self.cbVarOuter.get(),
                                     self.cbVarNegate.get())
        self.master.update_visible_image()
        self.master.update_child_windows()

    def place_widgets(self):
        Label(self, text="Poziome linie", font=("Helvetica", 15)).place(x=85,
                                                                        y=15)
        Label(self, text="Pionowe linie", font=("Helvetica", 15)).place(x=395,
                                                                        y=15)

        self.sizeHorizontalWSpin.place(width=100, height=50, x=150, y=60)
        self.sizeHorizontalHSpin.place(width=100, height=50, x=150, y=120)
        self.sizeVerticalWSpin.place(width=100, height=50, x=450, y=60)
        self.sizeVerticalHSpin.place(width=100, height=50, x=450, y=120)

        Label(self, text="Min. długość", font=("Helvetica", 15)).place(x=30,
                                                                       y=70)
        Label(self, text="Min. grubość", font=("Helvetica", 15)).place(x=30,
                                                                       y=130)
        Label(self, text="Min. długość", font=("Helvetica", 15)).place(x=330,
                                                                       y=70)
        Label(self, text="Min. grubość", font=("Helvetica", 15)).place(x=330,
                                                                       y=130)

        Label(self, text="Szukać poziomych?",
              font=("Helvetica", 9)).place(x=70, y=175)
        Label(self, text="Szukać pionowych?",
              font=("Helvetica", 9)).place(x=380, y=175)

        self.cbHorizontal.place(x=180, y=175)
        self.cbVertical.place(x=500, y=175)

        Label(self, text="Szukać tylko zewnętrznych?",
              font=("Helvetica", 11)).place(x=190, y=225)
        Label(self, text="Wstępnie zanegować?",
              font=("Helvetica", 11)).place(x=190, y=255)
        self.cbOuterOnly.place(x=390, y=225)
        self.cbNegateFirst.place(x=390, y=255)
        self.borderList.place(width=200, height=50, x=200, y=300)

        self.saveButton.place(width=40, height=40, x=220, y=355)
        self.cancelButton.place(width=40, height=40, x=340, y=355)

    def cancel(self):
        self.master.image.cv2Image = copy.deepcopy(self.master.image.copy)
        self.master.update_visible_image()
        self.master.image.fill_histogram()
        self.master.update_child_windows()
        self.destroy()
Esempio n. 14
0
class Interface:
    """ GUI class """
    def __init__(self, master):
        # colour swatches
        self.gray1 = "#f6f6f6"
        self.gray2 = "#eaeaea"
        self.gray3 = "#d9d9d9"
        # key parameters
        self.running = False
        self.sect_width = 360
        self.rb_choice = StringVar()
        self.dob1_val = StringVar()
        self.dob2_val = StringVar()
        self.df_records = StringVar()

        master.geometry("800x600+200+200")
        master.title("Red Snapper")
        master.resizable(False, False)
        master.configure(background=self.gray1)

        # LEFT SECTION LAYER
        # --------------------------------------------------------------------
        self.sect_left = Frame(master)
        self.sect_left.place(x=15, y=15, width=self.sect_width, height=570)
        self.sect_left.config(relief=RIDGE)
        self.sect_left.config(background=self.gray2)

        # RIGHT SECTION LAYER
        # --------------------------------------------------------------------
        self.sect_right = Frame(master)
        self.sect_right.place(x=-15, y=200, width=self.sect_width, height=385)
        self.sect_right.place(relx=1.0, anchor="ne")
        self.sect_right.config(relief=RIDGE)
        self.sect_right.config(background=self.gray2)

        # Sliders layer
        self.layer_sliders = Frame(self.sect_left)
        self.layer_sliders.place(y=0, width=self.sect_width, height=320)
        self.layer_sliders.config(**self.layer_props(self.gray2))
        self.lab_sliders = Label(self.layer_sliders)
        self.lab_sliders.config(**self.title_props("Parameters"))
        self.lab_sliders.pack()

        # DOB layer
        self.layer_dob = Frame(self.sect_left)
        self.layer_dob.place(y=320, width=self.sect_width, height=80)
        self.layer_dob.config(**self.layer_props(self.gray2))
        self.lab_dob = Label(self.layer_dob)
        self.lab_dob.config(**self.title_props("Birthdays range"))
        self.lab_dob.pack()

        # Export layer
        self.layer_export = Frame(self.sect_left)
        self.layer_export.place(y=400, width=self.sect_width, height=80)
        self.layer_export.config(**self.layer_props(self.gray2))
        self.lab_export = Label(self.layer_export)
        self.lab_export.config(**self.title_props("Export format"))
        self.lab_export.pack()

        # Run layer
        self.layer_run = Frame(self.sect_left)
        self.layer_run.place(y=480, width=self.sect_width, height=100)
        self.layer_run.config(**self.layer_props(self.gray2))
        self.lab_run = Label(self.layer_run)
        self.lab_run.config(**self.title_props("Run"))
        self.lab_run.pack()

        # About layer
        self.layer_about = Frame(self.sect_right)
        self.layer_about.place(width=self.sect_width, height=385)
        self.layer_about.config(**self.layer_props(self.gray2))
        self.lab_about = Label(self.layer_about)
        self.lab_about.config(**self.title_props("About Red Snapper"))
        self.lab_about.pack()

        # sliders
        self.sli_wom = Scale(self.layer_sliders, from_=0, to=100)
        self.sli_wom.config(**self.sli_props())
        self.sli_wom.config(label="Percentage of women in dataset.")
        self.sli_wom.pack(padx=20, pady=10)
        self.sli_wom.set(50)

        self.sli_nam = Scale(self.layer_sliders, from_=0, to=100)
        self.sli_nam.config(**self.sli_props())
        self.sli_nam.config(label="Percentage of people with double name")
        self.sli_nam.pack(padx=20, pady=0)
        self.sli_nam.set(25)

        self.sli_sur = Scale(self.layer_sliders, from_=0, to=100)
        self.sli_sur.config(**self.sli_props())
        self.sli_sur.config(label="Percentage of people with double surname")
        self.sli_sur.pack(padx=20, pady=10)
        self.sli_sur.set(15)

        # DOB Layer - From Date
        self.dob1_val.set("1945")
        self.lab_dob1 = Label(self.layer_dob, text="From date")
        self.lab_dob1.config(**self.label_props())
        self.lab_dob1.pack(side=LEFT, padx=5)
        self.box_dob1 = Spinbox(self.layer_dob)
        self.box_dob1.config(from_=1945, to=1996, textvariable=self.dob1_val)
        self.box_dob1.config(**self.date_props())
        self.box_dob1.pack(side=LEFT)

        # DOB Layer - To Date
        self.dob2_val.set("1997")
        self.lab_dob2 = Label(self.layer_dob, text="To date")
        self.lab_dob2.config(**self.label_props())
        self.lab_dob2.pack(side=LEFT, padx=17)
        self.box_dob2 = Spinbox(self.layer_dob)
        self.box_dob2.config(from_=1946, to=1997, textvariable=self.dob2_val)
        self.box_dob2.config(**self.date_props())
        self.box_dob2.pack(side=LEFT)

        # Export layer - JSON / CSV radio buttons
        self.rb_choice.set("CSV")
        self.rb1 = Radiobutton(self.layer_export,
                               text="Save as CSV",
                               variable=self.rb_choice,
                               value="CSV")
        self.rb1.config(**self.radio_props())
        self.rb1.place(y=35, x=50)
        self.rb2 = Radiobutton(self.layer_export,
                               text="Save as JSON",
                               variable=self.rb_choice,
                               value="JSON")
        self.rb2.config(**self.radio_props())
        self.rb2.place(y=35, x=200)

        # Run layer - no of records spinbox
        self.df_records.set("100")
        self.box_gen = Spinbox(self.layer_run)
        self.box_gen.config(from_=1, to=999999, textvariable=self.df_records)
        self.box_gen.config(increment=1000, width=19)
        self.box_gen.place(x=70, y=53)
        self.lab_gen = Label(self.layer_run, text="Number of records")
        self.lab_gen.config(**self.label_props())
        self.lab_gen.place(x=70, y=30)

        # Run layer - generate button
        self.btn_run = ttk.Button(self.layer_run)
        self.btn_run.place(x=225, y=35, height=40)
        self.btn_run_reset()

        # header & logo section
        self.sect_logo = Frame(master)
        self.sect_logo.place(x=-15, y=30, width=350, height=120)
        self.sect_logo.place(relx=1.0, anchor="ne")
        self.logo = PhotoImage(file="./redsnapper/interface/logo.png")
        self.lab_logo = Label(self.sect_logo, image=self.logo)
        self.lab_logo.config(background=self.gray1)
        self.lab_logo.pack()

        # About
        box_about = Text(self.layer_about)
        box_about.config(**self.text_props())
        box_about.pack(pady=10, padx=10)
        txt = """This program allows generating thousands of rows filled with pseudo-random data. """ \
              + """\nThe generated records (like name,  """ \
              + """ surname, date of birth, e-mail address) can be used to provide sample data to:
        - test query performance of your database 
        - practice data operations with BI tools.""" \
              + """ \nThe application uses 4 processes to generate data simultaneously. """ \
              + """ It takes about 25 seconds to create 1 million rows of data.\n"""

        box_about.insert(END, txt)

    # styling wrapped into functions for reusability
    def sli_props(self):
        """
        bundle popular attributes of TK control so they can be reused
        :return: dict of bundled props
        """
        return {
            "length": 300,
            "orient": HORIZONTAL,
            "sliderrelief": FLAT,
            "showvalue": 1,
            "resolution": 1,
            "sliderlength": 25,
            "tickinterval": 100,
            "font": ("Arial", 8),
            "activebackground": "#333333",
            "background": "#666666",
            "troughcolor": "#d0d4d2",
            "foreground": "#eeeeee",
            "highlightthickness": 8,
            "highlightcolor": "#ffffff",
            "highlightbackground": self.gray3,
            "borderwidth": 1
        }

    @staticmethod
    def layer_props(bgcolor):
        """
        bundle popular attributes of TK control so they can be reused
        :return: dict of bundled props
        """
        return {"relief": RIDGE, "background": bgcolor}

    def title_props(self, title):
        """
        bundle popular attributes of TK control so they can be reused
        :return: dict of bundled props
        """
        return {
            "text": title,
            "background": self.gray3,
            "width": self.sect_width,
            "borderwidth": 1,
            "relief": RIDGE
        }

    def radio_props(self):
        """
        bundle popular attributes of TK control so they can be reused
        :return: dict of bundled props
        """
        return {
            "background": self.gray2,
            "activebackground": self.gray2,
        }

    def date_props(self):
        """
        bundle popular attributes of TK control so they can be reused
        :return: dict of bundled props
        """
        return {
            "width": 8,
            "increment": 1,
            "font": ("Arial", 8),
            "background": "#666666",
            "buttonbackground": "#666666",
            "foreground": "#eeeeee",
            "highlightthickness": 8,
            "highlightcolor": "#ffffff",
            "highlightbackground": self.gray2,
            "borderwidth": 1
        }

    def label_props(self):
        """
        bundle popular attributes of TK control so they can be reused
        :return: dict of bundled props
        """
        return {
            "background": self.gray2,
            "highlightcolor": "#ffffff",
            "highlightbackground": self.gray2,
            "borderwidth": 1
        }

    def text_props(self):
        """
        bundle popular attributes of TK control so they can be reused
        :return: dict of bundled props
        """
        return {
            "font": ("Arial", 11),
            "background": self.gray1,
            "foreground": "#212121",
            "highlightthickness": 8,
            "highlightbackground": self.gray1,
            "highlightcolor": self.gray1,
            "borderwidth": 0,
            "wrap": "word",
            "spacing1": 11,
            "spacing2": 7,
        }

    def produce_props(self):
        """
        produce dict of key GUI parameters selected by user
        :return: no return parameters
        """
        rows = int(self.box_gen.get())
        props = {
            "pgender": self.sli_wom.get(),
            "pdname": self.sli_nam.get(),
            "pdsurname": self.sli_sur.get(),
            "dob1": self.box_dob1.get(),
            "dob2": self.box_dob2.get(),
        }
        dataset = Dataset().run_workload(rows, **props)
        exp_format = self.rb_choice.get()
        if exp_format == "CSV":
            Export().to_csv(dataset)
        else:
            Export().to_json(dataset)
        self.btn_run_reset()
        return

    def btn_run_reset(self):
        """
        abort button (when generating)
        :return: no return parameters
        """
        self.running = False
        self.btn_run.config(text="Generate", command=self.btn_run_start)
        return

    def btn_run_start(self):
        """
        handle the run button
        :return: no return parameters
        """
        self.running = True
        newthread = threading.Thread(target=self.produce_props)
        newthread.start()
        self.btn_run.config(text="Abort", command=self.btn_run_reset)
        return