示例#1
0
    def save_new_subtopic(self):
        if self.selected_subtopic.cget('text') != self.new_subtopic_label_text:
            return
        self.subtopic_dialog = Toplevel(self.root)
        self.subtopic_dialog.title('New Note: Subtopic Input Dialog')
        headlab = LabelH3(self.subtopic_dialog,
                          text='Unique subtopic name for new note:')
        self.subtopic_input = Entry(self.subtopic_dialog, width=64)
        self.subtopic_input.focus_set()
        buttonbox = Frame(self.subtopic_dialog)
        self.subtopic_dialog.grid_columnconfigure(0, weight=1)
        new_note_ok = Button(buttonbox,
                             text='Submit Note and Subtitle',
                             command=self.submit_new_note)
        new_note_cancel = Button(buttonbox,
                                 text='Cancel',
                                 command=self.close_subtopic_dialog)

        headlab.grid(column=0, row=0, pady=(24, 0), columnspan=2)
        self.subtopic_input.grid(column=0,
                                 row=1,
                                 padx=24,
                                 pady=24,
                                 columnspan=2)
        buttonbox.grid(column=1, row=2, sticky='we', padx=24, pady=24)
        new_note_ok.grid(column=0, row=0, sticky='e', padx=12)
        new_note_cancel.grid(column=1, row=0, sticky='e', padx=12)

        self.subtopic_dialog.bind('<Escape>', self.close_subtopic_dialog)
        self.subtopic_dialog.protocol('WM_DELETE_WINDOW',
                                      self.close_subtopic_dialog)
示例#2
0
    def __init__(self, master, resizer=True, *args, **kwargs):
        Frame.__init__(self, master, *args, **kwargs)

        self.master = master  # root or toplevel

        self.sizer = Sizer(self.master)

        self.grid_columnconfigure(0, weight=1)
        # With custom window border, you can't use the otherwise
        #   desirable option bd=2, relief='sunken' for a border on statusbar
        #   because edge grabber for resizing is below statusbar
        #   so border looks wrong there. Instead put a Separator
        #   above the statusbar frame.
        # relief = Frame(self, bd=2, relief='sunken')
        relief = Frame(self, bd=0)
        relief.grid(column=0, row=0, sticky='news')
        relief.grid_columnconfigure(0, weight=1)

        self.status_label = LabelStatusbar(relief, cursor='arrow', anchor='w')
        self.tooltip_label = LabelStatusbar(relief,
                                            bd=2,
                                            relief='sunken',
                                            anchor='e')

        if resizer is True:
            self.sizer.place(relx=1.0, x=-3, rely=1.0, anchor='se')
            self.sizer.bind('<Button-1>', self.sizer.get_pos)
        self.status_label.grid(column=0, row=0, sticky='w')
class Border(Canvas):
    def __init__(self,
                 master,
                 size=3,
                 menubar=False,
                 ribbon_menu=False,
                 *args,
                 **kwargs):
        Canvas.__init__(self, master, *args, **kwargs)
        '''
            This class replaces root and dialog borders with custom borders. 

            Since this custom "Toykinter" border is part of the app instead 
            of being controlled by Windows, its use allows clicks on the title 
            bar to be responded to with standard Tkinter configuration methods 
            and other Python code. 

            This class can't use Toykinter as a master since Toykinter is the 
            whole app and is only instantiated once, so this class has to use 
            its host toplevel as parent. Setting font size should change the size of 
            fonts, title bar, and max/min/quit buttons. The settings are 3, 4, 7, 
            for 11 pixels. Currently the title bar size is hard-coded upon
            instantiation, but should be linked to changes in font size.
        '''

        self.master = master
        self.size = size
        self.menubar = menubar
        self.ribbon_menu = ribbon_menu

        sizes = {
            3: ['tiny', 20, 0.25],
            4: ['small', 25, 0.75],
            7: ['medium', 31, 0.25],
            11: ['large', 45, 1.0]
        }

        for k, v in sizes.items():
            if self.size == k:
                self.icon_size = v[0]
                self.offset_x = v[1]
                self.rel_y = v[2]

        self.changing_values = None
        self.maxxed = False

        self.formats = make_formats_dict()

        self.make_widgets()

    def make_widgets(self):

        self.grid(column=0, row=1, sticky='news')

        self.border_top = FrameTitleBar(self.master, height=3, name='top')
        self.title_bar = FrameTitleBar(self.master)

        self.menu = Frame(self.master)
        self.ribbon = Frame(self.master)

        self.border_left = FrameTitleBar(self.master, width=3, name='left')
        self.border_right = FrameTitleBar(self.master, width=3, name='right')

        self.statusbar = StatusbarTooltips(self.master)

        self.border_bottom = FrameTitleBar(self.master,
                                           height=3,
                                           name='bottom')
        self.master.grid_columnconfigure(1, weight=1)
        self.master.grid_rowconfigure(4, weight=1)

        self.border_top.config(cursor='sb_v_double_arrow')
        self.border_left.config(cursor='sb_h_double_arrow')
        self.border_right.config(cursor='sb_h_double_arrow')
        self.border_bottom.config(cursor='sb_v_double_arrow')

        self.border_top.grid(column=0, row=0, columnspan=4, sticky='ew')
        self.title_bar.grid(column=1, row=1, columnspan=2, sticky='ew')
        if self.menubar is True:
            self.menu.grid(column=1, row=2, columnspan=2, sticky='ew')
        if self.ribbon_menu is True:
            self.ribbon.grid(column=1, row=3, columnspan=2, sticky='ew')
        self.grid(column=1, row=4, sticky='news')
        self.border_left.grid(column=0, row=1, rowspan=6, sticky='ns')
        self.border_right.grid(column=3, row=1, rowspan=6, sticky='ns')
        self.statusbar.grid(column=1, row=6, columnspan=2, sticky='ew')
        self.border_bottom.grid(column=0, row=7, columnspan=4, sticky='ew')

        self.config(cursor='arrow')

        # children of self.title_bar
        self.title_bar.grid_columnconfigure(0, weight=1)
        self.title_bar.grid_columnconfigure(1, weight=0)
        self.title_frame = FrameTitleBar(self.title_bar)
        self.buttonbox = FrameTitleBar(self.title_bar)

        self.title_frame.pack(side='left')
        self.buttonbox.place(relx=1.0, x=-100, rely=0.125, y=-2)

        # children of self.title_frame
        self.logo = TitleBarButtonSolidBG(self.title_frame,
                                          icon='logo',
                                          icon_size=self.icon_size)

        self.txt_frm = FrameTitleBar(self.title_frame)
        self.logo.pack(side='left', pady=(0, 3), padx=(0, 12))
        self.txt_frm.pack(side='left')

        # children of text_frm
        self.title_1 = LabelTitleBar(self.txt_frm,
                                     size=self.icon_size,
                                     text='Toykinter Demo')
        self.title_1b = FrameTitleBar(self.txt_frm, width=36)
        self.title_2 = LabelTitleBar(self.txt_frm,
                                     size=self.icon_size,
                                     text='for all ages')

        self.title_1.grid(column=0, row=0)
        self.title_1b.grid(column=1, row=0, sticky='ew')
        self.title_2.grid(column=2, row=0)

        # children of self.buttonbox
        self.minn = TitleBarButton(self.buttonbox,
                                   icon='min',
                                   icon_size=self.icon_size)
        self.maxx = TitleBarButton(self.buttonbox,
                                   icon='max',
                                   icon_size=self.icon_size)
        self.restore = TitleBarButton(self.buttonbox,
                                      icon='restore',
                                      icon_size=self.icon_size)
        self.quitt = TitleBarButton(self.buttonbox,
                                    icon='quit',
                                    icon_size=self.icon_size)

        self.minn.grid(column=0, row=0, sticky='w')
        self.maxx.grid(column=1, row=0, sticky='w', padx=(0, 3))
        self.restore.grid(column=1, row=0, sticky='w', padx=(0, 3))
        self.restore.grid_remove()
        self.quitt.grid(column=2, row=0, sticky='e', padx=(0, self.size))

        self.master.update_idletasks()
        to_the_left = self.buttonbox.winfo_reqwidth()
        self.buttonbox.place(relx=1.0,
                             x=-to_the_left,
                             rely=0.125,
                             y=-2 * self.rel_y)

        # bindings
        self.master.bind('<Map>', self.hide_windows_titlebar)
        self.minn.bind('<Button-1>', self.minimize)
        self.maxx.bind('<Button-1>', self.toggle_max_restore)
        self.restore.bind('<Button-1>', self.toggle_max_restore)
        self.quitt.bind('<Button-1>', close)
        x = [
            i.bind('<Map>', self.recolorize_on_restore)
            for i in (self.minn, self.quitt)
        ]

        for widg in (self.title_bar, self.title_frame, self.logo, self.title_1,
                     self.title_1b, self.title_2, self.txt_frm,
                     self.buttonbox):
            widg.bind('<B1-Motion>', self.move_window)
            widg.bind('<Button-1>', self.get_pos)
            widg.bind('<Double-Button-1>', self.toggle_max_restore)

        for widg in (self.border_top, self.border_left, self.border_right,
                     self.border_bottom):
            widg.bind('<Button-1>', self.start_edge_sizer)
            widg.bind('<B1-Motion>', self.stop_edge_sizer)
            widg.bind('<ButtonRelease-1>', self.stop_edge_sizer)

        config_generic(self.master)

    def recolorize_on_restore(self, evt):
        evt.widget.config(bg=NEUTRAL_COLOR)

    def move_window(self, evt):
        ''' Drag the window by the title frame
        '''

        self.master.update_idletasks()
        x_mouse_move_screen = evt.x_root
        y_mouse_move_screen = evt.y_root
        new_x = x_mouse_move_screen + self.adjust_x
        new_y = y_mouse_move_screen + self.adjust_y

        evt.widget.winfo_toplevel().geometry('+{}+{}'.format(new_x, new_y))

    def get_pos(self, evt):
        ''' Prepare to drag the window by the title frame. '''

        evt.widget.winfo_toplevel().lift()
        self.colorize_border()

        left_edge = self.master.winfo_rootx()
        top_edge = self.master.winfo_rooty()
        x_click_screen = evt.x_root
        y_click_screen = evt.y_root

        self.adjust_x = left_edge - x_click_screen
        self.adjust_y = top_edge - y_click_screen

    def toggle_max_restore(self, evt):
        '''
            When window is maximized, change window border button
            to restore down and vice versa. Have to return the
            Windows title bar first or Tkinter won't let it be
            maximized.
        '''

        if self.maxxed is False:
            self.maxxed = True
            self.init_geometry = evt.widget.winfo_toplevel().geometry()
            self.maxx.grid_remove()
            self.restore.grid()
            self.restore.config(bg=NEUTRAL_COLOR)
            self.maximize(evt)
        elif self.maxxed is True:
            self.maxxed = False
            self.restore.grid_remove()
            self.maxx.grid()
            self.maxx.config(bg=NEUTRAL_COLOR)
            self.restore_down(evt)

    def minimize(self, evt):
        '''
            Withdraw so return of Windows titlebar isn't visible.
            Return Windows titlebar so window can be iconified.
        '''
        dlg = evt.widget.winfo_toplevel()
        dlg.withdraw()  # this hides it
        self.master.update_idletasks()
        dlg.overrideredirect(0)
        dlg.iconify()  # this provides a taskbar icon to re-open it

    def hide_windows_titlebar(self, evt):
        self.update_idletasks()
        self.master.overrideredirect(1)

    def split_geometry_string(self, window):
        xy = window.geometry().split('+')
        wh = xy.pop(0).split('x')
        return int(wh[0]), int(wh[1]), int(xy[0]), int(xy[1])

    def maximize(self, evt):
        dlg = evt.widget.winfo_toplevel()
        self.master.update_idletasks()
        dlg.overrideredirect(0)
        dlg.attributes('-fullscreen', True)

    def restore_down(self, evt):
        dlg = evt.widget.winfo_toplevel()
        dlg.attributes('-fullscreen', False)
        dlg.geometry(self.init_geometry)

    def start_edge_sizer(self, evt):
        def pass_values():
            values = (resizee, init_geometry, click_down_x, click_down_y,
                      orig_pos_x, orig_pos_y)
            return values

        resizee = evt.widget.winfo_toplevel()
        init_geometry = resizee.geometry()

        (click_down_x, click_down_y) = resizee.winfo_pointerxy()

        orig_pos_x = resizee.winfo_rootx()
        orig_pos_y = resizee.winfo_rooty()

        self.changing_values = pass_values()

    def stop_edge_sizer(self, evt):

        values = self.changing_values
        resizee = values[0]
        init_geometry = values[1]
        click_down_x = values[2]
        click_down_y = values[3]
        orig_pos_x = values[4]
        orig_pos_y = values[5]

        click_up_x = click_down_x
        click_up_y = click_down_y
        new_pos_x = orig_pos_x
        new_pos_y = orig_pos_y

        klikt = evt.widget

        xy = init_geometry.split('+')
        wh = xy.pop(0).split('x')

        new_w = orig_wd = int(wh[0])
        new_h = orig_ht = int(wh[1])

        click_up_x = resizee.winfo_pointerx()
        click_up_y = resizee.winfo_pointery()

        dx = click_down_x - click_up_x
        dy = click_down_y - click_up_y
        if klikt.winfo_name() == 'left':
            new_w = orig_wd + dx
            new_pos_x = orig_pos_x - dx
        elif klikt.winfo_name() == 'right':
            new_w = orig_wd - dx
        elif klikt.winfo_name() == 'top':
            new_h = orig_ht + dy
            new_pos_y = orig_pos_y - dy
        elif klikt.winfo_name() == 'bottom':
            new_h = orig_ht - dy

        if new_w < 10:
            new_w = 10
        if new_h < 10:
            new_h = 10
        resizee.geometry('{}x{}+{}+{}'.format(new_w, new_h, new_pos_x,
                                              new_pos_y))

    def colorize_border(self):
        for widg in (self.title_bar, self.title_frame, self.logo, self.title_1,
                     self.title_1b, self.title_2, self.txt_frm, self.buttonbox,
                     self.border_top, self.border_left, self.border_right,
                     self.border_bottom):
            widg.config(bg=self.formats['head_bg'])
        for widg in (self.title_1, self.title_2):
            widg.config(fg=self.formats['fg'])
示例#4
0
            color = string_input
            ok = '{}\nis a\nvalid\ncolor.'.format(color.title())
            cbox_select.config(text=ok)
        else:
            cbox_select.config(text=msg)

    def test_bind_to_dropdown_items(evt):
        print("evt.widget.cget('text'):", evt.widget.cget('text'))

    root = tk.Tk()
    root.focus_set()
    root.grid_columnconfigure(0, weight=1)
    root.geometry('+500+200')

    content = Frame(root)
    content.grid()

    b = Combobox(content,
                 root,
                 callback=color_background,
                 height=75,
                 values=caseless_colors,
                 scrollbar_size=16)
    flat = ButtonFlatHilited(content, text='Apply Combo 1')
    flat.config(command=lambda button=flat: color_background(button))
    b.config_values(short_list)

    # You can't do this in ttk.Combobox:
    for widg in b.buttons:
        widg.bind('<FocusOut>', test_bind_to_dropdown_items)
示例#5
0
class MessageModel(Toplevelx):
    ''' 
        parent: modal dialog has no minimize/maximize buttons, goes where parent goes
        gparent: parent of parent might need to be destroyed on click of msg button
        title: goes on title bar of dialog using w.title('title') method
        prompt: tells the user to enter some data in an entry or combobox
        message: multiline Message widget text to inform user why dialog opened
        input: bad input from user displayed in dialog so he sees his typo/bad data
        x = inst.show(): data input by user into dialog is returned on dialog close
    '''
    def __init__(self,
                 parent,
                 gparent=None,
                 title=None,
                 prompt=None,
                 message=None,
                 input_text=None,
                 *args,
                 **kwargs):
        Toplevelx.__init__(self, parent, title=None, *args, **kwargs)

        self.edit_input = False
        self.add_data_to_db = True

        self.parent = parent
        self.gparent = gparent
        self.prompt = prompt
        self.message = message
        self.input_text = input_text

        if title:
            self.title(title)

        self.grab_set()
        self.transient(parent)

        self.make_widgets()

    def make_widgets(self):

        self.frm = Frame(self)
        self.frm.grid(column=0, row=0, pady=(0, 18))

        self.errlab = Label(self.frm, text='Input was: ')
        self.errlab.grid(column=0, row=0, padx=24, pady=(24, 0), sticky='w')
        self.errshow = LabelItalic(self.frm)
        self.errshow.grid(column=1, row=0, pady=(24, 0), sticky='w')

        self.errmsg = tk.Message(self.frm,
                                 text=self.message,
                                 bd=3,
                                 relief='raised',
                                 aspect=400)
        self.errmsg.grid(column=0, row=1, padx=36, pady=(0, 18), columnspan=2)

        self.promptlab = Label(self.frm)
        self.var = tk.StringVar()
        self.altentry = Entry(self.frm)
        self.altentry.config(textvariable=self.var)

        self.promptlab.grid(column=0, row=2, pady=24, padx=24, sticky='w')
        self.altentry.grid(column=1, row=2, pady=24, sticky='w')
        self.promptlab.grid_remove()
        self.altentry.grid_remove()

        self.altentry.focus_set()
        self.altentry.bind('<Return>', self.on_ok)

        self.bbox = Frame(self)
        self.bbox.grid(column=0, row=3, columnspan=2)

        self.done = Button(self.bbox, text='DONE', command=self.on_ok, width=9)
        self.done.grid(column=0, row=0, padx=24, pady=(12, 24))
        self.done.grid_remove()

        self.stop = Button(self.bbox,
                           text='CANCEL1',
                           command=self.on_cancel,
                           width=9)
        self.stop.grid(column=1, row=0, padx=24, pady=(12, 24))
        self.stop.grid_remove()

        self.done.focus_set()

        self.accept = Button(self.bbox,
                             text='Accept Original Input',
                             command=self.on_ok,
                             width=36)
        self.accept.grid(column=0, row=0, padx=24, pady=12)
        self.accept.grid_remove()

        self.edit = Button(self.bbox,
                           text='Submit Edited Input',
                           command=self.on_alt,
                           width=36)
        self.edit.grid(column=0, row=1, padx=24, pady=12)
        self.edit.grid_remove()

        self.cancel_all = Button(self.bbox,
                                 text="Cancel (Don't Submit Anything)",
                                 command=self.on_cancel,
                                 width=36)
        self.cancel_all.grid(column=0, row=2, padx=24, pady=(12, 36))
        self.cancel_all.grid_remove()

        self.bind('<Escape>', self.on_cancel)

        PlaySound('SystemHand', SND_ASYNC)

        self.protocol("WM_DELETE_WINDOW", self.on_cancel)

    def on_ok(self, event=None):
        print('original input is OK; input is:', self.input)

    def on_alt(self, event=None):
        self.edit_input = True
        self.destroy()

    def on_cancel(self, event=None):
        self.add_data_to_db = False
        self.destroy()
示例#6
0
    def make_widgets(self):
        def combobox_selected(combo):
            '''
                The reason this function is nested is that I have no experience 
                with overriding methods. When I tried to add `self` as the first 
                parameter, there was an error and I didn't know what to do. I 
                nested it so I wouldn't have to use `self`.
            '''
            if combo == self.combos["select_input_font"]:
                input_sample.config(font=(self.all_fonts[combo.current],
                                          self.fontSize))
            elif combo == self.combos["select_output_font"]:
                output_sample.config(font=(self.all_fonts[combo.current],
                                           self.fontSize))
            else:
                print("case not handled")
            # update_idletasks() seems to speed up the redrawing of the
            #   app with the new font
            self.update_idletasks()

        sample_text = ["Sample", "Text ABCDEFGHxyz 0123456789 iIl1 o0O"]

        self.columnconfigure(0, weight=1)
        self.rowconfigure(0, weight=1)

        sample = Frame(self)

        self.output_sample = Label(sample, text=" Output ".join(sample_text))

        self.input_sample = Entry(sample, width=50)
        self.input_sample.insert(0, " Input ".join(sample_text))

        self.fontSizeVar = tk.IntVar()
        self.fontSize = self.font_scheme[0]

        self.font_size = Scale(
            self,
            from_=8.0,
            to=26.0,
            tickinterval=6.0,
            label="Text Size",  # Can this be centered over the Scale?
            orient="horizontal",
            length=200,
            variable=self.fontSizeVar,
            command=self.show_font_size)
        self.font_size.set(self.fontSize)

        combo_names = ["select_output_font", "select_input_font"]
        self.combos = {}

        j = 2
        for name in combo_names:
            cbo = Combobox(self,
                           self.root,
                           values=self.all_fonts,
                           height=300,
                           scrollbar_size=12)
            self.combos[name] = cbo
            name = name.replace("_", " ").title()
            lab = Label(self, text=name)
            lab.grid(column=0, row=j, pady=(24, 6))
            cbo.grid(column=0, row=j + 1, pady=(6, 20))
            j += 2

        self.apply_button = Button(self, text="APPLY", command=self.apply)

        sample.grid(column=0, row=0)
        self.output_sample.grid(padx=24, pady=20)
        self.input_sample.grid(padx=24, pady=20)
        self.font_size.grid(column=0, row=1, pady=24)
        self.apply_button.grid(column=0,
                               row=7,
                               sticky="e",
                               padx=(0, 24),
                               pady=(0, 24))

        Combobox.combobox_selected = combobox_selected
示例#7
0
    def make_widgets(self):

        self.title('{}{} ({})'.format('Notes for Conclusion #',
                                      self.finding_id, self.birth_name))

        self.grid_columnconfigure(0, weight=1)
        self.grid_rowconfigure(1, weight=1)
        header = Frame(self)
        header.grid_columnconfigure(1, weight=1)
        header.grid_rowconfigure(0, weight=1)

        self.notes_dialog_header = Frame(header)

        content = Frame(self)

        left_panel = Frame(content)

        topiclab = Label(left_panel, text='Note Subtopics')

        self.toc = Listbox(left_panel,
                           self.sorted_subtopics,
                           view_height=424,
                           view_width=180,
                           scrollbar=False)

        self.new_index = len(self.subtopics)
        self.toc.insert(self.new_index, self.new_subtopic_label_text)
        self.toc.focus_set()
        self.toc.selection_set(0)

        self.toc.store_new_subtopic_name = self.store_new_subtopic_name
        self.toc.pass_ctrl_click = self.open_links_dialog
        self.toc.pass_delete_key = self.delete_note

        self.selected_subtopic = Label(content, text='New Note')

        self.note_input = ScrolledText(content)

        note_submit = Button(content,
                             text='Submit Changes',
                             command=self.save_changes)

        order = Button(content,
                       text='Change Order of Subtopics',
                       command=self.reorder_notes)

        radframe = LabelFrame(content, text='Make selected note...')

        self.public = Radiobutton(radframe,
                                  text='...public',
                                  anchor='w',
                                  variable=self.privacy,
                                  value=0,
                                  command=self.save_privacy_setting)

        self.private = Radiobutton(radframe,
                                   text='...private',
                                   anchor='w',
                                   variable=self.privacy,
                                   value=1,
                                   command=self.save_privacy_setting)

        close = Button(content, text='DONE', command=self.close_roles_dialog)

        # notes_statusbar = StatusbarTooltips(self)

        # visited = (
        # (above,
        # 'this is a notes_statusbar message',
        # 'this is a tooltip'),
        # (below,
        # 'this is also a notes_statusbar message',
        # 'this is another tooltip'))

        # run_statusbar_tooltips(
        # visited,
        # notes_statusbar.status_label,
        # notes_statusbar.tooltip_label)

        # grid in self
        header.grid(column=0, row=0, columnspan=2, pady=12, sticky='we')
        content.grid(column=0, row=1, sticky='news', padx=(0, 6))
        # notes_statusbar.grid(column=0, row=2, sticky='ew')

        # grid in header
        self.notes_dialog_header.grid(column=1, row=0, sticky='ew')
        self.notes_dialog_header.grid_columnconfigure(0, weight=1)

        # grid in content
        left_panel.grid(column=0, row=1, sticky='news', rowspan=2, pady=24)
        self.selected_subtopic.grid(column=1, row=1, sticky='w')
        self.note_input.grid(column=1,
                             row=2,
                             columnspan=3,
                             sticky='nsew',
                             padx=(0, 24),
                             pady=12)
        note_submit.grid(column=3, row=3, sticky='se')
        self.grid_rowconfigure(0, weight=1)
        self.grid_columnconfigure(0, weight=1)
        content.grid_rowconfigure(1, weight=1)
        order.grid(column=1, row=4)
        radframe.grid(column=2, row=5, sticky='n', pady=24)
        close.grid(column=3, row=6, sticky='se', padx=24, pady=(0, 24))

        # grid in left_panel
        topiclab.grid(column=0, row=0)
        self.toc.grid(column=0, row=1)
        for child in self.toc.listbox_content.winfo_children():
            child.bind('<<ListboxSelected>>', self.switch_note)

        self.subtopic_widgets = self.toc.listbox_content.winfo_children()

        # grid in radframe
        self.public.grid(column=0, row=0, sticky='news', padx=24)
        self.private.grid(column=0, row=1, sticky='news', padx=24)

        # rcm_widgets = (self.subtopic_input, self.note_input.text)
        # make_rc_menus(
        # rcm_widgets,
        # self.rc_menu,
        # note_dlg_msg,
        # header_parent=self.notes_dialog_header,
        # header=self.header,
        # which_dlg='notes')

        config_generic(self)
        center_window(self)
示例#8
0
    def make_widgets(self):

        stripview = Frame(self.parent)
        stripview.grid(column=0, row=0, padx=12, pady=12)

        self.parent.update_idletasks()
        self.colors_canvas = Canvas(
            stripview, 
            bd=1, highlightthickness=1, 
            highlightbackground=formats['highlight_bg'], 
            bg=formats['bg'],
            width=840,
            height=118
) 
        hscroll = Scrollbar(
            stripview, orient='horizontal', command=self.colors_canvas.xview)
        self.colors_canvas.configure(xscrollcommand=hscroll.set)
        
        self.colors_canvas.grid(column=0, row=0, sticky='news')
        hscroll.grid(column=0, row=1, sticky="ew")

        self.colors_content = Frame(self.colors_canvas)

        bbox1 = Frame(self.parent)
        bbox1.grid(column=0, row=1, padx=12, pady=12, sticky='we')
        bbox1.columnconfigure(1, weight=1)
        bbox1.rowconfigure(1, weight=1)

        self.try_button = Button(
            bbox1, text='TRY', width=7, command=self.config_local)
        self.try_button.grid(column=0, row=0, sticky='w')

        self.copy_button = Button(
            bbox1, text='COPY', width=7, command=self.copy_scheme)
        self.copy_button.grid(column=1, row=0)

        self.apply_button = Button(
            bbox1, text='APPLY', width=7, command=self.apply_scheme)
        self.apply_button.grid(column=2, row=0, sticky='e')

        bottom = Frame(self.parent)
        bottom.grid(column=0, row=2, padx=12, pady=12)

        addlab = LabelH3(bottom, text='New Color Scheme')
        addlab.grid(column=0, row=0, padx=6, pady=6, columnspan=2)

        self.colors_table = Frame(bottom)
        self.colors_table.grid(column=0, row=1, columnspan=2)
        self.colors_table.columnconfigure(0, weight=1)
        self.colors_table.rowconfigure(0, weight=1)

        all_schemes = get_color_schemes()

        self.h1 = Label(
            self.colors_table,
            anchor='w', 
            text=' Domain',
            font=formats['output_font'])

        self.h2 = Label(
            self.colors_table,
            anchor='w',
            text=' Color')

        opening_colors = (
            formats['bg'], 
            formats['highlight_bg'], 
            formats['head_bg'], 
            formats['fg'])

        displabel = self.make_colors_table(opening_colors)

        bbox2 = Frame(bottom)
        bbox2.grid(
            column=0, row=2, 
            padx=12, pady=12, 
            sticky='ew', columnspan=2)
        bbox2.columnconfigure(1, weight=1)
        bbox2.rowconfigure(0, weight=1)

        self.new_button = Button(
            bbox2, 
            text='CREATE NEW COLOR SAMPLE', 
            command=self.make_new_sample)
        self.new_button.grid(column=0, row=0, padx=6, pady=6, columnspan=2)

        self.make_samples()

        self.colors_canvas.create_window(
            0, 0, anchor='nw', window=self.colors_content)
        self.resize_color_samples_scrollbar()
示例#9
0
class Gallery(Frame):

    def __init__(
            self, master, notebook, graphics_tab, root, 
            canvas,
            *args, **kwargs):
        Frame.__init__(self, master, *args, **kwargs)

        self.parent = master
        self.nbook = notebook
        self.t7 = graphics_tab
        self.root = root
        self.canvas = canvas
        self.counter = 0
        self.thumb_labels = []
        self.width_strings = []
        self.height_strings = []

        formats = make_formats_dict()

        self.current_person = get_current_person()[0]

        set_window_max_size(self.parent)
        self.filter_pix_data()
        self.make_widgets()        

    def make_widgets(self):

        if self.parent.winfo_class() == 'Toplevel':
            gallery_canvas = Canvas(
                self.parent,
                bd=0,
                highlightthickness=0)

            self.gallery_content = Frame(gallery_canvas)
            gallery_canvas.grid(row=0, column=0, sticky='nsew')

            self.parent.grid_columnconfigure(0, weight=1)
            self.parent.grid_rowconfigure(0, weight=1)
        else:
            self.gallery_content = Frame(self.parent)
            self.gallery_content.grid(column=0, row=0)

        self.thumb_canvas = Canvas(
            self.gallery_content, 
            bd=0, 
            highlightthickness=0,
            bg=formats['bg'])
        self.thumb_canvas.pack(padx=12, pady=12)

        self.thumbstrip = Frame(self.thumb_canvas)
        self.thumbstrip.pack(side='top')

        self.previous_img = Button(self.gallery_content, text='<<', width=6)

        self.pic_canvas = Canvas(
            self.gallery_content, 
            highlightbackground=formats['bg'])
        self.pic_canvas.bind('<Button-1>', self.focus_clicked)
        self.pic_canvas.bind('<Button-1>', self.scroll_start, add='+')
        self.pic_canvas.bind('<B1-Motion>', self.scroll_move)     

        self.img_path = '{}treebard_gps\data\{}\images\{}'.format(
            root_drive, self.image_dir, self.main_pic)
        img_big = Image.open(self.img_path)
        self.tk_img = ImageTk.PhotoImage(img_big)
        self.pic_canvas.image = self.tk_img

        z = 0
        self.current_pictures = sorted(self.current_pictures)

        for img in self.current_pictures:
            pic_col = Frame(self.thumbstrip)
            pic_col.pack(side='left', expand=1, fill='y')

            pic_file = img
            self.img_path = '{}treebard_gps\data\{}\images\{}'.format(root_drive, self.image_dir, pic_file)
            idx = len(pic_file)
            bare = pic_file[0:idx-4]
            thumbsy = Image.open(self.img_path)
            self.width_strings.append(thumbsy.width)
            self.height_strings.append(thumbsy.height)
            thumbsy.thumbnail((185,85))
            thumb_path = 'images/{}_tmb.png'.format(bare)
            # overwrites file by same name if it exists 
            thumbsy.save(thumb_path)
            small = ImageTk.PhotoImage(file=thumb_path, master=self.thumbstrip)

            thumb = Label(
                pic_col,
                image=small)
            thumb.pack(expand=1, fill='y')
            thumb.image = small

            self.thumb_labels.append(thumb)

            # lambda used to save value in loop
            if self.parent.winfo_class() == 'Toplevel':
                rad = Radiobutton(
                    pic_col,
                    takefocus=0,
                    value=pic_file,
                    command=lambda pic_file=pic_file: self.set_main_pic(
                        pic_file))   
                rad.pack()

                if rad['value'] == self.main_pic:
                    rad.select()

            else:                
                rad = Frame(
                    pic_col,
                    height=24,
                    width=24)   
                rad.pack(expand=1, fill='both')
                if self.parent.winfo_name() == 'source_tab':
                    pic_file = '{}, {}'.format(self.source, pic_file)
            
            create_tooltip(rad, pic_file)

            z += 1

        self.pil_img = img_big
        self.fit_canvas_to_pic()

        self.thumb_dict = dict(zip(self.thumb_labels, self.current_pictures))
        self.next_img = Button(self.gallery_content, text='>>', width=6)

        panel = Frame(self.gallery_content)

        subject = LabelH3(panel, text=self.curr_entity)
        subject.grid(column=0, row=0, sticky='ew')

        # labels with selectable multiline text
        self.caption_lab = MessageCopiable(panel, width=36)
        self.picfile_lab = MessageCopiable(panel, width=36)
        self.picsize_lab = MessageCopiable(panel, width=36)
        edit = Button(
            panel, 
            text='EDIT', 
            width=8, 
            command=lambda graphics=self.t7: self.go_to_graphics(graphics))

        self.previous_img.config(command=self.back)
        self.next_img.config(command=self.forward)

        panel.grid_rowconfigure(0, weight=2)
        panel.grid_rowconfigure(1, weight=1)
        panel.grid_rowconfigure(4, weight=2)

        self.caption_lab.grid(column=0, row=1, pady=(12,12), sticky='ew')
        self.caption_lab.insert(1.0, self.caption_text)

        self.picfile_lab.grid(column=0, row=2, pady=(12,0), sticky='ew')
        self.picfile_lab.insert(1.0, self.img_path)

        self.picsize_lab.grid(column=0, row=3, pady=(0,24), sticky='ew')
        self.picsize_lab.insert(
            1.0, 
            'width: {}, height: {}'.format(
                self.pil_img.width, self.pil_img.height))

        edit.grid(column=0, row=4)

        self.caption_lab.set_height()
        self.picfile_lab.set_height()
        self.picsize_lab.set_height()

        self.previous_img.pack(side='left', padx=12)
        self.pic_canvas.pack(side='left', expand=1, fill='y')
        self.next_img.pack(side='left', padx=12)

        panel.pack(side='left', expand=1, fill='y')

        for thumb in self.thumb_labels:
            thumb.bind('<Button-1>', self.show_clicked)

        self.pic_canvas.bind('<Key-Left>', lambda evt: self.back())

        self.pic_canvas.bind('<Key-Right>', lambda evt: self.forward())

        # add statusbar-tooltips

        self.visited = (
            (self.thumbstrip, 
                "Thumbnail Views", 
                "Click thumbnail to display. Hover below to see "
                   "file name. If radio, click to make main image."),
            (self.pic_canvas, 
                "Image", 
                "Arrow keys change image when it's in focus."),
            (self.previous_img, 
                "Left Button", 
                "Click with mouse or when highlighted click with spacebar."),
            (self.next_img, 
                "Right Button", 
                "Click with mouse or when highlighted click with spacebar.")) 

        if self.parent.winfo_class() == 'Toplevel':
     
            box = Frame(self.parent)
            box.grid(column=0, row=1, pady=12)

            close = Button(
                box, 
                text='CLOSE', 
                width=8, 
                command=self.cancel_gallery)  
            close.grid()
            self.parent.protocol('WM_DELETE_WINDOW', self.cancel_gallery)

        self.thumb_canvas.create_window(0, 0, anchor='nw', window=self.thumbstrip)
        self.thumb_canvas.config(
            scrollregion=(
                0, 0, 
                self.thumbstrip.winfo_reqwidth(), 
                self.thumbstrip.winfo_reqheight()))
        
        self.thumb_canvas.config(
            width=self.root.maxsize()[0], 
            height=self.thumbstrip.winfo_reqheight())
        
        scroll_width = int(self.thumb_canvas['scrollregion'].split(' ')[2])

        if scroll_width >= int(self.thumb_canvas['width']):
            for child in self.thumbstrip.winfo_children():
                for gchild in child.winfo_children():
                    gchild.bind("<Enter>", self.thumb_start)
                    gchild.bind("<Motion>", self.thumb_move)

        if self.parent.winfo_class() == 'Toplevel':

            gallery_canvas.create_window(
                0, 0, anchor=tk.NW, window=self.gallery_content)
            self.resize_scrollbar()
            self.resize_window()

        self.config_labels()
            
    def resize_scrollbar(self):
        self.parent.update_idletasks()                     
        self.pic_canvas.config(scrollregion=self.pic_canvas.bbox("all")) 

    def resize_window(self):
        self.parent.update_idletasks()
        page_x = self.gallery_content.winfo_reqwidth()
        page_y = self.gallery_content.winfo_reqheight()+48
        self.parent.geometry('{}x{}'.format(page_x, page_y))

    def cancel_gallery(self, event=None):
        self.root.focus_set()
        self.parent.destroy() 

    def focus_clicked(self, evt):
        evt.widget.focus_set()

    def hilite(evt):
        evt.widget.config(bg=formats['highlight_bg'])

    def unhilite(evt):
        evt.widget.config(bg=formats['bg'])

    def show_clicked(self, evt):

        select_pic = self.current_pictures.index(self.thumb_dict[evt.widget])

        self.chosen_picfile = self.current_pictures[select_pic]
        current_dir = files.get_current_file()[1]
        self.img_path = '{}treebard_gps\data\{}\images\{}'.format(root_drive, current_dir, self.chosen_picfile)

        pix_data = self.get_current_pix_data()
        for tup in pix_data:
            if tup[1] == self.chosen_picfile:
                self.caption_text = tup[2]

        new = Image.open(self.img_path)
        self.tk_img = ImageTk.PhotoImage(new)

        self.pil_img = new
        self.fit_canvas_to_pic()

        self.pic_canvas.image = self.tk_img

        self.pic_canvas.config(
            scrollregion=(0, 0, self.pil_img.width, self.pil_img.height))

        self.config_labels()

        self.counter = select_pic

    def scroll_start(self, event):
        self.pic_canvas.scan_mark(event.x, event.y)

    def scroll_move(self, event):
        self.pic_canvas.scan_dragto(event.x, event.y, gain=5)

    def thumb_start(self, event):
        self.thumb_canvas.scan_mark(event.x, event.y)

    def thumb_move(self, event):
        self.thumb_canvas.scan_dragto(event.x, event.y, gain=1)

    def go_to_graphics(self, graphics):

        # if frame with this name already exists it's replaced
        # https://stackoverflow.com/questions/59518905/naming-a-widget-to-auto-destroy-replace-it
        picwin = Frame(graphics, name='exists')
        picwin.pack()

        curr_pic = self.picfile_lab.get(1.0, 'end')
        curr_pic = curr_pic.strip('\n')

        img_path = curr_pic
        edit_pic = Image.open(img_path)
        edit_img = ImageTk.PhotoImage(edit_pic)
        editlab = LabelStay(
            picwin,
            image=edit_img)

        editlab.image = edit_img
        self.nbook.select(graphics)

        # scroll to top so controls are seen when tab opens
        self.canvas.yview_moveto(0.0)
        
        if self.parent.winfo_class() == 'Toplevel':
            self.parent.lower(belowThis=self.nbook)

        editlab.pack() # When this grids a big pic, the whole notebook gets big
        
        # prevent large pics from blowing up size of the whole notebook
        #    when placed here by edit button on a gallery
        #    Will need more attention when ready to make the graphics tab.
        editlab.config(width=700, height=700)

    def filter_pix_data(self):

        def second_item(s):
            return s[1]

        pix_data = self.get_current_pix_data()

        pix_data = sorted(pix_data, key=second_item) 

        for tup in pix_data:
            if tup[3] == 1:
                self.main_pic = tup[1]
                self.caption_text = tup[2]
                if self.parent.winfo_name() == 'source_tab':
                    self.source = tup[4]

        self.current_pictures = []
        for tup in pix_data:
            self.current_pictures.append(tup[1]) 
            curr_entity = tup[0]
        self.curr_entity = curr_entity
        self.caption_path = []
        for tup in pix_data:
            self.caption_path.append((tup[1], tup[2])) 

    def back(self, evt=None):

        if self.counter == 0:
            self.counter = len(self.caption_path)    
        self.counter -= 1 
        current_dir = files.get_current_file()[1]
        self.img_path = '{}treebard_gps\data\{}\images\{}'.format(
            root_drive, current_dir, self.caption_path[self.counter][0])
        self.caption_text = self.caption_path[self.counter][1]

        new = Image.open(self.img_path)
        self.tk_img = ImageTk.PhotoImage(new)
        self.pil_img = new
        self.fit_canvas_to_pic()
        self.pic_canvas.image = self.tk_img

        self.pic_canvas.config(
            scrollregion=(0, 0, self.pil_img.width, self.pil_img.height))

        self.config_labels()

    def forward(self, evt=None):

        self.counter += 1 
        if self.counter == len(self.caption_path):
            self.counter = 0
        current_dir = files.get_current_file()[1]
        self.img_path = '{}treebard_gps\\data\\{}\\images\\{}'.format(
            root_drive, current_dir, self.caption_path[self.counter][0])
        self.caption_text = self.caption_path[self.counter][1]

        new = Image.open(self.img_path)
        self.tk_img = ImageTk.PhotoImage(new)
        self.pil_img = new
        self.fit_canvas_to_pic()
        self.pic_canvas.image = self.tk_img

        self.pic_canvas.config(
            scrollregion=(0, 0, self.pil_img.width, self.pil_img.height))

        self.config_labels()

    def get_current_pix_data(self):

        current_file_tup = files.get_current_file()
        current_file = current_file_tup[0]
        self.image_dir =  current_file_tup[1]
        conn = sqlite3.connect(current_file)
        cur = conn.cursor()

        if self.parent.winfo_name() == 'place_tab':
            cur.execute(select_all_place_images)
            # cur.execute('''
                # SELECT places, images, caption, main_image
                # FROM images_entities
                    # JOIN place
                        # ON images_entities.place_id = place.place_id 
                    # JOIN current
                        # ON current.place_id = place.place_id
                    # JOIN image
                        # ON image.image_id = images_entities.image_id 
                # ''')
        elif self.parent.winfo_name() == 'source_tab':
            cur.execute(select_all_source_images)
            # cur.execute('''
                # SELECT citations, images, caption, main_image, sources
                # FROM images_entities
                    # JOIN source
                        # ON citation.source_id = source.source_id
                    # JOIN citation
                        # ON images_entities.citation_id = citation.citation_id
                    # JOIN current
                        # ON current.citation_id = citation.citation_id
                    # JOIN image
                        # ON image.image_id = images_entities.image_id 
                # ''')
        elif self.parent.winfo_class() == 'Toplevel': # person images
            cur.execute(select_all_person_images, (self.current_person,))
            # cur.execute(
            # '''
                # SELECT names, images, caption, main_image
                # FROM images_entities
                    # JOIN person
                        # ON images_entities.person_id = person.person_id
                    # JOIN image
                        # ON image.image_id = images_entities.image_id 
                    # JOIN name
                        # ON person.person_id = name.person_id
                # WHERE images_entities.person_id = ?
                    # AND name_type_id = 1
            # ''',
            # (self.current_person,))

        if self.parent.winfo_class() != 'Toplevel':
            pix_data = cur.fetchall()
        else:
            pix_data = cur.fetchall()
            pix_data = [list(i) for i in pix_data]
        cur.close()
        conn.close()            

        return pix_data

    def fit_canvas_to_pic(self):

        # make the buttons stay in one place as pics change
        max_wd = max(self.width_strings)
        max_ht = max(self.height_strings)
        scr_wd = self.root.winfo_screenwidth()
        scr_ht = self.root.winfo_screenheight()

        FULL = 0.55

        if max_wd <= scr_wd * FULL:
            gallery_wd = max_wd
        else:
            gallery_wd = scr_wd * FULL
        if max_ht <= scr_ht * FULL:
            gallery_ht = max_ht
        else:
            gallery_ht = scr_ht * FULL

        self.pic_canvas.config(
            scrollregion=(0, 0, self.pil_img.width, self.pil_img.height),
            width=gallery_wd,
            height=gallery_ht)

        if (self.pil_img.width >= gallery_wd and 
                self.pil_img.height >= gallery_ht):
            image = self.pic_canvas.create_image(
                0, 0, anchor='nw', image=self.tk_img)

        elif (self.pil_img.width <= gallery_wd and 
                self.pil_img.height >= gallery_ht):
            image = self.pic_canvas.create_image(
                 self.pic_canvas.winfo_reqwidth()/2, 0, 
                 anchor='n', image=self.tk_img)

        elif (self.pil_img.width >= gallery_wd and 
                self.pil_img.height <= gallery_ht):
            image = self.pic_canvas.create_image(
                0, self.pic_canvas.winfo_reqheight()/2, 
                anchor='w', image=self.tk_img)

        elif (self.pil_img.width <= gallery_wd and 
                self.pil_img.height <= gallery_ht):
            image = self.pic_canvas.create_image(
            self.pic_canvas.winfo_reqwidth()/2,
            self.pic_canvas.winfo_reqheight()/2,
            anchor='center', 
            image=self.tk_img)

    def config_labels(self): 

        for widg in (self.caption_lab, self.picfile_lab, self.picsize_lab):
            widg.config(state='normal')
            widg.delete(1.0, 'end')

        self.caption_lab.insert(1.0, self.caption_text)
        self.picfile_lab.insert(1.0, self.img_path)
        self.picsize_lab.insert(
            1.0, 'width: {}, height: {}'.format(
                self.pil_img.width, self.pil_img.height))

        for widg in (self.caption_lab, self.picfile_lab, self.picsize_lab):
            widg.set_height()

    def set_main_pic(self, val): 

        radio_value = (val,)
        current_file = files.get_current_file()[0]
        conn = sqlite3.connect(current_file)
        conn.execute("PRAGMA foreign_keys = 1")
        cur = conn.cursor()
        cur.execute(select_current_person_id)
        # cur.execute('''
            # SELECT person_id 
            # FROM current WHERE current_id = 1''')
        curr_per = cur.fetchone()
        curr_per = curr_per
        cur.execute(select_current_person_image, curr_per)
        # cur.execute('''
            # SELECT images 
            # FROM image 
                # JOIN images_entities 
                    # ON image.image_id = images_entities.image_id 
            # WHERE main_image = 1 
                # AND images_entities.person_id = ?''', curr_per)
        old_top_pic = cur.fetchone()
        cur.execute(update_images_entities_zero, curr_per)
        # cur.execute('''
            # UPDATE images_entities 
            # SET main_image = 0 
            # WHERE main_image = 1 
                # AND images_entities.person_id = ?''', curr_per)
        conn.commit()
        cur.execute(update_images_entities_one, radio_value)
        # cur.execute('''
            # UPDATE images_entities 
            # SET main_image = 1
            # WHERE image_id = (
                # SELECT image_id 
                # FROM image WHERE images = ?)
            # AND person_id = 
                # (SELECT current.person_id 
                # FROM current WHERE current_id = 1)''', radio_value)

        conn.commit()
        cur.close()
        conn.close() 
示例#10
0
    def make_widgets(self):
        def show_message():

            window.columnconfigure(1, weight=1)
            window.rowconfigure(1, weight=1)
            lab = MessageHilited(window,
                                 text=self.message,
                                 justify='left',
                                 aspect=500)
            lab.grid(column=1, row=1, sticky='news', ipady=18)

        def ok():
            if self.do_on_ok:
                self.do_on_ok()
            cancel()

        def cancel():
            self.new_places_dialog.destroy()

        size = (self.parent.winfo_screenwidth(),
                self.parent.winfo_screenheight())
        self.new_places_dialog = Toplevel(self.parent)
        self.new_places_dialog.geometry("+84+84")
        self.new_places_dialog.maxsize(width=int(size[0] * 0.85),
                                       height=int(size[1] * 0.95))
        self.new_places_dialog.columnconfigure(1, weight=1)
        self.new_places_dialog.rowconfigure(4, weight=1)
        canvas = Border(self.new_places_dialog, size=3)  # don't hard-code size
        canvas.title_1.config(text=self.title)
        canvas.title_2.config(text='')

        window = Frame(canvas)
        canvas.create_window(0, 0, anchor='nw', window=window)
        scridth = 16
        scridth_n = Frame(window, height=scridth)
        scridth_w = Frame(window, width=scridth)
        scridth_n.grid(column=0, row=0, sticky='ew')
        scridth_w.grid(column=0, row=1, sticky='ns')
        # DO NOT DELETE THESE LINES, UNCOMMENT IN REAL APP
        # self.treebard.scroll_mouse.append_to_list([canvas, window])
        # self.treebard.scroll_mouse.configure_mousewheel_scrolling()

        window.vsb = Scrollbar(self.new_places_dialog,
                               hideable=True,
                               command=canvas.yview,
                               width=scridth)
        window.hsb = Scrollbar(self.new_places_dialog,
                               hideable=True,
                               width=scridth,
                               orient='horizontal',
                               command=canvas.xview)
        canvas.config(xscrollcommand=window.hsb.set,
                      yscrollcommand=window.vsb.set)
        window.vsb.grid(column=2, row=4, sticky='ns')
        window.hsb.grid(column=1, row=5, sticky='ew')

        buttonbox = Frame(window)
        b1 = Button(buttonbox, text=self.button_labels[0], width=7, command=ok)
        b2 = Button(buttonbox,
                    text=self.button_labels[1],
                    width=7,
                    command=cancel)

        scridth_n.grid(column=0, row=0, sticky='ew')
        scridth_w.grid(column=0, row=1, sticky='ns')
        window.columnconfigure(2, weight=1)
        window.rowconfigure(1, minsize=60)
        buttonbox.grid(column=1, row=3, sticky='se', pady=6)

        b1.grid(column=0, row=0)
        b2.grid(column=1, row=0, padx=(2, 0))

        self.frm = Frame(window)
        self.frm.grid(column=1, row=2, sticky='news', pady=12)

        show_message()
        self.show_choices()

        resize_scrolled_content(self.new_places_dialog, canvas, window)

        self.new_places_dialog.focus_set()
示例#11
0
class NewPlaceDialog():
    def __init__(self,
                 parent,
                 place_dicts,
                 message,
                 title,
                 button_labels,
                 treebard,
                 do_on_ok=None,
                 selection=None):

        self.parent = parent
        self.place_dicts = place_dicts
        self.message = message
        self.title = title
        self.button_labels = button_labels
        self.treebard = treebard
        self.do_on_ok = do_on_ok

        self.got_row = 0
        self.got_nest = None
        self.edit_hint_id = 0
        self.hint_to_edit = None
        self.edit_rows = {}
        # print("line", looky(seeline()).lineno, "self.place_dicts:", self.place_dicts)
        self.make_widgets()

    def make_widgets(self):
        def show_message():

            window.columnconfigure(1, weight=1)
            window.rowconfigure(1, weight=1)
            lab = MessageHilited(window,
                                 text=self.message,
                                 justify='left',
                                 aspect=500)
            lab.grid(column=1, row=1, sticky='news', ipady=18)

        def ok():
            if self.do_on_ok:
                self.do_on_ok()
            cancel()

        def cancel():
            self.new_places_dialog.destroy()

        size = (self.parent.winfo_screenwidth(),
                self.parent.winfo_screenheight())
        self.new_places_dialog = Toplevel(self.parent)
        self.new_places_dialog.geometry("+84+84")
        self.new_places_dialog.maxsize(width=int(size[0] * 0.85),
                                       height=int(size[1] * 0.95))
        self.new_places_dialog.columnconfigure(1, weight=1)
        self.new_places_dialog.rowconfigure(4, weight=1)
        canvas = Border(self.new_places_dialog, size=3)  # don't hard-code size
        canvas.title_1.config(text=self.title)
        canvas.title_2.config(text='')

        window = Frame(canvas)
        canvas.create_window(0, 0, anchor='nw', window=window)
        scridth = 16
        scridth_n = Frame(window, height=scridth)
        scridth_w = Frame(window, width=scridth)
        scridth_n.grid(column=0, row=0, sticky='ew')
        scridth_w.grid(column=0, row=1, sticky='ns')
        # DO NOT DELETE THESE LINES, UNCOMMENT IN REAL APP
        # self.treebard.scroll_mouse.append_to_list([canvas, window])
        # self.treebard.scroll_mouse.configure_mousewheel_scrolling()

        window.vsb = Scrollbar(self.new_places_dialog,
                               hideable=True,
                               command=canvas.yview,
                               width=scridth)
        window.hsb = Scrollbar(self.new_places_dialog,
                               hideable=True,
                               width=scridth,
                               orient='horizontal',
                               command=canvas.xview)
        canvas.config(xscrollcommand=window.hsb.set,
                      yscrollcommand=window.vsb.set)
        window.vsb.grid(column=2, row=4, sticky='ns')
        window.hsb.grid(column=1, row=5, sticky='ew')

        buttonbox = Frame(window)
        b1 = Button(buttonbox, text=self.button_labels[0], width=7, command=ok)
        b2 = Button(buttonbox,
                    text=self.button_labels[1],
                    width=7,
                    command=cancel)

        scridth_n.grid(column=0, row=0, sticky='ew')
        scridth_w.grid(column=0, row=1, sticky='ns')
        window.columnconfigure(2, weight=1)
        window.rowconfigure(1, minsize=60)
        buttonbox.grid(column=1, row=3, sticky='se', pady=6)

        b1.grid(column=0, row=0)
        b2.grid(column=1, row=0, padx=(2, 0))

        self.frm = Frame(window)
        self.frm.grid(column=1, row=2, sticky='news', pady=12)

        show_message()
        self.show_choices()

        resize_scrolled_content(self.new_places_dialog, canvas, window)

        self.new_places_dialog.focus_set()

    def ok_hint(self):
        edit_row = self.edit_rows[self.got_nest]
        new_hint = edit_row.ent.get()
        conn = sqlite3.connect(current_file)
        cur = conn.cursor()
        cur.execute(update_place_hint, ((new_hint, self.edit_hint_id)))
        conn.commit()
        cur.close()
        conn.close()

        self.hint_to_edit.config(text="hint: {}".format(new_hint))
        edit_row.remove_edit_row()

    def make_edit_row(self, parent, row=None):
        edit_row = EditRow(parent, self.ok_hint)
        self.edit_rows[parent] = edit_row

    def grid_edit_row(self, hint):
        edit_row = self.edit_rows[self.got_nest]
        edit_row.grid(column=0, row=self.got_row, sticky='ew', columnspan=2)
        edit_row.lift()
        for child in self.got_nest.winfo_children():
            if child.grid_info()['column'] == 0:
                if child.grid_info()['row'] == self.got_row - 1:
                    self.edit_hint_id = int(child.cget('text').split(': ')[0])
            elif child.grid_info()['column'] == 1:
                if child.grid_info()['row'] == self.got_row:
                    if child.winfo_class() == 'Label':
                        self.hint_to_edit = child
        edit_row.ent.delete(0, 'end')
        edit_row.ent.insert(0, hint)
        edit_row.ent.focus_set()

    def get_clicked_row(self, evt):
        self.got_row = evt.widget.grid_info()['row']
        self.got_nest = evt.widget.master

    def on_hover(self, evt):
        evt.widget.config(text='Edit')

    def on_unhover(self, evt):
        evt.widget.config(text='')

    def show_choices(self):
        conn = sqlite3.connect(current_file)
        cur = conn.cursor()

        self.radvars = []
        for dd in self.place_dicts:
            self.var = tk.IntVar(None, 0)
            self.radvars.append(self.var)

        d = 0
        t = 0
        bullet = len(self.place_dicts)
        # configure place_id for query
        for dkt in self.place_dicts:
            add_new_place_option = False
            place_hints = []
            if len(dkt["id"]) == 1:
                if dkt.get("temp_id") is None:
                    place_id = (dkt["id"][0], )
                else:
                    place_id = (dkt["id"][0])
                    add_new_place_option = True
            elif len(dkt["id"]) > 1:
                if dkt.get("temp_id") is not None:
                    add_new_place_option = True
                place_id = dkt["id"]
            elif dkt.get("temp_id") is None:
                place_id = ("none", )
            elif dkt.get("temp_id"):
                # place id will be int type which marks it as a new place
                place_id = dkt["temp_id"]
            else:
                print("line", looky(seeline()).lineno, "case not handled")
            if type(place_id) is int:
                place_hints.append('')
            else:
                for num in place_id:
                    if num == "none":
                        place_hints.append('')
                    else:
                        cur.execute(select_place_hint, (num, ))
                        place_hint = cur.fetchone()
                        if place_hint[0] is None:
                            place_hint = ''
                        else:
                            place_hint = place_hint[0]
                        place_hints.append(place_hint)
            # reconfigure place_id for display
            if type(place_id) is int:
                if dkt["temp_id"] is not None and len(dkt["id"]) > 0:
                    place_hints.append('')
            elif add_new_place_option is True:
                place_hints.append('')
            elif len(place_id) == 1:
                place_id = place_id[0]
            else:
                print("line", looky(seeline()).lineno, "case not handled")
            place_input = dkt["input"]
            place_string = '{}: {}, place ID #{}'.format(
                bullet, place_input, place_id)

            lab = Label(self.frm, text=place_string)
            lab.grid(column=0, row=d, sticky='w')

            self.hint_frm = Frame(self.frm, name="nest{}".format(bullet - 1))
            self.hint_frm.grid(column=0,
                               row=d + 1,
                               sticky='w',
                               padx=(0, 3),
                               columnspan=2)
            self.hint_frm.columnconfigure(0, minsize=48)

            self.make_edit_row(self.hint_frm)

            h = 0
            row = 0
            for hint in place_hints:
                if dkt.get("temp_id") is not None and len(dkt["id"]) > 0:
                    # user will choose between a new ID or one of the existing IDs
                    new_id = dkt["temp_id"]
                    last_idx = len(dkt["id"])
                    if h == last_idx:
                        current_id = new_id
                        rad_string = "{}: {} (new place and new place ID)".format(
                            current_id, dkt["input"])
                    else:
                        current_id = dkt["id"][h]
                        cur.execute(select_first_nested_place, (current_id, ))
                        nesting = cur.fetchone()
                        nesting = [i for i in nesting if i]
                        nesting = ", ".join(nesting)
                        rad_string = "{}: {}".format(current_id, nesting)
                elif dkt.get("temp_id") is not None and len(dkt["id"]) == 0:
                    # user will OK or CANCEL new ID
                    current_id = dkt["temp_id"]
                    rad_string = "{}: {} (new place and new place ID)".format(
                        current_id, dkt["input"])
                else:
                    current_id = dkt["id"][h]
                    cur.execute(select_first_nested_place, (current_id, ))
                    nesting = cur.fetchone()
                    nesting = [i for i in nesting if i]
                    nesting = ", ".join(nesting)
                    rad_string = "{}: {}".format(current_id, nesting)
                rad = RadiobuttonBig(self.hint_frm,
                                     variable=self.radvars[t],
                                     value=h,
                                     text=rad_string,
                                     anchor="w")
                lab = Label(self.hint_frm,
                            text="hint: {}".format(hint),
                            anchor='w',
                            bg='red')
                editx = ButtonQuiet(
                    self.hint_frm,
                    width=2,
                    command=lambda hint=hint: self.grid_edit_row(hint))

                self.hint_frm.columnconfigure(1, weight=1)
                rad.grid(column=0, row=row, sticky='we', columnspan=2)
                editx.grid(column=0, row=row + 1, pady=(0, 3), sticky='e')
                lab.grid(column=1, row=row + 1, sticky='w', padx=6)

                editx.bind('<Enter>', self.on_hover)
                editx.bind('<Leave>', self.on_unhover)
                editx.bind('<Button-1>', self.get_clicked_row)
                editx.bind('<space>', self.get_clicked_row)
                editx.bind('<FocusIn>', self.on_hover)
                editx.bind('<FocusOut>', self.on_unhover)
                h += 1
                row += 2

            sep = Separator(self.frm, 3)
            sep.grid(column=0,
                     row=d + 2,
                     sticky='ew',
                     columnspan=3,
                     pady=(3, 0))
            d += 3
            t += 1
            bullet -= 1

        cur.close()
        conn.close()
示例#12
0
    view = tk.Tk()
    treebard = view  # mockup; this isn't what really happens

    entry = EntryAutofill(view, width=50)
    entry.config(textvariable=entry.var)
    entry.values = place_strings
    entry.autofill = True
    entry.grid()
    entry.focus_set()
    entry.bind("<FocusOut>", get_final)

    traverse = Entry(view)
    traverse.grid()
    frame = Frame(view)
    frame.grid()

    view.mainloop()

# DO LIST

# input to db
# add a search box for ids by name or name by ids
# test all cases and make more cases to test
# concoct a case where there are
#   2 contiguous insertions not at first or last
#   2 contiguous insertions at first
#   2 contiguous insertions at last
#   2 non-contiguous insertions not at first or last
#   2 non-contiguous insertions at first
#   2 non-contiguous insertions at last
示例#13
0
    def make_widgets(self):

        self.make_scrollbars()

        self.make_menus()

        scridth = 20
        scridth_n = Frame(self, height=scridth)
        scridth_w = Frame(self, width=scridth)
        header = Frame(self)
        heading = LabelH3(header, text='header text')
        self.main_tabs = Frame(self)
        persons_tab = Frame(self.main_tabs)
        footer = Frame(self)
        boilerplate = Label(footer, text='footer')

        current_person_area = Frame(persons_tab)
        current_person = LabelH3(current_person_area)
        right_panel = Frame(persons_tab)
        attributes_table = Label(right_panel, text='attributes table')

        findings_table = EventsTable(persons_tab, self.view, self.treebard)

        # children of self
        scridth_n.grid(column=0, row=0, sticky='ew')
        scridth_w.grid(column=0, row=1, sticky='ns')
        header.grid(column=1, row=1, sticky='ew')
        self.columnconfigure(1, weight=1)
        self.rowconfigure(2, weight=1)
        self.main_tabs.grid(column=1, row=2, sticky='ew')
        footer.grid(column=1, row=3, sticky='ew')

        # children of header
        heading.grid(column=0, row=0, sticky='ew')

        # children of self.main_tabs
        persons_tab.grid(column=0, row=0, sticky='news')

        # children of persons_tab
        current_person_area.grid(column=0, row=0, sticky='w')
        right_panel.grid(column=1, row=0, sticky='e')
        findings_table.grid(column=0, row=1, columnspan=2, sticky='news')

        # children of current_person_area
        current_person.grid(column=0, row=0, sticky='w')

        # children of right_panel
        attributes_table.grid(column=0, row=0, sticky='news')

        # children of footer
        boilerplate.grid()
示例#14
0
class Main(Frame):
    def __init__(self, master, view, treebard, *args, **kwargs):
        Frame.__init__(self, master, *args, **kwargs)

        self.master = master  # the main canvas (instance of Border class)
        self.view = view
        self.treebard = treebard
        # print('19 self.view is', self.view)
        self.make_widgets()

    def make_menus(self):

        menu = Label(self.master.menu, text='menu bar')
        icon1 = Label(self.master.ribbon, text='ribbon menu')

        menu.grid()
        icon1.grid()

    def make_scrollbars(self):

        self.vsb = Scrollbar(self.view,
                             hideable=True,
                             command=self.master.yview,
                             width=20)
        self.hsb = Scrollbar(self.view,
                             hideable=True,
                             width=20,
                             orient='horizontal',
                             command=self.master.xview)
        self.master.config(xscrollcommand=self.hsb.set,
                           yscrollcommand=self.vsb.set)
        self.vsb.grid(column=2, row=4, sticky='ns')
        self.hsb.grid(column=1, row=5, sticky='ew')

    def make_widgets(self):

        self.make_scrollbars()

        self.make_menus()

        scridth = 20
        scridth_n = Frame(self, height=scridth)
        scridth_w = Frame(self, width=scridth)
        header = Frame(self)
        heading = LabelH3(header, text='header text')
        self.main_tabs = Frame(self)
        persons_tab = Frame(self.main_tabs)
        footer = Frame(self)
        boilerplate = Label(footer, text='footer')

        current_person_area = Frame(persons_tab)
        current_person = LabelH3(current_person_area)
        right_panel = Frame(persons_tab)
        attributes_table = Label(right_panel, text='attributes table')

        findings_table = EventsTable(persons_tab, self.view, self.treebard)

        # children of self
        scridth_n.grid(column=0, row=0, sticky='ew')
        scridth_w.grid(column=0, row=1, sticky='ns')
        header.grid(column=1, row=1, sticky='ew')
        self.columnconfigure(1, weight=1)
        self.rowconfigure(2, weight=1)
        self.main_tabs.grid(column=1, row=2, sticky='ew')
        footer.grid(column=1, row=3, sticky='ew')

        # children of header
        heading.grid(column=0, row=0, sticky='ew')

        # children of self.main_tabs
        persons_tab.grid(column=0, row=0, sticky='news')

        # children of persons_tab
        current_person_area.grid(column=0, row=0, sticky='w')
        right_panel.grid(column=1, row=0, sticky='e')
        findings_table.grid(column=0, row=1, columnspan=2, sticky='news')

        # children of current_person_area
        current_person.grid(column=0, row=0, sticky='w')

        # children of right_panel
        attributes_table.grid(column=0, row=0, sticky='news')

        # children of footer
        boilerplate.grid()
示例#15
0
class PersonAdd(Frame):
    def __init__(self, parent, autofill, root, *args, **kwargs):
        Frame.__init__(self, parent, *args, **kwargs)

        self.parent = parent
        self.root = root
        self.autofill = autofill

        self.config(padx=24, pady=24)

        self.gender = 'unknown'

        self.new_person_id = None

        self.role_person_edited = False
        self.findings_roles_id = None

        self.rc_menu = RightClickMenu(self.root)
        self.make_widgets()

    def make_widgets(self):

        all_pics = self.get_all_pics()

        lab1 = Label(self, text='Gender:')
        self.gender_input = ClearableReadonlyCombobox(self, values=GENDER_TYPES)

        lab2 = Label(self, text='Main Image:')
        self.image_input = ClickAnywhereCombo(self, values=all_pics)

        lab3 = Label(self, text='Name Type:')
        self.name_type_input = ClearableReadonlyCombobox(self, values=self.get_name_types())

        lab4 = Label(self, text='Full Name')
        self.name_input = Entry(self, width=65)

        self.how = LabelH3(
            self, 
            text='Alphabetize name: after clicking auto-sort, tab into '
                  'auto-filled name fields to modify\nsort order with '
                  'arrow keys or if sort order is correct, just click ADD.')

        autosort = Button(
            self, text='AUTOSORT', command=self.show_sort_order)

        self.order_frm = Frame(self)

        s = 0
        for stg in range(20):
            mov = LabelMovable(self.order_frm)
            mov.grid(column=s, row=0, padx=3)
            s += 1 

        self.buttonbox = Frame(self)
        self.add_butt = Button(self.buttonbox, text='ADD', width=8)

        lab1.grid(column=0, row=3)
        self.gender_input.grid(
            column=1, row=3, padx=12, pady=12, sticky='e')
        lab2.grid(column=2, row=3)
        self.image_input.grid(column=3, row=3, padx=12, pady=12)
        lab3.grid(column=0, row=4)
        self.name_type_input.grid(
            column=1, row=4,  padx=12, pady=12, sticky='e')
        lab4.grid(column=2, row=4)
        self.name_input.grid(column=3, row=4, padx=12, pady=12)

        self.how.grid(column=0, row=5, padx=6, pady=6, columnspan=4)
        autosort.grid(column=0, row=6, padx=6, pady=6)
        self.order_frm.grid(column=1, row=6, columnspan=4, pady=24)
        self.buttonbox.grid(column=1, row=7, sticky='e')
        self.add_butt.grid(column=0, row=0, padx=6, pady=6, sticky='e')

        self.new_person_statusbar = StatusbarTooltips(self.parent, resizer=False)
        visited = (
            (self.gender_input, 
                "Gender Input", 
                "'Unknown' used if left blank."),
            (self.image_input, 
                "Image Input", 
                "Use an old photo of person's home town if no photo available."),
            (self.name_type_input, 
                "Name Type Input", 
                "Choose the name type."),
            (self.name_input, 
                "Name Input", 
                "Autofills but you can change it."),
            (autosort, 
                "Autosort Button", 
                "Click to auto-create a sortable name."),
            (self.order_frm, 
                "", 
                "Tab to focus name element. Arrow to change order.")
)        
        run_statusbar_tooltips(
            visited, 
            self.new_person_statusbar.status_label, 
            self.new_person_statusbar.tooltip_label)

        self.preset()

        rcm_widgets = (self.name_input, self.name_type_input)
        make_rc_menus(
            rcm_widgets, 
            self.rc_menu, 
            person_add_msg)

    def preset(self):

        self.gender_input.config(state='normal')
        self.gender_input.delete(0, 'end')
        self.gender_input.config(state='readonly')
        self.image_input.delete(0, 'end')
        self.image_input.insert(0, 'no_photo_001.gif')
        self.name_type_input.config(state='normal')
        self.name_type_input.delete(0, 'end')
        self.name_type_input.insert(0, 'birth name')
        self.name_type_input.config(state='readonly')

    def reset(self):
        self.preset()
        self.name_input.delete(0, 'end')
        for child in self.order_frm.winfo_children():
            child['text'] = ''
        self.dupe_check = True  

    def add_person(self, findings_roles_id=None):
        self.get_entered_values()
        self.findings_roles_id = findings_roles_id
        self.check_for_dupes()

    def get_entered_values(self):
        ''' 
        '''
        if len(self.gender_input.get()) != 0:
            self.gender = self.gender_input.get()
        self.full_name = self.name_input.get()
        self.selected_image = self.image_input.get()
        self.name_type = self.name_type_input.get()

    def check_for_dupes(self):
        ''' 
            If birth name already exists in database, open dialog. 
        '''
 
        conn = sqlite3.connect(current_file)
        cur = conn.cursor()
        cur.execute(select_all_person_ids)
        all_people = cur.fetchall()
        cur.close()
        conn.close()
        
        all_people = [[i[0]] for i in all_people]

        names_only = []

        for id in all_people:
            display_name = get_name_with_id(id[0]) 
            names_only.append(display_name)
            id.insert(0, display_name)

        people_vals = []
        for lst in all_people:
            if not lst[0]:
                lst[0] = ''
            people_vals.append(' #'.join([lst[0], str(lst[1])]))

        if self.full_name not in names_only:
            self.make_new_person()
            self.make_sort_order()
            self.save_new_name(self.new_person_id)  
            self.reset()
        else:
            self.dupe_check = msg.YesNoMessage(
                self,
                title='Duplicate Check',
                message="This birth name already exists. To create a "
                    "new person by the same name, click SUBMIT. The "
                    "two persons can be merged later if desired.",
                show_input=self.full_name).show()                
            if self.dupe_check is True:  
                self.make_new_person() 
                self.make_sort_order()
                self.save_new_name(self.new_person_id)  
                self.reset()
            else:
                self.reset() 

    def make_new_person(self): 
        conn = sqlite3.connect(current_file)
        conn.execute('PRAGMA foreign_keys = 1')
        cur = conn.cursor()
        cur.execute(insert_person_null, (self.gender,))
        conn.commit()
        cur.execute("SELECT seq FROM SQLITE_SEQUENCE WHERE name = 'person' ")
        new_person_id = cur.fetchone()
        if new_person_id:
            self.new_person_id = new_person_id[0]

        if self.role_person_edited is True:
            cur.execute(
                update_findings_roles_person, 
                (self.new_person_id, self.findings_roles_id))
            conn.commit()
            self.role_person_edited = False 
        
        cur.close()
        conn.close()

    def make_sort_order(self): 

        self.order = []

        for child in self.order_frm.winfo_children():
            text = child['text']
            self.order.append(text)

        self.order = ' '.join(self.order)
        self.order = self.order.replace(' , ', ', ')
        self.order = self.order.strip(', ') 

    def save_new_name(self, subject_id):
        conn = sqlite3.connect(current_file)
        cur = conn.cursor()
        conn.execute('PRAGMA foreign_keys = 1')
        cur.execute(select_image_id, (self.selected_image,))
        img_id = cur.fetchone()[0]
        cur.execute(insert_images_entities, (img_id, subject_id))
        conn.commit()
        cur.execute(select_name_type_id, (self.name_type,))
        name_type_id = cur.fetchone()
        name_type_id = name_type_id[0]
        cur.execute(
            insert_name, 
            (subject_id, self.full_name, name_type_id, self.order))
        conn.commit()

        new_list = make_values_list_for_person_select()

        self.autofill.values = new_list
        
        cur.close()
        conn.close()

        self.image_input.delete(0, 'end')
        self.image_input.insert(0, 'no_photo_001.gif')

        for widg in (self.name_type_input, self.name_input):
            widg.config(state='normal')
            widg.delete(0, 'end')
        self.name_type_input.config(state='readonly')

        for child in self.order_frm.winfo_children():
            child.config(text='')
        self.gender_input.config(state='normal')
        self.gender_input.delete(0, 'end')
        self.gender_input.config(state='readonly')
        self.gender_input.focus_set()

    def show_sort_order(self):

        self.got = self.name_input.get()
        self.new_name = self.got
        self.got = self.got.split()
        if len(self.got) == 0:
            return
        else:
            length = len(self.got)-1
        word = self.got[length].lower()
        
        self.got.insert(0, ',')
        length += 1
        if word not in NAME_SUFFIXES:
            self.got.insert(0, self.got.pop())
        elif word in NAME_SUFFIXES and self.got[length].lower() == word:
            self.got.insert(0, self.got.pop())
            self.got.insert(0, self.got.pop())

        for child in self.order_frm.winfo_children():
            child.config(text='')

        v = 0
        for name in self.got:
            self.order_frm.winfo_children()[v].config(text=name)
            v += 1

    def get_name_types(self):

        conn = sqlite3.connect(current_file)
        cur = conn.cursor()
        cur.execute(select_all_name_types)
        name_types = cur.fetchall()
        cur.close()
        conn.close()
        name_types = [i[0] for i in name_types]

        return name_types

    def get_all_pics(self):

        conn = sqlite3.connect(current_file)
        cur = conn.cursor()
        picvals = cur.fetchall()
        cur.close()
        conn.close()
        return picvals
示例#16
0
class NotesDialog(Toplevel):
    def __init__(self,
                 master,
                 current_person,
                 finding_id=None,
                 header=None,
                 pressed=None,
                 *args,
                 **kwargs):
        Toplevel.__init__(self, master, *args, **kwargs)

        self.birth_name = get_name_with_id(current_person)
        self.title('{} ({})'.format('Notes for an Event', self.birth_name))

        self.current_person = current_person
        self.root = master
        self.finding_id = finding_id
        self.header = header
        self.pressed = pressed

        # self.self.new_index = None
        self.current_note_text = ''
        self.current_subtopic = ''
        self.current_note_id = None
        self.new_subtopic_label_text = 'New Note'
        self.current_subtopic_index = None
        self.new_subtopic_name = ''

        self.current_file = get_current_file()[0]

        self.bind('<Escape>', self.close_roles_dialog)
        self.subtopics = []

        self.privacy = tk.IntVar()

        self.refresh_notes_per_finding()
        self.rc_menu = RightClickMenu(self.root)
        self.make_widgets()
        self.protocol('WM_DELETE_WINDOW', self.close_roles_dialog)

    def make_widgets(self):

        self.title('{}{} ({})'.format('Notes for Conclusion #',
                                      self.finding_id, self.birth_name))

        self.grid_columnconfigure(0, weight=1)
        self.grid_rowconfigure(1, weight=1)
        header = Frame(self)
        header.grid_columnconfigure(1, weight=1)
        header.grid_rowconfigure(0, weight=1)

        self.notes_dialog_header = Frame(header)

        content = Frame(self)

        left_panel = Frame(content)

        topiclab = Label(left_panel, text='Note Subtopics')

        self.toc = Listbox(left_panel,
                           self.sorted_subtopics,
                           view_height=424,
                           view_width=180,
                           scrollbar=False)

        self.new_index = len(self.subtopics)
        self.toc.insert(self.new_index, self.new_subtopic_label_text)
        self.toc.focus_set()
        self.toc.selection_set(0)

        self.toc.store_new_subtopic_name = self.store_new_subtopic_name
        self.toc.pass_ctrl_click = self.open_links_dialog
        self.toc.pass_delete_key = self.delete_note

        self.selected_subtopic = Label(content, text='New Note')

        self.note_input = ScrolledText(content)

        note_submit = Button(content,
                             text='Submit Changes',
                             command=self.save_changes)

        order = Button(content,
                       text='Change Order of Subtopics',
                       command=self.reorder_notes)

        radframe = LabelFrame(content, text='Make selected note...')

        self.public = Radiobutton(radframe,
                                  text='...public',
                                  anchor='w',
                                  variable=self.privacy,
                                  value=0,
                                  command=self.save_privacy_setting)

        self.private = Radiobutton(radframe,
                                   text='...private',
                                   anchor='w',
                                   variable=self.privacy,
                                   value=1,
                                   command=self.save_privacy_setting)

        close = Button(content, text='DONE', command=self.close_roles_dialog)

        # notes_statusbar = StatusbarTooltips(self)

        # visited = (
        # (above,
        # 'this is a notes_statusbar message',
        # 'this is a tooltip'),
        # (below,
        # 'this is also a notes_statusbar message',
        # 'this is another tooltip'))

        # run_statusbar_tooltips(
        # visited,
        # notes_statusbar.status_label,
        # notes_statusbar.tooltip_label)

        # grid in self
        header.grid(column=0, row=0, columnspan=2, pady=12, sticky='we')
        content.grid(column=0, row=1, sticky='news', padx=(0, 6))
        # notes_statusbar.grid(column=0, row=2, sticky='ew')

        # grid in header
        self.notes_dialog_header.grid(column=1, row=0, sticky='ew')
        self.notes_dialog_header.grid_columnconfigure(0, weight=1)

        # grid in content
        left_panel.grid(column=0, row=1, sticky='news', rowspan=2, pady=24)
        self.selected_subtopic.grid(column=1, row=1, sticky='w')
        self.note_input.grid(column=1,
                             row=2,
                             columnspan=3,
                             sticky='nsew',
                             padx=(0, 24),
                             pady=12)
        note_submit.grid(column=3, row=3, sticky='se')
        self.grid_rowconfigure(0, weight=1)
        self.grid_columnconfigure(0, weight=1)
        content.grid_rowconfigure(1, weight=1)
        order.grid(column=1, row=4)
        radframe.grid(column=2, row=5, sticky='n', pady=24)
        close.grid(column=3, row=6, sticky='se', padx=24, pady=(0, 24))

        # grid in left_panel
        topiclab.grid(column=0, row=0)
        self.toc.grid(column=0, row=1)
        for child in self.toc.listbox_content.winfo_children():
            child.bind('<<ListboxSelected>>', self.switch_note)

        self.subtopic_widgets = self.toc.listbox_content.winfo_children()

        # grid in radframe
        self.public.grid(column=0, row=0, sticky='news', padx=24)
        self.private.grid(column=0, row=1, sticky='news', padx=24)

        # rcm_widgets = (self.subtopic_input, self.note_input.text)
        # make_rc_menus(
        # rcm_widgets,
        # self.rc_menu,
        # note_dlg_msg,
        # header_parent=self.notes_dialog_header,
        # header=self.header,
        # which_dlg='notes')

        config_generic(self)
        center_window(self)

    def open_links_dialog(self):
        links = Toplevel(self.root)
        links.title('Link Notes to Multiple Entities')
        instrux = LabelH3(
            links,
            text='The current note can be linked to any number of Entities\n'
            'such as Persons, Places, Assertions, Conclusions, or Sources.')
        instrux.grid(padx=24, pady=24)

    def save_changes(self):

        self.save_new_subtopic()

        conn = sqlite3.connect(self.current_file)
        conn.execute('PRAGMA foreign_keys = 1')
        cur = conn.cursor()

        new_note_text = self.note_input.text.get(1.0, 'end-1c')
        subtopic = self.current_subtopic
        cur.execute(update_note, (new_note_text, subtopic))
        conn.commit()
        cur.close()
        conn.close()

        self.master.current_note_text = new_note_text
        self.refresh()

    def save_new_subtopic(self):
        if self.selected_subtopic.cget('text') != self.new_subtopic_label_text:
            return
        self.subtopic_dialog = Toplevel(self.root)
        self.subtopic_dialog.title('New Note: Subtopic Input Dialog')
        headlab = LabelH3(self.subtopic_dialog,
                          text='Unique subtopic name for new note:')
        self.subtopic_input = Entry(self.subtopic_dialog, width=64)
        self.subtopic_input.focus_set()
        buttonbox = Frame(self.subtopic_dialog)
        self.subtopic_dialog.grid_columnconfigure(0, weight=1)
        new_note_ok = Button(buttonbox,
                             text='Submit Note and Subtitle',
                             command=self.submit_new_note)
        new_note_cancel = Button(buttonbox,
                                 text='Cancel',
                                 command=self.close_subtopic_dialog)

        headlab.grid(column=0, row=0, pady=(24, 0), columnspan=2)
        self.subtopic_input.grid(column=0,
                                 row=1,
                                 padx=24,
                                 pady=24,
                                 columnspan=2)
        buttonbox.grid(column=1, row=2, sticky='we', padx=24, pady=24)
        new_note_ok.grid(column=0, row=0, sticky='e', padx=12)
        new_note_cancel.grid(column=1, row=0, sticky='e', padx=12)

        self.subtopic_dialog.bind('<Escape>', self.close_subtopic_dialog)
        self.subtopic_dialog.protocol('WM_DELETE_WINDOW',
                                      self.close_subtopic_dialog)

    def submit_new_note(self):
        conn = sqlite3.connect(self.current_file)
        conn.execute('PRAGMA foreign_keys = 1')
        cur = conn.cursor()

        new_note_text = self.note_input.text.get(1.0, 'end-1c')
        new_subtopic = self.subtopic_input.get()
        cur.execute(select_count_subtopic, (new_subtopic, ))
        count = cur.fetchone()[0]
        if count > 0:
            non_unique_subtopic = ErrorMessage(
                self, message="Each subtopic can be\nused once in a tree.")
            non_unique_subtopic.title('Non-unique Note Title Error')
            self.subtopic_input.focus_set()
            return

        if len(new_subtopic) == 0:
            blank_subtopic = ErrorMessage(self,
                                          message="Blank notes are OK\n"
                                          "but not blank note titles.")
            blank_subtopic.title('Blank Note Title Error')
            self.subtopic_input.focus_set()
            return
        cur.execute(insert_note, (new_note_text, new_subtopic))
        conn.commit()
        cur.execute("SELECT seq FROM SQLITE_SEQUENCE WHERE name = 'note'")
        new_note_id = cur.fetchone()[0]

        cur.execute(insert_findings_notes,
                    (self.finding_id, new_note_id, self.new_index))
        conn.commit()
        cur.close()
        conn.close()

        self.master.current_note_text = new_note_text
        self.refresh_notes_per_finding()
        self.toc.insert(self.new_index, new_subtopic)
        items = self.toc.listbox_content.winfo_children()
        for child in items:
            child.bind('<<ListboxSelected>>', self.switch_note)
        self.toc.resize_scrollbar()
        self.toc.selection_set(self.new_index)
        self.switch_note()
        self.pressed.config(text=' ... ')
        self.new_index = len(self.subtopics)
        self.close_subtopic_dialog()
        self.refresh()

    def refresh_notes_per_finding(self):
        conn = sqlite3.connect(self.current_file)
        cur = conn.cursor()
        cur.execute(select_notes_refresh, (self.finding_id, ))
        notes = cur.fetchall()
        all_subtopics = []
        if len(notes) != 0:
            for tup in notes:
                all_subtopics.append([tup[1], tup[3]])
        all_subtopics.sort(key=lambda i: i[1])
        self.sorted_subtopics = []
        for lst in all_subtopics:
            self.sorted_subtopics.append(lst[0])

        self.subtopics = self.sorted_subtopics
        self.notesdict = {}
        for tup in notes:
            self.notesdict[tup[0]] = [tup[1], tup[2]]
        cur.close()
        conn.close()

    def close_roles_dialog(self, evt=None):
        self.destroy()
        self.master.focus_set()

    def close_subtopic_dialog(self, evt=None):
        self.subtopic_dialog.destroy()

    def save_privacy_setting(self):
        privacy_setting = self.privacy.get()
        conn = sqlite3.connect(self.current_file)
        conn.execute('PRAGMA foreign_keys = 1')
        cur = conn.cursor()
        cur.execute(update_note_private,
                    (privacy_setting, self.current_note_id))
        conn.commit()
        cur.close()
        conn.close()

    def get_selected_subtopic(self):
        # "is not None" has to be explicit here
        if self.toc.curselection() is not None:
            self.current_subtopic_index = self.toc.curselection()
        else:
            return
        self.current_subtopic = self.toc.get(self.current_subtopic_index)
        if len(self.notesdict) != 0:
            for k, v in self.notesdict.items():
                if v[0] == self.current_subtopic:
                    break
            self.current_note_id = k
            self.current_note_text = v[1]

    def store_new_subtopic_name(self):
        conn = sqlite3.connect(self.current_file)
        conn.execute('PRAGMA foreign_keys = 1')
        cur = conn.cursor()
        cur.execute(update_note_subtopic,
                    (self.toc.new_subtopic_name, self.current_note_id))
        conn.commit()
        cur.close()
        conn.close()

        self.subtopic_widgets = self.toc.listbox_content.winfo_children()
        for child in self.subtopic_widgets:
            child.bind('<<ListboxSelected>>', self.switch_note)
            if child.winfo_reqwidth() > self.toc.view_width:
                create_tooltip(child, self.toc.new_subtopic_name)

    def switch_note(self, evt=None):

        self.get_selected_subtopic()
        if len(self.current_subtopic) == 0:
            return
        self.selected_subtopic.config(text=self.current_subtopic)
        if self.current_subtopic == self.new_subtopic_label_text:
            self.note_input.text.delete(1.0, 'end')
            return
        self.note_input.text.delete(1.0, 'end')
        self.note_input.text.insert(1.0, self.current_note_text)

        conn = sqlite3.connect(self.current_file)
        cur = conn.cursor()
        cur.execute(select_private_note,
                    (self.current_subtopic, self.finding_id))
        privacy_setting = cur.fetchone()

        if privacy_setting:
            privacy_setting = privacy_setting[0]

        cur.close()
        conn.close()

        if privacy_setting is None:
            return
        elif privacy_setting == 0:
            self.public.select()
        elif privacy_setting == 1:
            self.private.select()

    def delete_note(self):
        '''
            Since any given note can be re-used more than once by linking it 
            to any number of findings, delete note from note table only if 
            the note_id no longer exists at all in the findings_notes table; 
            not every time a note_id is deleted from the findings_notes table. 
        '''
        def ok_delete():
            run_delete()
            cancel_delete()

        def cancel_delete():
            self.focus_set()
            deleter.destroy()

        def run_delete():

            note_count_per_finding = 0

            self.toc.delete(selected)
            self.note_input.text.delete(1.0, 'end')
            self.selected_subtopic.config(text='')
            cur.execute(delete_findings_notes, (deletable, self.finding_id))
            conn.commit()

            if delete_var.get() == 1:
                cur.execute(select_count_findings_notes_note_id, (deletable, ))
                linked_notes = cur.fetchone()[0]

                if linked_notes == 0:
                    cur.execute(delete_note, (deletable, ))
                    conn.commit()
                cur.execute(select_count_findings_notes_finding_id,
                            (self.finding_id, ))
                note_count_per_finding = cur.fetchone()[0]

            cur.close()
            conn.close()

            self.toc.selection_clear()

            if note_count_per_finding == 0:
                self.pressed.config(text='     ')

            self.refresh()

        selected = self.toc.curselection()
        subtopic = self.toc.get(selected)
        if subtopic is None:
            return

        conn = sqlite3.connect(self.current_file)
        conn.execute('PRAGMA foreign_keys = 1')
        cur = conn.cursor()
        cur.execute(select_note_id, (subtopic, ))
        deletable = cur.fetchone()
        if deletable is None:
            return
        elif deletable is not None:
            deletable = deletable[0]

        delete_var = tk.IntVar()

        deleter = Toplevel(self)
        deleter.title('Delete Note Dialog')

        instrux = LabelH3(
            deleter, text='Any note can be linked to any number of entities.')

        radio1 = Radiobutton(deleter,
                             text='Delete this instance of this note.',
                             value=0,
                             variable=delete_var)

        radio2 = Radiobutton(deleter,
                             text='Delete all instances of this note.',
                             value=1,
                             variable=delete_var)

        instrux.grid(column=0, row=0, columnspan=2, padx=24, pady=24)
        radio1.grid(column=0, row=1)
        radio2.grid(column=1, row=1)

        buttonbox = Frame(deleter)
        buttonbox.grid(column=1, row=2, sticky='e')
        b1 = Button(buttonbox, text='OK', command=ok_delete)
        b2 = Button(buttonbox, text='Cancel', command=cancel_delete)
        b1.grid(column=0, row=0)
        b2.grid(column=1, row=0)

    def refresh(self):

        self.refresh_notes_per_finding()
        self.toc.make_listbox_content()
        self.subtopic_widgets = self.toc.listbox_content.winfo_children()
        for child in self.subtopic_widgets:
            child.bind('<<ListboxSelected>>', self.switch_note)

    def reorder_notes(self):
        '''
        '''
        if self.toc.size() < 2:
            return

        self.order_dlg = Toplevel(self)
        self.order_dlg.grab_set()
        self.order_dlg.protocol('WM_DELETE_WINDOW', self.ignore_changes)
        self.order_dlg.bind('<Return>', self.save_close_reorder_dlg)
        self.order_dlg.bind('<Escape>', self.ignore_changes)
        self.order_dlg.grid_columnconfigure(0, weight=1)
        self.order_dlg.title('Reorder Subtopics')

        instrux = ('Tab or Ctrl+Tab selects movable subtopic.\n'
                   'Arrow keys change subtopic order up or down.')

        top = LabelH3(self.order_dlg, text=instrux, anchor='center')

        self.labels = Frame(self.order_dlg)

        e = 0
        for subtopic in self.subtopics:
            lab = LabelMovable(self.labels, text=subtopic, anchor='w')
            if e == 0:
                first = lab
            e += 1
            lab.grid(column=0, row=e, padx=3, sticky='ew')
        first.focus_set()

        close2 = Button(self.order_dlg,
                        text='OK',
                        command=self.save_close_reorder_dlg)

        top.grid(column=0, row=0, pady=(24, 0), padx=24, columnspan=2)
        self.labels.grid(column=0, row=1, columnspan=2, padx=24, pady=24)
        self.labels.grid_columnconfigure(0, weight=1)
        close2.grid(column=1, row=2, sticky='se', padx=12, pady=(0, 12))

        center_window(self.order_dlg)

    def ignore_changes(self, evt=None):
        self.order_dlg.grab_release()
        self.order_dlg.destroy()
        self.focus_set()

    def save_close_reorder_dlg(self, evt=None):
        '''
            Replace the values list.
        '''

        q = 0
        new_order = []
        save_order = []
        for child in self.labels.winfo_children():
            text = child.cget('text')
            new_order.append(text)
            save_order.append([text, q])
            q += 1

        conn = sqlite3.connect(self.current_file)
        conn.execute('PRAGMA foreign_keys = 1')
        cur = conn.cursor()

        for lst in save_order:
            cur.execute(select_note_id, (lst[0], ))
            note_id = cur.fetchone()[0]
            cur.execute(update_findings_notes,
                        (lst[1], self.finding_id, note_id))
            conn.commit()
        cur.close()
        conn.close()
        self.subtopics = self.toc.items = new_order
        self.refresh()
        self.order_dlg.grab_release()
        self.order_dlg.destroy()
        self.focus_set()
示例#17
0
    def delete_note(self):
        '''
            Since any given note can be re-used more than once by linking it 
            to any number of findings, delete note from note table only if 
            the note_id no longer exists at all in the findings_notes table; 
            not every time a note_id is deleted from the findings_notes table. 
        '''
        def ok_delete():
            run_delete()
            cancel_delete()

        def cancel_delete():
            self.focus_set()
            deleter.destroy()

        def run_delete():

            note_count_per_finding = 0

            self.toc.delete(selected)
            self.note_input.text.delete(1.0, 'end')
            self.selected_subtopic.config(text='')
            cur.execute(delete_findings_notes, (deletable, self.finding_id))
            conn.commit()

            if delete_var.get() == 1:
                cur.execute(select_count_findings_notes_note_id, (deletable, ))
                linked_notes = cur.fetchone()[0]

                if linked_notes == 0:
                    cur.execute(delete_note, (deletable, ))
                    conn.commit()
                cur.execute(select_count_findings_notes_finding_id,
                            (self.finding_id, ))
                note_count_per_finding = cur.fetchone()[0]

            cur.close()
            conn.close()

            self.toc.selection_clear()

            if note_count_per_finding == 0:
                self.pressed.config(text='     ')

            self.refresh()

        selected = self.toc.curselection()
        subtopic = self.toc.get(selected)
        if subtopic is None:
            return

        conn = sqlite3.connect(self.current_file)
        conn.execute('PRAGMA foreign_keys = 1')
        cur = conn.cursor()
        cur.execute(select_note_id, (subtopic, ))
        deletable = cur.fetchone()
        if deletable is None:
            return
        elif deletable is not None:
            deletable = deletable[0]

        delete_var = tk.IntVar()

        deleter = Toplevel(self)
        deleter.title('Delete Note Dialog')

        instrux = LabelH3(
            deleter, text='Any note can be linked to any number of entities.')

        radio1 = Radiobutton(deleter,
                             text='Delete this instance of this note.',
                             value=0,
                             variable=delete_var)

        radio2 = Radiobutton(deleter,
                             text='Delete all instances of this note.',
                             value=1,
                             variable=delete_var)

        instrux.grid(column=0, row=0, columnspan=2, padx=24, pady=24)
        radio1.grid(column=0, row=1)
        radio2.grid(column=1, row=1)

        buttonbox = Frame(deleter)
        buttonbox.grid(column=1, row=2, sticky='e')
        b1 = Button(buttonbox, text='OK', command=ok_delete)
        b2 = Button(buttonbox, text='Cancel', command=cancel_delete)
        b1.grid(column=0, row=0)
        b2.grid(column=1, row=0)
示例#18
0
    def make_widgets(self):

        if self.parent.winfo_class() == 'Toplevel':
            gallery_canvas = Canvas(
                self.parent,
                bd=0,
                highlightthickness=0)

            self.gallery_content = Frame(gallery_canvas)
            gallery_canvas.grid(row=0, column=0, sticky='nsew')

            self.parent.grid_columnconfigure(0, weight=1)
            self.parent.grid_rowconfigure(0, weight=1)
        else:
            self.gallery_content = Frame(self.parent)
            self.gallery_content.grid(column=0, row=0)

        self.thumb_canvas = Canvas(
            self.gallery_content, 
            bd=0, 
            highlightthickness=0,
            bg=formats['bg'])
        self.thumb_canvas.pack(padx=12, pady=12)

        self.thumbstrip = Frame(self.thumb_canvas)
        self.thumbstrip.pack(side='top')

        self.previous_img = Button(self.gallery_content, text='<<', width=6)

        self.pic_canvas = Canvas(
            self.gallery_content, 
            highlightbackground=formats['bg'])
        self.pic_canvas.bind('<Button-1>', self.focus_clicked)
        self.pic_canvas.bind('<Button-1>', self.scroll_start, add='+')
        self.pic_canvas.bind('<B1-Motion>', self.scroll_move)     

        self.img_path = '{}treebard_gps\data\{}\images\{}'.format(
            root_drive, self.image_dir, self.main_pic)
        img_big = Image.open(self.img_path)
        self.tk_img = ImageTk.PhotoImage(img_big)
        self.pic_canvas.image = self.tk_img

        z = 0
        self.current_pictures = sorted(self.current_pictures)

        for img in self.current_pictures:
            pic_col = Frame(self.thumbstrip)
            pic_col.pack(side='left', expand=1, fill='y')

            pic_file = img
            self.img_path = '{}treebard_gps\data\{}\images\{}'.format(root_drive, self.image_dir, pic_file)
            idx = len(pic_file)
            bare = pic_file[0:idx-4]
            thumbsy = Image.open(self.img_path)
            self.width_strings.append(thumbsy.width)
            self.height_strings.append(thumbsy.height)
            thumbsy.thumbnail((185,85))
            thumb_path = 'images/{}_tmb.png'.format(bare)
            # overwrites file by same name if it exists 
            thumbsy.save(thumb_path)
            small = ImageTk.PhotoImage(file=thumb_path, master=self.thumbstrip)

            thumb = Label(
                pic_col,
                image=small)
            thumb.pack(expand=1, fill='y')
            thumb.image = small

            self.thumb_labels.append(thumb)

            # lambda used to save value in loop
            if self.parent.winfo_class() == 'Toplevel':
                rad = Radiobutton(
                    pic_col,
                    takefocus=0,
                    value=pic_file,
                    command=lambda pic_file=pic_file: self.set_main_pic(
                        pic_file))   
                rad.pack()

                if rad['value'] == self.main_pic:
                    rad.select()

            else:                
                rad = Frame(
                    pic_col,
                    height=24,
                    width=24)   
                rad.pack(expand=1, fill='both')
                if self.parent.winfo_name() == 'source_tab':
                    pic_file = '{}, {}'.format(self.source, pic_file)
            
            create_tooltip(rad, pic_file)

            z += 1

        self.pil_img = img_big
        self.fit_canvas_to_pic()

        self.thumb_dict = dict(zip(self.thumb_labels, self.current_pictures))
        self.next_img = Button(self.gallery_content, text='>>', width=6)

        panel = Frame(self.gallery_content)

        subject = LabelH3(panel, text=self.curr_entity)
        subject.grid(column=0, row=0, sticky='ew')

        # labels with selectable multiline text
        self.caption_lab = MessageCopiable(panel, width=36)
        self.picfile_lab = MessageCopiable(panel, width=36)
        self.picsize_lab = MessageCopiable(panel, width=36)
        edit = Button(
            panel, 
            text='EDIT', 
            width=8, 
            command=lambda graphics=self.t7: self.go_to_graphics(graphics))

        self.previous_img.config(command=self.back)
        self.next_img.config(command=self.forward)

        panel.grid_rowconfigure(0, weight=2)
        panel.grid_rowconfigure(1, weight=1)
        panel.grid_rowconfigure(4, weight=2)

        self.caption_lab.grid(column=0, row=1, pady=(12,12), sticky='ew')
        self.caption_lab.insert(1.0, self.caption_text)

        self.picfile_lab.grid(column=0, row=2, pady=(12,0), sticky='ew')
        self.picfile_lab.insert(1.0, self.img_path)

        self.picsize_lab.grid(column=0, row=3, pady=(0,24), sticky='ew')
        self.picsize_lab.insert(
            1.0, 
            'width: {}, height: {}'.format(
                self.pil_img.width, self.pil_img.height))

        edit.grid(column=0, row=4)

        self.caption_lab.set_height()
        self.picfile_lab.set_height()
        self.picsize_lab.set_height()

        self.previous_img.pack(side='left', padx=12)
        self.pic_canvas.pack(side='left', expand=1, fill='y')
        self.next_img.pack(side='left', padx=12)

        panel.pack(side='left', expand=1, fill='y')

        for thumb in self.thumb_labels:
            thumb.bind('<Button-1>', self.show_clicked)

        self.pic_canvas.bind('<Key-Left>', lambda evt: self.back())

        self.pic_canvas.bind('<Key-Right>', lambda evt: self.forward())

        # add statusbar-tooltips

        self.visited = (
            (self.thumbstrip, 
                "Thumbnail Views", 
                "Click thumbnail to display. Hover below to see "
                   "file name. If radio, click to make main image."),
            (self.pic_canvas, 
                "Image", 
                "Arrow keys change image when it's in focus."),
            (self.previous_img, 
                "Left Button", 
                "Click with mouse or when highlighted click with spacebar."),
            (self.next_img, 
                "Right Button", 
                "Click with mouse or when highlighted click with spacebar.")) 

        if self.parent.winfo_class() == 'Toplevel':
     
            box = Frame(self.parent)
            box.grid(column=0, row=1, pady=12)

            close = Button(
                box, 
                text='CLOSE', 
                width=8, 
                command=self.cancel_gallery)  
            close.grid()
            self.parent.protocol('WM_DELETE_WINDOW', self.cancel_gallery)

        self.thumb_canvas.create_window(0, 0, anchor='nw', window=self.thumbstrip)
        self.thumb_canvas.config(
            scrollregion=(
                0, 0, 
                self.thumbstrip.winfo_reqwidth(), 
                self.thumbstrip.winfo_reqheight()))
        
        self.thumb_canvas.config(
            width=self.root.maxsize()[0], 
            height=self.thumbstrip.winfo_reqheight())
        
        scroll_width = int(self.thumb_canvas['scrollregion'].split(' ')[2])

        if scroll_width >= int(self.thumb_canvas['width']):
            for child in self.thumbstrip.winfo_children():
                for gchild in child.winfo_children():
                    gchild.bind("<Enter>", self.thumb_start)
                    gchild.bind("<Motion>", self.thumb_move)

        if self.parent.winfo_class() == 'Toplevel':

            gallery_canvas.create_window(
                0, 0, anchor=tk.NW, window=self.gallery_content)
            self.resize_scrollbar()
            self.resize_window()

        self.config_labels()
示例#19
0
class Colorizer(Frame):
    def __init__(self, parent, tabbook, root, *args, **kwargs):
        Frame.__init__(self, parent, *args, **kwargs)

        self.parent = parent
        self.tabbook = tabbook
        self.root = root

        self.old_col = 0
        self.parent.columnconfigure(0, weight=1)
        self.parent.rowconfigure(0, weight=1)

        self.root.bind('<Return>', self.apply_scheme)

        self.r_col = {}

        self.make_widgets()

    def make_widgets(self):

        stripview = Frame(self.parent)
        stripview.grid(column=0, row=0, padx=12, pady=12)

        self.parent.update_idletasks()
        self.colors_canvas = Canvas(
            stripview, 
            bd=1, highlightthickness=1, 
            highlightbackground=formats['highlight_bg'], 
            bg=formats['bg'],
            width=840,
            height=118
) 
        hscroll = Scrollbar(
            stripview, orient='horizontal', command=self.colors_canvas.xview)
        self.colors_canvas.configure(xscrollcommand=hscroll.set)
        
        self.colors_canvas.grid(column=0, row=0, sticky='news')
        hscroll.grid(column=0, row=1, sticky="ew")

        self.colors_content = Frame(self.colors_canvas)

        bbox1 = Frame(self.parent)
        bbox1.grid(column=0, row=1, padx=12, pady=12, sticky='we')
        bbox1.columnconfigure(1, weight=1)
        bbox1.rowconfigure(1, weight=1)

        self.try_button = Button(
            bbox1, text='TRY', width=7, command=self.config_local)
        self.try_button.grid(column=0, row=0, sticky='w')

        self.copy_button = Button(
            bbox1, text='COPY', width=7, command=self.copy_scheme)
        self.copy_button.grid(column=1, row=0)

        self.apply_button = Button(
            bbox1, text='APPLY', width=7, command=self.apply_scheme)
        self.apply_button.grid(column=2, row=0, sticky='e')

        bottom = Frame(self.parent)
        bottom.grid(column=0, row=2, padx=12, pady=12)

        addlab = LabelH3(bottom, text='New Color Scheme')
        addlab.grid(column=0, row=0, padx=6, pady=6, columnspan=2)

        self.colors_table = Frame(bottom)
        self.colors_table.grid(column=0, row=1, columnspan=2)
        self.colors_table.columnconfigure(0, weight=1)
        self.colors_table.rowconfigure(0, weight=1)

        all_schemes = get_color_schemes()

        self.h1 = Label(
            self.colors_table,
            anchor='w', 
            text=' Domain',
            font=formats['output_font'])

        self.h2 = Label(
            self.colors_table,
            anchor='w',
            text=' Color')

        opening_colors = (
            formats['bg'], 
            formats['highlight_bg'], 
            formats['head_bg'], 
            formats['fg'])

        displabel = self.make_colors_table(opening_colors)

        bbox2 = Frame(bottom)
        bbox2.grid(
            column=0, row=2, 
            padx=12, pady=12, 
            sticky='ew', columnspan=2)
        bbox2.columnconfigure(1, weight=1)
        bbox2.rowconfigure(0, weight=1)

        self.new_button = Button(
            bbox2, 
            text='CREATE NEW COLOR SAMPLE', 
            command=self.make_new_sample)
        self.new_button.grid(column=0, row=0, padx=6, pady=6, columnspan=2)

        self.make_samples()

        self.colors_canvas.create_window(
            0, 0, anchor='nw', window=self.colors_content)
        self.resize_color_samples_scrollbar()

    def resize_color_samples_scrollbar(self):
        self.colors_content.update_idletasks()                   
        self.colors_canvas.config(scrollregion=self.colors_canvas.bbox("all")) 

    def apply_scheme(self, evt=None):
        # APPLY button not invoked by RETURN key unless its tab is on top
        # change index if tab order changes
        # `self.tabbook.index('current')` is from ttk.Notebook, ignoring it for 
        #   now, need to add this method to Toykinter TabBook
        # if self.tabbook.index('current') == 2:
        self.recolorize()

    def recolorize(self):

        color_scheme = []
        for child in self.colors_content.winfo_children():
            if self.parent.focus_get() == child:
                frm = child

        foc = self.root.focus_get()

        if foc.master != self.colors_content:
            return

        for child in frm.winfo_children():
            color_scheme.append(child['bg'])
            child = child
        color_scheme.append(child['fg'])

        color_scheme = tuple(color_scheme)

        conn = sqlite3.connect(current_file)
        conn.execute('PRAGMA foreign_keys = 1')
        cur = conn.cursor()
        cur.execute(update_format_color_scheme, color_scheme)
        conn.commit()
        cur.close()
        conn.close()

        mbg = color_scheme[0]
        hbg = color_scheme[1]
        thbg = color_scheme[2]
        fg = color_scheme[3]

        config_generic(self.root)
        self.root.config(bg=mbg)

    def make_samples(self):

        all_schemes_plus = get_color_schemes_plus()

        y = 0
        for scheme in all_schemes_plus:
            frm = FrameStay(
                self.colors_content,
                name = '{}{}'.format('cs_', str(scheme[5])),
                bg='lightgray', 
                takefocus=1, 
                bd=1)
            frm.grid(column=y, row=0)
            frm.bind('<FocusIn>', self.change_border_color)
            frm.bind('<FocusOut>', self.unchange_border_color)
            frm.bind('<Key-Delete>', self.delete_sample)

            z = 0
            for color in scheme[0:3]:
                lab = LabelStay(
                    frm, 
                    width=12, 
                    bg=color, 
                    text=color, fg=scheme[3])
                lab.grid(column=y, row=z, ipadx=6, ipady=6)
                lab.bind('<Button-1>', self.config_local)
                z += 1
            y += 1

        self.resize_color_samples_scrollbar()

        self.clear_entries()

    def clear_entries(self):
        for widg in self.colors_table.winfo_children():
            if widg.winfo_class() == 'Entry':
                widg.delete(0, tk.END)

    def detect_colors(self, frm):

        color_scheme = []
        if frm.winfo_class() == 'Label':
            frm = frm.master

        for child in frm.winfo_children():
            color_scheme.append(child['bg'])
            child = child
        color_scheme.append(child['fg'])

        return color_scheme

    def preview_scheme(self, scheme):
        
        trial_widgets = []
        all_widgets_in_tab1 = get_all_descends(
            self.parent, trial_widgets)
        all_widgets_in_tab1.append(self.parent)

        for widg in (all_widgets_in_tab1):
            if (widg.winfo_class() == 'Label' and 
                widg.winfo_subclass() == 'LabelStay'):
                    pass
            elif (widg in self.colors_table.winfo_children() and 
                widg.grid_info()['row'] == 0):
                    widg.config(
                        bg=scheme[2],
                        fg=scheme[3])
            elif (widg.winfo_class() == 'Label' and 
                    widg.winfo_subclass() in ('Label', 'LabelH3')):
                        widg.config(
                            bg=scheme[0],
                            fg=scheme[3])
            elif widg.winfo_class() == 'Button':
                widg.config(
                        bg=scheme[1], 
                        fg=scheme[3],
                        activebackground=scheme[2])
            elif widg.winfo_class() == 'Entry':
                widg.config(bg=scheme[1]),
            elif widg in self.colors_content.winfo_children():
                widg.config(bg='lightgray')
            elif widg.winfo_class() in ('Frame', 'Toplevel', 'Canvas'):
                widg.config(bg=scheme[0])

    def config_local(self, evt=None):

        all_schemes = get_color_schemes()

        self.clear_entries()

        # if double-click
        if evt:
     
            if evt.type == '4':
                evt.widget.master.focus_set()
            color_scheme = self.detect_colors(evt.widget)
            self.preview_scheme(color_scheme)

        # if TRY button
        else:
            print("line", looky(seeline()).lineno, "self.colors_content.focus_get().winfo_class():", self.colors_content.focus_get().winfo_class())
            for widg in self.colors_table.winfo_children():

                # if entries not all filled out
                if (widg.winfo_class() == 'Entry' and
                    len(widg.get()) == 0): # prob. shd be break or continue
                        pass

                # if new scheme to try
                if (widg.winfo_class() == 'Entry' and
                    len(widg.get()) > 0):
                        inputs = []
                        inputs = tuple(inputs)

                        # if typed scheme is new
                        if inputs not in all_schemes:
                            self.preview_scheme(inputs)

                        # if scheme already exists
                        else:
                            self.clear_entries()

                # if no sample hilited
                elif self.colors_content.focus_get().winfo_class() != 'Frame':
                    return
                elif (widg.winfo_class() == 'Entry' and
                    len(widg.get()) == 0):
                            color_scheme = self.detect_colors(
                                self.parent.focus_get())
                            self.preview_scheme(color_scheme)

    def change_border_color(self, evt):
        evt.widget.config(bg='white', bd=2)        

    def unchange_border_color(self, evt):
        evt.widget.config(bg='lightgray', bd=1)

    def make_colors_table(self, colors):

        def clear_select(evt):
            evt.widget.selection_clear()

        l_col = [
            'background 1', 'background 2', 'background 3', 'font color']

        self.h1.grid(
            column=0, row=0, 
            sticky='ew', 
            ipady=3,
            pady=6)

        self.h2.grid(
            column=1, row=0, 
            sticky='ew', 
            ipady=3,
            pady=6)

        self.entries_combos = []
        j = 1
        for name in l_col:
            lab = Label(
                self.colors_table,
                anchor='w',
                text=name)
            lab.grid(column=0, row=j, sticky='ew', padx=(6,12), pady=3)
            ent = Entry(self.colors_table, width=12)
            self.r_col[name] = ent
            ent.grid(column=1, row=j, pady=3)
            self.entries_combos.append(ent)
            ent.bind('<FocusOut>', clear_select)
            ent.bind('<Double-Button-1>', self.open_color_chooser)
            j += 1

    def drop_scheme_from_db(self, frame, scheme):
        id = frame.split('_')[1]
        conn = sqlite3.connect(current_file)
        conn.execute('PRAGMA foreign_keys = 1')
        cur = conn.cursor()
        cur.execute(delete_color_scheme, (id,))
        conn.commit()    
        cur.execute(select_color_scheme_current)
        current_scheme = cur.fetchone()

        if scheme == current_scheme:
            cur.execute(update_color_scheme_null)
            conn.commit()

        cur.close()
        conn.close()    

    def delete_sample(self, evt):
        dflt = self.colors_content.winfo_children()[0]
        drop_me = self.colors_content.focus_get()
        all_schemes_plus = get_color_schemes_plus()
        color_scheme = tuple(self.detect_colors(drop_me))
        all_schemes = []
        for scheme_plus in all_schemes_plus:
            all_schemes.append(scheme_plus[0:4])
        if color_scheme in all_schemes: # try set intersection?
            idx = all_schemes.index(color_scheme)
            # don't allow built-in color schemes to be deleted
            # currently all are set as built_in but that could be changed
            #   to allow deletion: update `built_in` column of `formats` 
            #   table in db to `0`
            if all_schemes_plus[idx][4] == 0:
                drop_name = drop_me.winfo_name()
                self.drop_scheme_from_db(drop_name, color_scheme)

                drop_me.destroy()
                self.resize_color_samples_scrollbar()
                # reset to default scheme; only current scheme can be deleted
                dflt.focus_set()
                fix = []
                for child in self.parent.focus_get().winfo_children():
                    fix.append(child['bg']) 
                child = child
                fix.append(child['fg'])
                entries = []
                for child in self.colors_table.winfo_children():
                    if child.winfo_class() == 'Entry':
                        entries.append(child)
                self.apply_button.invoke()

    def get_new_scheme(self):
        all_schemes = get_color_schemes()
        inputs = []
        for widg in self.colors_table.winfo_children():
            if widg.winfo_class() == 'Entry':
                inputs.append(widg.get())
        inputs = tuple(inputs)
        for scheme in all_schemes:
            if inputs == scheme:
                return

        self.put_new_scheme_in_db(inputs)

    def put_new_scheme_in_db(self, new_scheme):
        all_schemes = get_color_schemes()
        if new_scheme not in all_schemes:

            conn = sqlite3.connect(current_file)
            conn.execute('PRAGMA foreign_keys = 1')
            cur = conn.cursor()
            cur.execute(insert_color_scheme, (new_scheme))
            conn.commit()
            cur.close()
            conn.close()

    def make_new_sample(self):

        # validate colors

        back = self.r_col['background 1'].get()
        high = self.r_col['background 2'].get()
        table = self.r_col['background 3'].get()
        fonts = self.r_col['font color'].get()    

        try_these = [
            (back, self.r_col['background 1']), 
            (high, self.r_col['background 2']), 
            (table, self.r_col['background 3']), 
            (fonts, self.r_col['font color'])]

        for tup in try_these:
            if len(tup[0]) == 0:
                return
        
        test_color = Frame(self.root) # don't grid this

        for tup in try_these:
            try:
                test_color.config(bg=tup[0])
            except tk.TclError:
                tup[1].delete(0, tk.END)
                messagebox.showerror(
                    'Color Not Recognized.',
                    'A color was entered that is unknown to the system.')
                return

        self.get_new_scheme()
        for child in self.colors_content.winfo_children():
            child.destroy()
        self.make_samples()

    def copy_scheme(self):

        colors = []
        if self.root.focus_get().master == self.colors_content:
            for child in self.root.focus_get().winfo_children():
                colors.append(child['bg'])
                child=child
            colors.append(child['fg'])

        color_entries = []
        for child in self.colors_table.winfo_children():
            if child.grid_info()['row'] == 0:
                pass
            elif child.grid_info()['column'] == 1:
                color_entries.append(child)

        place_colors = dict(zip(color_entries, colors))

        for k,v in place_colors.items():
            k.delete(0, 'end')
            k.insert(0, v)

    def open_color_chooser(self, evt):
        chosen_color = colorchooser.askcolor(parent=self.root)[1]
        if chosen_color:
            evt.widget.delete(0, 'end')
            evt.widget.insert(0, chosen_color)