Exemple #1
0
class TimerUi:
    """View"""
    def __init__(self, app):
        self.time_label = Label(app.root,
                                textvariable=app.time,
                                anchor=CENTER,
                                foreground='black',
                                background='lightgray',
                                font=('Helvetica', 60))
        self.time_label.pack(fill=BOTH, expand=True)

        validate_command = (app.root.register(self.check), '%P')
        self.entry = Spinbox(app.root,
                             from_=1,
                             to=MAX_COUNT,
                             textvariable=app.count_start,
                             validate='all',
                             validatecommand=validate_command)
        self.entry.pack(fill=X)
        self.entry.focus()

        buttons_frame = Frame(app.root)
        buttons_frame.pack(fill=X)
        self.start_button = Button(buttons_frame,
                                   text='Start',
                                   command=app.start_timer)
        self.stop_button = Button(buttons_frame,
                                  text='Stop',
                                  state=DISABLED,
                                  command=app.stop_timer)
        self.start_button.pack(side=LEFT, fill=X, expand=True)
        self.stop_button.pack(side=RIGHT, fill=X, expand=True)

    def check(self, new_val):
        return new_val.isdigit() and 1 <= int(new_val) <= MAX_COUNT

    def state_started(self):
        self.stop_button.config(state=NORMAL)
        self.start_button.config(state=DISABLED)
        self.entry.config(state=DISABLED)
        self.time_label.config(foreground='white', background='red')

    def state_stopped(self):
        self.stop_button.config(state=DISABLED)
        self.start_button.config(state=NORMAL)
        self.entry.config(state=NORMAL)
        self.time_label.config(foreground='black', background='lightgray')
Exemple #2
0
class View(Frame):
    def __init__(self, master, controller, label, width, minimum, maximum,
                 current, *args, **kwargs):
        super(View, self).__init__(master, *args, **kwargs)
        self._controller = controller
        self._create_label(label, width)
        self._create_spinbox(minimum, maximum)
        self._create_scale(minimum, maximum)

    def w_label(self):
        return self._label

    def w_spinbox(self):
        return self._spinbox

    def w_scale(self):
        return self._scale

    def _create_label(self, label, width):
        self._label = LabelTtk(self, text=label)

        if width:
            self._label.config(width=width)

        self._label.pack(side='left', anchor='s')

    def _create_spinbox(self, minimum, maximum):
        self._spinbox = Spinbox(self, from_=minimum, to=maximum)

        self._spinbox['command'] = lambda: \
            self._controller.set_current(int(self._spinbox.get()))

        self._spinbox.bind('<Return>', lambda e: \
            self._controller.set_current(self._spinbox.get()))

        self._spinbox.pack(side="left", anchor="s")

    def _create_scale(self, minimum, maximum):
        self._scale = Scale(self,
                            orient="horizontal",
                            from_=minimum,
                            to=maximum)

        self._scale['command'] = lambda e: \
            self._controller.set_current(self._scale.get())

        self._scale.pack(side="left", fill="x", expand=True, anchor="s")
Exemple #3
0
    def __init__(self, form_type):
        Curso.__init__(self)
        Form.__init__(self)

        self.id_curso = None
        self.form_type = form_type

        fieldsFrame = Frame(self.root, padding=10)
        fieldsFrame.grid(row=0, column=0, padx=10, pady=10)

        lbl_alumnos = Label(fieldsFrame, width=30)
        lbl_alumnos.grid(row=2, column=0, columnspan=30)

        self.listaPersonas = Listbox(fieldsFrame, highlightthickness=0, selectmode="extended", 
                                     height=25, width=40)
        self.listaPersonas.grid(row=3, column=0, columnspan=40, pady=(5,10))

        btn_aceptar = Button(fieldsFrame, text="Aceptar", width=16)
        btn_aceptar.grid(row=4, column=0, columnspan=16)
        
        btn_cancelar = Button(fieldsFrame, text="Cancelar", width=16,
                              command=self.hide)
        btn_cancelar.grid(row=4, column=26, columnspan=16)

        if form_type == "add":
            self.set_title("Inscribir alumnos")
            lbl_alumnos.config(text="Seleccione los alumnos:")

            lbl_date = Label(fieldsFrame, text="Seleccione la fecha:", width=20)
            lbl_date.grid(row=0, column=0, columnspan=20)

            self.date = StringVar()
            e_date = Entry(fieldsFrame, textvariable=self.date, width=30)
            e_date.grid(row=1, column=0, columnspan=30, pady=(0,10))
            e_date.config(state="readonly")

            btn_date = Button(fieldsFrame, text="...", width=8,
                            command=lambda: self.date.set(DatePicker(fieldsFrame).selection()))
            btn_date.grid(row=1, column=32, columnspan=8, pady=(0,10))

            btn_aceptar.config(command=lambda: self.add_cursante())

        elif form_type == "remove":
            self.set_title("Remover inscriptos")
            lbl_alumnos.config(text="Seleccione los inscriptos:")
            btn_aceptar.config(command=lambda: self.remove_cursante())
Exemple #4
0
 def init_ui(self):
     self.master.title("Speech Demo")
     self.pack(fill=BOTH, expand=True)
     label_frame = LabelFrame(self, text="System words")
     label_frame.pack(fill=X, padx=40, pady=20)
     self.labels = []
     rows = 8
     cols = 2
     for j in range(rows):
         for i in range(cols):
             k = i + j * cols
             label = Label(label_frame, text=labels[k])
             label.config(font=("Cambria Math", 20))
             label.grid(row=j, column=i, padx=20, pady=10)
             self.labels += [label]
     self.selected = None
     self.after(100, self.ontick)
Exemple #5
0
    def init_ui(self, rows=4, cols=3):
        """ setup the GUI for the app """
        self.master.title("Speech Demo")
        self.pack(fill=BOTH, expand=True)

        label_frame = LabelFrame(self, text="Try these categories")
        label_frame.pack(fill=X, padx=10, pady=10)
        self.labels = []

        for j in range(rows):
            for i in range(cols):
                k = i + j * cols
                label = Label(label_frame, text=self.skeet[k])
                label.config(font=("Courier", 36))
                label.grid(row=j, column=i, padx=10, pady=10)
                self.labels += [label]
        self.selected = None
        self.after(100, self.on_tick)
class DetectionPathFrame(Frame):
    def __init__(self, parent, configuration):
        Frame.__init__(self, parent)
        self.configuration = configuration

        self.detection_path = None
        self.detection_path_res = configuration.detection_path

        self.results_path = None
        self.results_path_res = configuration.results_path

        self.init_ui()

    def init_ui(self):
        self.detection_path = Label(self,
                                    text=FileUtils.get_filename_from_path(
                                        self.configuration.detection_path))
        self.detection_path.grid(row=0, column=1)
        Button(self,
               text="Input image",
               command=self.browse_image_path) \
            .grid(row=0, column=0)

        self.results_path = Label(self,
                                  text=FileUtils.get_filename_from_path(
                                      self.configuration.results_path))
        self.results_path.grid(row=1, column=1)
        Button(self,
               text="Result path",
               command=self.browse_results_path) \
            .grid(row=1, column=0)

    def browse_image_path(self):
        self.detection_path_res = filedialog.askopenfilename()
        self.detection_path.config(
            text=FileUtils.get_filename_from_path(self.detection_path_res))

    def browse_results_path(self):
        self.results_path_res = filedialog.askdirectory()
        self.results_path.config(
            text=FileUtils.get_filename_from_path(self.results_path_res))

    def get_values(self):
        return self.detection_path_res, self.results_path_res
class ConfidenceScale(Frame):
    def __init__(self, master, **kw):
        super().__init__(master)

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

        self.var = kw.get('variable', IntVar())
        kw['variable'] = self.var
        kw['from_'] = ConfidenceLevel.Low.value
        kw['to'] = ConfidenceLevel.VeryHigh.value
        # kw['command'] = self.scale_change
        kw['orient'] = HORIZONTAL

        self.lbl_scale = Label(self)
        self.scale = Scale(self, **kw)

        self.scale_font = tkfont.nametofont(Style().lookup('TLabel',
                                                           'font')).copy()
        self.scale_font.config(weight=tkfont.BOLD, size=9)
        self.lbl_scale.config(font=self.scale_font, width=3, anchor=CENTER)
        self.var.trace_variable('w', lambda a, b, c: self.scale_change())

        self.scale.grid(row=0, column=0, sticky='ns')
        self.lbl_scale.grid(row=0, column=1, sticky='ns', padx=(3, 0))

    def scale_change(self):
        rval = self.get()

        if rval >= ConfidenceLevel.High:
            fg = '#4CAF50'
        elif rval >= ConfidenceLevel.Medium:
            fg = '#FF9800'
        else:
            fg = '#FF5722'
        self.lbl_scale.config(foreground=fg, text=str(rval))

    def get(self):
        return round(float(self.var.get()))
Exemple #8
0
class FeedbackFrame(Frame):
    def __init__(self, parent):
        Frame.__init__(self, parent)

        self.output_text = None
        self.progress_bar = None
        self.progress_label = None

        self.init_view()

    def init_view(self):
        self.output_text = Text(self, height=10, width=40)
        self.output_text.grid(row=0, column=0, padx=5, pady=5, sticky="ew")
        self.progress_bar = Progressbar(self, orient='horizontal')
        self.progress_bar['maximum'] = 100
        self.progress_bar.grid(row=1, column=0, padx=5, pady=5, sticky="ew")
        self.progress_label = Label(self)
        self.progress_label.grid(row=2, column=0, padx=5, pady=5, sticky="ew")

    def reset(self):
        self.progress_bar["value"] = 0
        self.progress_label.config(text="")
        self.output_text.delete("1.0", END)
Exemple #9
0
    def __init__(self, **kwargs):
        """
        Build the main screen as a notebook.
        """

        # initialize the parent class
        super(ExplorerProGui, self).__init__(
            back_plane_ip_address=kwargs['back_plane_ip_address'],
            subscriber_port=kwargs['subscriber_port'],
            publisher_port=kwargs['publisher_port'],
            process_name=kwargs['process_name'])

        self.set_subscriber_topic('report_from_hardware')

        self.main = Tk()
        self.main.title('Demo Station For Explorer-Pro HAT')

        # gives weight to the cells in the grid
        rows = 0
        while rows < 50:
            self.main.rowconfigure(rows, weight=1)
            self.main.columnconfigure(rows, weight=1)
            rows += 1

        # Defines and places the notebook widget
        self.nb = Notebook(self.main, padding=20, height=300, width=800)
        self.nb.grid(row=1, column=0, columnspan=50, rowspan=49, sticky='NESW')

        # create the analog inputs tab
        self.analog_inputs_tab = Frame(self.nb, padding=[130, 20])
        self.nb.add(self.analog_inputs_tab, text='Analog Inputs')
        # create an instance of the AnalogInputs class
        self.analog_inputs = AnalogInputs(self.analog_inputs_tab, self)

        # create the digital inputs tab
        self.digital_inputs_tab = Frame(self.nb, padding=[130, 20])
        self.nb.add(self.digital_inputs_tab, text='Digital Inputs')
        # create an instance of the DigitalInputs class
        # to populate and control Signal inputs
        self.digital_inputs = DigitalInputs(self.digital_inputs_tab, self)

        # create the touch tab
        self.touch_tab = Frame(self.nb, padding=10)
        self.nb.add(self.touch_tab, text='Touch Inputs')
        self.touch_inputs = TouchInputs(self.touch_tab, self)

        # create the digital outputs tab
        self.digital_outputs_tab = Frame(self.nb, padding=10)
        self.nb.add(self.digital_outputs_tab, text='Digital Outputs')
        # create an instance of the DigitalOutputs class
        # to populate and control digital outputs
        self.digital_outputs = DigitalOutputs(self.digital_outputs_tab, self)

        # create the LED digital outputs tab
        self.led_digital_outputs_tab = Frame(self.nb, padding=10)
        self.nb.add(self.led_digital_outputs_tab, text='LED Digital Outputs')
        # create an instance of the DigitalOutputs class
        # to populate and control digital outputs
        self.led_digital_outputs = LedDigitalOutputs(self.led_digital_outputs_tab, self)

        # create the pwm output tab
        self.pwm_output_tab = Frame(self.nb, padding=10)
        self.nb.add(self.pwm_output_tab, text='PWM Outputs')
        self.pwm_output = PwmOutputs(self.pwm_output_tab, self)

        # create the LED PWM output tab
        self.led_pwm_output_tab = Frame(self.nb, padding=10)
        self.nb.add(self.led_pwm_output_tab, text='LED PWM Outputs')
        self.led_pwm_output = LedPwmOutputs(self.led_pwm_output_tab, self)

        # create the dc motors tab
        self.motors_tab = Frame(self.nb, padding=10)
        self.nb.add(self.motors_tab, text='DC Motors')
        self.dc_motors = DcMotors(self.motors_tab, self)

        l = Label(self.main,
                  text='Copyright (c) 2019 Alan Yorinks All Rights Reserved.')
        l.config(font="Helvetica 8 ")
        l.grid(row=48, column=0, padx=[505, 0])

        self.main.after(5, self.get_message)

        try:
            self.main.mainloop()
        except KeyboardInterrupt:
            self.on_closing()
class DialogPluginManager(Toplevel):
    def __init__(self, mainWin, modulesWithNewerFileDates):
        super(DialogPluginManager, self).__init__(mainWin.parent)
        
        self.ENABLE = _("Enable")
        self.DISABLE = _("Disable")
        self.parent = mainWin.parent
        self.cntlr = mainWin
        
        # copy plugins for temporary display
        self.pluginConfig = PluginManager.pluginConfig
        self.pluginConfigChanged = False
        self.uiClassMethodsChanged = False
        self.modulesWithNewerFileDates = modulesWithNewerFileDates
        
        parentGeometry = re.match("(\d+)x(\d+)[+]?([-]?\d+)[+]?([-]?\d+)", self.parent.geometry())
        dialogX = int(parentGeometry.group(3))
        dialogY = int(parentGeometry.group(4))

        self.title(_("Plug-in Manager"))
        frame = Frame(self)
        
        # left button frame
        buttonFrame = Frame(frame, width=40)
        buttonFrame.columnconfigure(0, weight=1)
        addLabel = Label(buttonFrame, text=_("Find plug-in modules:"), wraplength=60, justify="center")
        addLocalButton = Button(buttonFrame, text=_("Locally"), command=self.findLocally)
        ToolTip(addLocalButton, text=_("File chooser allows selecting python module files to add (or reload) plug-ins, from the local file system."), wraplength=240)
        addWebButton = Button(buttonFrame, text=_("On Web"), command=self.findOnWeb)
        ToolTip(addWebButton, text=_("Dialog to enter URL full path to load (or reload) plug-ins, from the web or local file system."), wraplength=240)
        addLabel.grid(row=0, column=0, pady=4)
        addLocalButton.grid(row=1, column=0, pady=4)
        addWebButton.grid(row=2, column=0, pady=4)
        buttonFrame.grid(row=0, column=0, rowspan=2, sticky=(N, S, W), padx=3, pady=3)
        
        # right tree frame (plugins already known to arelle)
        modulesFrame = Frame(frame, width=700)
        vScrollbar = Scrollbar(modulesFrame, orient=VERTICAL)
        hScrollbar = Scrollbar(modulesFrame, orient=HORIZONTAL)
        self.modulesView = Treeview(modulesFrame, xscrollcommand=hScrollbar.set, yscrollcommand=vScrollbar.set, height=7)
        self.modulesView.grid(row=0, column=0, sticky=(N, S, E, W))
        self.modulesView.bind('<<TreeviewSelect>>', self.moduleSelect)
        hScrollbar["command"] = self.modulesView.xview
        hScrollbar.grid(row=1, column=0, sticky=(E,W))
        vScrollbar["command"] = self.modulesView.yview
        vScrollbar.grid(row=0, column=1, sticky=(N,S))
        modulesFrame.columnconfigure(0, weight=1)
        modulesFrame.rowconfigure(0, weight=1)
        modulesFrame.grid(row=0, column=1, columnspan=4, sticky=(N, S, E, W), padx=3, pady=3)
        self.modulesView.focus_set()

        self.modulesView.column("#0", width=120, anchor="w")
        self.modulesView.heading("#0", text=_("Name"))
        self.modulesView["columns"] = ("author", "ver", "status", "date", "update", "descr", "license")
        self.modulesView.column("author", width=100, anchor="w", stretch=False)
        self.modulesView.heading("author", text=_("Author"))
        self.modulesView.column("ver", width=50, anchor="w", stretch=False)
        self.modulesView.heading("ver", text=_("Version"))
        self.modulesView.column("status", width=50, anchor="w", stretch=False)
        self.modulesView.heading("status", text=_("Status"))
        self.modulesView.column("date", width=70, anchor="w", stretch=False)
        self.modulesView.heading("date", text=_("File Date"))
        self.modulesView.column("update", width=50, anchor="w", stretch=False)
        self.modulesView.heading("update", text=_("Update"))
        self.modulesView.column("descr", width=200, anchor="w", stretch=False)
        self.modulesView.heading("descr", text=_("Description"))
        self.modulesView.column("license", width=70, anchor="w", stretch=False)
        self.modulesView.heading("license", text=_("License"))

        classesFrame = Frame(frame)
        vScrollbar = Scrollbar(classesFrame, orient=VERTICAL)
        hScrollbar = Scrollbar(classesFrame, orient=HORIZONTAL)
        self.classesView = Treeview(classesFrame, xscrollcommand=hScrollbar.set, yscrollcommand=vScrollbar.set, height=5)
        self.classesView.grid(row=0, column=0, sticky=(N, S, E, W))
        hScrollbar["command"] = self.classesView.xview
        hScrollbar.grid(row=1, column=0, sticky=(E,W))
        vScrollbar["command"] = self.classesView.yview
        vScrollbar.grid(row=0, column=1, sticky=(N,S))
        classesFrame.columnconfigure(0, weight=1)
        classesFrame.rowconfigure(0, weight=1)
        classesFrame.grid(row=1, column=1, columnspan=4, sticky=(N, S, E, W), padx=3, pady=3)
        self.classesView.focus_set()
        
        self.classesView.column("#0", width=200, anchor="w")
        self.classesView.heading("#0", text=_("Class"))
        self.classesView["columns"] = ("modules")
        self.classesView.column("modules", width=500, anchor="w", stretch=False)
        self.classesView.heading("modules", text=_("Modules"))
        
        # bottom frame module info details
        moduleInfoFrame = Frame(frame, width=700)
        moduleInfoFrame.columnconfigure(1, weight=1)
        
        self.moduleNameLabel = Label(moduleInfoFrame, wraplength=600, justify="left", 
                                     font=font.Font(family='Helvetica', size=12, weight='bold'))
        self.moduleNameLabel.grid(row=0, column=0, columnspan=4, sticky=W)
        self.moduleAuthorHdr = Label(moduleInfoFrame, text=_("author:"), state=DISABLED)
        self.moduleAuthorHdr.grid(row=1, column=0, sticky=W)
        self.moduleAuthorLabel = Label(moduleInfoFrame, wraplength=600, justify="left")
        self.moduleAuthorLabel.grid(row=1, column=1, columnspan=3, sticky=W)
        self.moduleDescrHdr = Label(moduleInfoFrame, text=_("description:"), state=DISABLED)
        self.moduleDescrHdr.grid(row=2, column=0, sticky=W)
        self.moduleDescrLabel = Label(moduleInfoFrame, wraplength=600, justify="left")
        self.moduleDescrLabel.grid(row=2, column=1, columnspan=3, sticky=W)
        self.moduleClassesHdr = Label(moduleInfoFrame, text=_("classes:"), state=DISABLED)
        self.moduleClassesHdr.grid(row=3, column=0, sticky=W)
        self.moduleClassesLabel = Label(moduleInfoFrame, wraplength=600, justify="left")
        self.moduleClassesLabel.grid(row=3, column=1, columnspan=3, sticky=W)
        ToolTip(self.moduleClassesLabel, text=_("List of classes that this plug-in handles."), wraplength=240)
        self.moduleUrlHdr = Label(moduleInfoFrame, text=_("URL:"), state=DISABLED)
        self.moduleUrlHdr.grid(row=4, column=0, sticky=W)
        self.moduleUrlLabel = Label(moduleInfoFrame, wraplength=600, justify="left")
        self.moduleUrlLabel.grid(row=4, column=1, columnspan=3, sticky=W)
        ToolTip(self.moduleUrlLabel, text=_("URL of plug-in module (local file path or web loaded file)."), wraplength=240)
        self.moduleDateHdr = Label(moduleInfoFrame, text=_("date:"), state=DISABLED)
        self.moduleDateHdr.grid(row=5, column=0, sticky=W)
        self.moduleDateLabel = Label(moduleInfoFrame, wraplength=600, justify="left")
        self.moduleDateLabel.grid(row=5, column=1, columnspan=3, sticky=W)
        ToolTip(self.moduleDateLabel, text=_("Date of currently loaded module file (with parenthetical node when an update is available)."), wraplength=240)
        self.moduleLicenseHdr = Label(moduleInfoFrame, text=_("license:"), state=DISABLED)
        self.moduleLicenseHdr.grid(row=6, column=0, sticky=W)
        self.moduleLicenseLabel = Label(moduleInfoFrame, wraplength=600, justify="left")
        self.moduleLicenseLabel.grid(row=6, column=1, columnspan=3, sticky=W)
        self.moduleEnableButton = Button(moduleInfoFrame, text=self.ENABLE, state=DISABLED, command=self.moduleEnable)
        ToolTip(self.moduleEnableButton, text=_("Enable/disable plug in."), wraplength=240)
        self.moduleEnableButton.grid(row=7, column=1, sticky=E)
        self.moduleReloadButton = Button(moduleInfoFrame, text=_("Reload"), state=DISABLED, command=self.moduleReload)
        ToolTip(self.moduleReloadButton, text=_("Reload/update plug in."), wraplength=240)
        self.moduleReloadButton.grid(row=7, column=2, sticky=E)
        self.moduleRemoveButton = Button(moduleInfoFrame, text=_("Remove"), state=DISABLED, command=self.moduleRemove)
        ToolTip(self.moduleRemoveButton, text=_("Remove plug in from plug in table (does not erase the plug in's file)."), wraplength=240)
        self.moduleRemoveButton.grid(row=7, column=3, sticky=E)
        moduleInfoFrame.grid(row=2, column=0, columnspan=5, sticky=(N, S, E, W), padx=3, pady=3)
        moduleInfoFrame.config(borderwidth=4, relief="groove")
        
        okButton = Button(frame, text=_("Close"), command=self.ok)
        ToolTip(okButton, text=_("Accept and changes (if any) and close dialog."), wraplength=240)
        cancelButton = Button(frame, text=_("Cancel"), command=self.close)
        ToolTip(cancelButton, text=_("Cancel changes (if any) and close dialog."), wraplength=240)
        okButton.grid(row=3, column=3, sticky=(S,E), pady=3)
        cancelButton.grid(row=3, column=4, sticky=(S,E), pady=3, padx=3)
        
        self.loadTreeViews()

        frame.grid(row=0, column=0, sticky=(N,S,E,W))
        frame.columnconfigure(0, weight=1)
        frame.columnconfigure(1, weight=1)
        window = self.winfo_toplevel()
        window.columnconfigure(0, weight=1)
        self.geometry("+{0}+{1}".format(dialogX+50,dialogY+100))
        
        self.bind("<Return>", self.ok)
        self.bind("<Escape>", self.close)
        
        self.protocol("WM_DELETE_WINDOW", self.close)
        self.grab_set()
        self.wait_window(self)
        
    def loadTreeViews(self):
        self.selectedModule = None

        # clear previous treeview entries
        for previousNode in self.modulesView.get_children(""): 
            self.modulesView.delete(previousNode)

        for i, moduleItem in enumerate(sorted(self.pluginConfig.get("modules", {}).items())):
            moduleInfo = moduleItem[1]
            name = moduleInfo.get("name", moduleItem[0])
            node = self.modulesView.insert("", "end", name, text=name)
            self.modulesView.set(node, "author", moduleInfo.get("author"))
            self.modulesView.set(node, "ver", moduleInfo.get("version"))
            self.modulesView.set(node, "status", moduleInfo.get("status"))
            self.modulesView.set(node, "date", moduleInfo.get("fileDate"))
            if name in self.modulesWithNewerFileDates:
                self.modulesView.set(node, "update", _("available"))
            self.modulesView.set(node, "descr", moduleInfo.get("description"))
            self.modulesView.set(node, "license", moduleInfo.get("license"))
        
        # clear previous treeview entries
        for previousNode in self.classesView.get_children(""): 
            self.classesView.delete(previousNode)

        for i, classItem in enumerate(sorted(self.pluginConfig.get("classes", {}).items())):
            className, moduleList = classItem
            node = self.classesView.insert("", "end", className, text=className)
            self.classesView.set(node, "modules", ', '.join(moduleList))
            
        self.moduleSelect()  # clear out prior selection

    def ok(self, event=None):
        if self.pluginConfigChanged:
            PluginManager.pluginConfig = self.pluginConfig
            PluginManager.pluginConfigChanged = True
            PluginManager.reset()  # force reloading of modules
        if self.uiClassMethodsChanged:  # may require reloading UI
            if messagebox.askyesno(_("User interface plug-in change"),
                                   _("A change in plug-in class methods may have affected the menus "
                                     "of the user interface.  It may be necessary to restart Arelle to "
                                     "access the menu entries or the changes to their plug-in methods.  \n\n"
                                     "Should Arelle restart with changed user interface language, "
                                     "(if there are any unsaved changes they would be lost!)?"),
                                   parent=self):
                self.cntlr.uiThreadQueue.put((self.cntlr.quit, [None, True]))
        self.close()
        
    def close(self, event=None):
        self.parent.focus_set()
        self.destroy()
                
    def moduleSelect(self, *args):
        node = (self.modulesView.selection() or (None,))[0]
        moduleInfo = self.pluginConfig.get("modules", {}).get(node)
        if moduleInfo:
            self.selectedModule = node
            name = moduleInfo["name"]
            self.moduleNameLabel.config(text=name)
            self.moduleAuthorHdr.config(state=ACTIVE)
            self.moduleAuthorLabel.config(text=moduleInfo["author"])
            self.moduleDescrHdr.config(state=ACTIVE)
            self.moduleDescrLabel.config(text=moduleInfo["description"])
            self.moduleClassesHdr.config(state=ACTIVE)
            self.moduleClassesLabel.config(text=', '.join(moduleInfo["classMethods"]))
            self.moduleUrlHdr.config(state=ACTIVE)
            self.moduleUrlLabel.config(text=moduleInfo["moduleURL"])
            self.moduleDateHdr.config(state=ACTIVE)
            self.moduleDateLabel.config(text=moduleInfo["fileDate"] + " " +
                    (_("(an update is available)") if name in self.modulesWithNewerFileDates else ""))
            self.moduleLicenseHdr.config(state=ACTIVE)
            self.moduleLicenseLabel.config(text=moduleInfo["license"])
            self.moduleEnableButton.config(state=ACTIVE,
                                           text={"enabled":self.DISABLE,
                                                 "disabled":self.ENABLE}[moduleInfo["status"]])
            self.moduleReloadButton.config(state=ACTIVE)
            self.moduleRemoveButton.config(state=ACTIVE)
        else:
            self.selectedModule = None
            self.moduleNameLabel.config(text="")
            self.moduleAuthorHdr.config(state=DISABLED)
            self.moduleAuthorLabel.config(text="")
            self.moduleDescrHdr.config(state=DISABLED)
            self.moduleDescrLabel.config(text="")
            self.moduleClassesHdr.config(state=DISABLED)
            self.moduleClassesLabel.config(text="")
            self.moduleUrlHdr.config(state=DISABLED)
            self.moduleUrlLabel.config(text="")
            self.moduleDateHdr.config(state=DISABLED)
            self.moduleDateLabel.config(text="")
            self.moduleLicenseHdr.config(state=DISABLED)
            self.moduleLicenseLabel.config(text="")
            self.moduleEnableButton.config(state=DISABLED, text=self.ENABLE)
            self.moduleReloadButton.config(state=DISABLED)
            self.moduleRemoveButton.config(state=DISABLED)
        
    def findLocally(self):
        filename = self.cntlr.uiFileDialog("open",
                                           owner=self,
                                           title=_("Choose plug-in module file"),
                                           initialdir=self.cntlr.config.setdefault("pluginOpenDir","."),
                                           filetypes=[(_("Python files"), "*.py")],
                                           defaultextension=".py")
        if filename:
            self.cntlr.config["pluginOpenDir"] = os.path.dirname(filename)
            moduleInfo = PluginManager.moduleModuleInfo(filename)
            self.loadFoundModuleInfo(moduleInfo, filename)
                

    def findOnWeb(self):
        url = DialogURL.askURL(self)
        if url:  # url is the in-cache or local file
            moduleInfo = PluginManager.moduleModuleInfo(url)
            self.cntlr.showStatus("") # clear web loading status
            self.loadFoundModuleInfo(moduleInfo, url)
                
    def loadFoundModuleInfo(self, moduleInfo, url):
        if moduleInfo and moduleInfo.get("name"):
            self.addPluginConfigModuleInfo(moduleInfo)
            self.loadTreeViews()
        else:
            messagebox.showwarning(_("Module is not a plug-in"),
                                   _("File does not contain a python program with an appropriate __pluginInfo__ declaration: \n\n{0}")
                                   .format(url),
                                   parent=self)
            
    def removePluginConfigModuleInfo(self, name):
        moduleInfo = self.pluginConfig["modules"].get(name)
        if moduleInfo:
            for classMethod in moduleInfo["classMethods"]:
                classMethods = self.pluginConfig["classes"].get(classMethod)
                if classMethods and name in classMethods:
                    classMethods.remove(name)
                    if not classMethods: # list has become unused
                        del self.pluginConfig["classes"][classMethod] # remove class
                    if classMethod.startswith("CntlrWinMain.Menu"):
                        self.uiClassMethodsChanged = True  # may require reloading UI
            del self.pluginConfig["modules"][name]
            self.pluginConfigChanged = True

    def addPluginConfigModuleInfo(self, moduleInfo):
        name = moduleInfo["name"]
        self.removePluginConfigModuleInfo(name)  # remove any prior entry for this module
        self.modulesWithNewerFileDates.discard(name) # no longer has an update available
        self.pluginConfig["modules"][name] = moduleInfo
        # add classes
        for classMethod in moduleInfo["classMethods"]:
            classMethods = self.pluginConfig["classes"].setdefault(classMethod, [])
            if name not in classMethods:
                classMethods.append(name)
            if classMethod.startswith("CntlrWinMain.Menu"):
                self.uiClassMethodsChanged = True  # may require reloading UI
        self.pluginConfigChanged = True

    def moduleEnable(self):
        if self.selectedModule in self.pluginConfig["modules"]:
            moduleInfo = self.pluginConfig["modules"][self.selectedModule]
            if self.moduleEnableButton['text'] == self.ENABLE:
                moduleInfo["status"] = "enabled"
                self.moduleEnableButton['text'] = self.DISABLE
            elif self.moduleEnableButton['text'] == self.DISABLE:
                moduleInfo["status"] = "disabled"
                self.moduleEnableButton['text'] = self.ENABLE
            self.pluginConfigChanged = True
            self.loadTreeViews()
            
    def moduleReload(self):
        if self.selectedModule in self.pluginConfig["modules"]:
            url = self.pluginConfig["modules"][self.selectedModule].get("moduleURL")
            if url:
                moduleInfo = PluginManager.moduleModuleInfo(url, reload=True)
                if moduleInfo:
                    self.addPluginConfigModuleInfo(moduleInfo)
                    self.loadTreeViews()
                    self.cntlr.showStatus(_("{0} reloaded").format(moduleInfo.get("name")), clearAfter=5000)
                else:
                    messagebox.showwarning(_("Module error"),
                                           _("File or module cannot be reloaded: \n\n{0}")
                                           .format(url),
                                           parent=self)

    def moduleRemove(self):
        if self.selectedModule in self.pluginConfig["modules"]:
            self.removePluginConfigModuleInfo(self.selectedModule)
            self.pluginConfigChanged = True
            self.loadTreeViews()
Exemple #11
0
class Example(Frame):
    def __init__(self, parent):
        Frame.__init__(self, parent)

        self.parent = parent
        self.initUI()

    def initUI(self):
        self.username = ''
        self.r = praw.Reddit(USERAGENT)
        self.parent.title("")
        self.style = Style()
        self.style.theme_use("clam")
        self.pack(fill=BOTH, expand = 1)

        self.labelU = Label(self, text="U:")
        self.labelP = Label(self, text="P:")
        
        self.entryUsername = Entry(self)
        self.entryUsername.config(relief='flat')
        self.entryUsername.focus_set()
        self.entryUsername.bind('<Return>', lambda event: self.login(self.entryUsername.get()))
        self.entryUsername.bind('<Up>', lambda event: self.entryUsername.insert(0, self.username))

        self.quitbutton = Button(self, text="Quit", command= lambda: self.quit())
        self.quitbutton.config(width=6)
        
    
        self.labelKarma = Label(self, text = '•')
        self.labelKarma.grid(row = 3, column = 1)


        self.labelU.grid(row=0, column=0)
        self.entryUsername.grid(row=0, column=1)
        self.quitbutton.grid(row=2, column=1, pady=4)

        self.usernamelabel = Label(self, text='')
        self.usernamelabel.grid(row=1, column=1)


    def login(self, username):
        print('U: ' + username)
        self.username = username
        self.entryUsername.delete(0, 200)
        if username == '':
            self.entryUsername.focus_set()
            
        else:
            try:
                self.user = self.r.get_redditor(self.username)
                lkarma = str(self.user.link_karma)
                ckarma = str(self.user.comment_karma)
                lkarma = self.karmaRound(lkarma)
                ckarma = self.karmaRound(ckarma)
                karmastring = lkarma + ' • ' + ckarma
                self.labelKarma.config(text = karmastring)
                self.usernamelabel.config(text= self.username)

            except:
                self.labelKarma.config(text = '•')
                self.usernamelabel.config(text= 'User not found')
                pass

    def karmaRound(self, karma):
        if len(karma) > 4 and len(karma) < 7:
            tstring = karma[:-3]
            tstring2 = karma[-3:]
            karma = tstring + '.' + tstring2[:2] + 'K'
            return karma
        if len(karma) > 6:
            tstring = karma[:-6]
            tstring2 = karma[-6:]
            karma = tstring + '.' + tstring2[:2] + 'M'
            return karma
        else:
            return karma
Exemple #12
0
    def setupUI(self):
        # build UI base on URLS
        if self.option[2] == SEARCH:
            # title window
            label_title = Label(self, text='Search Photos')
            label_title.config(anchor='center', foreground='white', background='#8e44ad')
            label_title.grid(row=0, column=0, columnspan=6, sticky='we')

            # progress
            self.progress = Progressbar(self) 
            self.progress.config(orient='horizontal', length=100, mode='determinate')
            self.progress.grid(row=2, column=0, columnspan=5, sticky='we')

            self.var_progress = StringVar()
            self.var_progress.set('0%')
            self.label_show_progress = Label(self) 
            self.label_show_progress.config(textvariable=self.var_progress, anchor='center')
            self.label_show_progress.var = self.var_progress
            self.label_show_progress.grid(row=2, column=5, sticky='w')

            # query
            self.label_query = Label(self, text='Query')
            self.label_query.grid(row=1, column=0, sticky='e')

            self.var_entry_query = StringVar()
            self.entry_query = Entry(self)
            self.entry_query.config(textvariable=self.var_entry_query, state='readonly')
            self.entry_query.grid(row=1, column=1, sticky='w')

            # total
            self.var_total = StringVar()
            self.var_total.set('Total')
            self.label_total = Label(self, textvariable=self.var_total)
            self.label_total.grid(row=1, column=2, sticky='e')

            self.var_entry_total = IntVar()
            self.entry_total = Entry(self)
            self.entry_total.config(textvariable=self.var_entry_total, state='readonly')
            self.entry_total.grid(row=1, column=3, sticky='w')

            # total pages
            self.label_total_page = Label(self, text='Total pages:')
            self.label_total_page.grid(row=1, column=4, sticky='e')

            self.var_entry_total_pages = IntVar()
            self.entry_total_page = Entry(self)
            self.entry_total_page.config(textvariable=self.var_entry_total_pages, state='readonly')
            self.entry_total_page.grid(row=1, column=5, sticky='w')

            # show image is downloaded
            self.label_image_downloaded = Label(self, anchor='center')
            self.label_image_downloaded.grid(row=3, column=0, columnspan=6, sticky='wesn')
            
            # self.change_ui()

        elif self.option[2] == LIST:
            # title window
            label_title = Label(self, text='List of Photos')
            label_title.config(
                anchor='center', foreground='white', background='#2c3e50')
            label_title.grid(row=0, column=0, columnspan=4, sticky='we')

            # progress
            self.progress = Progressbar(self)
            self.progress.config(orient='horizontal',
                                 length=100, mode='determinate')
            self.progress.grid(row=2, column=0, columnspan=3, sticky='we')

            self.var_progress = StringVar()
            self.var_progress.set('0%')
            self.label_show_progress = Label(self)
            self.label_show_progress.config(
                textvariable=self.var_progress, anchor='center')
            self.label_show_progress.var = self.var_progress
            self.label_show_progress.grid(row=2, column=3, sticky='w')

            # query
            self.label_query = Label(self, text='Query:')
            self.label_query.grid(row=1, column=0, sticky='e')

            self.entry_query = Entry(self)
            self.entry_query.insert(0,'LIST')
            self.entry_query.config(state='readonly')
            self.entry_query.grid(row=1, column=1, sticky='w')

            # amount
            self.label_total = Label(self, text='Amount:')
            self.label_total.grid(row=1, column=2, sticky='e')

            self.entry_total = Entry(self)
            self.entry_total.insert(0,self.option[3]['per_page'])
            self.entry_total.config(state='readonly')
            self.entry_total.grid(row=1, column=3, sticky='w')

            # show image is downloaded
            self.label_image_downloaded = Label(self, anchor='center')
            self.label_image_downloaded.grid(
                row=3, column=0, columnspan=4, sticky='wesn')

            # self.change_ui()

        elif self.option[2] == RANDOM:
            # title window
            label_title = Label(self, text='Random Photos')
            label_title.config(
                anchor='center', foreground='white', background='#16a085')
            label_title.grid(row=0, column=0, columnspan=4, sticky='we')

            # progress
            self.progress = Progressbar(self)
            self.progress.config(orient='horizontal',
                                 length=100, mode='determinate')
            self.progress.grid(row=2, column=0, columnspan=3, sticky='we')

            self.var_progress = StringVar()
            self.var_progress.set('0%')
            self.label_show_progress = Label(self)
            self.label_show_progress.config(
                textvariable=self.var_progress, anchor='center')
            self.label_show_progress.var = self.var_progress
            self.label_show_progress.grid(row=2, column=3, sticky='w')

            # query
            self.label_query = Label(self, text='Query')
            self.label_query.grid(row=1, column=0, sticky='e')

            self.entry_query = Entry(self)
            self.entry_query.insert(0,'RANDOM')
            self.entry_query.config(state='readonly')
            self.entry_query.grid(row=1, column=1, sticky='w')

            # amount
            self.label_total = Label(self, text='Amount')
            self.label_total.grid(row=1, column=2, sticky='e')

            self.var_entry_total = IntVar()
            if self.option[3]['count'] > 30:
                self.var_entry_total.set(30)
            else:
                self.var_entry_total.set(self.option[3]['count'])
            self.entry_total = Entry(self)
            self.entry_total.config(textvariable=self.var_entry_total, state='readonly')
            self.entry_total.grid(row=1, column=3, sticky='w')
            

            # show image is downloaded
            self.label_image_downloaded = Label(self, anchor='center')
            self.label_image_downloaded.grid(
                row=3, column=0, columnspan=4, sticky='wesn')
Exemple #13
0
class DialogPluginManager(Toplevel):
    def __init__(self, mainWin, modulesWithNewerFileDates):
        super(DialogPluginManager, self).__init__(mainWin.parent)
        
        self.ENABLE = _("Enable")
        self.DISABLE = _("Disable")
        self.parent = mainWin.parent
        self.cntlr = mainWin
        
        # copy plugins for temporary display
        self.pluginConfig = PluginManager.pluginConfig
        self.pluginConfigChanged = False
        self.uiClassMethodsChanged = False
        self.modelClassesChanged = False
        self.disclosureSystemTypesChanged = False
        self.modulesWithNewerFileDates = modulesWithNewerFileDates
        
        parentGeometry = re.match("(\d+)x(\d+)[+]?([-]?\d+)[+]?([-]?\d+)", self.parent.geometry())
        dialogX = int(parentGeometry.group(3))
        dialogY = int(parentGeometry.group(4))

        self.title(_("Plug-in Manager"))
        frame = Frame(self)
        
        # left button frame
        buttonFrame = Frame(frame, width=40)
        buttonFrame.columnconfigure(0, weight=1)
        addLabel = Label(buttonFrame, text=_("Find plug-in modules:"), wraplength=60, justify="center")
        addLocalButton = Button(buttonFrame, text=_("Locally"), command=self.findLocally)
        ToolTip(addLocalButton, text=_("File chooser allows selecting python module files to add (or reload) plug-ins, from the local file system."), wraplength=240)
        addWebButton = Button(buttonFrame, text=_("On Web"), command=self.findOnWeb)
        ToolTip(addWebButton, text=_("Dialog to enter URL full path to load (or reload) plug-ins, from the web or local file system."), wraplength=240)
        addLabel.grid(row=0, column=0, pady=4)
        addLocalButton.grid(row=1, column=0, pady=4)
        addWebButton.grid(row=2, column=0, pady=4)
        buttonFrame.grid(row=0, column=0, rowspan=2, sticky=(N, S, W), padx=3, pady=3)
        
        # right tree frame (plugins already known to arelle)
        modulesFrame = Frame(frame, width=700)
        vScrollbar = Scrollbar(modulesFrame, orient=VERTICAL)
        hScrollbar = Scrollbar(modulesFrame, orient=HORIZONTAL)
        self.modulesView = Treeview(modulesFrame, xscrollcommand=hScrollbar.set, yscrollcommand=vScrollbar.set, height=7)
        self.modulesView.grid(row=0, column=0, sticky=(N, S, E, W))
        self.modulesView.bind('<<TreeviewSelect>>', self.moduleSelect)
        hScrollbar["command"] = self.modulesView.xview
        hScrollbar.grid(row=1, column=0, sticky=(E,W))
        vScrollbar["command"] = self.modulesView.yview
        vScrollbar.grid(row=0, column=1, sticky=(N,S))
        modulesFrame.columnconfigure(0, weight=1)
        modulesFrame.rowconfigure(0, weight=1)
        modulesFrame.grid(row=0, column=1, columnspan=4, sticky=(N, S, E, W), padx=3, pady=3)
        self.modulesView.focus_set()

        self.modulesView.column("#0", width=120, anchor="w")
        self.modulesView.heading("#0", text=_("Name"))
        self.modulesView["columns"] = ("author", "ver", "status", "date", "update", "descr", "license")
        self.modulesView.column("author", width=100, anchor="w", stretch=False)
        self.modulesView.heading("author", text=_("Author"))
        self.modulesView.column("ver", width=50, anchor="w", stretch=False)
        self.modulesView.heading("ver", text=_("Version"))
        self.modulesView.column("status", width=50, anchor="w", stretch=False)
        self.modulesView.heading("status", text=_("Status"))
        self.modulesView.column("date", width=70, anchor="w", stretch=False)
        self.modulesView.heading("date", text=_("File Date"))
        self.modulesView.column("update", width=50, anchor="w", stretch=False)
        self.modulesView.heading("update", text=_("Update"))
        self.modulesView.column("descr", width=200, anchor="w", stretch=False)
        self.modulesView.heading("descr", text=_("Description"))
        self.modulesView.column("license", width=70, anchor="w", stretch=False)
        self.modulesView.heading("license", text=_("License"))

        classesFrame = Frame(frame)
        vScrollbar = Scrollbar(classesFrame, orient=VERTICAL)
        hScrollbar = Scrollbar(classesFrame, orient=HORIZONTAL)
        self.classesView = Treeview(classesFrame, xscrollcommand=hScrollbar.set, yscrollcommand=vScrollbar.set, height=5)
        self.classesView.grid(row=0, column=0, sticky=(N, S, E, W))
        hScrollbar["command"] = self.classesView.xview
        hScrollbar.grid(row=1, column=0, sticky=(E,W))
        vScrollbar["command"] = self.classesView.yview
        vScrollbar.grid(row=0, column=1, sticky=(N,S))
        classesFrame.columnconfigure(0, weight=1)
        classesFrame.rowconfigure(0, weight=1)
        classesFrame.grid(row=1, column=1, columnspan=4, sticky=(N, S, E, W), padx=3, pady=3)
        self.classesView.focus_set()
        
        self.classesView.column("#0", width=200, anchor="w")
        self.classesView.heading("#0", text=_("Class"))
        self.classesView["columns"] = ("modules",)
        self.classesView.column("modules", width=500, anchor="w", stretch=False)
        self.classesView.heading("modules", text=_("Modules"))
        
        # bottom frame module info details
        moduleInfoFrame = Frame(frame, width=700)
        moduleInfoFrame.columnconfigure(1, weight=1)
        
        self.moduleNameLabel = Label(moduleInfoFrame, wraplength=600, justify="left", 
                                     font=font.Font(family='Helvetica', size=12, weight='bold'))
        self.moduleNameLabel.grid(row=0, column=0, columnspan=4, sticky=W)
        self.moduleAuthorHdr = Label(moduleInfoFrame, text=_("author:"), state=DISABLED)
        self.moduleAuthorHdr.grid(row=1, column=0, sticky=W)
        self.moduleAuthorLabel = Label(moduleInfoFrame, wraplength=600, justify="left")
        self.moduleAuthorLabel.grid(row=1, column=1, columnspan=3, sticky=W)
        self.moduleDescrHdr = Label(moduleInfoFrame, text=_("description:"), state=DISABLED)
        self.moduleDescrHdr.grid(row=2, column=0, sticky=W)
        self.moduleDescrLabel = Label(moduleInfoFrame, wraplength=600, justify="left")
        self.moduleDescrLabel.grid(row=2, column=1, columnspan=3, sticky=W)
        self.moduleClassesHdr = Label(moduleInfoFrame, text=_("classes:"), state=DISABLED)
        self.moduleClassesHdr.grid(row=3, column=0, sticky=W)
        self.moduleClassesLabel = Label(moduleInfoFrame, wraplength=600, justify="left")
        self.moduleClassesLabel.grid(row=3, column=1, columnspan=3, sticky=W)
        ToolTip(self.moduleClassesLabel, text=_("List of classes that this plug-in handles."), wraplength=240)
        self.moduleUrlHdr = Label(moduleInfoFrame, text=_("URL:"), state=DISABLED)
        self.moduleUrlHdr.grid(row=4, column=0, sticky=W)
        self.moduleUrlLabel = Label(moduleInfoFrame, wraplength=600, justify="left")
        self.moduleUrlLabel.grid(row=4, column=1, columnspan=3, sticky=W)
        ToolTip(self.moduleUrlLabel, text=_("URL of plug-in module (local file path or web loaded file)."), wraplength=240)
        self.moduleDateHdr = Label(moduleInfoFrame, text=_("date:"), state=DISABLED)
        self.moduleDateHdr.grid(row=5, column=0, sticky=W)
        self.moduleDateLabel = Label(moduleInfoFrame, wraplength=600, justify="left")
        self.moduleDateLabel.grid(row=5, column=1, columnspan=3, sticky=W)
        ToolTip(self.moduleDateLabel, text=_("Date of currently loaded module file (with parenthetical node when an update is available)."), wraplength=240)
        self.moduleLicenseHdr = Label(moduleInfoFrame, text=_("license:"), state=DISABLED)
        self.moduleLicenseHdr.grid(row=6, column=0, sticky=W)
        self.moduleLicenseLabel = Label(moduleInfoFrame, wraplength=600, justify="left")
        self.moduleLicenseLabel.grid(row=6, column=1, columnspan=3, sticky=W)
        self.moduleEnableButton = Button(moduleInfoFrame, text=self.ENABLE, state=DISABLED, command=self.moduleEnable)
        ToolTip(self.moduleEnableButton, text=_("Enable/disable plug in."), wraplength=240)
        self.moduleEnableButton.grid(row=7, column=1, sticky=E)
        self.moduleReloadButton = Button(moduleInfoFrame, text=_("Reload"), state=DISABLED, command=self.moduleReload)
        ToolTip(self.moduleReloadButton, text=_("Reload/update plug in."), wraplength=240)
        self.moduleReloadButton.grid(row=7, column=2, sticky=E)
        self.moduleRemoveButton = Button(moduleInfoFrame, text=_("Remove"), state=DISABLED, command=self.moduleRemove)
        ToolTip(self.moduleRemoveButton, text=_("Remove plug in from plug in table (does not erase the plug in's file)."), wraplength=240)
        self.moduleRemoveButton.grid(row=7, column=3, sticky=E)
        moduleInfoFrame.grid(row=2, column=0, columnspan=5, sticky=(N, S, E, W), padx=3, pady=3)
        moduleInfoFrame.config(borderwidth=4, relief="groove")
        
        okButton = Button(frame, text=_("Close"), command=self.ok)
        ToolTip(okButton, text=_("Accept and changes (if any) and close dialog."), wraplength=240)
        cancelButton = Button(frame, text=_("Cancel"), command=self.close)
        ToolTip(cancelButton, text=_("Cancel changes (if any) and close dialog."), wraplength=240)
        okButton.grid(row=3, column=3, sticky=(S,E), pady=3)
        cancelButton.grid(row=3, column=4, sticky=(S,E), pady=3, padx=3)
        
        enableDisableFrame = Frame(frame)
        enableDisableFrame.grid(row=3, column=1, sticky=(S,W), pady=3)
        enableAllButton = Button(enableDisableFrame, text=_("Enable All"), command=self.enableAll)
        ToolTip(enableAllButton, text=_("Enable all plug ins."), wraplength=240)
        disableAllButton = Button(enableDisableFrame, text=_("Disable All"), command=self.disableAll)
        ToolTip(disableAllButton, text=_("Disable all plug ins."), wraplength=240)
        enableAllButton.grid(row=1, column=1)
        disableAllButton.grid(row=1, column=2)
        
        self.loadTreeViews()

        self.geometry("+{0}+{1}".format(dialogX+50,dialogY+100))
        frame.grid(row=0, column=0, sticky=(N,S,E,W))
        frame.columnconfigure(0, weight=0)
        frame.columnconfigure(1, weight=1)
        frame.rowconfigure(0, weight=1)
        window = self.winfo_toplevel()
        window.columnconfigure(0, weight=1)
        window.rowconfigure(0, weight=1)
        
        self.bind("<Return>", self.ok)
        self.bind("<Escape>", self.close)
        
        self.protocol("WM_DELETE_WINDOW", self.close)
        self.grab_set()
        self.wait_window(self)
        
    def loadTreeViews(self):
        self.selectedModule = None

        # clear previous treeview entries
        for previousNode in self.modulesView.get_children(""): 
            self.modulesView.delete(previousNode)

        for i, moduleItem in enumerate(sorted(self.pluginConfig.get("modules", {}).items())):
            moduleInfo = moduleItem[1]
            name = moduleInfo.get("name", moduleItem[0])
            node = self.modulesView.insert("", "end", name, text=name)
            self.modulesView.set(node, "author", moduleInfo.get("author"))
            self.modulesView.set(node, "ver", moduleInfo.get("version"))
            self.modulesView.set(node, "status", moduleInfo.get("status"))
            self.modulesView.set(node, "date", moduleInfo.get("fileDate"))
            if name in self.modulesWithNewerFileDates:
                self.modulesView.set(node, "update", _("available"))
            self.modulesView.set(node, "descr", moduleInfo.get("description"))
            self.modulesView.set(node, "license", moduleInfo.get("license"))
        
        # clear previous treeview entries
        for previousNode in self.classesView.get_children(""): 
            self.classesView.delete(previousNode)

        for i, classItem in enumerate(sorted(self.pluginConfig.get("classes", {}).items())):
            className, moduleList = classItem
            node = self.classesView.insert("", "end", className, text=className)
            self.classesView.set(node, "modules", ', '.join(moduleList))
            
        self.moduleSelect()  # clear out prior selection

    def ok(self, event=None):
        if self.pluginConfigChanged:
            PluginManager.pluginConfig = self.pluginConfig
            PluginManager.pluginConfigChanged = True
            PluginManager.reset()  # force reloading of modules
        if self.uiClassMethodsChanged or self.modelClassesChanged or self.disclosureSystemTypesChanged:  # may require reloading UI
            affectedItems = ""
            if self.uiClassMethodsChanged:
                affectedItems += _("menus of the user interface")
            if self.modelClassesChanged:
                if self.uiClassMethodsChanged:
                    affectedItems += _(" and ")
                affectedItems += _("model objects of the processor")
            if (self.uiClassMethodsChanged or self.modelClassesChanged):
                affectedItems += _(" and ")
            if self.disclosureSystemTypesChanged:
                if (self.uiClassMethodsChanged or self.modelClassesChanged):
                    affectedItems += _(" and ")
                affectedItems += _("disclosure system types")
            if messagebox.askyesno(_("User interface plug-in change"),
                                   _("A change in plug-in class methods may have affected {0}.  " 
                                     "Please restart Arelle to due to these changes.  \n\n"
                                     "Should Arelle restart itself now "
                                     "(if there are any unsaved changes they would be lost!)?"
                                     ).format(affectedItems),
                                   parent=self):
                self.cntlr.uiThreadQueue.put((self.cntlr.quit, [None, True]))
        self.close()
        
    def close(self, event=None):
        self.parent.focus_set()
        self.destroy()
                
    def moduleSelect(self, *args):
        node = (self.modulesView.selection() or (None,))[0]
        moduleInfo = self.pluginConfig.get("modules", {}).get(node)
        if moduleInfo:
            self.selectedModule = node
            name = moduleInfo["name"]
            self.moduleNameLabel.config(text=name)
            self.moduleAuthorHdr.config(state=ACTIVE)
            self.moduleAuthorLabel.config(text=moduleInfo["author"])
            self.moduleDescrHdr.config(state=ACTIVE)
            self.moduleDescrLabel.config(text=moduleInfo["description"])
            self.moduleClassesHdr.config(state=ACTIVE)
            self.moduleClassesLabel.config(text=', '.join(moduleInfo["classMethods"]))
            self.moduleUrlHdr.config(state=ACTIVE)
            self.moduleUrlLabel.config(text=moduleInfo["moduleURL"])
            self.moduleDateHdr.config(state=ACTIVE)
            self.moduleDateLabel.config(text=moduleInfo["fileDate"] + " " +
                    (_("(an update is available)") if name in self.modulesWithNewerFileDates else ""))
            self.moduleLicenseHdr.config(state=ACTIVE)
            self.moduleLicenseLabel.config(text=moduleInfo["license"])
            self.moduleEnableButton.config(state=ACTIVE,
                                           text={"enabled":self.DISABLE,
                                                 "disabled":self.ENABLE}[moduleInfo["status"]])
            self.moduleReloadButton.config(state=ACTIVE)
            self.moduleRemoveButton.config(state=ACTIVE)
        else:
            self.selectedModule = None
            self.moduleNameLabel.config(text="")
            self.moduleAuthorHdr.config(state=DISABLED)
            self.moduleAuthorLabel.config(text="")
            self.moduleDescrHdr.config(state=DISABLED)
            self.moduleDescrLabel.config(text="")
            self.moduleClassesHdr.config(state=DISABLED)
            self.moduleClassesLabel.config(text="")
            self.moduleUrlHdr.config(state=DISABLED)
            self.moduleUrlLabel.config(text="")
            self.moduleDateHdr.config(state=DISABLED)
            self.moduleDateLabel.config(text="")
            self.moduleLicenseHdr.config(state=DISABLED)
            self.moduleLicenseLabel.config(text="")
            self.moduleEnableButton.config(state=DISABLED, text=self.ENABLE)
            self.moduleReloadButton.config(state=DISABLED)
            self.moduleRemoveButton.config(state=DISABLED)
        
    def findLocally(self):
        initialdir = self.cntlr.pluginDir # default plugin directory
        if not self.cntlr.isMac: # can't navigate within app easily, always start in default directory
            initialdir = self.cntlr.config.setdefault("pluginOpenDir", initialdir)
        filename = self.cntlr.uiFileDialog("open",
                                           parent=self,
                                           title=_("Choose plug-in module file"),
                                           initialdir=initialdir,
                                           filetypes=[(_("Python files"), "*.py")],
                                           defaultextension=".py")
        if filename:
            # check if a package is selected (any file in a directory containing an __init__.py
            if (os.path.isdir(os.path.dirname(filename)) and
                os.path.isfile(os.path.join(os.path.dirname(filename), "__init__.py"))):
                filename = os.path.dirname(filename) # refer to the package instead
            self.cntlr.config["pluginOpenDir"] = os.path.dirname(filename)
            moduleInfo = PluginManager.moduleModuleInfo(filename)
            self.loadFoundModuleInfo(moduleInfo, filename)
                

    def findOnWeb(self):
        url = DialogURL.askURL(self)
        if url:  # url is the in-cache or local file
            moduleInfo = PluginManager.moduleModuleInfo(url)
            self.cntlr.showStatus("") # clear web loading status
            self.loadFoundModuleInfo(moduleInfo, url)
                
    def loadFoundModuleInfo(self, moduleInfo, url):
        if moduleInfo and moduleInfo.get("name"):
            self.addPluginConfigModuleInfo(moduleInfo)
            self.loadTreeViews()
        else:
            messagebox.showwarning(_("Module is not itself a plug-in or in a directory with package __init__.py plug-in.  "),
                                   _("File does not itself contain a python program with an appropriate __pluginInfo__ declaration: \n\n{0}")
                                   .format(url),
                                   parent=self)
            
    def removePluginConfigModuleInfo(self, name):
        moduleInfo = self.pluginConfig["modules"].get(name)
        if moduleInfo:
            for classMethod in moduleInfo["classMethods"]:
                classMethods = self.pluginConfig["classes"].get(classMethod)
                if classMethods and name in classMethods:
                    classMethods.remove(name)
                    if not classMethods: # list has become unused
                        del self.pluginConfig["classes"][classMethod] # remove class
                    if classMethod.startswith("CntlrWinMain.Menu"):
                        self.uiClassMethodsChanged = True  # may require reloading UI
                    elif classMethod == "ModelObjectFactory.ElementSubstitutionClasses":
                        self.modelClassesChanged = True # model object factor classes changed
                    elif classMethod == "DisclosureSystem.Types":
                        self.disclosureSystemTypesChanged = True # disclosure system types changed
            del self.pluginConfig["modules"][name]
            self.pluginConfigChanged = True

    def addPluginConfigModuleInfo(self, moduleInfo):
        name = moduleInfo["name"]
        self.removePluginConfigModuleInfo(name)  # remove any prior entry for this module
        self.modulesWithNewerFileDates.discard(name) # no longer has an update available
        self.pluginConfig["modules"][name] = moduleInfo
        # add classes
        for classMethod in moduleInfo["classMethods"]:
            classMethods = self.pluginConfig["classes"].setdefault(classMethod, [])
            if name not in classMethods:
                classMethods.append(name)
            if classMethod.startswith("CntlrWinMain.Menu"):
                self.uiClassMethodsChanged = True  # may require reloading UI
            elif classMethod == "ModelObjectFactory.ElementSubstitutionClasses":
                self.modelClassesChanged = True # model object factor classes changed
            elif classMethod == "DisclosureSystem.Types":
                self.disclosureSystemTypesChanged = True # disclosure system types changed
        self.pluginConfigChanged = True

    def moduleEnable(self):
        if self.selectedModule in self.pluginConfig["modules"]:
            moduleInfo = self.pluginConfig["modules"][self.selectedModule]
            if self.moduleEnableButton['text'] == self.ENABLE:
                moduleInfo["status"] = "enabled"
                self.moduleEnableButton['text'] = self.DISABLE
            elif self.moduleEnableButton['text'] == self.DISABLE:
                moduleInfo["status"] = "disabled"
                self.moduleEnableButton['text'] = self.ENABLE
            self.pluginConfigChanged = True
            self.loadTreeViews()
            
    def moduleReload(self):
        if self.selectedModule in self.pluginConfig["modules"]:
            url = self.pluginConfig["modules"][self.selectedModule].get("moduleURL")
            if url:
                moduleInfo = PluginManager.moduleModuleInfo(url, reload=True)
                if moduleInfo:
                    self.addPluginConfigModuleInfo(moduleInfo)
                    self.loadTreeViews()
                    self.cntlr.showStatus(_("{0} reloaded").format(moduleInfo.get("name")), clearAfter=5000)
                else:
                    messagebox.showwarning(_("Module error"),
                                           _("File or module cannot be reloaded: \n\n{0}")
                                           .format(url),
                                           parent=self)

    def moduleRemove(self):
        if self.selectedModule in self.pluginConfig["modules"]:
            self.removePluginConfigModuleInfo(self.selectedModule)
            self.pluginConfigChanged = True
            self.loadTreeViews()
                    
    def enableAll(self):
        self.enableDisableAll(True)
                    
    def disableAll(self):
        self.enableDisableAll(False)
                    
    def enableDisableAll(self, doEnable):
        for module in self.pluginConfig["modules"]:
            moduleInfo = self.pluginConfig["modules"][module]
            if doEnable:
                moduleInfo["status"] = "enabled"
                self.moduleEnableButton['text'] = self.DISABLE
            else:
                moduleInfo["status"] = "disabled"
                self.moduleEnableButton['text'] = self.ENABLE
        self.pluginConfigChanged = True
        self.loadTreeViews()
            
class Example(Frame):
    def __init__(self, parent):
        Frame.__init__(self, parent)

        self.parent = parent
        self.initUI()

    def initUI(self):
        self.parent.title("")
        self.style = Style()
        self.style.theme_use("clam")
        self.pack(fill=BOTH, expand = 1)

        self.labelU = Label(self, text="U:")
        self.labelP = Label(self, text="P:")
        
        self.entryUsername = Entry(self)
        self.entryUsername.config(relief='flat')
        self.entryUsername.focus_set()
        self.entryUsername.bind('<Return>', lambda event: self.entryPassword.focus_set())

        self.entryPassword = Entry(self)
        self.entryPassword.config(relief='flat', show='•')
        self.entryPassword.bind('<Return>', lambda event: self.login(self.entryUsername.get(), self.entryPassword.get()))

        self.newbutton = Button(self, text="Login", command= lambda: self.login(self.entryUsername.get(), self.entryPassword.get()))
        self.newbutton.bind('<Return>', lambda event: self.login(self.entryUsername.get(), self.entryPassword.get()))
        self.newbutton.config(width=6)
        self.quitbutton = Button(self, text="Quit", command= lambda: self.quit())
        self.quitbutton.config(width=6)
        
        self.mailIconRed = PhotoImage(file="mail.gif")
        self.labelRed = Label(self, image=self.mailIconRed)
        self.mailIconGray = PhotoImage(file="mail2.gif")
        self.labelGray = Label(self, image=self.mailIconGray)
        self.labelKarma = Label(self, text = '•')

        self.labelU.grid(row=0, column=0)
        self.entryUsername.grid(row=0, column=1)
        self.labelP.grid(row=1, column=0)
        self.entryPassword.grid(row=1, column=1, pady=4)
        self.newbutton.grid(row=2, column=1)
        self.quitbutton.grid(row=3, column=1, pady=4)
        

        '''
        sw = self.parent.winfo_screenwidth()
        sh = self.parent.winfo_screenheight()

        w=150
        h=112
        x = (sw - w) / 2
        y = (sh - h) / 2

        self.parent.geometry('%dx%d+%d+%d' % (w, h, x, y-50))
        '''


    def login(self, username, password):
        #print('U: ' + username)
        self.username = username
        if username == '':
            #print('Please enter a username')
            self.entryUsername.focus_set()
        elif password == '':
            #print('Please enter a password')
            self.entryPassword.set_focus()
            
        if username != '' and password != '':
            #print('Attempting login for ' + username)
            try:
                self.USERAGENT = username + ' scans his inbox for new mail.'
                self.r = praw.Reddit(self.USERAGENT)
                #self.r.config._ssl_url = None
                self.r.login(username, password)
                #print('You have logged in as ' + username)
                self.labelU.grid_forget()
                self.labelP.grid_forget()
                self.entryUsername.grid_forget()
                self.entryPassword.grid_forget()
                self.newbutton.grid_forget()
                self.quitbutton.grid_forget()
                self.usernamelabel = Label(self, text=username)
                self.usernamelabel.grid(row=0, column=0, pady = 10, padx = 30)
                self.quitbutton.grid(row=1, column=0)
                self.labelKarma.grid(row = 3, column = 0)
                self.playedSound = 'false'
                self.loop()
            except praw.errors.InvalidUserPass:
                pass
                #print('Invalid username or password')

    def loop(self):
        while True:
            try:
                #print('Starting new search')
                hasmail = 'false'
                for msg in self.r.get_unread(limit=None):
                    hasmail = 'true'
                
                if hasmail == 'true':
                    #print("You've got mail!")
                    if self.playedSound == 'false':
                        winsound.PlaySound('pop.wav', winsound.SND_FILENAME)
                    self.playedSound = 'true'
                    self.labelGray.grid_forget()
                    self.labelRed.grid(row=2, column=0)
                if hasmail == 'false':
                    self.playedSound = 'false'
                    #print('No mail!')
                    self.labelRed.grid_forget()
                    self.labelGray.grid(row=2, column=0)
                self.user = self.r.get_redditor(self.username)
                lkarma = str(self.user.link_karma)
                ckarma = str(self.user.comment_karma)
                lkarma = self.karmaRound(lkarma)
                ckarma = self.karmaRound(ckarma)
                karmastring = lkarma + ' • ' + ckarma
                self.labelKarma.config(text = karmastring)
                time.sleep(10)
            except Exception:
                time.sleep(10)


    def karmaRound(self, karma):
        if len(karma) > 4 and len(karma) < 7:
            tstring = karma[:-3]
            tstring2 = karma[-3:]
            karma = tstring + '.' + tstring2[:2] + 'K'
            return karma
        if len(karma) > 6:
            tstring = karma[:-6]
            tstring2 = karma[-6:]
            karma = tstring + '.' + tstring2[:2] + 'M'
            return karma
        else:
            return karma
Exemple #15
0
class GameView(Frame):
    def __init__(self, ui_root, play_service):
        super().__init__(master=ui_root)
        self._ui_root = ui_root
        self._play_service = play_service
        self._current_word_var = StringVar(self)
        self._current_word_label = Label(master=self,
                                         textvariable=self._current_word_var)
        self._current_word_label.config(font=("TkDefaultFont", 24))
        self._current_word_label.pack(pady=6)
        self._images_container = Frame(master=self)
        self._images_container.pack(expand=True)
        self._images = []

    def start(self, game):
        self._play_service.start_game(game)
        self._start_round()

    def _start_round(self):
        self._images_container.destroy()
        self._images_container = Frame(master=self)
        self._images_container.pack(expand=True)
        self._images = []
        row = Frame(master=self._images_container)
        row.pack(pady=3)
        row_count = 0
        for image, index in self._play_service.get_images():
            if row_count >= IMAGES_PER_ROW:
                row = Frame(master=self._images_container)
                row.pack(pady=3)
                row_count = 0
            row_count += 1
            img = ImageTk.PhotoImage(image.loaded_image)
            label = ImgLabel(master=row, image=img)
            label.bind("<Button-1>",
                       lambda e, index=index, ctx=self: ctx.guess(index))
            label.pack(side=RIGHT, padx=3)
            self._images.append((label, index, img))

        self._update()

    def _update(self):
        self._current_word_var.set(self._play_service.get_text())

    def _end_game(self):
        self._play_service.reset()
        self._ui_root.show_start_view()

    def guess(self, index):
        result = self._play_service.submit_guess(index)
        if result == GuessResult.INCORRECT:
            msg = FlashMessage(self, "Väärin", "#a00612", "#c8abb6")
            msg.show_timer(None)
        elif result == GuessResult.CORRECT_ONE:
            msg = FlashMessage(self, "Oikein!", "#06a012", "#ABC8B6")
            msg.show_timer(self._update)
        elif result == GuessResult.CORRECT_ROUND_COMPLETE:
            if self._play_service.next_round():
                msg = FlashMessage(self, "Oikein!\nSeuraava kierros",
                                   "#068010", "#ABC8B6")
                msg.show_timer(self._start_round, 2000)
            else:
                msg = FlashMessage(self, "Oikein!\nPeli loppu", "#068010",
                                   "#ABC8B6")
                msg.show_timer(self._end_game, 4000)
Exemple #16
0
class MainApp():
    def __init__(self):
        self.File_name = None
        self.Programe_Name = "CHE-Editor"
        self.WDG = Tk()
        self.WDG.title(self.Programe_Name)
        self.WDG.iconbitmap("icons/icon_editor.ico")
        self.WDG.geometry("860x620")
        self.WDG.maxsize(width=1340, height=700)
        self.WDG.minsize(width=860, height=620)
        self.Main_UI()

    def Main_UI(self):
        self.MenuBar = Menu(self.WDG)

        #1      #MenuBar
        #File_menu
        self.File_menu = Menu(self.MenuBar, tearoff=0, title="File")
        self.MenuBar.add_cascade(label="File", menu=self.File_menu)
        #Edit_menu
        self.Edit_menu = Menu(self.MenuBar, tearoff=0, title="Edit")
        self.MenuBar.add_cascade(label="Edit", menu=self.Edit_menu)
        #View_menu
        self.View_menu = Menu(self.MenuBar, tearoff=0, title="View")
        self.MenuBar.add_cascade(label="View", menu=self.View_menu)
        #Theme_menu in View
        self.Theme_menu = Menu(self.View_menu, tearoff=0, title="Theme")
        self.View_menu.add_cascade(label="Theme", menu=self.Theme_menu)
        #Option_menu
        self.Options_menu = Menu(self.MenuBar, tearoff=0, title="Options")
        self.MenuBar.add_cascade(label="Options", menu=self.Options_menu)
        #Help_menu
        self.Help_menu = Menu(self.MenuBar, tearoff=0, title="Help")
        self.MenuBar.add_cascade(label="Help", menu=self.Help_menu)

        #2      #Icons Variables
        #Edit_Menu Icons
        Undo = PhotoImage(file="icons/Undo.gif")
        Redo = PhotoImage(file="icons/redo.gif")
        Paste = PhotoImage(file="icons/paste.gif")
        Copy = PhotoImage(file="icons/copy.gif")
        Cut = PhotoImage(file="icons/cut.gif")
        #Help_Menu_Icons
        Help = PhotoImage(file="icons/help.gif")
        About = PhotoImage(file="icons/about.gif")
        #File_Menu_Icons
        New = PhotoImage(file="icons/new.gif")
        Open = PhotoImage(file="icons/open.gif")
        Save = PhotoImage(file="icons/save.gif")
        Save_As = PhotoImage(file="icons/save_as.gif")
        Exit = PhotoImage(file="icons/exit.gif")

        #Appear menubar in app
        self.WDG.config(menu=self.MenuBar)
        #self.WDG.config(menu=self.IconBar)

        #3      #Set commands in menus
        #File_Menu
        self.File_menu.add_command(label="New",
                                   accelerator="Ctrl+N",
                                   compound="left",
                                   underline=0,
                                   command=self.New)
        self.File_menu.add_command(label="Open",
                                   accelerator="Ctrl+O",
                                   compound="left",
                                   underline=0,
                                   command=self.Open)
        self.File_menu.add_command(label="Save",
                                   accelerator="Ctrl+S",
                                   compound="left",
                                   underline=0,
                                   command=self.Save)
        self.File_menu.add_command(label="Save as",
                                   accelerator="Shift+Ctrl+S",
                                   compound="left",
                                   underline=0,
                                   command=self.Save_As)
        self.File_menu.add_separator()
        self.File_menu.add_command(label="Exit",
                                   accelerator="F4",
                                   compound="left",
                                   underline=0,
                                   command=self.Exit)
        #Edit_Menu
        self.Edit_menu.add_command(label="Undo",
                                   accelerator="Ctrl+Z",
                                   compound="left",
                                   underline=0,
                                   command=self.Undo)
        self.Edit_menu.add_command(label="Redo",
                                   accelerator='Ctrl+Y',
                                   compound='left',
                                   underline=0,
                                   command=self.Redo)
        self.Edit_menu.add_command(label="Select all",
                                   accelerator='Ctrl+A',
                                   compound='left',
                                   underline=0,
                                   command=self.Select)
        self.Edit_menu.add_command(label="Cut",
                                   accelerator='Ctrl+X',
                                   compound='left',
                                   underline=7,
                                   command=self.Cut)
        self.Edit_menu.add_command(label="Copy",
                                   accelerator='Ctrl+C',
                                   compound='left',
                                   underline=0,
                                   command=self.Copy)
        self.Edit_menu.add_command(label="Paste",
                                   accelerator='Ctrl+V',
                                   compound='left',
                                   underline=0,
                                   command=self.Paste)
        self.Edit_menu.add_command(label="Search",
                                   accelerator='Ctrl+F',
                                   compound='left',
                                   underline=0,
                                   command=self.Search)
        #Help_Menu
        self.Help_menu.add_command(label="Help",
                                   accelerator="F1",
                                   compound="left",
                                   underline=0,
                                   command=self.Help)
        self.Help_menu.add_command(label="About",
                                   compound="left",
                                   underline=0,
                                   command=self.About)
        #View_Menu
        self.Show_line_number = IntVar()
        self.Show_line_number.set(1)
        self.theme_name = StringVar()
        self.View_menu.add_checkbutton(label="Show Line Number",
                                       variable=self.Show_line_number)
        self.Highlightline = BooleanVar()
        self.View_menu.add_checkbutton(label='Highlight Current Line',
                                       onvalue=1,
                                       offvalue=0,
                                       variable=self.Highlightline,
                                       command=self.Toggle_highlight)
        self.cursorcoord = BooleanVar()
        self.View_menu.add_checkbutton(label='Show Cursor Location',
                                       variable=self.cursorcoord,
                                       command=self.Show_cursor_coord)
        self.Theme_menu.add_radiobutton(label="Default",
                                        variable=self.theme_name)

        #4      #add Shortcut_Bar & Row_Number_Bar
        #Shortcut_Bar
        self.Shortcut_Bar = Frame(self.WDG, height=25)
        self.Shortcut_Bar.pack(expand='no', fill='x')
        Icons = ['New', 'Open', 'Save', 'Copy', 'Cut', 'Paste', 'Undo', 'Redo']
        for i, icon in enumerate(Icons):
            Tool_icon = PhotoImage(file='icons/{}.gif'.format(icon))
            #c_var = 'self.{}'.format(icon)
            cmd = eval('self.{}'.format(icon))
            self.Tool_bar_btn = Button(self.Shortcut_Bar,
                                       image=Tool_icon,
                                       command=cmd)
            self.Tool_bar_btn.image = Tool_icon
            self.Tool_bar_btn.pack(side='left')
        #Row_Number_Bar
        self.Row_Number_Bar = Text(self.WDG,
                                   width=3,
                                   padx=3,
                                   takefocus=0,
                                   border=0,
                                   background='khaki',
                                   state='disabled',
                                   wrap='none')
        self.Row_Number_Bar.pack(side='left', fill='y')

        #5      #add Content_Text
        self.Content_Text = Text(self.WDG, wrap='word', undo=1)
        self.Content_Text.pack(expand='yes', fill='both')
        self.Content_Text.tag_configure('active_line', background='ivory2')
        self.Scroll_Bar = Scrollbar(self.Content_Text)
        self.Content_Text.configure(yscrollcommand=self.Scroll_Bar.set)
        self.Scroll_Bar.config(command=self.Content_Text.yview)
        self.Scroll_Bar.pack(side='right', fill='y')

        #6      #add_Cursor_Coord_Bar
        self.Cursor_Coord_Bar = Label(self.Content_Text,
                                      text='Row: 1 | Column: 1')
        self.Cursor_Coord_Bar.pack(fill=None,
                                   expand='no',
                                   side='right',
                                   anchor='se')

        #7      #Binding
        self.Content_Text.bind("<Control-o>", self.Open)
        self.Content_Text.bind("<Control-O>", self.Open)
        self.Content_Text.bind("<Control-s>", self.Save)
        self.Content_Text.bind("<Control-S>", self.Save)
        self.Content_Text.bind("<Shift-Control-KeyPress-s>", self.Save_As)
        self.Content_Text.bind("<Shift-Control-KeyPress-S>", self.Save_As)
        self.Content_Text.bind("<Control-n>", self.New)
        self.Content_Text.bind("<Control-N>", self.New)
        self.Content_Text.bind("<Control-z>", self.Undo)
        self.Content_Text.bind("<Control-Z>", self.Undo)
        self.Content_Text.bind("<Control-y>", self.Redo)
        self.Content_Text.bind("<Control-Y>", self.Redo)
        self.Content_Text.bind("<Control-x>", self.Cut)
        self.Content_Text.bind("<Control-X>", self.Cut)
        self.Content_Text.bind("<Control-a>", self.Select)
        self.Content_Text.bind("<Control-A>", self.Select)
        self.Content_Text.bind("<Control-c>", self.Copy)
        self.Content_Text.bind("<Control-C>", self.Copy)
        self.Content_Text.bind("<Control-v>", self.Paste)
        self.Content_Text.bind("<Control-V>", self.Paste)
        self.Content_Text.bind("<Control-f>", self.Search)
        self.Content_Text.bind("<Control-F>", self.Search)
        self.Content_Text.bind("<Any-KeyPress>", self.Content_changed)
        self.WDG.bind_all("<KeyPress-F1>", self.Help)
        self.WDG.bind_all("<KeyPress-F4>", self.Exit)


#8  #Built In Finctions
#File_Menu_Functions

    def New(self, event=None):
        self.Content_Text.delete(1., 'end')
        self.WDG.title('{} - {}'.format('Untitled', self.Programe_Name))

    ##
    def Open(self, event=None):
        self.Open_file_name = filedialog.askopenfilename(
            defaultextension=".txt",
            filetypes=[("All Files", "*.*"), ("Text Documents", "*.txt")])
        if self.Open_file_name:
            self.File_name = self.Open_file_name
            self.WDG.title("{} - {}".format(os.path.basename(self.File_name),
                                            self.Programe_Name))
            self.Content_Text.delete(1.0, 'end')
            with open(self.File_name) as _File:
                self.Content_Text.insert(1.0, _File.read())

    ##
    def Save(self, event=None):
        if not self.File_name:
            self.Save_As()
        else:
            self.Write_to_file(self.File_name)
        return "break"

    ##
    def Save_As(self, event=None):
        self.Save_file_name = filedialog.asksaveasfilename(
            defaultextension='.txt',
            filetypes=[('All Files', '*.*'), ('Text Documents', '*.txt')])
        if self.Save_file_name:
            self.File_name = self.Save_file_name
            self.Write_to_file(self.File_name)
            self.WDG.title('{} - {}'.format(os.path.basename(self.File_name),
                                            self.Programe_Name))
        return "break"

    ##
    def Write_to_file(self, filename):
        try:
            self.content = self.Content_Text.get(1.0, 'end')
            with open(self.File_name, 'w') as the_file:
                the_file.write(self.content)
        except IOError as er:
            print(er)

    ##
    def Exit(self, event=None):
        self.msg_exit = messagebox.askyesno('Exit Editor',
                                            'Do you want to exit?')
        if self.msg_exit:
            self.WDG.destroy()

    #Edit_Menu_Functions
    ##
    def Select(self, event=None):
        self.Content_Text.tag_add("sel", 1.0, "end")
        print("Done1")
        return "breake"

    ##
    def Cut(self, event=None):
        self.Content_Text.event_generate("<<Cut>>")
        return "breake"

    ##
    def Copy(self, event=None):
        self.Content_Text.event_generate("<<Copy>>")
        return "breake"

    ##
    def Paste(self, event=None):
        self.Content_Text.event_generate("<<Paste>>")
        return "breake"

    ##
    def Undo(self, event=None):
        self.Content_Text.event_generate("<<Undo>>")
        return "breake"

    ##
    def Redo(self, event=None):
        self.Content_Text.event_generate("<<Redo>>")
        return "breake"

    ##
    def Search(self, event=None):
        self.Search_Window = Toplevel(self.WDG)
        self.Search_Window.title("Search About...")
        self.Search_Window.transient(self.WDG)
        self.Search_Window.resizable(False, False)
        self.S_lbl_1 = Label(self.Search_Window, text='Search About :')
        self.S_lbl_1.grid(row=0, column=0, sticky='e')
        self.S_ent_1 = Entry(self.Search_Window, width=28)
        self.S_ent_1.grid(row=0, column=1, padx=2, pady=2, sticky='we')
        self.S_ent_1.focus_set()
        Ignore_case_value = IntVar()
        self.S_chk_1 = Checkbutton(self.Search_Window,
                                   text='Ignor Case',
                                   variable=Ignore_case_value)
        self.S_chk_1.grid(row=1, column=1, padx=2, pady=2, sticky='e')
        self.S_btn_1 = Button(
            self.Search_Window,
            text='Find',
            underline=0,
            command=lambda: self.Search_results(self.S_ent_1.get(
            ), Ignore_case_value.get(), self.Content_Text, self.Search_Window,
                                                self.S_ent_1))
        self.S_btn_1.grid(row=0, column=2, padx=2, pady=2, sticky='e' + 'w')
        self.S_btn_2 = Button(self.Search_Window,
                              text='Cancel',
                              underline=0,
                              command=self.Close_Search_Window)
        self.S_btn_2.grid(row=1, column=2, padx=2, pady=2, sticky='e' + 'w')

    ##
    def Search_results(self, Keyword, IfIgnoreCase, Content, Output, Input):
        Content.tag_remove('match', '1.0', 'end')
        matches_found = 0
        if Keyword:
            start_pos = '1.0'
            while True:
                start_pos = Content.search(Keyword,
                                           start_pos,
                                           nocase=IfIgnoreCase,
                                           stopindex='end')
                if not start_pos:
                    break
                end_pos = "{} + {}c".format(start_pos, len(Keyword))
                Content.tag_add('match', start_pos, end_pos)
                matches_found += 1
                start_pos = end_pos
            Content.tag_config('match', foreground='red', background='yellow')
            Input.focus_set()
            Output.title("{} matches found".format(matches_found))

    ##
    def Close_Search_Window(self):
        self.Content_Text.tag_remove('match', '1.0', 'end')
        self.Search_Window.destroy()
        #self.Search_Window.protocol('WM_DELETE_WINDOW',self.Close_Search_Window)
        return "break"

    #View_Menu_Functions
    ##
    def Content_changed(self, event=None):
        self.Update_line_numbers()
        self.Update_cursor_coord()

    ##
    def Get_line_numbers(self, event=None):
        self.Number = ""
        if self.Show_line_number.get():
            self.Row, self.Column = self.Content_Text.index('end').split('.')
            for i in range(1, int(self.Row)):
                self.Number += str(i) + "\n"
        return self.Number

    ##
    def Update_line_numbers(self):
        self.Line_Number = self.Get_line_numbers()
        self.Row_Number_Bar.config(state='normal')
        self.Row_Number_Bar.delete(1.0, 'end')
        self.Row_Number_Bar.insert(1.0, self.Line_Number)
        self.Row_Number_Bar.config(state='disabled')

    ##
    def Toggle_highlight(self, event=None):
        if self.Highlightline.get():
            self.Highlight_line()
        else:
            self.Undo_highlight()

    ##
    def Highlight_line(self, interval=100):
        self.Content_Text.tag_remove('active_line', 1.0, 'end')
        self.Content_Text.tag_add('active_line', "insert linestart",
                                  "insert lineend+1c")
        self.Content_Text.after(interval, self.Toggle_highlight)

    ##
    def Undo_highlight(self):
        self.Content_Text.tag_remove('active_line', 1.0, 'end')

    ##
    def Show_cursor_coord(self):
        self.cursor_coord_checked = self.cursorcoord.get()
        if self.cursor_coord_checked:
            self.Cursor_Coord_Bar.pack(expand='no',
                                       fill=None,
                                       side='right',
                                       anchor='se')
        else:
            self.Cursor_Coord_Bar.pack_forget()

    ##
    def Update_cursor_coord(self):
        self.Row_2, self.Column_2 = self.Content_Text.index('insert').split(
            '.')
        self.row_num, self.col_num = str(int(
            self.Row_2)), str(int(self.Column_2) + 1)
        self.Coord = "Row: {} | Column: {}".format(self.row_num, self.col_num)
        self.Cursor_Coord_Bar.config(text=self.Coord)

    #Help_Menu_Functions
    ##
    def About(self, event=None):
        messagebox.showinfo(
            'About', '{} {}'.format(self.Programe_Name,
                                    '\nDeveloped by \n TaReK'))

    ##
    def Help(self, event=None):
        messagebox.showinfo('Help',
                            'Text Editor building in python',
                            icon='question')
class TtkScale(Scale):
    def __init__(self,
                 parent,
                 length=0,
                 from_=0,
                 to=255,
                 orient='vertical',
                 variable=0,
                 digits=None,
                 tickinterval=None,
                 command=None,
                 style=None,
                 showvalue=True,
                 resolution=1):

        self.from_ = from_
        self.to = to
        self.variable = variable
        self.length = length
        self.command = command
        self.parent = parent

        super().__init__(parent,
                         length=length,
                         from_=from_,
                         to=to,
                         orient=orient,
                         variable=variable,
                         command=command,
                         style=style)

        self.digits = digits
        self.tickinterval = tickinterval
        self.showvalue = showvalue
        self.resolution = resolution

        # set sliderlength
        st = Style(self)
        self.bw_val = bw_val = st.lookup('Vertical.Scale.trough',
                                         'borderwidth')
        self.sliderlength = sliderlength = 32

        if showvalue:
            self.configure(command=self.display_value)

        def_font = font.nametofont('TkDefaultFont')
        # if from_ more than to swap values
        if from_ < to:
            pass
        else:
            from_, to = to, from_

        data = np.arange(from_,
                         (to + 1 if tickinterval >= 1 else to + tickinterval),
                         tickinterval)
        self.data = data = np.round(data, 1)
        range_vals = tuple(data)
        len_rvs = len(range_vals)
        lspace = def_font.metrics('linespace')
        len_rvs = len(range_vals)
        data_size = len_rvs * lspace

        space_size = len_rvs * 3
        sizes = data_size + space_size
        min_len = (sizes if sizes % 50 == 0 else sizes + 50 - sizes % 50)
        self.len_val = len_val = min_len if length < min_len else length
        self.configure(length=len_val)

        self.rel_min = rel_min = (sliderlength / 2 + bw_val) / len_val
        self.rel_max = rel_max = 1 - (sliderlength / 2 - bw_val) / len_val
        if range_vals[-1] == to:
            pass
        else:
            max_rv = range_vals[-1]
            self.mult_y = mult_y = ((max_rv - from_) * rel_max / (to - from_))

        self.bind("<Button-1>", self.resolve)

        self.build(from_, to, rel_min, rel_max, range_vals, len_rvs)

    def build(self, from_, to, rel_min, rel_max, range_vals, len_rvs):

        for i, rv in enumerate(range_vals):
            item = Label(self.parent, text=rv)
            item.place(
                in_=self,
                bordermode='outside',
                rely=(rel_min + i / (len_rvs - 1) *
                      ((rel_max if range_vals[-1] == to else self.mult_y) -
                       rel_min)),
                relx=1,
                anchor='w')

        if self.showvalue:
            self.disp_lab = Label(self.parent, text=self.get())
            rel_y = self.convert_to_rely(float(
                self.get()))  #, textvariable = self.act_val)
            self.disp_lab.place(in_=self,
                                bordermode='outside',
                                rely=rel_y,
                                relx=0,
                                anchor='e')

    def convert_to_rely(self, curr_val):
        return ((curr_val - self.from_) * (self.rel_max - self.rel_min) /
                (self.to - self.from_) + self.rel_min)

    def convert_to_acty(self, curr_val):
        y_max = self.rel_max * self.len_val
        y_min = self.rel_min * self.len_val
        return ((curr_val - self.from_) * (y_max - y_min) /
                (self.to - self.from_) + y_min)

    def display_value(self, value):
        # position (in pixel) of the center of the slider
        rel_y = self.convert_to_rely(float(value))
        self.disp_lab.config(text=value)  # text=""
        self.disp_lab.place_configure(rely=rel_y)
        digits = self.digits
        self.disp_lab.configure(text=f'{float(value):.{dig_val}f}')
        # if your python is not 3.6 or above use the following 2 lines
        #   instead of the line above
        #my_precision = '{:.{}f}'.format
        #self.disp_lab.configure(text=my_precision(float(value), digits))

    def resolve(self, evt):
        resolution = self.resolution
        if resolution < 1 or self.tickinterval < 1:
            pass
        else:
            value = self.get()
            curr_y = self.convert_to_acty(value)
            if evt.y < curr_y - self.sliderlength / 2:
                self.set(value - resolution + 1)
            elif evt.y > curr_y + self.sliderlength / 2:
                self.set(value + resolution - 1)
Exemple #18
0
class MainGUI:
    def __init__(self, master):
        """
         Constructor: Creates the GUI and creates a socket
         Args:
            self: calling object
            master: parent widget
         Returns:
            void
         """
        # sets host and port of server
        self.host = '10.18.207.18'
        self.port = 9998

        # sets up empty var for ticker
        self.tkr = ''

        # sets up prediction variable
        self.prediction = 0

        self.master = master
        master.title('Stock Predictor')
        master.geometry('800x600')

        # creates label
        self.lbl = Label(master, text='Input Stock Ticker')
        self.lbl.pack(side=TOP)

        # creates text field
        self.txt = Entry(master, width=10)
        self.txt.pack(side=TOP)

        # creates submission button
        self.btn = Button(master, text='Submit', command=self.clicked_tkr)
        self.btn.pack(side=TOP)

        # creates prediction explicit label
        self.p_lbl = Label(master, text='Prediction(1 day in the future): ')
        self.p_lbl.pack(side=TOP)

        # creates prediction output label
        self.p_out_lbl = Label(master, text=self.get_prediction())
        self.p_out_lbl.config(font=17)
        self.p_out_lbl.pack(side=TOP)

    def disp_graph(self, wait=False):
        """
         Displays the image stored as imgFile.png to the GUI
         Args:
            self: calling object
            wait: boolean True if waiting for image False if not
         Returns:
            void
         """
        try:
            if wait:
                img = Image.open('waitImg.png')
            else:
                img = Image.open('imgFile.png')
            render = ImageTk.PhotoImage(img)
            # create image label
            img = Label(self.master, image=render)
            img.image = render
            img.place(x=95, y=110)
        except OSError as OSE:
            messagebox.showinfo('Graph Retrieval Failed', 'The graph requested was not received correctly. Please '
                                                          'submit the request again.')

    def clicked_tkr(self):
        """
         Gathers the input from self.txt, verifies it, then requests a prediction and a graph. It then finally calls
         disp_graph(). Also handles server offline and invalid input cases.
         Args:
            self: calling object
         Returns:
            void
         """
        ticker = ""
        try:
            if self.txt.get().strip():
                ticker = self.txt.get().strip()
            else:
                raise ValueError('Empty string')

            self.update_prediction_out('Please wait. This could take up to 1 minute.')

            client_socket = StockPSocket(self.host, self.port)
            if client_socket.validate(ticker + 'v') == 'error':
                client_socket.close()
                self.update_prediction_out('Invalid input')
                raise ValueError()
            else:
                self.tkr = ticker
                self.disp_graph(wait=True)

                # gets predicted value of stock
                client_socket = StockPSocket(self.host, self.port)
                client_socket.send_request(self.tkr + 'p')
                prediction = client_socket.rec_pred()
                client_socket.close()
                self.update_prediction_out(prediction)  # after Ryan finishes lstm prediction

                # gets graph of stock
                client_socket = StockPSocket(self.host, self.port)
                client_socket.send_request(self.tkr + 'g')
                client_socket.receive()
                client_socket.close()
                self.disp_graph()

        except ValueError as VE:
            messagebox.showinfo('Invalid Ticker', 'Please enter a proper stock ticker. If you are trying to get data '
                                                  'about a market index prefix the ticker with a ^ (ie. ^dji).')
        except ConnectionRefusedError as CRE:
            messagebox.showinfo('Server Offline', 'Sorry for the inconvenience, but this service is not available '
                                                  'right now.')

    def set_prediction(self, prediction):
        """
         Updates the prediction variable
         Args:
            self: calling object
            prediction: int updated value
         Returns:
            void
         """
        self.prediction = prediction

    def get_prediction(self):
        """
         Returns the current value stored in prediction
         Args:
            self: calling object
         Returns:
            prediction: int
         """
        return self.prediction

    def update_prediction_out(self, prediction):
        """
         Updates the prediction label
         Args:
            self: calling object
            prediction: int value for updated presiction
         Returns:
            void
         """
        self.set_prediction(prediction)
        self.p_out_lbl['text'] = self.get_prediction()
        self.p_out_lbl.update()
Exemple #19
0
class retailPage(Frame):
    ''' the main page that actually branches into 2 seperate frames for buying and selling
        this frame provides the use with the
'''
    def __init__(self, parent, main, **kw):
        Frame.__init__(self, parent, **kw)
        self.main = main
        self.Head = Label(font=MED_FONT)

        self.retail_back_b = Button(text='BACK', command=self.back_fb)
        self.stock_name = StringVar()
        self.stock_name_ = ''
        self.stock_name_c = Combobox(textvariable=self.stock_name)
        self.stock_name_l = Label(text='Stock name: ')
        self.amount = Entry()
        self.amount_l = Label(text='Number of stocks :')

        self.check_avail_b = Button(text='Check')
        self.cost_l = Label(text='Cost: ')
        self.cost = Label()
        self.buy_stock_b = Button(text='BUY Stock')
        self.sellp_l = Label(text='Current Selling Price: ')
        self.profit_l = Label(text='PROFIT/LOSS')
        self.sell_stock_b = Button(text='SELL Stock')
        self.page = None

    def showItems(self, main):
        self.Head.grid(column=0, row=0, columnspan=2)
        self.Head.configure(text='logged in as %s' % main.present_user)
        if self.page == 'b':
            self.buy()
        elif self.page == 's':
            self.sell()

    def hideItems(self, main):
        self.Head.grid_forget()

    def buy(self):
        '''This function creates the buy window
'''
        self.retail_back_b.grid(column=1, row=5)
        self.retail_back_b.config(command=self.back_fb)
        self.stock_name_l.grid(column=0, row=1)
        self.stock_name_c.grid(column=1, row=1)
        self.stock_name_c.config(values=self.main.shares_dict.keys())
        self.amount_l.grid(column=0, row=2)
        self.amount.grid(column=1, row=2)
        self.check_avail_b.config(command=self.check_avail_buy)
        self.check_avail_b.grid(column=0, row=3)
        self.cost_l.grid(column=0, row=4, columnspan=2)
        self.buy_stock_b.config(command=self.buy_stock,
                                text='Buy Stock',
                                state='disabled')
        self.buy_stock_b.grid(column=0, row=5)

    def sell(self):
        '''This function creats the sell window'''
        self.retail_back_b.grid(column=1, row=6)
        self.retail_back_b.config(command=self.back_fs)
        self.check_avail_b.config(command=self.check_avail_sell)
        self.stock_name_l.grid(column=0, row=1)
        self.stock_name_c.grid(column=1, row=1)
        self.stock_name_c.config(values=self.main.shares_dict.keys())
        self.amount_l.grid(column=0, row=2)
        self.amount.grid(column=1, row=2)
        self.check_avail_b.grid(column=0, row=3)
        self.sellp_l.grid(column=0, row=4, columnspan=2)
        self.profit_l.grid(column=0, row=5, columnspan=2)
        self.sell_stock_b.config(command=self.sell_stock,
                                 state='disabled',
                                 text='Check')
        self.sell_stock_b.grid(column=0, row=6)

    def back_fb(self):
        '''Back from buy i.e. removes all the items needed to make buy'''
        self.retail_back_b.grid_forget()
        self.Head.grid(column=0, row=0, columnspan=2)
        self.stock_name_l.grid_forget()
        self.stock_name_c.grid_forget()
        self.amount_l.grid_forget()
        self.amount.grid_forget()
        self.check_avail_b.grid_forget()
        self.cost_l.grid_forget()
        self.buy_stock_b.grid_forget()
        self.buy_stock_b.config(state='disabled')

        self.main.show_frame(VIEW_STOCK, RETAIL_PAGE)
        self.stock_name.set('')
        self.amount.delete(0, END)

    def back_fs(self):
        ''' Back from sell i.e. removes all the items needed to make it sell window'''
        self.Head.grid(column=0, row=0, columnspan=2)
        self.retail_back_b.grid_forget()
        self.check_avail_b.grid_forget()
        self.stock_name_l.grid_forget()
        self.stock_name_c.grid_forget()
        self.amount_l.grid_forget()
        self.amount.grid_forget()
        self.sellp_l.grid_forget()
        self.profit_l.grid_forget()
        self.sell_stock_b.grid_forget()

        self.main.show_frame(VIEW_STOCK, RETAIL_PAGE)
        self.stock_name.set('')
        self.amount.delete(0, END)
        self.check_avail_b.grid_forget()

    def check_avail_buy(self):
        ''' Performs a check whether the number of shares requisted are available or not and then check whether the
            person has the required amounts of fund or not for the transaction to go through'''
        name = self.stock_name.get()
        l2 = self.main.accounts[self.main.present_user]

        if name in self.main.shares_dict.keys():
            li = self.main.shares_dict[name]
        else:
            self.stock_name.delete(0, END)
            showinfo(meassage='Enter a Valid Stock name')

        available_num = int(li['tot_amount']) - int(li['tot_sold'])
        req = int(self.amount.get())
        cost = req * int(li['cost'])

        if req < 0:
            showinfo(message='Enter a Valid amount')
        elif req > available_num:
            showinfo(message='Enter an amount less than ' + str(available_num))
        elif cost > int(l2['balance']):
            showinfo(message='You have only %s in you account' % l2['balance'])
        else:
            self.cost_l.config(text='Cost: \t' + li['cost'] + '*' + str(req) +
                               '=' + str(cost))
            self.buy_stock_b.config(state='normal')

    def check_avail_sell(self):
        ''' Performs a check whether the user has enough stocks to sell'''
        name = self.stock_name.get()
        if name in self.main.shares_dict.keys():
            li = self.main.shares_dict[name]
        else:
            self.stock_name.delete(0, END)
            showinfo(message='Enter a Valid Stock name')
        req = int(self.amount.get())
        if req < 0:
            showinfo(message='Please Enter a Valid amount')
            self.amount.delete(0, END)
        li = self.main.p_user_dict
        ok = False
        for i in li:
            if name == i['name']:
                ok = True
                buff = i

        if req > int(buff['tot_owned']):
            showinfo(message='You dont have that many stocks try less than ' +
                     buff['tot_owned'])
            self.amount.delete(0, END)
        cost = self.main.shares_dict[name]['cost']
        tot_cost = req * int(cost)
        try:
            spent = req * float(buff['money_spent']) / int(buff['tot_owned'])
        except:
            spent = 0
        pol = tot_cost - spent

        if pol >= 0:
            self.profit_l.config()
        elif pol < 0:
            self.profit_l.config()
        if req <= int(buff['tot_owned']):
            self.sellp_l.config(text='Current Selling Price: \t' + cost)
            self.profit_l.config(text="PROFIT-LOSS: \t" + str(pol))
            self.sell_stock_b.config(command=self.sell_stock,
                                     text='Sell Stock')
            showinfo(message=
                     'Everthing is ok, \nClicking Sell will execute the trade')
            self.sell_stock_b.config(state='normal')

    def buy_stock(self):
        '''Finally Executes the transaction and asks the user for conformation one last time'''
        name = self.stock_name.get()
        li = self.main.shares_dict[name]

        for i in range(len(self.main.p_user_dict)):
            if name == self.main.p_user_dict[i]['name']:
                index = i
        req = int(self.amount.get())
        tot_cost = req * int(li['cost'])
        self.main.shares_dict[name]['tot_sold'] = str(
            int(self.main.shares_dict[name]['tot_sold']) + req)
        self.main.p_user_dict[index]['tot_owned'] = str(
            int(self.main.p_user_dict[index]['tot_owned']) + req)
        self.main.p_user_dict[index]['money_spent'] = str(
            int(self.main.p_user_dict[index]['money_spent']) + tot_cost)
        self.main.users_dict[
            self.main.present_user][index] = self.main.p_user_dict[index]
        balance = int(self.main.accounts[self.main.present_user]['balance'])
        self.main.accounts[self.main.present_user]['balance'] = str(balance -
                                                                    tot_cost)
        self.cost_l.config(text='Cost: ')

        showinfo(
            message='You have just bought %s of the stock %s at the price %s' %
            (str(req), name, str(tot_cost)))
        self.stock_name.set('')
        self.main.show_frame(VIEW_STOCK, RETAIL_PAGE)
        self.back_fb()

    def sell_stock(self):
        '''Asks the user for conformation and then completes the transaction
        of selling, at this point the profit field is
        also updated'''
        name = self.stock_name.get()
        req = int(self.amount.get())

        li = self.main.p_user_dict
        for i in range(len(li)):
            if name == li[i]['name']:
                ok = True
                buff = i

        tot_cost = req * int(self.main.shares_dict[name]['cost'])
        try:
            spent = req * float(
                self.main.p_user_dict[buff]['money_spent']) / int(
                    self.main.p_user_dict[buff]['tot_owned'])
        except ZeroDivisionError:
            spent = 0
        self.main.shares_dict[name]['tot_sold'] = str(
            int(self.main.shares_dict[name]['tot_sold']) - req)
        self.main.p_user_dict[buff]['tot_owned'] = str(
            int(self.main.p_user_dict[buff]['tot_owned']) - req)
        pol = tot_cost - spent
        diff = int(self.main.p_user_dict[buff]['money_spent']) - tot_cost
        self.main.p_user_dict[buff]['money_spent'] = str(
            diff) if diff > 0 else '0'
        self.main.users_dict[self.main.present_user] = self.main.p_user_dict
        profit = int(self.main.accounts[self.main.present_user]['profit'])
        self.main.accounts[self.main.present_user]['profit'] = str(
            int(profit + pol))
        balance = int(self.main.accounts[self.main.present_user]['balance'])
        self.main.accounts[self.main.present_user]['balance'] = str(balance +
                                                                    tot_cost)
        self.retail_back_b.grid_forget()
        self.profit_l.config(text='PROFIT/LOSS: ')
        self.sellp_l.config(text='Current selling price: ')
        self.main.show_frame(VIEW_STOCK, RETAIL_PAGE)
        self.back_fs()
Exemple #20
0
class App(Frame):
    # Fields
    root = None

    itemList = None
    statusLabel = None

    image_width = 202
    image_height = 360

    imageLabel = None

    def __init__(self, root):
        super().__init__()
        self.initUI()
        self.root = root

    def initUI(self):

        # TitleBar
        self.master.title("Easy Checkout")
        self.pack(fill=BOTH, expand=True)

        # Stretch
        self.columnconfigure(3, weight=1)
        self.columnconfigure(0, pad=7)
        self.rowconfigure(3, weight=1)
        self.rowconfigure(5, pad=7)

        # Row0 : Labels for Sections
        cmd = Label(self, text="Commands")
        cmd.grid(sticky=W, pady=4, padx=5, row=0, column=0)

        pic = Label(self, text="Picture")
        pic.grid(sticky=W, pady=4, padx=5, row=0, column=1)

        items = Label(self, text="Items")
        items.grid(sticky=W, pady=4, padx=5, row=0, column=3)

        self.statusLabel = Label(
            self,
            text="Hello!\nThis is\nEasyCheckout\n\nPress Activate\nto Start")
        self.statusLabel.grid(sticky=W, pady=4, padx=5, row=3, column=0)

        self.itemList = Listbox(self)
        self.itemList.grid(row=1,
                           column=3,
                           rowspan=4,
                           padx=5,
                           sticky=E + W + S + N)

        #Buttons
        abtn = Button(self,
                      text="Activate",
                      command=lambda: easycheckout.run(self))
        abtn.grid(row=1, column=0)

        qbtn = Button(self, text="Quit", command=self.quit)
        qbtn.grid(row=2, column=0, pady=4)

        clearbtn = Button(self, text="Clear", command=self.clearItem)
        clearbtn.grid(row=5, column=0, padx=5)

        obtn = Button(self, text="OK", command=self.changeImage)
        obtn.grid(row=5, column=3)

        #Pictures
        path = "result.jpg"
        pil_img = Image.open(path)

        #Pictures : Resize to Show
        w, h = pil_img.size
        resizedImg = self.resize(w, h, self.image_width, self.image_height,
                                 pil_img)

        img = ImageTk.PhotoImage(resizedImg)

        self.imageLabel = Label(self, image=img)
        self.imageLabel.image = img
        self.imageLabel.grid(row=1,
                             column=1,
                             columnspan=2,
                             rowspan=4,
                             sticky=E + W + S + N,
                             padx=5)

    # METHODS
    def resize(self, w, h, w_box, h_box, pil_image):
        '''
        resize a pil_image object so it will fit into
        a box of size w_box times h_box, but retain aspect ratio
        '''
        f1 = 1.0 * w_box / w  # 1.0 forces float division in Python2
        f2 = 1.0 * h_box / h
        factor = min([f1, f2])
        #print(f1, f2, factor)  # test
        # use best down-sizing filter
        width = int(w * factor)
        height = int(h * factor)
        return pil_image.resize((width, height), Image.ANTIALIAS)

    # changeImage NEEDTOBE IMPLEMENTED
    def changeImage(self, path='test.png', resize=True):
        pil_img = Image.open(path)

        if (resize):
            #Pictures : Resize to Show
            w, h = pil_img.size
            resizedImg = self.resize(w, h, self.image_width, self.image_height,
                                     pil_img)
        else:
            resizedImg = pil_img

        img = ImageTk.PhotoImage(resizedImg)

        self.imageLabel.config(image=img)
        self.imageLabel.image = img

    # Insert Item in the ListBox
    def insertItem(self, item):
        self.itemList.insert(END, item)

    # Delete Item(s) in the ListBox
    def clearItem(self):
        selection = self.itemList.curselection()
        if (len(selection) == 0):
            self.itemList.delete(0, self.itemList.size())
        else:
            idx = selection[0]
            self.itemList.delete(idx)

    # Quit Window
    def quit(self):
        self.root.quit()

    # ChangeStatus Text
    def changeStatus(self, status):
        self.statusLabel.config(text=status)

    # Update TK
    def update(self):
        self.root.update()
class SolutionTabFrame(Frame):
    ''' This class is responsible for displaying solution on the screen.
        It extends Frame class.

        Attributes:
                parent (Tk object that can contain Frame): parent that can
                        contain Frame, MUST implement method
                        change_solution_tab_name(str).
                data_from_file_lbl (Label): label that contains file name
                    with data if specified.
                solution_tab (SolutionFrameWithText): notebook with tabs
                    describing solution.
                model_solutions (list of Solution): list with one or more
                    solutions that have been generated after running algorithm.
                param_strs (list of str): list with strings that should appear
                    before printing every solution from model_solutions.
                ranks (list of list of int): list of ranks corresponding to
                    every solution from model_solutions, ranks are generated
                    by peel-the-onion algorithm.
                categorical (str): name of the categorical variable used in
                    categorical analysis.
                progress_bar (Progressbar): progress bar to show how solution
                    is loaded or saved to file.
                status_lbl (Label): label for displaying solution status.
                solution_format_var (IntVar): IntVar object that tracks which
                    file format is chosen for solution.
    '''
    def __init__(self, parent, *args, **kw):
        super().__init__(parent, *args, **kw)
        self.parent = parent
        self.data_from_file_lbl = None
        self.solution_tab = None
        self.model_solutions = None
        self.param_strs = None
        self.ranks = None
        self.params = None
        self.categorical = None
        self.run_date = None
        self.total_seconds = 0
        self.progress_bar = None
        self.status_lbl = None
        self.solution_format_var = IntVar()
        self.create_widgets()

    def create_widgets(self):
        ''' Creates appropriate widgets on this frame.
        '''
        self.columnconfigure(0, weight=1)
        self.rowconfigure(3, weight=1)
        frame_for_save_btn = Frame(self)
        frame_for_save_btn.columnconfigure(1, weight=1)
        self.status_lbl = Label(frame_for_save_btn, text='')
        self.status_lbl.grid(row=0, column=1, sticky=N+W)
        save_solution_btn = Button(frame_for_save_btn, text='Save solution',
                                   command=self.on_save_solution)
        save_solution_btn.grid(row=1, column=0, sticky=W+N, padx=5, pady=5)
        self.progress_bar = Progressbar(frame_for_save_btn,
                                        mode='determinate', maximum=100)
        self.progress_bar.grid(row=1, column=1, sticky=W+E, padx=10, pady=5)

        frame_for_save_btn.grid(sticky=W+N+E+S, padx=5, pady=5)

        frame_for_btns = Frame(self)
        self._create_file_format_btn('*.xlsx', 1, frame_for_btns, 0)
        self._create_file_format_btn('*.xls', 2, frame_for_btns, 1)
        self._create_file_format_btn('*.csv', 3, frame_for_btns, 2)
        self.solution_format_var.set(1)

        frame_for_btns.grid(row=1, column=0, sticky=W+N+E+S, padx=5, pady=5)
        self.data_from_file_lbl = Label(self, text=TEXT_FOR_FILE_LBL, anchor=W,
                                        justify=LEFT,
                                        wraplength=MAX_FILE_PARAMS_LBL_LENGTH)
        self.data_from_file_lbl.grid(row=2, column=0, padx=5, pady=5,
                                     sticky=W+N)

        self.solution_tab = SolutionFrameWithText(self)
        self.solution_tab.grid(row=3, column=0, sticky=W+E+S+N, padx=5, pady=5)

    def _create_file_format_btn(self, btn_text, var_value, parent, column):
        ''' Creates and grids Radiobutton used for choosing solution file
            format.

            Args:
                btn_text (str): text displayed next to the Radiobutton.
                var_value (int): value of the IntVar associated with this
                    Radiobutton.
                parent (Tk object): parent of this Radiobutton.
                column (int): column index where this Radiobutton
                    should be gridded.
        '''
        sol_format_btn = Radiobutton(parent, text=btn_text,
                                     variable=self.solution_format_var,
                                     value=var_value)
        sol_format_btn.grid(row=2, column=column, sticky=W+N, padx=2)

    def on_save_solution(self):
        ''' Saves solution to file.

            This method is called when save solution button is pressed.
            If there is a solution, this method will ask user to provide
            a file name where solution should be stored. If a valid name
            is provided,
            solution is saved to that file. Allowed file formats are:
            .xls and .xlsx.
            Default file extension is .xlsx.

            If the user checked 'csv' as solution output format, then
            the user will be asked to choose a directory where all csv files
            will be written.
        '''
        if self.model_solutions is not None:
            assert(self.param_strs is not None)
            if (self.solution_format_var.get() == 1 or
                    self.solution_format_var.get() == 2):
                file_name = self.ask_file_name_to_save(
                    self.solution_format_var.get())
                dir_name = ''
            else:
                dir_name = askdirectory()
                file_name = ''
            if file_name or dir_name:
                print(file_name)
                self.status_lbl.config(text='Saving solution to file...')
                if file_name.endswith('.xls'):
                    work_book = xlwt.Workbook()
                elif file_name.endswith('.xlsx'):
                    work_book = XlsxWorkbook()
                else:
                    # all not supported formats will be written to csv
                    assert(dir_name)
                    work_book = TxtWriter(dir_name)
                writer = XLSWriter(self.params, work_book, self.run_date,
                                   self.total_seconds,
                                   ranks=self.ranks,
                                   categorical=self.categorical)
                nb_models = len(self.model_solutions)
                # +1 for parameters sheet, it is stored separately
                nb_sheets = len(writer.worksheets) + 1
                progress_recorder = GuiProgress(self.progress_bar, nb_models,
                                                nb_sheets)

                try:
                    for count, sol in enumerate(self.model_solutions):
                        writer.write_data(sol, self.param_strs[count],
                                          progress_recorder)
                    work_book.save(file_name)
                except ValueError:
                    # can happen if maximum number of rows is exceeded
                    self.status_lbl.config(
                        text='File is too large for xls format,'
                        ' it will be saved to csv instead')
                    work_book = TxtWriter(os.path.splitext(file_name)[0])
                    writer = XLSWriter(self.params, work_book, self.run_date,
                                       self.total_seconds,
                                       ranks=self.ranks,
                                       categorical=self.categorical)
                    progress_recorder.set_position(0)
                    for count, sol in enumerate(self.model_solutions):
                        writer.write_data(sol, self.param_strs[count],
                                          progress_recorder)
                    work_book.save(file_name)
                progress_recorder.set_position(100)
                self.parent.change_solution_tab_name('Solution')
                self.status_lbl.config(text='Solution saved')

    def ask_file_name_to_save(self, ext_code):
        ''' Calls asksaveasfilename dialogue to ask the user where file
            should be saved.
            If file without extension is entered, default extension
            will be used (.xlsx).
            This method is used to mock this object for unit tests.

            Args:
                ext_code (int): code for file extension 1 - xlsx, 2 - xls.
        '''
        if ext_code == 1:
            filetype = SOLUTION_XLSX_FILE
        else:
            filetype = SOLUTION_XLS_FILE
        return asksaveasfilename(filetypes=filetype, defaultextension='xlsx')

    def show_solution(self, solutions, params, param_strs, run_date,
                      total_seconds, ranks=None, categorical=None):
        ''' Displays solution on the screen.

            Args:
                solutions (list of Solution): list of solutions (might
                    contain just one solution)
                    that have been generated after running algorithm.
                params (Parameters): object with parameters that will
                    be written to file on the Parameters page.
                param_strs (list of str): list with strings that
                    should appear before
                    printing every solution from model_solutions.
                ranks (list of list of int): list of ranks corresponding
                    to every solution from model_solutions, ranks are
                    generated by peel-the-onion algorithm.
                categorical (str): name of the categorical variable used
                    in categorical analysis.
        '''
        self.status_lbl.config(text='')
        self.model_solutions = solutions
        self.param_strs = param_strs
        self.ranks = ranks
        self.params = params
        self.categorical = categorical
        self.run_date = run_date
        self.total_seconds = total_seconds
        self.status_lbl.config(text='Loading solution...')
        self.solution_tab.show_solution(solutions, params, param_strs, run_date,
                                        total_seconds, ranks, categorical)
        self.parent.change_solution_tab_name('Solution*')
        self.status_lbl.config(text='Solution loaded')

    def update_data_file_name(self, new_data_file_name):
        ''' Updates label with data file name.

            Args:
                new_data_file_name (str): new value of the data file name
        '''
        self.data_from_file_lbl.config(text=TEXT_FOR_FILE_LBL
                                       + new_data_file_name)
Exemple #22
0
class Application(Frame):
    """The main Tk application, a simple dialog."""
    def __init__(self, master=None):
        super().__init__(master)
        self.badge = None
        self.grid()
        self.columnconfigure(0, minsize=200)
        self.columnconfigure(1, minsize=200)
        self.rowconfigure(0, minsize=300)
        self.rowconfigure(3, minsize=30)
        self.create_widgets()
        self.connect()

    def create_widgets(self):
        """Sets up dialog elements."""
        self.select = tix.FileSelectBox(self, browsecmd=self.on_file_selected,
                                        pattern="*.fs", directory="forth")
        # self.select["textVariable"] = self.forth_file
        self.select.grid(row=0, columnspan=2, sticky='n'+'w'+'e')
        self.connect_btn = Button(self, text="Connect",
                                  command=self.toggle_connect)
        self.connect_btn.grid(row=1, column=0, columnspan=2)
        self.exec_btn = Button(self, text="Execute", command=self.send_file)
        self.exec_btn.state(["disabled"])
        self.exec_btn.grid(row=2, column=0, sticky='w' + 'e', padx=5, pady=3)
        self.quit = Button(self, text="QUIT", command=self.master.destroy)
        self.quit.grid(row=2, column=1, sticky='w' + 'e', padx=5, pady=3)
        self.status_panel = Frame(self, relief="groove", borderwidth=3)
        self.status_panel.grid(row=3, columnspan=2, sticky='nwse')
        self.connect_status = Label(self.status_panel, text="Not Connected")
        self.connect_status.grid(row=0, padx=5, pady=5, sticky="w")
        if self.badge is not None:
            self.connect_btn.state(["disabled"])
            self.connect_status.config(text="Connected: " + self.badge.os_device)

    def send_file(self, _retry=False):
        """Send the selected file to the badge."""
        if self.badge:
            try:
                # oddly, very first set LED seems to not set correct color
                self.badge.led(0, 0, 128)
                self.badge.led(0, 0, 128)
                with open(self.select.cget("value"), 'r') as forthin:
                    self.badge.forth_run(forthin.read())
                time.sleep(1)  # because forth_run() may be too fast
                self.badge.led(0, 128, 0)
            except IOError:
                if not _retry:
                    self.connect()
                    self.send_file(True)
                else:
                    raise

    def toggle_connect(self):
        "If connected, disconnect, otherwise connect."
        if self.connect_btn.cget("text") == "Connect":
            self.connect()
        else:
            self.disconnect()

    def disconnect(self):
        "Disconnect from current badge."
        isinstance(self.badge, Badge)
        self.badge.close()
        self.badge = None
        self.connect_btn.config(text="Connect")
        self.connect_status.config(text="Not connected.")
        self.exec_btn.state(["disabled"])

    def connect(self):
        """Attempt to connect to a badge; toggle Connect button if successful."""
        try:
            self.badge = Badge()
            self.connect_status.config(text="Connected: " + self.badge.os_device)
            self.connect_btn.config(text="Disconnect")
            # enable "Execute" if file is selected
            self.on_file_selected(self.select.cget("value"))
        except BadgeSerialException:
            self.connect_status.config(text="Not connected")

    def on_file_selected(self, selected_file):
        """Respond to user selection of file by enabling the Execute button."""
        if Path(selected_file).is_file:
            self.exec_btn.state(["!disabled"])
        else:
            self.exec_btn.state(["disabled"])
class Download(Frame):
    def __init__(self, master, **kwargs):
        super(Download, self).__init__(master, borderwidth=20, **kwargs)
        self.fs = None
        self.tree = None
        self.logfile = None

        # User informations
        self.info_tree = False
        self.start_time = None
        info = Frame(self, borderwidth=10)
        self.info_label = Label(info, wraplength=350, borderwidth=20, justify='center', font=('a', 10, 'bold'))
        self.info_indis = Label(info)
        self.info_fams = Label(info)
        self.info_sources = Label(info)
        self.info_notes = Label(info)
        self.time = Label(info)
        self.info_label.grid(row=0, column=0, columnspan=2)
        self.info_indis.grid(row=1, column=0)
        self.info_fams.grid(row=1, column=1)
        self.info_sources.grid(row=2, column=0)
        self.info_notes.grid(row=2, column=1)
        self.time.grid(row=3, column=0, columnspan=2)

        self.form = Frame(self)
        self.sign_in = SignIn(self.form)
        self.options = None
        self.title = Label(self, text=_('Sign In to FamilySearch'), font=('a', 12, 'bold'))
        buttons = Frame(self)
        self.btn_quit = Button(buttons, text=_('Quit'), command=Thread(target=self.quit).start)
        self.btn_valid = Button(buttons, text=_('Sign In'), command=self.command_in_thread(self.login))
        self.title.pack()
        self.sign_in.pack()
        self.form.pack()
        self.btn_quit.pack(side='left', padx=(0, 40))
        self.btn_valid.pack(side='right', padx=(40, 0))
        info.pack()
        buttons.pack(side='bottom')
        self.pack()
        self.update_needed = False

    def info(self, text):
        self.info_label.config(text=text)

    def save(self):
        filename = filedialog.asksaveasfilename(title=_('Save as'), defaultextension='.ged', filetypes=(('GEDCOM', '.ged'), (_('All files'), '*.*')))
        if not filename:
            return
        with open(filename, 'w', encoding='utf-8') as file:
            self.tree.print(file)

    def login(self):
        global _
        username = self.sign_in.username.get()
        password = self.sign_in.password.get()
        if not (username and password):
            messagebox.showinfo(message=_('Please enter your FamilySearch username and password.'))
            return
        self.btn_valid.config(state='disabled')
        self.info(_('Login to FamilySearch...'))
        self.logfile = open('download.log', 'w', encoding='utf-8')
        self.fs = Session(self.sign_in.username.get(), self.sign_in.password.get(), verbose=True, logfile=self.logfile, timeout=1)
        if not self.fs.logged:
            messagebox.showinfo(_('Error'), message=_('The username or password was incorrect'))
            self.btn_valid.config(state='normal')
            self.info('')
            return
        self.tree = Tree(self.fs)
        _ = self.fs._
        self.title.config(text=_('Options'))
        cache.delete('lang')
        cache.add('lang', self.fs.lang)
        self.options = Options(self.form, True)
        self.info('')
        self.sign_in.destroy()
        self.options.pack()
        self.master.change_lang()
        self.btn_valid.config(command=self.command_in_thread(self.download), state='normal', text=_('Download'))
        self.options.start_indis.add_indi(self.fs.get_userid())
        self.update_needed = False

    def quit(self):
        self.update_needed = False
        if self.logfile:
            self.logfile.close()
        super(Download, self).quit()
        # prevent exception during download
        os._exit(1)

    def download(self):
        todo = [self.options.start_indis.indis[key] for key in sorted(self.options.start_indis.indis)]
        for fid in todo:
            if not re.match(r'[A-Z0-9]{4}-[A-Z0-9]{3}', fid):
                messagebox.showinfo(_('Error'), message=_('Invalid FamilySearch ID: ') + fid)
                return
        self.start_time = time.time()
        self.options.destroy()
        self.form.destroy()
        self.title.config(text='FamilySearch to GEDCOM')
        self.btn_valid.config(state='disabled')
        self.info(_('Download starting individuals...'))
        self.info_tree = True
        self.tree.add_indis(todo)
        todo = set(todo)
        done = set()
        for i in range(self.options.ancestors.get()):
            if not todo:
                break
            done |= todo
            self.info(_('Download ') + str(i + 1) + _('th generation of ancestors...'))
            todo = self.tree.add_parents(todo) - done

        todo = set(self.tree.indi.keys())
        done = set()
        for i in range(self.options.descendants.get()):
            if not todo:
                break
            done |= todo
            self.info(_('Download ') + str(i + 1) + _('th generation of descendants...'))
            todo = self.tree.add_children(todo) - done

        if self.options.spouses.get():
            self.info(_('Download spouses and marriage information...'))
            todo = set(self.tree.indi.keys())
            self.tree.add_spouses(todo)
        ordi = self.options.ordinances.get()
        cont = self.options.contributors.get()

        async def download_stuff(loop):
            futures = set()
            for fid, indi in self.tree.indi.items():
                futures.add(loop.run_in_executor(None, indi.get_notes))
                if ordi:
                    futures.add(loop.run_in_executor(None, self.tree.add_ordinances, fid))
                if cont:
                    futures.add(loop.run_in_executor(None, indi.get_contributors))
            for fam in self.tree.fam.values():
                futures.add(loop.run_in_executor(None, fam.get_notes))
                if cont:
                    futures.add(loop.run_in_executor(None, fam.get_contributors))
            for future in futures:
                await future

        loop = asyncio.get_event_loop()
        self.info(_('Download notes') + (((',' if cont else _(' and')) + _(' ordinances')) if ordi else '') + (_(' and contributors') if cont else '') + '...')
        loop.run_until_complete(download_stuff(loop))

        self.tree.reset_num()
        self.btn_valid.config(command=self.save, state='normal', text=_('Save'))
        self.info(text=_('Success ! Click below to save your GEDCOM file'))
        self.update_info_tree()
        self.update_needed = False

    def command_in_thread(self, func):
        def res():
            self.update_needed = True
            Thread(target=self.update_gui).start()
            Thread(target=func).start()
        return res

    def update_info_tree(self):
        if self.info_tree and self.start_time and self.tree:
            self.info_indis.config(text=_('Individuals: %s') % len(self.tree.indi))
            self.info_fams.config(text=_('Families: %s') % len(self.tree.fam))
            self.info_sources.config(text=_('Sources: %s') % len(self.tree.sources))
            self.info_notes.config(text=_('Notes: %s') % len(self.tree.notes))
            t = round(time.time() - self.start_time)
            minutes = t // 60
            seconds = t % 60
            self.time.config(text=_('Elapsed time: %s:%s') % (minutes, '00%s'[len(str(seconds)):] % seconds))

    def update_gui(self):
        while self.update_needed:
            self.update_info_tree()
            self.master.update()
            time.sleep(0.1)
class ParamsFrame(Notebook):
    ''' This class implements various operations with parameters like
        loading and saving from and to file, modifying parameters values.

        Attributes:
            parent (Tk object): parent of this widget.
            params (Parameters): Parameters object with values of all
                parameters.
            current_categories (list of str): list of current valid categories.
            input_categories (CategoriesCheckBox): frame for displaying
                input categories.
            output_categories (CategoriesCheckBox): frame for displaying
                output categories.
            params_from_file_lbl (Label): label for displaying file name if
                parameters were loaded from file.
            data_from_params_file(StringVar): StringVar object used for
                communication of this widget with DataFrame. Changing the
                value of data_from_params_file
                triggers changes in DataFrame (like clearing all data and
                loading data from file).
            str_var_for_input_output_boxes (ObserverStringVar):
                ObserverStringVar
                object used for storing input and output categories and for
                tracking changes in input and output categories.
            weight_tab (WeightFrame): widget used for displaying and
                editing weights.
            load_without_data (IntVar): IntVar object used for Checkbutton,
                if its value
                is 1, then parameters will be loaded from file without data,
                if its value
                is 0, then parameters will be loaded from file with data.
            options_frame (OptionsFrame): widget used for displaying and
                modifying some of the parameters.

        Args:
            parent (Tk object): parent of this widget.
            current_categories (list of str): list of current valid categories.
            data_from_params_file(StringVar): StringVar object used for
                communication of this widget with DataFrame. Changing the value
                of data_from_params_file
                triggers changes in DataFrame (like clearing all data and
                loading data from file).
            str_var_for_input_output_boxes (ObserverStringVar):
                ObserverStringVar object used for
                storing input and output categories and for tracking changes
                in input and output categories.
            weights_status_str (StringVar): StringVar object used for changing
                label of weights editor, for details see WeightFrame.
    '''
    def __init__(self, parent, current_categories, data_from_params_file,
                 str_var_for_input_output_boxes, weights_status_str, *args,
                 **kw):
        Notebook.__init__(self, parent, *args, **kw)
        self.parent = parent
        self.params = Parameters()
        self.current_categories = current_categories
        self.input_categories_frame = None
        self.output_categories_frame = None
        self.params_from_file_lbl = None
        self.data_from_params_file = data_from_params_file
        self.str_var_for_input_output_boxes = str_var_for_input_output_boxes
        self.weight_tab = None
        self.load_without_data = IntVar()
        self.options_frame = None
        self.create_widgets(weights_status_str)

    def create_widgets(self, weights_status_str):
        ''' Creates all widgets.
        '''
        self.enable_traversal()
        self._create_params_tab()
        self.weight_tab = WeightFrame(self, self.current_categories,
                                      self.params, weights_status_str)
        self.add(self.weight_tab, text='Weights editor')

    def change_weight_tab_name(self, new_name):
        ''' Changes name of weights editor tab.

            Args:
                new_name (str): new name for weights editor tab.
        '''
        self.tab(1, text=new_name)

    def _create_params_tab(self):
        ''' Creates all widgets of the parameters tab.
        '''
        frame_for_all_objects = VerticalScrolledFrame(self)
        frame_for_all_objects.columnconfigure(0, weight=1)
        frame_for_all_objects.rowconfigure(0, weight=1)

        params_tab = frame_for_all_objects.interior
        params_tab.columnconfigure(0, weight=1, pad=5)

        frame_for_save_btns = Frame(params_tab)
        frame_for_save_btns.columnconfigure(0, weight=1)
        frame_for_save_btns.columnconfigure(1, weight=1)
        load_btn = Button(frame_for_save_btns,
                          text='Load parameters',
                          command=self.load_file)
        load_btn.grid(row=0, column=0, sticky=W + N, pady=2)
        load_wo_data_box = Checkbutton(frame_for_save_btns,
                                       text='Load without data',
                                       variable=self.load_without_data)
        load_wo_data_box.grid(row=1, column=0, sticky=W + N, pady=2)
        save_btn = Button(frame_for_save_btns,
                          text='Save parameters',
                          command=self.on_save_params)
        save_btn.grid(row=0, column=1, sticky=E + N, pady=2)
        save_btn = Button(frame_for_save_btns,
                          text='Save parameters as...',
                          command=self.on_save_params_as)
        save_btn.grid(row=1, column=1, sticky=E + N, pady=2)
        frame_for_save_btns.grid(row=0,
                                 column=0,
                                 sticky=E + W,
                                 padx=XPAD_VALUE,
                                 pady=YPAD_VALUE)

        self.params_from_file_lbl = Label(params_tab,
                                          text=TEXT_FOR_PARAMS_LBL,
                                          anchor=W,
                                          justify=LEFT,
                                          wraplength=MAX_FILE_LBL_LENGTH)
        self.params_from_file_lbl.grid(row=1,
                                       column=0,
                                       columnspan=3,
                                       sticky=W + N,
                                       padx=XPAD_VALUE,
                                       pady=YPAD_VALUE)

        input_categories_list = CategoriesCheckBox(params_tab,
                                                   'Input categories:', True,
                                                   self.params,
                                                   'INPUT_CATEGORIES')
        self.input_categories_frame = input_categories_list
        input_categories_list.grid(row=4,
                                   column=0,
                                   sticky=W + N + S + E,
                                   padx=XPAD_VALUE,
                                   pady=YPAD_VALUE,
                                   columnspan=2)
        output_categories_list = CategoriesCheckBox(params_tab,
                                                    'Output categories:',
                                                    False, self.params,
                                                    'OUTPUT_CATEGORIES')
        self.output_categories_frame = output_categories_list
        output_categories_list.grid(row=5,
                                    column=0,
                                    sticky=W + N + S + E,
                                    padx=XPAD_VALUE,
                                    pady=YPAD_VALUE,
                                    columnspan=2)

        self.options_frame = OptionsFrame(params_tab, self.params,
                                          self.current_categories,
                                          self.input_categories_frame,
                                          self.output_categories_frame)
        self.options_frame.grid(row=6,
                                column=0,
                                columnspan=2,
                                sticky=N + S + W + E,
                                padx=XPAD_VALUE,
                                pady=YPAD_VALUE)
        self.add(frame_for_all_objects, text='Parameters')

    def on_save_params(self):
        ''' Saves current parameter values to a file from where the\
            parameters were loaded.
            This file name is displayed. If no file name is displayed
            (i.e. parameters were not
            previously loaded from file), then asksaveasfilename dialogue
            is called.
        '''
        file_name = self.params_from_file_lbl.cget('text')
        if TEXT_FOR_PARAMS_LBL in file_name:
            file_name = file_name[len(TEXT_FOR_PARAMS_LBL):]
        if file_name:
            write_parameters_to_file(self.params, file_name)
        else:
            self.on_save_params_as()

    def on_save_params_as(self):
        ''' Calls asksaveasfilename dialogue and saves current values of
            parameters to
            the specified file.
        '''
        file_name = self._get_file_name_to_save()
        if file_name:
            write_parameters_to_file(self.params, file_name)

    def _get_file_name_to_save(self):
        ''' Calls asksaveasfilename dialogue. This method is overridden
            in unit tests.

            Returns:
                (str): file name.
        '''
        return asksaveasfilename(filetypes=[('Text files', '*.txt')],
                                 defaultextension='.txt')

    def load_file(self):
        ''' Loads parameters from file specified by the user.
        '''
        file_name = self._get_filename_for_load()
        if file_name:

            self.str_var_for_input_output_boxes.input_categories.clear()
            self.str_var_for_input_output_boxes.output_categories.clear()

            # save previous params
            params_to_restore = dict()
            for param_name in CATEGORICAL_AND_DATA_FIELDS:
                params_to_restore[
                    param_name] = self.params.get_parameter_value(param_name)
            self.params.copy_all_params(parse_parameters_from_file(file_name))

            if self.load_without_data.get() == 0:
                self.load_data_file_and_related_params(file_name,
                                                       params_to_restore)
            else:
                self.data_from_params_file.set('')
                # restore previous parameters
                for param_name, value in params_to_restore.items():
                    self.params.update_parameter(param_name, value)
            self.options_frame.set_params_values()

    def _get_filename_for_load(self):
        ''' Calls askopenfilename dialogue. This method is overridden
            in unit tests.

            Returns:
                (str): file name.
        '''
        file_types = [('Text files', '*.txt'), ('All files', '*.*')]
        file_name = askopenfilename(title='Choose a file',
                                    filetypes=file_types)
        return file_name

    def load_data_file_and_related_params(self, file_name, params_to_restore):
        ''' Loads data if possible and sets widgets to proper values
            depending on parameters.

            Args:
                file_name (str): file name of file with parameters. It is needed
                    to display it on parameters frame.
                params_to_restore (dict of str to str): dictionary of
                    previous values of parameters. They are used in order
                    to restore
                    previous values if loading of data from file fails.
        '''
        data_file = self.params.get_parameter_value('DATA_FILE')
        norm_data_path = os.path.normpath(data_file)
        if os.path.isfile(norm_data_path):
            params_to_restore = dict()
            # I have to store this here, because when I clean all data
            # from data tab, it deletes these values from params
            for param_name in CATEGORICAL_AND_DATA_FIELDS:
                params_to_restore[
                    param_name] = self.params.get_parameter_value(param_name)
            # this line calls clear all from data_tab
            self.data_from_params_file.set(norm_data_path)

            self.params_from_file_lbl.config(text=TEXT_FOR_PARAMS_LBL +
                                             file_name)
            for param_name, value in params_to_restore.items():
                self.params.update_parameter(param_name, value)

            self.add_categories(
                'INPUT_CATEGORIES', self.input_categories_frame,
                self.str_var_for_input_output_boxes.input_categories)
            self.add_categories(
                'OUTPUT_CATEGORIES', self.output_categories_frame,
                self.str_var_for_input_output_boxes.output_categories)
            self.str_var_for_input_output_boxes.set('notify')
            self.weight_tab.add_weights()
        else:
            self._show_warning(norm_data_path)
            for param_name, value in params_to_restore.items():
                self.params.update_parameter(param_name, value)

    def _show_warning(self, norm_data_path):
        ''' Shows warning that data cannot be loaded from file.
            This method is overridden in unit tests.
        '''
        showwarning(
            'Warning', 'Cannot load data file: ' + norm_data_path +
            '. Parameters will be loaded without data.')

    def change_category_name(self, old_name, new_name):
        ''' Changes category name in parameters and all widgets to a new name.
            If new name is empty string, then some of the parameters might
            be lost (for example, weight restrictions will be lost).

            Args:
                old_name (str): old name of the category.
                new_name (str): new name of the category.
        '''
        if old_name != new_name:
            self.input_categories_frame.change_category_name(
                old_name, new_name)
            self.output_categories_frame.change_category_name(
                old_name, new_name)
            self.weight_tab.add_weights()
            if self.options_frame.combobox_text_var.get() == old_name:
                self.options_frame.change_categorical_box()
                self.options_frame.set_categorical_box(new_name)

    def add_categories(self, name, frame, categories_container):
        ''' Adds input or output categories to a specified widget
            with categories from parameters.

            Args:
                name (str): name of the parameter where categories come from,
                    possible values INPUT_CATEGORIES, OUTPUT_CATEGORIES.
                frame (CategoriesCheckBox): widget where categories will
                    be added.
                categories_container (list of str): list of categories where
                    categories from parameters will be added.
        '''
        categories = self.params.get_set_of_parameters(name)
        for category in categories:
            # we add only categories that are
            # present in data file
            if category in self.current_categories:
                frame.add_category(category)
                categories_container.append(category)
            else:
                self.params.remove_category_from_params(name, category)

    def clear_all(self):
        ''' Clears all parameters and corresponding widgets.
        '''
        self.input_categories_frame.remove_all_categories()
        self.output_categories_frame.remove_all_categories()
        self.options_frame.combobox_text_var.set('')
        self.weight_tab.remove_all_weights()
        self.params.clear_all_categorical_and_data_fields()
        self.params_from_file_lbl.config(text='')
        self.str_var_for_input_output_boxes.input_categories.clear()
        self.str_var_for_input_output_boxes.output_categories.clear()
Exemple #25
0
buttons = {}
butlist = []
for i in range(7*7):
    b = tk.Button(root, text=sdx['butval'][i])
    buttons[b] = i 
    b.bind("<Button-1>", butfunction)
    c1 = 21 + ((i % 7) * 27)
    c2 = 113 + ((math.trunc(i / 7)) * 16)
    b.place(x=c1,y=c2)
    b.config(height=1, width=2, borderwidth=0, bg='white', font=("Helvetica", 7))
    butlist.append(b)
butlist[sdx['tdateoffset']].config(bg='skyblue') 

label = Label(root, background='white')
label.place(relx=0.5,rely=0.005,anchor='n')
label.config(text=str(sdx['juldate']),font=("Helvetica", 74))

month_up_icon = tk.PhotoImage(file='./juldate22/assets/bluedot15.png') 
month_up_button = ttk.Button(
    root,
    image=month_up_icon,
    command=month_up_clicked
)
month_up_button.place(x=190,y=0) 

month_down_icon = tk.PhotoImage(file='./juldate22/assets/bluedot15.png') 
month_down_button = ttk.Button(
    root,
    image=month_down_icon,
    command=month_down_clicked
)
Exemple #26
0
class MainDialog(Frame):
    def __init__(self, root):
        super().__init__()
        self.assetFile = ('./DefaultAssetList.xlsx')
        self.root = root
        self.initUI()

    def initUI(self):
        #Task menu
        menubar = Menu(self.master)
        self.master.config(menu=menubar)

        fileMenu = Menu(menubar)
        fileMenu.add_command(label="Load Asset File", command=self.onOpen)
        fileMenu.add_command(label="Close", command=sys.exit)
        menubar.add_cascade(label="File", menu=fileMenu)

        #Note: Each time a .pack is called, it creates a new frame
        self.master.title("MobileView Assistant")

        self.root.rowconfigure(1, pad=10)
        self.root.rowconfigure(2, pad=10)
        self.root.rowconfigure(3, pad=10)
        self.root.rowconfigure(4, pad=10)
        self.root.rowconfigure(5, pad=10)
        self.root.rowconfigure(6, pad=10)
        self.root.rowconfigure(7, pad=10)
        self.root.rowconfigure(8, pad=10)
        self.root.rowconfigure(9, pad=10)
        self.root.rowconfigure(10, pad=10)
        self.root.rowconfigure(11, pad=10)

        self.root.columnconfigure(1, pad=5)
        self.root.columnconfigure(2, pad=5)
        self.root.columnconfigure(3, pad=5)
        self.root.columnconfigure(4, pad=5)

        #Username area
        lbl1 = Label(self.root, text="MV Username:"******"RSQ Username:"******"MV Password:"******"*")
        MVPassword.grid(row=2, column=2)

        lbl10 = Label(self.root, text="RSQ Password:"******"*")
        RSQPassword.grid(row=2, column=4)

        #File area
        lbl3 = Label(self.root, text="Asset File:", width=10)
        lbl3.grid(row=3, column=1)
        assetButton = Button(self.root, text="Browse", command=self.onOpen)
        assetButton.grid(row=3, column=2, sticky="w")
        self.lbl4 = Label(self.root, text=os.path.basename(self.assetFile))
        self.lbl4.grid(row=4, column=2, columnspan=2, sticky="w")

        #Trial Type Selector
        lbl7 = Label(self.root, text="Trial Type:", width=10)
        lbl7.grid(row=5, column=1)
        options = [
            "All Assets", "PM Month: January", "PM Month: February",
            "PM Month: March", "PM Month: April", "PM Month: May",
            "PM Month: June", "PM Month: July", "PM Month: August",
            "PM Month: September", "PM Month: October", "PM Month: November",
            "PM Month: December"
        ]
        trial_type = StringVar()
        trial_type.set(options[0])
        trial_selector = OptionMenu(self.root, trial_type, *options)
        trial_selector.grid(row=5, column=2, columnspan=2, sticky="WE")

        #Admin Access Checker
        self.admin_access = IntVar(value=1)
        Checkbutton(self.root,
                    text="I have access to Mobile View Admin.",
                    variable=self.admin_access).grid(row=6,
                                                     column=1,
                                                     columnspan=2,
                                                     sticky=W)

        #Active PMs only Checker
        self.cross_checker = IntVar(value=1)
        Checkbutton(self.root,
                    text="Print only the active PMs.",
                    variable=self.cross_checker).grid(row=7,
                                                      column=1,
                                                      columnspan=2,
                                                      sticky=W)

        #Run a test only Checker
        self.test_case = IntVar(value=0)
        Checkbutton(self.root,
                    text="Run a test trial only.",
                    variable=self.test_case).grid(row=6,
                                                  column=3,
                                                  columnspan=2,
                                                  sticky=W)

        #Email Results Checker
        self.email_results = IntVar(value=0)
        Checkbutton(self.root,
                    text="Email results to ResultsMailingList.txt.",
                    variable=self.email_results).grid(row=7,
                                                      column=3,
                                                      columnspan=2,
                                                      sticky=W)

        #Status Indicator
        lbl5 = Label(self.root, text="Status:", width=10)
        lbl5.grid(row=10, column=1)
        self.lbl6 = Label(self.root, text="Awaiting Inputs...", width=50)
        self.lbl6.grid(row=10, column=2, columnspan=5)

        #Ok and close button

        okButton = Button(
            self.root,
            text="Run",
            command=lambda: self.mainProgram(
                MVUsername.get(), MVPassword.get(), RSQUsername.get(),
                RSQPassword.get(), self.assetFile, trial_type.get(),
                self.admin_access.get(), self.test_case.get(),
                self.email_results.get(), self.cross_checker.get()))
        okButton.grid(row=11, column=2, sticky="WE")
        closeButton = Button(self.root, text="Close",
                             command=sys.exit)  #use quit to close window
        closeButton.grid(row=11, column=3, sticky="E")

        #Copyright Line
        lbl8 = Label(self.root, text="© Ryan Mooney Industries", width=10)
        lbl8.grid(row=12, column=1, columnspan=3, sticky="WE")

        self.centerWindow()

    def mainProgram(self, MVUsername, MVPassword, RSQUsername, RSQPassword,
                    assetfile, trial_type, admin_access, test_case,
                    email_results, cross_checker):
        #Checks credentials before continuing
        credentials_correct = checkCredentials(MVUsername, MVPassword,
                                               RSQUsername, RSQPassword,
                                               cross_checker, self.root,
                                               self.lbl6)
        if credentials_correct == "NO":
            return ()

        #Compiles a dictionary with each asset and its descriptors
        self.lbl6.config(text='Finding Assets...')
        self.root.update()

        #Determines how to find asset locations
        if test_case == 1:
            trial_type = 'TEST'
            assetList, floor_counter, floor_list = get_asset_locations_test(
                MVUsername, MVPassword,
                assetListCreator(assetfile, trial_type), self.root, self.lbl6)
        elif admin_access == 1:
            assetList, floor_counter, floor_list = get_asset_locations_admin(
                MVUsername, MVPassword,
                assetListCreator(assetfile, trial_type), self.root, self.lbl6)
        else:
            assetList, floor_counter, floor_list = get_asset_locations_nonadmin(
                MVUsername, MVPassword,
                assetListCreator(assetfile, trial_type), self.root, self.lbl6)

        #Saves each new asset data point to database with unique 'trial' number
        self.lbl6.config(text='Saving Data...')
        self.root.update()
        connection = connect()
        assetList, trial = assign_trial_number(assetList, connection,
                                               trial_type, test_case)
        save_to_db(assetList, self.root, self.lbl6, connection)
        connection.close()

        #If only active PMs are wanted, we cross check them with an RSQ list and return only the assets with active PMs
        if cross_checker == 1:
            self.lbl6.config(text='Cross checking for active PMs...')
            self.root.update()
            activeAssets = crossCheckAssets(assetList, RSQUsername,
                                            RSQPassword, self.root, self.lbl6)
            trial_type = trial_type + ' Active PMs Only'
        else:
            activeAssets = 'None'

        #Creates and Exports Data to Excel
        self.lbl6.config(text='Exporting to Excel...')
        self.root.update()
        file = exportToExcel(assetList, trial, floor_counter, floor_list,
                             trial_type, activeAssets)

        #Sends results to email addresses if requested
        if email_results == 1:
            self.lbl6.config(text='Sending Emails...')
            self.root.update()
            email_file = './ResultsMailingList.txt'
            send_results(file, email_file)

        self.lbl6.config(text='Completed!')
        self.root.update()
        os.startfile(file)

        #Emails results, if possible

    def centerWindow(self):

        w = 475
        h = 325

        sw = self.master.winfo_screenwidth()
        sh = self.master.winfo_screenheight()

        x = (sw - w) / 2
        y = (sh - h) / 2
        self.master.geometry('%dx%d+%d+%d' % (w, h, x, y))

    def onOpen(self):

        filename = filedialog.askopenfilename()
        self.lbl4.config(text=os.path.basename(filename))

        self.assetFile = filename

    def readFile(self, filename):

        with open(filename, "rb") as f:
            text = f.read()

        return text

    def run(self):
        print('I am running')
class ResourcePathFrame(Frame):
    def __init__(self, parent, configuration):
        Frame.__init__(self, parent)
        self.configuration = configuration

        self.test_path_in = None
        self.test_path_in_res = configuration.test_path_in

        self.test_path_expected = None
        self.test_path_expected_res = configuration.test_path_expected

        self.results_path = None
        self.results_path_res = configuration.results_path

        self.logging_path = None
        self.logging_path_res = configuration.logging_path

        self.init_view()

    def init_view(self):
        self.test_path_in = Label(self,
                                  text=FileUtils.get_filename_from_path(
                                      self.configuration.test_path_in))
        self.test_path_in.grid(row=0, column=1)
        Button(self,
               text="Browse...",
               command=self.browse_test_path_in) \
            .grid(row=0, column=0)

        self.test_path_expected = Label(
            self,
            text=FileUtils.get_filename_from_path(
                self.configuration.test_path_expected))
        self.test_path_expected.grid(row=1, column=1)
        Button(self,
               text="Browse...",
               command=self.browse_test_path_expected) \
            .grid(row=1, column=0)

        self.results_path = Label(self,
                                  text=FileUtils.get_filename_from_path(
                                      self.configuration.results_path))
        self.results_path.grid(row=2, column=1)
        Button(self,
               text="Browse...",
               command=self.browse_results_path) \
            .grid(row=2, column=0)

        self.logging_path = Label(self,
                                  text=FileUtils.get_filename_from_path(
                                      self.configuration.logging_path))
        self.logging_path.grid(row=3, column=1)
        Button(self,
               text="Browse...",
               command=self.browse_logging_path) \
            .grid(row=3, column=0)

    def browse_test_path_in(self):
        self.test_path_in_res = filedialog.askdirectory()
        self.test_path_in.config(text=FileUtils.get_filename_from_path(
            self.test_path_in_res.split('/')[-1]))

    def browse_test_path_expected(self):
        self.test_path_expected_res = filedialog.askdirectory()
        self.test_path_expected.config(text=FileUtils.get_filename_from_path(
            self.test_path_expected_res.split('/')[-1]))

    def browse_results_path(self):
        self.results_path_res = filedialog.askdirectory()
        self.results_path.config(text=FileUtils.get_filename_from_path(
            self.results_path_res.split('/')[-1]))

    def browse_logging_path(self):
        self.logging_path_res = filedialog.askopenfilename()
        self.logging_path.config(
            text=FileUtils.get_filename_from_path(self.logging_path_res))

    def get_values(self):
        return self.test_path_in_res, \
               self.test_path_expected_res,\
               self.results_path_res,\
               self.logging_path_res
Exemple #28
0
class BIDSSearchFrame(Frame):
    def __init__(self, master, parent=None, *args, **kwargs):
        self.master = master
        self.parent = parent
        super(BIDSSearchFrame, self).__init__(self.master, *args, **kwargs)

        # create some inital variables
        self.obj_var = OptionsVar(
            options=['project', 'subject', 'session', 'scan'])
        self.condition_var = OptionsVar(
            options=['<', '<=', '=', '!=', '!!=', '>=', '>'])
        self.results = None

        self._create_widgets()

        # the associated file
        self._file = None

#region public methods

    def set_text(self, text):
        self.info_label.config(text=text)

#region private methods

    def _create_widgets(self):
        self.info_label = Label(self, text='Search')
        self.info_label.grid(column=0, row=0, sticky='nw')

        Label(self, text='Search for a...').grid(column=0, row=1, sticky='nw')

        self.search_table = WidgetTable(
            self,
            headings=None,
            pattern=[{
                'var': self.obj_var,
                'configs': {
                    'state': 'readonly'
                }
            }, {
                'text': 'with'
            }, StringVar, {
                'var': self.condition_var,
                'configs': {
                    'state': 'readonly'
                }
            }, StringVar],
            widgets_pattern=[Combobox, Label, Entry, Combobox, Entry],
            data_array=[{
                'var': self.obj_var,
                'configs': {
                    'state': 'readonly'
                }
            }, {
                'text': 'with'
            },
                        StringVar(), {
                            'var': self.condition_var,
                            'configs': {
                                'state': 'readonly'
                            }
                        },
                        StringVar()],
            style={'nodividers': True})
        self.search_table.grid(column=0, row=2, columnspan=2, sticky='nsew')

        self.search_button = Button(self, text='Search', command=self._search)
        self.search_button.grid(column=0, row=3, sticky='e')

        # results section
        Label(self, text='Results:').grid(column=0, row=4, sticky='nw')

        frame = Frame(self)

        frame.grid_rowconfigure(0, weight=1)
        frame.grid_columnconfigure(0, weight=1)

        xscrollbar = Scrollbar(frame, orient=HORIZONTAL)
        xscrollbar.grid(row=1, column=0, sticky='ew')

        yscrollbar = Scrollbar(frame)
        yscrollbar.grid(row=0, column=1, sticky='ns')

        self.results_frame = Text(frame,
                                  relief=FLAT,
                                  undo=False,
                                  takefocus=0,
                                  bg=OSCONST.TEXT_BG,
                                  wrap=NONE,
                                  xscrollcommand=xscrollbar.set,
                                  yscrollcommand=yscrollbar.set,
                                  state=DISABLED)

        self.results_frame.grid(row=0, column=0, sticky='nsew')

        self.hyperlink = HyperlinkManager(self.results_frame)

        xscrollbar.config(command=self.results_frame.xview)
        yscrollbar.config(command=self.results_frame.yview)

        frame.grid(column=0, row=5, columnspan=2, sticky='nsew')

        self.result_count_label = Label(self, text="Total results: 0")
        self.result_count_label.grid(column=0, row=6, sticky='w')

        export_button = Button(self,
                               text='Export',
                               command=self._export_results)
        export_button.grid(column=0, row=7, sticky='e')
        help_button = Button(self, text='Help', command=self._open_help)
        help_button.grid(column=1, row=7, sticky='e')

        self.grid_columnconfigure(0, weight=1)
        self.grid_rowconfigure(2, weight=1)
        self.grid_rowconfigure(5, weight=1)

    def _export_results(self):
        if len(self.results) != 0:
            # ask where to copy the data to
            dst = filedialog.askdirectory(title="Select BIDS folder")
            if dst != '':
                SendFilesWindow(self, self.results, dst, opt_verify=True)
        else:
            messagebox.showerror(
                'No Results', 'No results to export. Please enter a set of '
                'valid search parameters to export data.')

    def _open_help(self):
        open_hyperlink(HELP_LINK)

    def _search(self):
        query = self.search_table.get()
        self.results = None
        try:
            for q in query:
                if self.results is None:
                    self.results = self.file.query(q[0], q[2], q[3],
                                                   str_to_obj(q[4]))
                else:
                    self.results = self.results.query(q[0], q[2], q[3],
                                                      str_to_obj(q[4]))
        except ValueError:
            messagebox.showerror(
                'Invalid search', 'One or more search parameters are invalid. '
                'Please ensure your search criteria is '
                'correct.')
            self.results = []
        str_results = list(get_bidsobj_info(x) for x in self.results)
        self.results_frame.config(state=NORMAL)
        # Clear all the current text.
        self.results_frame.delete(1.0, END)
        # Then add all the new results.
        for i, result in enumerate(str_results):
            self.results_frame.insert(
                END, result + '\n',
                self.hyperlink.add(
                    lambda obj=self.results[i]: self._select_obj(obj)))
        # Set the frame to not be writable any more.
        if len(self.results) == 0:
            self.results_frame.insert(END, 'None')
        self.results_frame.config(state=DISABLED)

        self.result_count_label.config(
            text="Total results: {0}".format(len(self.results)))

    def _select_obj(self, obj):
        """Highlight the selected object in the treeview."""
        # find the selected object's sid
        if isinstance(obj, Scan):
            # for scan objects we want to go to the actual raw object
            fpath = obj.raw_file
        else:
            fpath = obj.path
        obj_sid = self.parent.file_treeview.sid_from_filepath(fpath)
        # then show it
        self.parent.file_treeview.see(obj_sid)
        self.parent.file_treeview.focus(item=obj_sid)
        self.parent.file_treeview.selection_set((obj_sid, ))

#region properties

    @property
    def file(self):
        return self._file

    @file.setter
    def file(self, other):
        """
        Set the file property to whatever the new file is.
        When this happens the update command will be called which will redraw
        the channel info list
        """
        if other != self._file:
            self._file = other
Exemple #29
0
class Application(Frame):
    def __init__(self, parent):
        super().__init__(parent)
        self.Version = "YEDDA-V1.0 Annotator"
        self.OS = platform.system().lower()
        self.fileName = ""
        self.file_encoding = 'utf-8'
        self.debug = False
        self.history = deque(maxlen=20)
        self.pressCommand = [
            KeyDef('a', "Artificial"),
            KeyDef('b', "Event"),
            KeyDef('c', "Fin-Concept"),
            KeyDef('d', "Location"),
            KeyDef('e', "Organization"),
            KeyDef('f', "Person"),
            KeyDef('g', "Sector"),
            KeyDef('h', "Other")
        ]
        for key, color in zip(self.pressCommand, all_colors()):
            key.color = color

        # default GUI display parameter
        self.textRow = max(len(self.pressCommand), 20)
        self.textColumn = 5

        self.configFile = "configs/default.config"
        self.entity_regex = r'\[\@.*?\#.*?\*\](?!\#)'
        self.recommendRe = r'\[\$.*?\#.*?\*\](?!\#)'
        self.goldAndrecomRe = r'\[[\@\$)].*?\#.*?\*\](?!\#)'
        self.textFontStyle = "Times"
        self.initUI()

    def initUI(self):
        self.master.title(self.Version)
        self.pack(fill=BOTH, expand=True)

        for i in range(0, self.textColumn):
            self.columnconfigure(i, weight=2)
        # self.columnconfigure(0, weight=2)
        self.columnconfigure(self.textColumn + 2, weight=1)
        self.columnconfigure(self.textColumn + 4, weight=1)
        for i in range(0, 16):
            self.rowconfigure(i, weight=1)

        self.filename_lbl = Label(self, text="File: no file is opened")
        self.filename_lbl.grid(sticky=W, pady=4, padx=5)
        self.text = Editor(self, self.entity_regex, self.recommendRe)
        self.text.grid(row=1,
                       column=0,
                       columnspan=self.textColumn,
                       rowspan=self.textRow,
                       padx=12,
                       sticky=NSEW)

        btn = Button(self, text="Open", command=self.onOpen)
        btn.grid(row=1, column=self.textColumn + 1)
        btn = Button(self, text="ReMap", command=self.renewPressCommand)
        btn.grid(row=2, column=self.textColumn + 1, pady=4)
        btn = Button(self, text="NewMap", command=self.savenewPressCommand)
        btn.grid(row=3, column=self.textColumn + 1, pady=4)
        btn = Button(self, text="Export", command=self.generateSequenceFile)
        btn.grid(row=4, column=self.textColumn + 1, pady=4)

        self.use_recommend = BooleanVar(self, True)
        check = Checkbutton(self,
                            text='Recommend',
                            command=self.toggle_use_recommend,
                            variable=self.use_recommend)
        check.grid(row=5, column=self.textColumn + 1, sticky=W, pady=4)

        show_tags_var = BooleanVar(self, True)
        check = Checkbutton(
            self,
            text='Show Tags',
            variable=show_tags_var,
            command=lambda: self.text.show_annotation_tag(show_tags_var.get()))
        check.grid(row=6, column=self.textColumn + 1, sticky=W)

        self.use_colorful_var = BooleanVar(self, False)
        check = Checkbutton(self,
                            text='Colorful',
                            variable=self.use_colorful_var,
                            command=self.toggle_use_colorful)
        check.grid(row=7, column=self.textColumn + 1, sticky=W)

        self.cursor_index_label = Label(self, text="Ln 1, Col 0")
        self.cursor_index_label.grid(row=self.textRow + 1,
                                     sticky=NSEW,
                                     pady=4,
                                     padx=4)
        cmd_var = StringVar()
        cmd_var.trace_add('write', lambda _, _1, _2: self.preview_cmd_range())
        self.entry = Entry(self,
                           validate='focus',
                           vcmd=self.preview_cmd_range,
                           textvariable=cmd_var)
        self.entry.grid(row=self.textRow + 1,
                        column=1,
                        columnspan=self.textColumn - 2,
                        sticky=NSEW,
                        pady=4,
                        padx=8)
        self.entry.bind('<FocusOut>', self.clear_preview_mark)
        self.entry.bind('<Return>', self.execute_command)

        btn = Button(self,
                     text="Enter",
                     command=lambda: self.execute_command(None))
        btn.grid(row=self.textRow + 1, column=self.textColumn - 1)

        all_keys = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
        for press_key in all_keys:
            self.text.bind(press_key, self.alphanum_key_pressed, add='')
            if self.OS != "windows":
                self.text.bind(f'<Control-Key-"{press_key}">',
                               self.keepCurrent)
                self.text.bind(f'<Command-Key-"{press_key}">',
                               self.keepCurrent)

        self.text.bind('<Control-Key-z>', self.backToHistory)

        self.text.bind('<Double-Button-1>', self.doubleLeftClick)
        self.text.bind('<ButtonRelease-1>', self.show_cursor_pos)
        self.text.bind('<KeyRelease>', self.show_cursor_pos)

        self.keymap_frame = KeyMapFrame(self, self.pressCommand)
        self.keymap_frame.grid(row=1,
                               column=self.textColumn + 2,
                               rowspan=self.keymap_frame.rows,
                               columnspan=2,
                               padx=6,
                               pady=6,
                               sticky=NW)

        Label(self, text="KeyMap Templates:").grid(row=8,
                                                   column=self.textColumn + 1)
        self.configListBox = Combobox(self,
                                      values=getConfigList(),
                                      state='readonly')
        self.configListBox.grid(row=8,
                                column=self.textColumn + 2,
                                columnspan=2)
        # select current config file
        self.configListBox.set(self.configFile.split(os.sep)[-1])
        self.configListBox.bind('<<ComboboxSelected>>',
                                self.on_select_configfile)

    def show_cursor_pos(self, _):
        cursor_index = self.text.index(INSERT)
        row, col = cursor_index.split('.')
        self.cursor_index_label.config(text=f"Ln {row}, Col {col}")

    # TODO: select entity by double left click
    def doubleLeftClick(self, _):
        if self.debug:
            print("Action Track: doubleLeftClick")
        pass
        # cursor_index = self.text.index(INSERT)
        # start_index = ("%s - %sc" % (cursor_index, 5))
        # end_index = ("%s + %sc" % (cursor_index, 5))
        # self.text.tag_add('SEL', '1.0',"end-1c")

    def toggle_use_recommend(self):
        if not self.use_recommend.get():
            content = self.text.get_text()
            content = removeRecommendContent(content, self.recommendRe)
            self.writeFile(self.fileName, content, '1.0')

    def toggle_use_colorful(self):
        if self.use_colorful_var.get():
            self.text.set_colors([(d.name, d.color)
                                  for d in self.pressCommand])
        else:
            self.text.set_colors(None)
        self.text.update_view()

    def onOpen(self):
        filename = filedialog.askopenfilename(
            filetypes=[('all files', '.*'), ('text files',
                                             '.txt'), ('ann files', '.ann')])
        if filename != '':
            self.text.delete("1.0", END)
            text = self.readFile(filename)
            self.text.insert(END, text)
            self.filename_lbl.config(text="File: " + filename)
            self.autoLoadNewFile(self.fileName, "1.0")
            self.text.mark_set(INSERT, "1.0")
            self.show_cursor_pos(None)

    def readFile(self, filename):
        f = open(filename)
        try:
            text = f.read()
            self.file_encoding = f.encoding
        except UnicodeDecodeError:
            f = open(filename, encoding='utf-8')
            text = f.read()
        self.fileName = filename
        return text

    def setFont(self, value):
        _family = self.textFontStyle
        _size = value
        _weight = "bold"
        _underline = 0
        fnt = font.Font(family=_family,
                        size=_size,
                        weight=_weight,
                        underline=_underline)
        Text(self, font=fnt)

    def setCursorLabel(self, cursor_index):
        row, col = cursor_index.split('.')
        self.cursor_index_label.config(text=f"Ln {row}, Col {col}")

    def clear_preview_mark(self, _):
        self.text.tag_delete('cmd-preview')

    def preview_cmd_range(self):
        preview_tag = 'cmd-preview'
        cmd = self.entry.get().strip()
        self.text.tag_delete(preview_tag)
        self.text.tag_configure(preview_tag, background='light salmon')
        match = re.match(r'^(-?[0-9]+).*', cmd)
        if match:
            count = int(match.group(1))
        else:
            count = 1
        if count > 0:
            self.text.tag_add(preview_tag, INSERT, f'{INSERT}+{count}c')
        else:
            self.text.tag_add(preview_tag, f'{INSERT}-{abs(count)}c', INSERT)
        return True

    def execute_command(self, _):
        self.pushToHistory()
        content = self.entry.get()
        self.clearCommand()
        self.execute_entry_command(content.strip())
        return content

    def alphanum_key_pressed(self, event):
        press_key = event.char
        self.pushToHistory()
        self.clearCommand()
        self.execute_cursor_command(press_key.lower())
        return 'break'

    def backToHistory(self, _):
        if self.debug:
            print("Action Track: backToHistory")
        if len(self.history) > 0:
            content, cursor = self.history.pop()
            self.writeFile(self.fileName, content, cursor)
        else:
            print("History is empty!")

    def keepCurrent(self, _):
        if self.debug:
            print("Action Track: keepCurrent")
        print("keep current, insert:", INSERT)
        print("before:", self.text.index(INSERT))
        self.text.insert(INSERT, 'p')
        print("after:", self.text.index(INSERT))

    def clearCommand(self):
        if self.debug:
            print("Action Track: clearCommand")
        self.entry.delete(0, 'end')

    def execute_cursor_command(self, command):
        print("Command:" + command)
        found, (start, end) = self.text.current_entity()
        selected = self.text.get_selection()
        if not found and not selected:
            print(f'{command} outside entity, no selection, do nothing')
            return
        # selected whole entity, cursor just outside it
        selected_whole = selected is not None and \
                         (re.match(self.entity_regex, selected) or re.match(self.recommendRe, selected))

        # cursor outside existing entity & has selection
        if not found and selected is not None and not selected_whole:
            if self.get_cmd_by_key(command) is None:
                print(f'{command} key not bound, outside entity, do nothing')
                return
            cursor_index = self.text.index(SEL_LAST)
            entity_content, cursor_index = self.replaceString(
                selected, selected, command, cursor_index)
            above_half = self.text.get('1.0', SEL_FIRST) + entity_content
            below_half = self.text.get(SEL_LAST, "end-1c")
            content = self.addRecommendContent(above_half, below_half,
                                               self.use_recommend.get())
            self.writeFile(self.fileName, content, cursor_index)
        # Cursor inside existing entity, no matter has or not has selection.
        # Or Cursor outside existing entity (just on the edge), with the whole entity selected
        else:
            if selected_whole:
                start, end = self.text.index(SEL_FIRST), self.text.index(
                    SEL_LAST)
            covered_string = self.text.get(start, end)
            old_entity, old_label = covered_string.strip('[@$*]').rsplit(
                '#', 1)

            if command == "q":
                print('q: remove entity label')
                new_cursor = f'{end}-{5 + len(old_label)}c'
                entity_content = old_entity
            elif command == 'y':
                print("y: confirm recommend label")
                entity_content = f'[@{old_entity}#{old_label}*]'
                new_cursor = end
            elif len(old_entity) > 0 and self.get_cmd_by_key(
                    command) is not None:
                print(f'{command}: change entity type')
                cmd = self.get_cmd_by_key(command)
                entity_content = f'[@{old_entity}#{cmd.name}*]'
                delta = len(cmd.name) - len(old_label)
                new_cursor = end + (f'+{delta}c'
                                    if delta >= 0 else f'{delta}c')
            else:
                print(f'{command}: key not bound, do nothing')
                return
            above_half = self.text.get('1.0', start) + entity_content
            below_half = self.text.get(end, 'end-1c')
            content = self.addRecommendContent(above_half, below_half,
                                               self.use_recommend.get())
            self.writeFile(self.fileName, content, new_cursor)

    def execute_entry_command(self, command):
        print(f"EntryCommand: {command}")
        if command == '':  # move to next line
            row, _ = self.text.index(INSERT).split('.')
            self.text.mark_set(INSERT, f'{int(row) + 1}.0')
            self.show_cursor_pos(None)
        elif command.isdigit():
            self.text.mark_set(INSERT, f'{INSERT}+{command}c')
            self.show_cursor_pos(None)
            self.preview_cmd_range()
        elif len(command) >= 2 and command[0] == '-' and command[1:].isdigit():
            self.text.mark_set(INSERT, f'{INSERT}{command}c')
            self.show_cursor_pos(None)
            self.preview_cmd_range()
        else:

            def split_commands(string):
                commands = []
                num = ''
                for c in string:
                    if c.isdigit():
                        num += c
                    else:
                        commands.append((int(num), c))
                        num = ''
                return commands

            for select_num, cmd in split_commands(command):
                assert select_num > 0
                sel_start = self.text.index(INSERT)
                sel_end = self.text.index(f'{INSERT}+{select_num}c')
                selected = self.text.get(sel_start, sel_end)
                if self.get_cmd_by_key(cmd) is not None:
                    above_half = self.text.get('1.0', sel_start)
                    below_half = self.text.get(sel_start, "end-1c")
                    below_half, new_cursor = self.replaceString(
                        below_half, selected, cmd, sel_end)
                    content = self.addRecommendContent(
                        above_half, below_half, self.use_recommend.get())
                    self.writeFile(self.fileName, content, new_cursor)

    def replaceString(self, content, string, replaceType, cursor_index):
        keydef = self.get_cmd_by_key(replaceType)
        if keydef is not None:
            new_string = "[@" + string + "#" + keydef.name + "*]"
            row, col = cursor_index.split('.')
            newcursor_index = f"{row}.{int(col) + len(keydef.name) + 5}"
            content = content.replace(string, new_string, 1)
            return content, newcursor_index
        else:
            print("Invalid command!")
            print("cursor index: ", self.text.index(INSERT))
            return content, cursor_index

    def writeFile(self, fileName, content, newcursor_index):
        print("writeFile")
        if len(fileName) > 0:
            if ".ann" in fileName:
                new_name = fileName
                ann_file = open(new_name, 'w', encoding=self.file_encoding)
                ann_file.write(content)
                ann_file.close()
            else:
                new_name = fileName + '.ann'
                ann_file = open(new_name, 'w', encoding=self.file_encoding)
                ann_file.write(content)
                ann_file.close()
            self.autoLoadNewFile(new_name, newcursor_index)
        else:
            print("Don't write to empty file!")

    def addRecommendContent(self, train_data, decode_data, recommendMode):
        if not recommendMode:
            content = train_data + decode_data
        else:
            if self.debug:
                print(
                    "Action Track: addRecommendContent, start Recommend entity"
                )
            content = maximum_matching(train_data, decode_data)
        return content

    def autoLoadNewFile(self, fileName, newcursor_index):
        if self.debug:
            print("Action Track: autoLoadNewFile")
        if len(fileName) > 0:
            self.text.delete("1.0", END)
            text = self.readFile(fileName)
            self.text.insert("end-1c", text)
            self.filename_lbl.config(text="File: " + fileName)
            self.text.mark_set(INSERT, newcursor_index)
            self.text.see(newcursor_index)
            self.show_cursor_pos(None)
            self.text.update_view()

    def pushToHistory(self):
        self.history.append((self.text.get_text(), self.text.index(INSERT)))

    # update shortcut map, directly in current configfile
    def renewPressCommand(self):
        if self.debug:
            print("Action Track: renewPressCommand")
        self.pressCommand = self.keymap_frame.read_keymap()
        with open(self.configFile, 'w') as fp:
            fp.write(str(self.pressCommand))
        self.keymap_frame.update_keymap(self.pressCommand)
        messagebox.showinfo(
            "Remap Notification", "Shortcut map has been updated!\n\n" +
            "Configure file has been saved in File:" + self.configFile)

    # save as new shortcut map
    def savenewPressCommand(self):
        if self.debug:
            print("Action Track: savenewPressCommand")
        self.pressCommand = self.keymap_frame.read_keymap()
        # prompt to ask configFile name
        self.configFile = filedialog.asksaveasfilename(
            initialdir="./configs/",
            title="Save New Config",
            filetypes=(("YEDDA configs", "*.config"), ("all files", "*.*")))
        # change to relative path following self.init()
        self.configFile = os.path.relpath(self.configFile)
        # make sure ending with ".config"
        if not self.configFile.endswith(".config"):
            self.configFile += ".config"
        with open(self.configFile, 'w') as fp:
            fp.write(str(self.pressCommand))
        self.keymap_frame.update_keymap(self.pressCommand)
        messagebox.showinfo(
            "Save New Map Notification",
            "Shortcut map has been saved and updated!\n\n" +
            "Configure file has been saved in File:" + self.configFile)

    def on_select_configfile(self, event=None):
        if event and self.debug:
            print("Change shortcut map to: ", event.widget.get())
        self.configFile = os.path.join("configs", event.widget.get())
        self.keymap_frame.update_keymap(self.pressCommand)

    def generateSequenceFile(self):
        if (".ann" not in self.fileName) and (".txt" not in self.fileName):
            out_error = "Export only works on filename ended in .ann or .txt!\nPlease rename file."
            print(out_error)
            messagebox.showerror("Export error!", out_error)
            return -1
        dlg = QueryExport(self, self.fileName, self.text.get_text()[:100])
        if not dlg.confirmed:
            print("Operation canceled")
            return
        fileLines = open(self.fileName, 'r',
                         encoding=self.file_encoding).readlines()
        lineNum = len(fileLines)
        new_filename = self.fileName.split(
            '.ann')[0] + '.' + dlg.tag_scheme().lower()
        seqFile = open(new_filename, 'w', encoding=self.file_encoding)
        for line in fileLines:
            if len(line) <= 2:
                seqFile.write('\n')
                continue
            else:
                if not dlg.keep_recommended():
                    line = removeRecommendContent(line, self.recommendRe)
                    pattern = self.entity_regex
                else:
                    pattern = self.goldAndrecomRe
                wordTagPairs = getWordTagPairs(line, dlg.segmented(),
                                               dlg.tag_scheme(), dlg.only_NP(),
                                               pattern)
                for wordTag in wordTagPairs:
                    seqFile.write(wordTag)
                # use null line to separate sentences
                seqFile.write('\n')
        seqFile.close()
        print("Exported file into sequence style in file: ", new_filename)
        print("Line number:", lineNum)
        showMessage = "Exported file successfully!\n\n"
        showMessage += "Tag scheme: " + dlg.tag_scheme() + "\n\n"
        showMessage += "Keep Recom: " + str(dlg.keep_recommended()) + "\n\n"
        showMessage += "Text Segmented: " + str(dlg.segmented()) + "\n\n"
        showMessage += "Line Number: " + str(lineNum) + "\n\n"
        showMessage += "Saved to File: " + new_filename
        messagebox.showinfo("Export Message", showMessage)

    def get_cmd_by_key(self, key):
        return next((item for item in self.pressCommand if item.key == key),
                    None)

    def get_cmd_by_name(self, name):
        return next((item for item in self.pressCommand if item.name == name),
                    None)
Exemple #30
0
class DialogPluginManager(Toplevel):
    def __init__(self, mainWin, modulesWithNewerFileDates):
        super(DialogPluginManager, self).__init__(mainWin.parent)

        self.ENABLE = _("Enable")
        self.DISABLE = _("Disable")
        self.parent = mainWin.parent
        self.cntlr = mainWin

        # copy plugins for temporary display
        self.pluginConfig = PluginManager.pluginConfig
        self.pluginConfigChanged = False
        self.uiClassMethodsChanged = False
        self.modelClassesChanged = False
        self.customTransformsChanged = False
        self.disclosureSystemTypesChanged = False
        self.hostSystemFeaturesChanged = False
        self.modulesWithNewerFileDates = modulesWithNewerFileDates

        parentGeometry = re.match("(\d+)x(\d+)[+]?([-]?\d+)[+]?([-]?\d+)",
                                  self.parent.geometry())
        dialogX = int(parentGeometry.group(3))
        dialogY = int(parentGeometry.group(4))

        self.title(_("Plug-in Manager"))
        frame = Frame(self)

        # left button frame
        buttonFrame = Frame(frame, width=40)
        buttonFrame.columnconfigure(0, weight=1)
        addLabel = Label(buttonFrame,
                         text=_("Find plug-in modules:"),
                         wraplength=60,
                         justify="center")
        addSelectLocalButton = Button(buttonFrame,
                                      text=_("Select"),
                                      command=self.selectLocally)
        ToolTip(
            addSelectLocalButton,
            text=_(
                "Select python module files from the local plugin directory."),
            wraplength=240)
        addBrowseLocalButton = Button(buttonFrame,
                                      text=_("Browse"),
                                      command=self.browseLocally)
        ToolTip(
            addBrowseLocalButton,
            text=
            _("File chooser allows browsing and selecting python module files to add (or reload) plug-ins, from the local file system."
              ),
            wraplength=240)
        addWebButton = Button(buttonFrame,
                              text=_("On Web"),
                              command=self.findOnWeb)
        ToolTip(
            addWebButton,
            text=
            _("Dialog to enter URL full path to load (or reload) plug-ins, from the web or local file system."
              ),
            wraplength=240)
        addLabel.grid(row=0, column=0, pady=4)
        addSelectLocalButton.grid(row=1, column=0, pady=4)
        addBrowseLocalButton.grid(row=2, column=0, pady=4)
        addWebButton.grid(row=3, column=0, pady=4)
        buttonFrame.grid(row=0,
                         column=0,
                         rowspan=3,
                         sticky=(N, S, W),
                         padx=3,
                         pady=3)

        # right tree frame (plugins already known to arelle)
        modulesFrame = Frame(frame, width=720)
        vScrollbar = Scrollbar(modulesFrame, orient=VERTICAL)
        hScrollbar = Scrollbar(modulesFrame, orient=HORIZONTAL)
        self.modulesView = Treeview(modulesFrame,
                                    xscrollcommand=hScrollbar.set,
                                    yscrollcommand=vScrollbar.set,
                                    height=7)
        self.modulesView.grid(row=0, column=0, sticky=(N, S, E, W))
        self.modulesView.bind('<<TreeviewSelect>>', self.moduleSelect)
        hScrollbar["command"] = self.modulesView.xview
        hScrollbar.grid(row=1, column=0, sticky=(E, W))
        vScrollbar["command"] = self.modulesView.yview
        vScrollbar.grid(row=0, column=1, sticky=(N, S))
        modulesFrame.columnconfigure(0, weight=1)
        modulesFrame.rowconfigure(0, weight=1)
        modulesFrame.grid(row=0,
                          column=1,
                          columnspan=4,
                          sticky=(N, S, E, W),
                          padx=3,
                          pady=3)
        self.modulesView.focus_set()

        self.modulesView.column("#0", width=120, anchor="w")
        self.modulesView.heading("#0", text=_("Name"))
        self.modulesView["columns"] = ("author", "ver", "status", "date",
                                       "update", "descr", "license")
        self.modulesView.column("author", width=100, anchor="w", stretch=False)
        self.modulesView.heading("author", text=_("Author"))
        self.modulesView.column("ver", width=60, anchor="w", stretch=False)
        self.modulesView.heading("ver", text=_("Version"))
        self.modulesView.column("status", width=50, anchor="w", stretch=False)
        self.modulesView.heading("status", text=_("Status"))
        self.modulesView.column("date", width=70, anchor="w", stretch=False)
        self.modulesView.heading("date", text=_("File Date"))
        self.modulesView.column("update", width=50, anchor="w", stretch=False)
        self.modulesView.heading("update", text=_("Update"))
        self.modulesView.column("descr", width=200, anchor="w", stretch=False)
        self.modulesView.heading("descr", text=_("Description"))
        self.modulesView.column("license", width=70, anchor="w", stretch=False)
        self.modulesView.heading("license", text=_("License"))

        classesFrame = Frame(frame)
        vScrollbar = Scrollbar(classesFrame, orient=VERTICAL)
        hScrollbar = Scrollbar(classesFrame, orient=HORIZONTAL)
        self.classesView = Treeview(classesFrame,
                                    xscrollcommand=hScrollbar.set,
                                    yscrollcommand=vScrollbar.set,
                                    height=5)
        self.classesView.grid(row=0, column=0, sticky=(N, S, E, W))
        hScrollbar["command"] = self.classesView.xview
        hScrollbar.grid(row=1, column=0, sticky=(E, W))
        vScrollbar["command"] = self.classesView.yview
        vScrollbar.grid(row=0, column=1, sticky=(N, S))
        classesFrame.columnconfigure(0, weight=1)
        classesFrame.rowconfigure(0, weight=1)
        classesFrame.grid(row=1,
                          column=1,
                          columnspan=4,
                          sticky=(N, S, E, W),
                          padx=3,
                          pady=3)
        self.classesView.focus_set()

        self.classesView.column("#0", width=200, anchor="w")
        self.classesView.heading("#0", text=_("Class"))
        self.classesView["columns"] = ("modules", )
        self.classesView.column("modules",
                                width=500,
                                anchor="w",
                                stretch=False)
        self.classesView.heading("modules", text=_("Modules"))

        # bottom frame module info details
        moduleInfoFrame = Frame(frame, width=700)
        moduleInfoFrame.columnconfigure(1, weight=1)

        self.moduleNameLabel = Label(moduleInfoFrame,
                                     wraplength=600,
                                     justify="left",
                                     font=font.Font(family='Helvetica',
                                                    size=12,
                                                    weight='bold'))
        self.moduleNameLabel.grid(row=0, column=0, columnspan=4, sticky=W)
        self.moduleAuthorHdr = Label(moduleInfoFrame,
                                     text=_("author:"),
                                     state=DISABLED)
        self.moduleAuthorHdr.grid(row=1, column=0, sticky=W)
        self.moduleAuthorLabel = Label(moduleInfoFrame,
                                       wraplength=600,
                                       justify="left")
        self.moduleAuthorLabel.grid(row=1, column=1, columnspan=3, sticky=W)
        self.moduleDescrHdr = Label(moduleInfoFrame,
                                    text=_("description:"),
                                    state=DISABLED)
        self.moduleDescrHdr.grid(row=2, column=0, sticky=W)
        self.moduleDescrLabel = Label(moduleInfoFrame,
                                      wraplength=600,
                                      justify="left")
        self.moduleDescrLabel.grid(row=2, column=1, columnspan=3, sticky=W)
        self.moduleClassesHdr = Label(moduleInfoFrame,
                                      text=_("classes:"),
                                      state=DISABLED)
        self.moduleClassesHdr.grid(row=3, column=0, sticky=W)
        self.moduleClassesLabel = Label(moduleInfoFrame,
                                        wraplength=600,
                                        justify="left")
        self.moduleClassesLabel.grid(row=3, column=1, columnspan=3, sticky=W)
        ToolTip(self.moduleClassesLabel,
                text=_("List of classes that this plug-in handles."),
                wraplength=240)
        self.moduleVersionHdr = Label(moduleInfoFrame,
                                      text=_("version:"),
                                      state=DISABLED)
        self.moduleVersionHdr.grid(row=4, column=0, sticky=W)
        self.moduleVersionLabel = Label(moduleInfoFrame,
                                        wraplength=600,
                                        justify="left")
        self.moduleVersionLabel.grid(row=4, column=1, columnspan=3, sticky=W)
        ToolTip(self.moduleVersionLabel,
                text=_("Version of plug-in module."),
                wraplength=240)
        self.moduleUrlHdr = Label(moduleInfoFrame,
                                  text=_("URL:"),
                                  state=DISABLED)
        self.moduleUrlHdr.grid(row=5, column=0, sticky=W)
        self.moduleUrlLabel = Label(moduleInfoFrame,
                                    wraplength=600,
                                    justify="left")
        self.moduleUrlLabel.grid(row=5, column=1, columnspan=3, sticky=W)
        ToolTip(
            self.moduleUrlLabel,
            text=_(
                "URL of plug-in module (local file path or web loaded file)."),
            wraplength=240)
        self.moduleDateHdr = Label(moduleInfoFrame,
                                   text=_("date:"),
                                   state=DISABLED)
        self.moduleDateHdr.grid(row=6, column=0, sticky=W)
        self.moduleDateLabel = Label(moduleInfoFrame,
                                     wraplength=600,
                                     justify="left")
        self.moduleDateLabel.grid(row=6, column=1, columnspan=3, sticky=W)
        ToolTip(
            self.moduleDateLabel,
            text=
            _("Date of currently loaded module file (with parenthetical node when an update is available)."
              ),
            wraplength=240)
        self.moduleLicenseHdr = Label(moduleInfoFrame,
                                      text=_("license:"),
                                      state=DISABLED)
        self.moduleLicenseHdr.grid(row=7, column=0, sticky=W)
        self.moduleLicenseLabel = Label(moduleInfoFrame,
                                        wraplength=600,
                                        justify="left")
        self.moduleLicenseLabel.grid(row=7, column=1, columnspan=3, sticky=W)
        self.moduleImportsHdr = Label(moduleInfoFrame,
                                      text=_("imports:"),
                                      state=DISABLED)
        self.moduleImportsHdr.grid(row=8, column=0, sticky=W)
        self.moduleImportsLabel = Label(moduleInfoFrame,
                                        wraplength=600,
                                        justify="left")
        self.moduleImportsLabel.grid(row=8, column=1, columnspan=3, sticky=W)
        self.moduleEnableButton = Button(moduleInfoFrame,
                                         text=self.ENABLE,
                                         state=DISABLED,
                                         command=self.moduleEnable)
        ToolTip(self.moduleEnableButton,
                text=_("Enable/disable plug in."),
                wraplength=240)
        self.moduleEnableButton.grid(row=9, column=1, sticky=E)
        self.moduleReloadButton = Button(moduleInfoFrame,
                                         text=_("Reload"),
                                         state=DISABLED,
                                         command=self.moduleReload)
        ToolTip(self.moduleReloadButton,
                text=_("Reload/update plug in."),
                wraplength=240)
        self.moduleReloadButton.grid(row=9, column=2, sticky=E)
        self.moduleRemoveButton = Button(moduleInfoFrame,
                                         text=_("Remove"),
                                         state=DISABLED,
                                         command=self.moduleRemove)
        ToolTip(
            self.moduleRemoveButton,
            text=
            _("Remove plug in from plug in table (does not erase the plug in's file)."
              ),
            wraplength=240)
        self.moduleRemoveButton.grid(row=9, column=3, sticky=E)
        moduleInfoFrame.grid(row=2,
                             column=0,
                             columnspan=5,
                             sticky=(N, S, E, W),
                             padx=3,
                             pady=3)
        moduleInfoFrame.config(borderwidth=4, relief="groove")

        okButton = Button(frame, text=_("Close"), command=self.ok)
        ToolTip(okButton,
                text=_("Accept and changes (if any) and close dialog."),
                wraplength=240)
        cancelButton = Button(frame, text=_("Cancel"), command=self.close)
        ToolTip(cancelButton,
                text=_("Cancel changes (if any) and close dialog."),
                wraplength=240)
        okButton.grid(row=3, column=3, sticky=(S, E), pady=3)
        cancelButton.grid(row=3, column=4, sticky=(S, E), pady=3, padx=3)

        enableDisableFrame = Frame(frame)
        enableDisableFrame.grid(row=3, column=1, sticky=(S, W), pady=3)
        enableAllButton = Button(enableDisableFrame,
                                 text=_("Enable All"),
                                 command=self.enableAll)
        ToolTip(enableAllButton,
                text=_("Enable all plug ins."),
                wraplength=240)
        disableAllButton = Button(enableDisableFrame,
                                  text=_("Disable All"),
                                  command=self.disableAll)
        ToolTip(disableAllButton,
                text=_("Disable all plug ins."),
                wraplength=240)
        enableAllButton.grid(row=1, column=1)
        disableAllButton.grid(row=1, column=2)

        self.loadTreeViews()

        self.geometry("+{0}+{1}".format(dialogX + 50, dialogY + 100))
        frame.grid(row=0, column=0, sticky=(N, S, E, W))
        frame.columnconfigure(0, weight=0)
        frame.columnconfigure(1, weight=1)
        frame.rowconfigure(0, weight=1)
        window = self.winfo_toplevel()
        window.columnconfigure(0, weight=1)
        window.rowconfigure(0, weight=1)

        self.bind("<Return>", self.ok)
        self.bind("<Escape>", self.close)

        self.protocol("WM_DELETE_WINDOW", self.close)
        self.grab_set()
        self.wait_window(self)

    def loadTreeViews(self):
        self.selectedModule = None

        # clear previous treeview entries
        for previousNode in self.modulesView.get_children(""):
            self.modulesView.delete(previousNode)

        def loadSubtree(parentNode, moduleItems):
            for moduleItem in sorted(moduleItems, key=lambda item: item[0]):
                moduleInfo = moduleItem[1]
                if parentNode or not moduleInfo.get("isImported"):
                    nodeName = moduleItem[0]
                    if parentNode:
                        nodeName = parentNode + GROUPSEP + nodeName
                    name = moduleInfo.get("name", nodeName)
                    node = self.modulesView.insert(parentNode,
                                                   "end",
                                                   nodeName,
                                                   text=name)
                    self.modulesView.set(node, "author",
                                         moduleInfo.get("author"))
                    self.modulesView.set(node, "ver",
                                         moduleInfo.get("version"))
                    self.modulesView.set(node, "status",
                                         moduleInfo.get("status"))
                    self.modulesView.set(node, "date",
                                         moduleInfo.get("fileDate"))
                    if name in self.modulesWithNewerFileDates:
                        self.modulesView.set(node, "update", _("available"))
                    self.modulesView.set(node, "descr",
                                         moduleInfo.get("description"))
                    self.modulesView.set(node, "license",
                                         moduleInfo.get("license"))
                    if moduleInfo.get("imports"):
                        loadSubtree(
                            node,
                            [(importModuleInfo["name"], importModuleInfo)
                             for importModuleInfo in moduleInfo["imports"]])

        loadSubtree("", self.pluginConfig.get("modules", {}).items())

        # clear previous treeview entries
        for previousNode in self.classesView.get_children(""):
            self.classesView.delete(previousNode)

        for i, classItem in enumerate(
                sorted(self.pluginConfig.get("classes", {}).items())):
            className, moduleList = classItem
            node = self.classesView.insert("",
                                           "end",
                                           className,
                                           text=className)
            self.classesView.set(node, "modules", ', '.join(moduleList))

        self.moduleSelect()  # clear out prior selection

    def ok(self, event=None):
        # check for orphaned classes (for which there is no longer a corresponding module)
        _moduleNames = self.pluginConfig.get("modules", {}).keys()
        _orphanedClassNames = set()
        for className, moduleList in self.pluginConfig.get("classes",
                                                           {}).items():
            for _moduleName in moduleList.copy():
                if _moduleName not in _moduleNames:  # it's orphaned
                    moduleList.remove(_moduleName)
                    self.pluginConfigChanged = True
            if not moduleList:  # now orphaned
                _orphanedClassNames.add(className)
                self.pluginConfigChanged = True
        for _orphanedClassName in _orphanedClassNames:
            del self.pluginConfig["classes"][_orphanedClassName]

        if self.pluginConfigChanged:
            PluginManager.pluginConfig = self.pluginConfig
            PluginManager.pluginConfigChanged = True
            PluginManager.reset()  # force reloading of modules
        if self.uiClassMethodsChanged or self.modelClassesChanged or self.customTransformsChanged or self.disclosureSystemTypesChanged or self.hostSystemFeaturesChanged:  # may require reloading UI
            affectedItems = ""
            if self.uiClassMethodsChanged:
                affectedItems += _("menus of the user interface")
            if self.modelClassesChanged:
                if affectedItems:
                    affectedItems += _(" and ")
                affectedItems += _("model objects of the processor")
            if self.customTransformsChanged:
                if affectedItems:
                    affectedItems += _(" and ")
                affectedItems += _("custom transforms")
            if self.disclosureSystemTypesChanged:
                if affectedItems:
                    affectedItems += _(" and ")
                affectedItems += _("disclosure system types")
            if self.hostSystemFeaturesChanged:
                if affectedItems:
                    affectedItems += _(" and ")
                affectedItems += _("host system features")
            if messagebox.askyesno(
                    _("User interface plug-in change"),
                    _("A change in plug-in class methods may have affected {0}.  "
                      "Please restart Arelle to due to these changes.  \n\n"
                      "Should Arelle restart itself now "
                      "(if there are any unsaved changes they would be lost!)?"
                      ).format(affectedItems),
                    parent=self):
                self.cntlr.uiThreadQueue.put((self.cntlr.quit, [None, True]))
        self.close()

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

    def moduleSelect(self, *args):
        node = (self.modulesView.selection() or (None, ))[0]
        if node:
            node = node.rpartition(GROUPSEP)[
                2]  # drop leading path names for module name
        moduleInfo = self.pluginConfig.get("modules", {}).get(node)
        if moduleInfo:
            self.selectedModule = node
            name = moduleInfo["name"]
            self.moduleNameLabel.config(text=name)
            self.moduleAuthorHdr.config(state=ACTIVE)
            self.moduleAuthorLabel.config(text=moduleInfo.get("author"))
            self.moduleDescrHdr.config(state=ACTIVE)
            self.moduleDescrLabel.config(text=moduleInfo.get("description"))
            self.moduleClassesHdr.config(state=ACTIVE)
            self.moduleClassesLabel.config(
                text=', '.join(moduleInfo["classMethods"]))
            self.moduleVersionHdr.config(state=ACTIVE)
            self.moduleVersionLabel.config(text=moduleInfo.get("version"))
            self.moduleUrlHdr.config(state=ACTIVE)
            self.moduleUrlLabel.config(text=moduleInfo["moduleURL"])
            self.moduleDateHdr.config(state=ACTIVE)
            self.moduleDateLabel.config(
                text=moduleInfo["fileDate"] + " " +
                (_("(an update is available)") if name in
                 self.modulesWithNewerFileDates else ""))
            self.moduleLicenseHdr.config(state=ACTIVE)
            self.moduleLicenseLabel.config(text=moduleInfo.get("license"))
            if moduleInfo.get("imports"):
                self.moduleImportsHdr.config(state=ACTIVE)
                _text = ", ".join(mi["name"]
                                  for mi in moduleInfo["imports"][:3])
                if len(moduleInfo["imports"]) >= 3:
                    _text += ", ..."
                self.moduleImportsLabel.config(text=_text)
            _buttonState = DISABLED if moduleInfo.get("isImported") else ACTIVE
            self.moduleEnableButton.config(state=_buttonState,
                                           text={
                                               "enabled": self.DISABLE,
                                               "disabled": self.ENABLE
                                           }[moduleInfo["status"]])
            self.moduleReloadButton.config(state=_buttonState)
            self.moduleRemoveButton.config(state=_buttonState)
        else:
            self.selectedModule = None
            self.moduleNameLabel.config(text="")
            self.moduleAuthorHdr.config(state=DISABLED)
            self.moduleAuthorLabel.config(text="")
            self.moduleDescrHdr.config(state=DISABLED)
            self.moduleDescrLabel.config(text="")
            self.moduleClassesHdr.config(state=DISABLED)
            self.moduleClassesLabel.config(text="")
            self.moduleVersionHdr.config(state=DISABLED)
            self.moduleVersionLabel.config(text="")
            self.moduleUrlHdr.config(state=DISABLED)
            self.moduleUrlLabel.config(text="")
            self.moduleDateHdr.config(state=DISABLED)
            self.moduleDateLabel.config(text="")
            self.moduleLicenseHdr.config(state=DISABLED)
            self.moduleLicenseLabel.config(text="")
            self.moduleImportsHdr.config(state=DISABLED)
            self.moduleImportsLabel.config(text="")
            self.moduleEnableButton.config(state=DISABLED, text=self.ENABLE)
            self.moduleReloadButton.config(state=DISABLED)
            self.moduleRemoveButton.config(state=DISABLED)

    def selectLocally(self):
        choices = []  # list of tuple of (file name, description)

        def sortOrder(key):
            return {
                "EdgarRenderer": "1",
                "validate": "2",
                "xbrlDB": "3"
            }.get(key, "4") + key.lower()

        def selectChoices(dir, indent=""):
            dirHasEntries = False
            for f in sorted(os.listdir(dir), key=sortOrder):
                if f not in (".", "..", "__pycache__", "__init__.py"):
                    fPath = os.path.join(dir, f)
                    fPkgInit = os.path.join(fPath, "__init__.py")
                    dirInsertPoint = len(choices)
                    moduleInfo = None
                    if ((os.path.isdir(fPath) and os.path.exists(fPkgInit)) or
                        ((os.path.isfile(fPath) and f.endswith(".py")))):
                        moduleInfo = PluginManager.moduleModuleInfo(fPath)
                        if moduleInfo:
                            choices.append((
                                indent + f,
                                "name: {}\ndescription: {}\nversion: {}\nlicense: {}"
                                .format(moduleInfo["name"],
                                        moduleInfo.get("description"),
                                        moduleInfo.get("version"),
                                        moduleInfo.get("license")), fPath,
                                moduleInfo["name"], moduleInfo.get("version"),
                                moduleInfo.get("description"),
                                moduleInfo.get("license")))
                            dirHasEntries = True
                    if os.path.isdir(fPath) and f not in ("DQC_US_Rules", ):
                        if selectChoices(fPath, indent=indent +
                                         "   ") and not moduleInfo:
                            choices.insert(dirInsertPoint,
                                           (indent + f, None, None, None, None,
                                            None, None))
            return dirHasEntries

        selectChoices(self.cntlr.pluginDir)
        selectedPath = DialogOpenArchive.selectPlugin(self, choices)
        if selectedPath:
            moduleInfo = PluginManager.moduleModuleInfo(
                selectedPath[len(self.cntlr.pluginDir) + 1:])
            self.loadFoundModuleInfo(moduleInfo, selectedPath)

    def browseLocally(self):
        initialdir = self.cntlr.pluginDir  # default plugin directory
        if not self.cntlr.isMac:  # can't navigate within app easily, always start in default directory
            initialdir = self.cntlr.config.setdefault("pluginOpenDir",
                                                      initialdir)
        filename = self.cntlr.uiFileDialog(
            "open",
            parent=self,
            title=_("Choose plug-in module file"),
            initialdir=initialdir,
            filetypes=[(_("Python files"), "*.py")],
            defaultextension=".py")
        if filename:
            # check if a package is selected (any file in a directory containing an __init__.py
            #if (os.path.basename(filename) == "__init__.py" and os.path.isdir(os.path.dirname(filename)) and
            #    os.path.isfile(filename)):
            #    filename = os.path.dirname(filename) # refer to the package instead
            self.cntlr.config["pluginOpenDir"] = os.path.dirname(filename)
            moduleInfo = PluginManager.moduleModuleInfo(filename)
            self.loadFoundModuleInfo(moduleInfo, filename)

    def findOnWeb(self):
        url = DialogURL.askURL(self)
        if url:  # url is the in-cache or local file
            moduleInfo = PluginManager.moduleModuleInfo(url)
            self.cntlr.showStatus("")  # clear web loading status
            self.loadFoundModuleInfo(moduleInfo, url)

    def loadFoundModuleInfo(self, moduleInfo, url):
        if moduleInfo and moduleInfo.get("name"):
            self.addPluginConfigModuleInfo(moduleInfo)
            self.loadTreeViews()
        else:
            messagebox.showwarning(
                _("Module is not itself a plug-in or in a directory with package __init__.py plug-in.  "
                  ),
                _("File does not itself contain a python program with an appropriate __pluginInfo__ declaration: \n\n{0}"
                  ).format(url),
                parent=self)

    def checkIfImported(self, moduleInfo):
        if moduleInfo.get("isImported"):
            messagebox.showwarning(
                _("Plug-in is imported by a parent plug-in.  "),
                _("Plug-in has a parent, please request operation on the parent: \n\n{0}"
                  ).format(moduleInfo.get("name")),
                parent=self)
            return True
        return False

    def checkClassMethodsChanged(self, moduleInfo):
        for classMethod in moduleInfo["classMethods"]:
            if classMethod.startswith("CntlrWinMain.Menu"):
                self.uiClassMethodsChanged = True  # may require reloading UI
            elif classMethod == "ModelObjectFactory.ElementSubstitutionClasses":
                self.modelClassesChanged = True  # model object factor classes changed
            elif classMethod == "ModelManager.LoadCustomTransforms":
                self.customTransformsChanged = True
            elif classMethod == "DisclosureSystem.Types":
                self.disclosureSystemTypesChanged = True  # disclosure system types changed
            elif classMethod.startswith("Proxy."):
                self.hostSystemFeaturesChanged = True  # system features (e.g., proxy) changed

    def removePluginConfigModuleInfo(self, name):
        moduleInfo = self.pluginConfig["modules"].get(name)
        if moduleInfo:
            if self.checkIfImported(moduleInfo):
                return

            def _removePluginConfigModuleInfo(moduleInfo):
                _name = moduleInfo.get("name")
                if _name:
                    self.checkClassMethodsChanged(moduleInfo)
                    for classMethod in moduleInfo["classMethods"]:
                        classMethods = self.pluginConfig["classes"].get(
                            classMethod)
                        if classMethods and _name in classMethods:
                            classMethods.remove(_name)
                            if not classMethods:  # list has become unused
                                del self.pluginConfig["classes"][
                                    classMethod]  # remove class
                    for importModuleInfo in moduleInfo.get(
                            "imports", EMPTYLIST):
                        _removePluginConfigModuleInfo(importModuleInfo)
                    self.pluginConfig["modules"].pop(_name, None)

            _removePluginConfigModuleInfo(moduleInfo)
            if not self.pluginConfig["modules"] and self.pluginConfig[
                    "classes"]:
                self.pluginConfig["classes"].clear()  # clean orphan classes
            self.pluginConfigChanged = True

    def addPluginConfigModuleInfo(self, moduleInfo):
        if self.checkIfImported(moduleInfo):
            return
        name = moduleInfo.get("name")
        self.removePluginConfigModuleInfo(
            name)  # remove any prior entry for this module

        def _addPlugin(moduleInfo):
            _name = moduleInfo.get("name")
            if _name:
                self.modulesWithNewerFileDates.discard(
                    _name)  # no longer has an update available
                self.pluginConfig["modules"][_name] = moduleInfo
                # add classes
                for classMethod in moduleInfo["classMethods"]:
                    classMethods = self.pluginConfig["classes"].setdefault(
                        classMethod, [])
                    if name not in classMethods:
                        classMethods.append(_name)
                self.checkClassMethodsChanged(moduleInfo)
            for importModuleInfo in moduleInfo.get("imports", EMPTYLIST):
                _addPlugin(importModuleInfo)

        _addPlugin(moduleInfo)
        self.pluginConfigChanged = True

    def moduleEnable(self):
        if self.selectedModule in self.pluginConfig["modules"]:
            moduleInfo = self.pluginConfig["modules"][self.selectedModule]
            if self.checkIfImported(moduleInfo):
                return

            def _moduleEnable(moduleInfo):
                if self.moduleEnableButton['text'] == self.ENABLE:
                    moduleInfo["status"] = "enabled"
                elif self.moduleEnableButton['text'] == self.DISABLE:
                    moduleInfo["status"] = "disabled"
                self.checkClassMethodsChanged(moduleInfo)
                for importModuleInfo in moduleInfo.get("imports", EMPTYLIST):
                    _moduleEnable(
                        importModuleInfo)  # set status on nested moduleInfo
                    if importModuleInfo['name'] in self.pluginConfig[
                            "modules"]:  # set status on top level moduleInfo
                        _moduleEnable(self.pluginConfig["modules"][
                            importModuleInfo['name']])

            _moduleEnable(moduleInfo)
            if self.moduleEnableButton['text'] == self.ENABLE:
                self.moduleEnableButton['text'] = self.DISABLE
            elif self.moduleEnableButton['text'] == self.DISABLE:
                self.moduleEnableButton['text'] = self.ENABLE
            self.pluginConfigChanged = True
            self.loadTreeViews()

    def moduleReload(self):
        if self.selectedModule in self.pluginConfig["modules"]:
            url = self.pluginConfig["modules"][self.selectedModule].get(
                "moduleURL")
            if url:
                moduleInfo = PluginManager.moduleModuleInfo(url, reload=True)
                if moduleInfo:
                    if self.checkIfImported(moduleInfo):
                        return
                    self.addPluginConfigModuleInfo(moduleInfo)
                    self.loadTreeViews()
                    self.cntlr.showStatus(_("{0} reloaded").format(
                        moduleInfo["name"]),
                                          clearAfter=5000)
                else:
                    messagebox.showwarning(
                        _("Module error"),
                        _("File or module cannot be reloaded: \n\n{0}").format(
                            url),
                        parent=self)

    def moduleRemove(self):
        if self.selectedModule in self.pluginConfig["modules"]:
            self.removePluginConfigModuleInfo(self.selectedModule)
            self.pluginConfigChanged = True
            self.loadTreeViews()

    def enableAll(self):
        self.enableDisableAll(True)

    def disableAll(self):
        self.enableDisableAll(False)

    def enableDisableAll(self, doEnable):
        for module in self.pluginConfig["modules"]:
            moduleInfo = self.pluginConfig["modules"][module]
            if not moduleInfo.get("isImported"):

                def _enableDisableAll(moduleInfo):
                    if doEnable:
                        moduleInfo["status"] = "enabled"
                    else:
                        moduleInfo["status"] = "disabled"
                    for importModuleInfo in moduleInfo.get(
                            "imports", EMPTYLIST):
                        _enableDisableAll(importModuleInfo)

                _enableDisableAll(moduleInfo)
                if doEnable:
                    self.moduleEnableButton['text'] = self.DISABLE
                else:
                    self.moduleEnableButton['text'] = self.ENABLE
        self.pluginConfigChanged = True
        self.loadTreeViews()
class TtkScale(Scale):
    def __init__(self,
                 parent,
                 length=0,
                 from_=0,
                 to=255,
                 orient='horizontal',
                 variable=0,
                 digits=0,
                 tickinterval=None,
                 sliderlength=32,
                 command=None,
                 style=None,
                 showvalue=True,
                 resolution=1):

        self.from_ = from_
        self.to = to
        self.variable = variable
        self.length = length
        self.command = command
        self.parent = parent
        self.orient = orient

        super().__init__(parent,
                         length=length,
                         from_=from_,
                         to=to,
                         orient=orient,
                         variable=variable,
                         command=command,
                         style=style)

        self.digits = digits
        self.tickinterval = tickinterval
        self.showvalue = showvalue
        self.resolution = resolution
        self.sliderlength = sliderlength  # = 32

        theme_sl = {
            'alt': 9,
            'clam': 30,
            'classic': 30,
            'default': 30,
            'lime': 9,
            'winnative': 9
        }

        theme_bw = {
            'alt': 0,
            'clam': 1,
            'classic': 2,
            'default': 1,
            'lime': 6,
            'winnative': 0
        }

        # set trough borderwidth
        st = Style(self)
        theme_used = st.theme_use()
        if theme_used in ('alt', 'clam', 'classic', 'default', 'lime',
                          'winnative'):
            self.bw_val = bw_val = theme_bw[theme_used]
            self.sliderlength = sliderlength = theme_sl[theme_used]
        else:
            self.bw_val = bw_val = 1
        if showvalue:
            self.configure(command=self.display_value)

        def_font = font.nametofont('TkDefaultFont')
        # if from_ more than to swap values
        if from_ < to:
            pass
        else:
            from_, to = to, from_

        data = np.arange(from_,
                         (to + 1 if tickinterval >= 1 else to + tickinterval),
                         tickinterval)
        self.data = data = np.round(data, 1)
        range_vals = tuple(data)
        len_rvs = len(range_vals)
        if self.orient == 'horizontal':
            vals_size = [def_font.measure(str(i)) for i in range_vals]
            data_size = sum(vals_size)
            space_size = len_rvs * def_font.measure('0')
        else:
            lspace = def_font.metrics('linespace')
            data_size = len_rvs * lspace
            space_size = len_rvs * 3
        sizes = data_size + space_size
        min_len = (sizes if sizes % 50 == 0 else sizes + 50 - sizes % 50)
        self.len_val = len_val = min_len if length < min_len else length
        self.configure(length=len_val)

        self.rel_min = rel_min = (sliderlength // 2 + bw_val) / len_val
        self.rel_max = rel_max = 1 - (sliderlength // 2 + bw_val) / len_val

        if range_vals[-1] == to:
            pass
        else:
            max_rv = range_vals[-1]
            self.mult_l = ((max_rv - from_) * rel_max / (to - from_))

        self.bind("<Button-1>", self.resolve)

        self.build(from_, to, rel_min, rel_max, range_vals, len_rvs)

    def build(self, from_, to, rel_min, rel_max, range_vals, len_rvs):
        if self.orient == 'horizontal':
            for i, rv in enumerate(range_vals):
                item = Label(self.parent, text=rv)
                item.place(
                    in_=self,
                    bordermode='outside',
                    relx=(rel_min + i / (len_rvs - 1) *
                          ((rel_max if range_vals[-1] == to else self.mult_l) -
                           rel_min)),
                    rely=1,
                    anchor='n')
        else:
            for i, rv in enumerate(range_vals):
                item = Label(self.parent, text=rv)
                item.place(
                    in_=self,
                    bordermode='outside',
                    rely=(rel_min + i / (len_rvs - 1) *
                          ((rel_max if range_vals[-1] == to else self.mult_l) -
                           rel_min)),
                    relx=1,
                    anchor='w')

        if self.showvalue:
            self.disp_lab = Label(self.parent, text=self.get())
            rel_l = self.convert_to_rel(float(self.get()))
            if self.orient == 'horizontal':
                self.disp_lab.place(in_=self,
                                    bordermode='outside',
                                    relx=rel_l,
                                    rely=0,
                                    anchor='s')
            else:
                self.disp_lab.place(in_=self,
                                    bordermode='outside',
                                    rely=rel_l,
                                    relx=0,
                                    anchor='e')

    def convert_to_rel(self, curr_val):
        return ((curr_val - self.from_) * (self.rel_max - self.rel_min) /
                (self.to - self.from_) + self.rel_min)

    def convert_to_act(self, curr_val):
        l_max = self.rel_max * self.len_val
        l_min = self.rel_min * self.len_val
        return ((curr_val - self.from_) * (l_max - l_min) /
                (self.to - self.from_) + l_min)

    def display_value(self, value):
        # position (in pixel) of the center of the slider
        rel_l = self.convert_to_rel(float(value))
        self.disp_lab.config(text=value)  # text=""
        if self.orient == 'horizontal':
            self.disp_lab.place_configure(relx=rel_l)
        else:
            self.disp_lab.place_configure(rely=rel_l)
        digits = self.digits
        self.disp_lab.configure(text=f'{float(value):.{digits}f}')
        # if your python is not 3.6 or above use the following 2 lines
        #   instead of the line above
        #my_precision = '{:.{}f}'.format
        #self.disp_lab.configure(text=my_precision(float(value), digits))

    def resolve(self, evt):
        resolution = self.resolution
        if resolution < 1 or self.tickinterval < 1:
            pass
        else:
            value = self.get()
            curr_l = self.convert_to_act(value)
            if self.orient == 'horizontal':
                if evt.x < curr_l - self.sliderlength / 2:
                    self.set(value - resolution + 1)
                elif evt.x > curr_l + self.sliderlength / 2:
                    self.set(value + resolution - 1)
            else:
                if evt.y < curr_l - self.sliderlength / 2:
                    self.set(value - resolution + 1)
                elif evt.y > curr_l + self.sliderlength / 2:
                    self.set(value + resolution - 1)
Exemple #32
0
class MatsFrame(Frame):
    """
    The frame that interacts with the test sequence in order to display the \
    test results as the test is executing.

    :param parent: the tk parent frame
    :param sequence: the instance of `TestSequence` to monitor
    :param vertical: if `True`, will stack tests vertically; \
    otherwise, horizontally
    :param start_btn: if `True`, will populate a start button; \
    otherwise, will not
    :param loglevel: the logging level, for instance 'logging.INFO'
    """
    def __init__(self,
                 parent,
                 sequence: TestSequence,
                 vertical=False,
                 start_btn=True,
                 loglevel=logging.INFO):
        self._logger = logging.getLogger(self.__class__.__name__)
        self._logger.setLevel(loglevel)

        self._parent = parent
        super().__init__(self._parent)

        self._sequence = sequence

        arrow = '\u2b9e' if not vertical else '\u2b9f'

        row = 0
        col = 0

        if start_btn:
            Button(self, text='Start', command=sequence.start)\
                .grid(row=row, column=col, sticky='news')

        if not vertical:
            col += 1 if not vertical else 0
            row += 1 if vertical else 0
            Label(self, text=arrow, justify='center', anchor='center')\
                .grid(row=row, column=col, sticky='news')

        col += 1 if not vertical else 0
        row += 1 if vertical else 0

        self._test_status_frames = []
        for test in self._sequence.tests:
            self._test_status_frames.append(
                _TestLabel(self, test, vertical=vertical))

        for i, tl in enumerate(self._test_status_frames):
            col += 1 if not vertical else 0
            row += 1 if vertical else 0

            tl.grid(row=row, column=col, sticky='news')

            if not vertical:
                col += 1 if not vertical else 0
                row += 1 if vertical else 0

                Label(self, text=arrow, justify='center', anchor='center')\
                    .grid(row=row, column=col, sticky='news')

        col += 1 if not vertical else 0
        row += 1 if vertical else 0

        self._complete_label = Label(self,
                                     text='-',
                                     anchor='center',
                                     justify='center')
        self._complete_label.grid(row=row, column=col, sticky='news')
        self._complete_label.config(relief=_relief, padding=_label_padding)

        self._update()

    def _update(self):
        if self._sequence.in_progress:
            self._complete_label.config(text='in progress',
                                        background=_light_yellow)
        elif self._sequence.is_aborted:
            self._complete_label.config(text='aborted', background=_light_red)
        elif self._sequence.is_passing:
            self._complete_label.config(text='pass', background=_light_green)
        else:
            self._complete_label.config(text='fail', background=_light_red)

        self.after(100, self._update)
Exemple #33
0
class Report(Frame):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.root = self.winfo_toplevel()
        self.root.title(" ".join((APPNAME, VERSION, "| Report")))
        self.root.resizable(0, 0)
        self.items = None
        headers = ('Page', 'Rank', 'PageRank Value', 'Incoming')
        self.t = Scale(self,
                       from_=0,
                       to=1,
                       label='n-th iteration',
                       bd=1,
                       width=7,
                       orient='horizontal',
                       command=self.__set_t)
        self.t.pack(fill='x')
        self.label = Label(self, anchor='e')
        self.label.pack(fill='x')
        self.tree = Treeview(self,
                             columns=headers,
                             show="headings",
                             height=REPORT_HEIGHT)
        self.tree.column(0, anchor='center', width=55)
        self.tree.column(1, anchor='center', width=55)
        self.tree.column(2, width=175)
        self.tree.column(3, anchor='center', width=55)
        self.scroll = Scrollbar(self, command=self.tree.yview)
        self.scroll.pack(side='right', fill='y')
        self.tree.config(yscrollcommand=self.scroll.set)
        for col in headers:
            self.tree.heading(col, text=col.title())
        self.root.master.focus_force()
        self.root.bind('<Key>', self.__keys)

    def __keys(self, event):
        if event.char == 'i':
            self.t.set(self.t.get() - 1)
        elif event.char == 'I':
            self.t.set(0)
        elif event.char == 'o':
            self.t.set(self.t.get() + 1)
        elif event.char == 'O':
            self.t.set(self.pagerank[1])

    def __set_t(self, t=None):
        self.render(self.pagerank, self.edge_counts, self.d, self.e, t=int(t))

    def render(self, pagerank, edge_counts, d, e, t=None):
        self.d, self.e = d, e
        self.edge_counts = edge_counts
        self.pagerank = pagerank
        if t is not None:
            pr = pagerank[0][t]
        else:
            self.t.config(command=None)
            self.t.config(to=self.pagerank[1])
            self.t.set(self.pagerank[1])
            self.t.config(command=self.__set_t)
            pr = pagerank[0][-1]
        label_text = '# of ranks:{0:>3}     # of iterations:{1:>3}'.format(
            len(set(pr.values())), self.pagerank[1])
        self.label.config(text=label_text)
        in_map = {k: 0 for k in pr.keys()}  # incoming edges by nodes
        for (tail, head), n in edge_counts.items():
            if tail is not head:
                in_map[head] += n

        get_rank = lambda k: sorted(pr.values())[::-1].index(pr[k]) + 1
        data = tuple(
            (k, get_rank(k), pr[k], in_map[k]) for k in sorted(pr.keys()))
        if self.items: self.tree.delete(*self.items)
        self.items = [
            self.tree.insert('', 'end', values=line) for line in data
        ]
        self.tree.pack(side='left', fill='y')
        #self.root.master.focus_force()

    def destroy(self):
        super().destroy()
        self.root.master.r_win = False
        self.root.master.windowsmenu.entryconfig(0, label='[ ] Report window')
        self.root.destroy()
class DialogPackageManager(Toplevel):
    def __init__(self, mainWin, packageNamesWithNewerFileDates):
        super(DialogPackageManager, self).__init__(mainWin.parent)
        
        self.ENABLE = _("Enable")
        self.DISABLE = _("Disable")
        self.parent = mainWin.parent
        self.cntlr = mainWin
        
        # copy plugins for temporary display
        self.packagesConfig = PackageManager.packagesConfig
        self.packagesConfigChanged = False
        self.packageNamesWithNewerFileDates = packageNamesWithNewerFileDates
        
        parentGeometry = re.match("(\d+)x(\d+)[+]?([-]?\d+)[+]?([-]?\d+)", self.parent.geometry())
        dialogX = int(parentGeometry.group(3))
        dialogY = int(parentGeometry.group(4))

        self.title(_("Taxonomy Packages Manager"))
        frame = Frame(self)
        
        # left button frame
        buttonFrame = Frame(frame, width=40)
        buttonFrame.columnconfigure(0, weight=1)
        addLabel = Label(buttonFrame, text=_("Find taxonomy packages:"), wraplength=64, justify="center")
        addLocalButton = Button(buttonFrame, text=_("Locally"), command=self.findLocally)
        ToolTip(addLocalButton, text=_("File chooser allows selecting taxonomy packages to add (or reload), from the local file system.  "
                                       "Select either a taxonomy package zip file, or a taxonomy manifest (.taxonomyPackage.xml) within an unzipped taxonomy package.  "), wraplength=240)
        addWebButton = Button(buttonFrame, text=_("On Web"), command=self.findOnWeb)
        ToolTip(addWebButton, text=_("Dialog to enter URL full path to load (or reload) package, from the web or local file system.  "
                                     "URL may be either a taxonomy package zip file, or a taxonomy manifest (.taxonomyPackage.xml) within an unzipped taxonomy package.  "), wraplength=240)
        manifestNameButton = Button(buttonFrame, text=_("Manifest"), command=self.manifestName)
        ToolTip(manifestNameButton, text=_("Provide non-standard archive manifest file name pattern (e.g., *taxonomyPackage.xml).  "
                                           "Uses unix file name pattern matching.  "
                                           "Multiple manifest files are supported in archive (such as oasis catalogs).  "
                                           "(Replaces search for either .taxonomyPackage.xml or catalog.xml).  "), wraplength=240)
        self.manifestNamePattern = ""
        addLabel.grid(row=0, column=0, pady=4)
        addLocalButton.grid(row=1, column=0, pady=4)
        addWebButton.grid(row=2, column=0, pady=4)
        manifestNameButton.grid(row=3, column=0, pady=4)
        buttonFrame.grid(row=0, column=0, rowspan=3, sticky=(N, S, W), padx=3, pady=3)
        
        # right tree frame (packages already known to arelle)
        packagesFrame = Frame(frame, width=700)
        vScrollbar = Scrollbar(packagesFrame, orient=VERTICAL)
        hScrollbar = Scrollbar(packagesFrame, orient=HORIZONTAL)
        self.packagesView = Treeview(packagesFrame, xscrollcommand=hScrollbar.set, yscrollcommand=vScrollbar.set, height=7)
        self.packagesView.grid(row=0, column=0, sticky=(N, S, E, W))
        self.packagesView.bind('<<TreeviewSelect>>', self.packageSelect)
        hScrollbar["command"] = self.packagesView.xview
        hScrollbar.grid(row=1, column=0, sticky=(E,W))
        vScrollbar["command"] = self.packagesView.yview
        vScrollbar.grid(row=0, column=1, sticky=(N,S))
        packagesFrame.columnconfigure(0, weight=1)
        packagesFrame.rowconfigure(0, weight=1)
        packagesFrame.grid(row=0, column=1, columnspan=4, sticky=(N, S, E, W), padx=3, pady=3)
        self.packagesView.focus_set()

        self.packagesView.column("#0", width=120, anchor="w")
        self.packagesView.heading("#0", text=_("Name"))
        self.packagesView["columns"] = ("ver", "status", "date", "update", "descr")
        self.packagesView.column("ver", width=150, anchor="w", stretch=False)
        self.packagesView.heading("ver", text=_("Version"))
        self.packagesView.column("status", width=50, anchor="w", stretch=False)
        self.packagesView.heading("status", text=_("Status"))
        self.packagesView.column("date", width=170, anchor="w", stretch=False)
        self.packagesView.heading("date", text=_("File Date"))
        self.packagesView.column("update", width=50, anchor="w", stretch=False)
        self.packagesView.heading("update", text=_("Update"))
        self.packagesView.column("descr", width=200, anchor="w", stretch=False)
        self.packagesView.heading("descr", text=_("Description"))

        remappingsFrame = Frame(frame)
        vScrollbar = Scrollbar(remappingsFrame, orient=VERTICAL)
        hScrollbar = Scrollbar(remappingsFrame, orient=HORIZONTAL)
        self.remappingsView = Treeview(remappingsFrame, xscrollcommand=hScrollbar.set, yscrollcommand=vScrollbar.set, height=5)
        self.remappingsView.grid(row=0, column=0, sticky=(N, S, E, W))
        hScrollbar["command"] = self.remappingsView.xview
        hScrollbar.grid(row=1, column=0, sticky=(E,W))
        vScrollbar["command"] = self.remappingsView.yview
        vScrollbar.grid(row=0, column=1, sticky=(N,S))
        remappingsFrame.columnconfigure(0, weight=1)
        remappingsFrame.rowconfigure(0, weight=1)
        remappingsFrame.grid(row=1, column=1, columnspan=4, sticky=(N, S, E, W), padx=3, pady=3)
        self.remappingsView.focus_set()
        
        self.remappingsView.column("#0", width=200, anchor="w")
        self.remappingsView.heading("#0", text=_("Prefix"))
        self.remappingsView["columns"] = ("remapping")
        self.remappingsView.column("remapping", width=500, anchor="w", stretch=False)
        self.remappingsView.heading("remapping", text=_("Remapping"))
        
        # bottom frame package info details
        packageInfoFrame = Frame(frame, width=700)
        packageInfoFrame.columnconfigure(1, weight=1)
        
        self.packageNameLabel = Label(packageInfoFrame, wraplength=600, justify="left", 
                                      font=font.Font(family='Helvetica', size=12, weight='bold'))
        self.packageNameLabel.grid(row=0, column=0, columnspan=6, sticky=W)
        self.packageVersionHdr = Label(packageInfoFrame, text=_("version:"), state=DISABLED)
        self.packageVersionHdr.grid(row=1, column=0, sticky=W)
        self.packageVersionLabel = Label(packageInfoFrame, wraplength=600, justify="left")
        self.packageVersionLabel.grid(row=1, column=1, columnspan=5, sticky=W)
        self.packageDescrHdr = Label(packageInfoFrame, text=_("description:"), state=DISABLED)
        self.packageDescrHdr.grid(row=2, column=0, sticky=W)
        self.packageDescrLabel = Label(packageInfoFrame, wraplength=600, justify="left")
        self.packageDescrLabel.grid(row=2, column=1, columnspan=5, sticky=W)
        self.packagePrefixesHdr = Label(packageInfoFrame, text=_("prefixes:"), state=DISABLED)
        self.packagePrefixesHdr.grid(row=3, column=0, sticky=W)
        self.packagePrefixesLabel = Label(packageInfoFrame, wraplength=600, justify="left")
        self.packagePrefixesLabel.grid(row=3, column=1, columnspan=5, sticky=W)
        ToolTip(self.packagePrefixesLabel, text=_("List of prefixes that this package remaps."), wraplength=240)
        self.packageUrlHdr = Label(packageInfoFrame, text=_("URL:"), state=DISABLED)
        self.packageUrlHdr.grid(row=4, column=0, sticky=W)
        self.packageUrlLabel = Label(packageInfoFrame, wraplength=600, justify="left")
        self.packageUrlLabel.grid(row=4, column=1, columnspan=5, sticky=W)
        ToolTip(self.packageUrlLabel, text=_("URL of taxonomy package (local file path or web loaded file)."), wraplength=240)
        self.packageDateHdr = Label(packageInfoFrame, text=_("date:"), state=DISABLED)
        self.packageDateHdr.grid(row=5, column=0, sticky=W)
        self.packageDateLabel = Label(packageInfoFrame, wraplength=600, justify="left")
        self.packageDateLabel.grid(row=5, column=1, columnspan=5, sticky=W)
        ToolTip(self.packageDateLabel, text=_("Date of currently loaded package file (with parenthetical node when an update is available)."), wraplength=240)
        self.packageEnableButton = Button(packageInfoFrame, text=self.ENABLE, state=DISABLED, command=self.packageEnable)
        ToolTip(self.packageEnableButton, text=_("Enable/disable package."), wraplength=240)
        self.packageEnableButton.grid(row=6, column=1, sticky=E)
        self.packageMoveUpButton = Button(packageInfoFrame, text=_("Move Up"), state=DISABLED, command=self.packageMoveUp)
        ToolTip(self.packageMoveUpButton, text=_("Move package up (above other remappings)."), wraplength=240)
        self.packageMoveUpButton.grid(row=6, column=2, sticky=E)
        self.packageMoveDownButton = Button(packageInfoFrame, text=_("Move Down"), state=DISABLED, command=self.packageMoveDown)
        ToolTip(self.packageMoveDownButton, text=_("Move package down (below other remappings)."), wraplength=240)
        self.packageMoveDownButton.grid(row=6, column=3, sticky=E)
        self.packageReloadButton = Button(packageInfoFrame, text=_("Reload"), state=DISABLED, command=self.packageReload)
        ToolTip(self.packageReloadButton, text=_("Reload/update package."), wraplength=240)
        self.packageReloadButton.grid(row=6, column=4, sticky=E)
        self.packageRemoveButton = Button(packageInfoFrame, text=_("Remove"), state=DISABLED, command=self.packageRemove)
        ToolTip(self.packageRemoveButton, text=_("Remove package from packages table (does not erase the package file)."), wraplength=240)
        self.packageRemoveButton.grid(row=6, column=5, sticky=E)
        packageInfoFrame.grid(row=2, column=0, columnspan=5, sticky=(N, S, E, W), padx=3, pady=3)
        packageInfoFrame.config(borderwidth=4, relief="groove")
        
        okButton = Button(frame, text=_("Close"), command=self.ok)
        ToolTip(okButton, text=_("Accept and changes (if any) and close dialog."), wraplength=240)
        cancelButton = Button(frame, text=_("Cancel"), command=self.close)
        ToolTip(cancelButton, text=_("Cancel changes (if any) and close dialog."), wraplength=240)
        okButton.grid(row=3, column=3, sticky=(S,E), pady=3)
        cancelButton.grid(row=3, column=4, sticky=(S,E), pady=3, padx=3)
        
        self.loadTreeViews()

        self.geometry("+{0}+{1}".format(dialogX+50,dialogY+100))
        frame.grid(row=0, column=0, sticky=(N,S,E,W))
        frame.columnconfigure(0, weight=0)
        frame.columnconfigure(1, weight=1)
        frame.rowconfigure(0, weight=1)
        window = self.winfo_toplevel()
        window.columnconfigure(0, weight=1)
        window.rowconfigure(0, weight=1)
        
        self.bind("<Return>", self.ok)
        self.bind("<Escape>", self.close)
        
        self.protocol("WM_DELETE_WINDOW", self.close)
        self.grab_set()
        self.wait_window(self)
        
    def loadTreeViews(self):
        self.selectedModule = None

        # clear previous treeview entries
        for previousNode in self.packagesView.get_children(""): 
            self.packagesView.delete(previousNode)

        for i, packageInfo in enumerate(self.packagesConfig.get("packages", [])):
            name = packageInfo.get("name", "package{}".format(i))
            node = self.packagesView.insert("", "end", "_{}".format(i), text=name)
            self.packagesView.set(node, "ver", packageInfo.get("version"))
            self.packagesView.set(node, "status", packageInfo.get("status"))
            self.packagesView.set(node, "date", packageInfo.get("fileDate"))
            if name in self.packageNamesWithNewerFileDates:
                self.packagesView.set(node, "update", _("available"))
            self.packagesView.set(node, "descr", packageInfo.get("description"))
        
        # clear previous treeview entries
        for previousNode in self.remappingsView.get_children(""): 
            self.remappingsView.delete(previousNode)

        for i, remappingItem in enumerate(sorted(self.packagesConfig.get("remappings", {}).items())):
            prefix, remapping = remappingItem
            node = self.remappingsView.insert("", "end", prefix, text=prefix)
            self.remappingsView.set(node, "remapping", remapping)
            
        self.packageSelect()  # clear out prior selection

    def ok(self, event=None):
        if self.packagesConfigChanged:
            PackageManager.packagesConfig = self.packagesConfig
            PackageManager.packagesConfigChanged = True
            self.cntlr.onPackageEnablementChanged()
        self.close()
        
    def close(self, event=None):
        self.parent.focus_set()
        self.destroy()
                
    def packageSelect(self, *args):
        node = (self.packagesView.selection() or (None,))[0]
        try:
            nodeIndex = int(node[1:])
        except (ValueError, TypeError):
            nodeIndex = -1
        if 0 <= nodeIndex < len(self.packagesConfig["packages"]):
            packageInfo = self.packagesConfig["packages"][nodeIndex]
            self.selectedPackageIndex = nodeIndex
            name = packageInfo["name"]
            self.packageNameLabel.config(text=name)
            self.packageVersionHdr.config(state=ACTIVE)
            self.packageVersionLabel.config(text=packageInfo["version"])
            self.packageDescrHdr.config(state=ACTIVE)
            self.packageDescrLabel.config(text=packageInfo["description"])
            self.packagePrefixesHdr.config(state=ACTIVE)
            self.packagePrefixesLabel.config(text=', '.join(packageInfo["remappings"].keys()))
            self.packageUrlHdr.config(state=ACTIVE)
            self.packageUrlLabel.config(text=packageInfo["URL"])
            self.packageDateHdr.config(state=ACTIVE)
            self.packageDateLabel.config(text=packageInfo["fileDate"] + " " +
                    (_("(an update is available)") if name in self.packageNamesWithNewerFileDates else ""))
            self.packageEnableButton.config(state=ACTIVE,
                                           text={"enabled":self.DISABLE,
                                                 "disabled":self.ENABLE}[packageInfo["status"]])
            self.packageMoveUpButton.config(state=ACTIVE if 0 < nodeIndex else DISABLED)
            self.packageMoveDownButton.config(state=ACTIVE if nodeIndex < (len(self.packagesConfig["packages"]) - 1) else DISABLED)
            self.packageReloadButton.config(state=ACTIVE)
            self.packageRemoveButton.config(state=ACTIVE)
        else:
            self.selectedPackageIndex = -1
            self.packageNameLabel.config(text="")
            self.packageVersionHdr.config(state=DISABLED)
            self.packageVersionLabel.config(text="")
            self.packageDescrHdr.config(state=DISABLED)
            self.packageDescrLabel.config(text="")
            self.packagePrefixesHdr.config(state=DISABLED)
            self.packagePrefixesLabel.config(text="")
            self.packageUrlHdr.config(state=DISABLED)
            self.packageUrlLabel.config(text="")
            self.packageDateHdr.config(state=DISABLED)
            self.packageDateLabel.config(text="")

            self.packageEnableButton.config(state=DISABLED, text=self.ENABLE)
            self.packageMoveUpButton.config(state=DISABLED)
            self.packageMoveDownButton.config(state=DISABLED)
            self.packageReloadButton.config(state=DISABLED)
            self.packageRemoveButton.config(state=DISABLED)
        
    def findLocally(self):
        initialdir = self.cntlr.pluginDir # default plugin directory
        if not self.cntlr.isMac: # can't navigate within app easily, always start in default directory
            initialdir = self.cntlr.config.setdefault("packageOpenDir", initialdir)
        filename = self.cntlr.uiFileDialog("open",
                                           parent=self,
                                           title=_("Choose taxonomy package file"),
                                           initialdir=initialdir,
                                           filetypes=[(_("Taxonomy package files (*.zip)"), "*.zip"),
                                                      (_("Manifest (*.taxonomyPackage.xml)"), "*.taxonomyPackage.xml"),
                                                      (_("Oasis Catalog (*catalog.xml)"), "*catalog.xml")],
                                           defaultextension=".zip")
        if filename:
            # check if a package is selected (any file in a directory containing an __init__.py
            self.cntlr.config["packageOpenDir"] = os.path.dirname(filename)
            packageInfo = PackageManager.packageInfo(filename, packageManifestName=self.manifestNamePattern)
            self.loadFoundPackageInfo(packageInfo, filename)
                

    def findOnWeb(self):
        url = DialogURL.askURL(self)
        if url:  # url is the in-cache or local file
            packageInfo = PackageManager.packageInfo(url, packageManifestName=self.manifestNamePattern)
            self.cntlr.showStatus("") # clear web loading status
            self.loadFoundPackageInfo(packageInfo, url)
                
    def manifestName(self):
        self.manifestNamePattern = simpledialog.askstring(_("Archive manifest file name pattern"),
                                                          _("Provide non-standard archive manifest file name pattern (e.g., *taxonomyPackage.xml).  \n"
                                                            "Uses unix file name pattern matching.  \n"
                                                            "Multiple manifest files are supported in archive (such as oasis catalogs).  \n"
                                                            "(If blank, search for either .taxonomyPackage.xml or catalog.xml).  "),
                                                          initialvalue=self.manifestNamePattern,
                                                          parent=self)
                
    def loadFoundPackageInfo(self, packageInfo, url):
        if packageInfo and packageInfo.get("name"):
            self.addPackageInfo(packageInfo)
            self.loadTreeViews()
        else:
            messagebox.showwarning(_("Package is not itself a taxonomy package.  "),
                                   _("File does not itself contain a manifest file: \n\n{0}\n\n  "
                                     "If opening an archive file, the manifest file search pattern currently is \"\", please press \"Manifest\" to change manifest file name pattern, e.g.,, \"*.taxonomyPackage.xml\", if needed.  ")
                                   .format(url),
                                   parent=self)
            
    def removePackageInfo(self, name, version):
        # find package entry
        packagesList = self.packagesConfig["packages"]
        j = -1
        for i, packageInfo in enumerate(packagesList):
            if packageInfo['name'] == name and packageInfo['version'] == version:
                j = i
                break
        if 0 <= j < len(packagesList):
            del self.packagesConfig["packages"][i]
            self.packagesConfigChanged = True

    def addPackageInfo(self, packageInfo):
        name = packageInfo["name"]
        version = packageInfo["version"]
        self.removePackageInfo(name, version)  # remove any prior entry for this package
        self.packageNamesWithNewerFileDates.discard(name) # no longer has an update available
        self.packagesConfig["packages"].append(packageInfo)
        PackageManager.rebuildRemappings()
        self.packagesConfigChanged = True

    def packageEnable(self):
        if 0 <= self.selectedPackageIndex < len(self.packagesConfig["packages"]):
            packageInfo = self.packagesConfig["packages"][self.selectedPackageIndex]
            if self.packageEnableButton['text'] == self.ENABLE:
                packageInfo["status"] = "enabled"
                self.packageEnableButton['text'] = self.DISABLE
            elif self.packageEnableButton['text'] == self.DISABLE:
                packageInfo["status"] = "disabled"
                self.packageEnableButton['text'] = self.ENABLE
            self.packagesConfigChanged = True
            PackageManager.rebuildRemappings()
            self.loadTreeViews()
            
    def packageMoveUp(self):
        if 1 <= self.selectedPackageIndex < len(self.packagesConfig["packages"]):
            packages = self.packagesConfig["packages"]
            packageInfo = packages[self.selectedPackageIndex]
            del packages[self.selectedPackageIndex]
            packages.insert(self.selectedPackageIndex -1, packageInfo)
            self.packagesConfigChanged = True
            PackageManager.rebuildRemappings()
            self.loadTreeViews()
            
    def packageMoveDown(self):
        if 0 <= self.selectedPackageIndex < len(self.packagesConfig["packages"]) - 1:
            packages = self.packagesConfig["packages"]
            packageInfo = packages[self.selectedPackageIndex]
            del packages[self.selectedPackageIndex]
            packages.insert(self.selectedPackageIndex + 1, packageInfo)
            self.packagesConfigChanged = True
            PackageManager.rebuildRemappings()
            self.loadTreeViews()
            
    def packageReload(self):
        if 0 <= self.selectedPackageIndex < len(self.packagesConfig["packages"]):
            packageInfo = self.packagesConfig["packages"][self.selectedPackageIndex]
            url = packageInfo.get("URL")
            if url:
                packageInfo = PackageManager.packageInfo(url, reload=True, packageManifestName=packageInfo.get("manifestName"))
                if packageInfo:
                    self.addPackageInfo(packageInfo)
                    PackageManager.rebuildRemappings()
                    self.loadTreeViews()
                    self.cntlr.showStatus(_("{0} reloaded").format(packageInfo.get("name")), clearAfter=5000)
                else:
                    messagebox.showwarning(_("Package error"),
                                           _("File or package cannot be reloaded: \n\n{0}")
                                           .format(url),
                                           parent=self)

    def packageRemove(self):
        if 0 <= self.selectedPackageIndex < len(self.packagesConfig["packages"]):
            packageInfo = self.packagesConfig["packages"][self.selectedPackageIndex]
            self.removePackageInfo(packageInfo["name"], packageInfo["version"])
            self.packagesConfigChanged = True
            PackageManager.rebuildRemappings()
            self.loadTreeViews()
class SolutionTabFrame(Frame):
    ''' This class is responsible for displaying solution on the screen.
        It extends Frame class.

        Attributes:
                parent (Tk object that can contain Frame): parent that can
                        contain Frame, MUST implement method
                        change_solution_tab_name(str).
                data_from_file_lbl (Label): label that contains file name
                    with data if specified.
                solution_tab (SolutionFrameWithText): notebook with tabs
                    describing solution.
                model_solutions (list of Solution): list with one or more
                    solutions that have been generated after running algorithm.
                param_strs (list of str): list with strings that should appear
                    before printing every solution from model_solutions.
                ranks (list of list of int): list of ranks corresponding to
                    every solution from model_solutions, ranks are generated
                    by peel-the-onion algorithm.
                categorical (str): name of the categorical variable used in
                    categorical analysis.
                progress_bar (Progressbar): progress bar to show how solution
                    is loaded or saved to file.
                status_lbl (Label): label for displaying solution status.
                solution_format_var (IntVar): IntVar object that tracks which
                    file format is chosen for solution.
    '''
    def __init__(self, parent, *args, **kw):
        super().__init__(parent, *args, **kw)
        self.parent = parent
        self.data_from_file_lbl = None
        self.solution_tab = None
        self.model_solutions = None
        self.param_strs = None
        self.ranks = None
        self.params = None
        self.categorical = None
        self.run_date = None
        self.total_seconds = 0
        self.progress_bar = None
        self.status_lbl = None
        self.solution_format_var = IntVar()
        self.create_widgets()

    def create_widgets(self):
        ''' Creates appropriate widgets on this frame.
        '''
        self.columnconfigure(0, weight=1)
        self.rowconfigure(3, weight=1)
        frame_for_save_btn = Frame(self)
        frame_for_save_btn.columnconfigure(1, weight=1)
        self.status_lbl = Label(frame_for_save_btn, text='')
        self.status_lbl.grid(row=0, column=1, sticky=N + W)
        save_solution_btn = Button(frame_for_save_btn,
                                   text='Save solution',
                                   command=self.on_save_solution)
        save_solution_btn.grid(row=1, column=0, sticky=W + N, padx=5, pady=5)
        self.progress_bar = Progressbar(frame_for_save_btn,
                                        mode='determinate',
                                        maximum=100)
        self.progress_bar.grid(row=1, column=1, sticky=W + E, padx=10, pady=5)

        frame_for_save_btn.grid(sticky=W + N + E + S, padx=5, pady=5)

        frame_for_btns = Frame(self)
        self._create_file_format_btn('*.xlsx', 1, frame_for_btns, 0)
        self._create_file_format_btn('*.xls', 2, frame_for_btns, 1)
        self._create_file_format_btn('*.csv', 3, frame_for_btns, 2)
        self.solution_format_var.set(1)

        frame_for_btns.grid(row=1,
                            column=0,
                            sticky=W + N + E + S,
                            padx=5,
                            pady=5)
        self.data_from_file_lbl = Label(self,
                                        text=TEXT_FOR_FILE_LBL,
                                        anchor=W,
                                        justify=LEFT,
                                        wraplength=MAX_FILE_PARAMS_LBL_LENGTH)
        self.data_from_file_lbl.grid(row=2,
                                     column=0,
                                     padx=5,
                                     pady=5,
                                     sticky=W + N)

        self.solution_tab = SolutionFrameWithText(self)
        self.solution_tab.grid(row=3,
                               column=0,
                               sticky=W + E + S + N,
                               padx=5,
                               pady=5)

    def _create_file_format_btn(self, btn_text, var_value, parent, column):
        ''' Creates and grids Radiobutton used for choosing solution file
            format.

            Args:
                btn_text (str): text displayed next to the Radiobutton.
                var_value (int): value of the IntVar associated with this
                    Radiobutton.
                parent (Tk object): parent of this Radiobutton.
                column (int): column index where this Radiobutton
                    should be gridded.
        '''
        sol_format_btn = Radiobutton(parent,
                                     text=btn_text,
                                     variable=self.solution_format_var,
                                     value=var_value)
        sol_format_btn.grid(row=2, column=column, sticky=W + N, padx=2)

    def on_save_solution(self):
        ''' Saves solution to file.

            This method is called when save solution button is pressed.
            If there is a solution, this method will ask user to provide
            a file name where solution should be stored. If a valid name
            is provided,
            solution is saved to that file. Allowed file formats are:
            .xls and .xlsx.
            Default file extension is .xlsx.

            If the user checked 'csv' as solution output format, then
            the user will be asked to choose a directory where all csv files
            will be written.
        '''
        if self.model_solutions is not None:
            assert (self.param_strs is not None)
            if (self.solution_format_var.get() == 1
                    or self.solution_format_var.get() == 2):
                file_name = self.ask_file_name_to_save(
                    self.solution_format_var.get())
                dir_name = ''
            else:
                dir_name = askdirectory()
                file_name = ''
            if file_name or dir_name:
                print(file_name)
                self.status_lbl.config(text='Saving solution to file...')
                if file_name.endswith('.xls'):
                    work_book = xlwt.Workbook()
                elif file_name.endswith('.xlsx'):
                    work_book = XlsxWorkbook()
                else:
                    # all not supported formats will be written to csv
                    assert (dir_name)
                    work_book = TxtWriter(dir_name)
                writer = XLSWriter(self.params,
                                   work_book,
                                   self.run_date,
                                   self.total_seconds,
                                   ranks=self.ranks,
                                   categorical=self.categorical)
                nb_models = len(self.model_solutions)
                # +1 for parameters sheet, it is stored separately
                nb_sheets = len(writer.worksheets) + 1
                progress_recorder = GuiProgress(self.progress_bar, nb_models,
                                                nb_sheets)

                try:
                    for count, sol in enumerate(self.model_solutions):
                        writer.write_data(sol, self.param_strs[count],
                                          progress_recorder)
                    work_book.save(file_name)
                except ValueError:
                    # can happen if maximum number of rows is exceeded
                    self.status_lbl.config(
                        text='File is too large for xls format,'
                        ' it will be saved to csv instead')
                    work_book = TxtWriter(os.path.splitext(file_name)[0])
                    writer = XLSWriter(self.params,
                                       work_book,
                                       self.run_date,
                                       self.total_seconds,
                                       ranks=self.ranks,
                                       categorical=self.categorical)
                    progress_recorder.set_position(0)
                    for count, sol in enumerate(self.model_solutions):
                        writer.write_data(sol, self.param_strs[count],
                                          progress_recorder)
                    work_book.save(file_name)
                progress_recorder.set_position(100)
                self.parent.change_solution_tab_name('Solution')
                self.status_lbl.config(text='Solution saved')

    def ask_file_name_to_save(self, ext_code):
        ''' Calls asksaveasfilename dialogue to ask the user where file
            should be saved.
            If file without extension is entered, default extension
            will be used (.xlsx).
            This method is used to mock this object for unit tests.

            Args:
                ext_code (int): code for file extension 1 - xlsx, 2 - xls.
        '''
        if ext_code == 1:
            filetype = SOLUTION_XLSX_FILE
        else:
            filetype = SOLUTION_XLS_FILE
        return asksaveasfilename(filetypes=filetype, defaultextension='xlsx')

    def show_solution(self,
                      solutions,
                      params,
                      param_strs,
                      run_date,
                      total_seconds,
                      ranks=None,
                      categorical=None):
        ''' Displays solution on the screen.

            Args:
                solutions (list of Solution): list of solutions (might
                    contain just one solution)
                    that have been generated after running algorithm.
                params (Parameters): object with parameters that will
                    be written to file on the Parameters page.
                param_strs (list of str): list with strings that
                    should appear before
                    printing every solution from model_solutions.
                ranks (list of list of int): list of ranks corresponding
                    to every solution from model_solutions, ranks are
                    generated by peel-the-onion algorithm.
                categorical (str): name of the categorical variable used
                    in categorical analysis.
        '''
        self.status_lbl.config(text='')
        self.model_solutions = solutions
        self.param_strs = param_strs
        self.ranks = ranks
        self.params = params
        self.categorical = categorical
        self.run_date = run_date
        self.total_seconds = total_seconds
        self.status_lbl.config(text='Loading solution...')
        self.solution_tab.show_solution(solutions, params, param_strs,
                                        run_date, total_seconds, ranks,
                                        categorical)
        self.parent.change_solution_tab_name('Solution*')
        self.status_lbl.config(text='Solution loaded')

    def update_data_file_name(self, new_data_file_name):
        ''' Updates label with data file name.

            Args:
                new_data_file_name (str): new value of the data file name
        '''
        self.data_from_file_lbl.config(text=TEXT_FOR_FILE_LBL +
                                       new_data_file_name)
Exemple #36
0
class Download(Frame):
    def __init__(self, master, **kwargs):
        super(Download, self).__init__(master, borderwidth=20, **kwargs)
        self.fs = None
        self.tree = None
        self.logfile = None

        # User informations
        self.info_tree = False
        self.start_time = None
        info = Frame(self, borderwidth=10)
        self.info_label = Label(info,
                                wraplength=350,
                                borderwidth=20,
                                justify='center',
                                font=('a', 10, 'bold'))
        self.info_indis = Label(info)
        self.info_fams = Label(info)
        self.time = Label(info)
        self.info_label.grid(row=0, column=0, columnspan=2)
        self.info_indis.grid(row=1, column=0)
        self.info_fams.grid(row=1, column=1)
        self.time.grid(row=3, column=0, columnspan=2)

        self.form = Frame(self)
        self.sign_in = SignIn(self.form)
        self.options = None
        self.title = Label(self,
                           text=_('Sign In to FamilySearch'),
                           font=('a', 12, 'bold'))
        buttons = Frame(self)
        self.btn_quit = Button(buttons,
                               text=_('Quit'),
                               command=Thread(target=self.quit).start)
        self.btn_valid = Button(buttons,
                                text=_('Sign In'),
                                command=self.command_in_thread(self.login))
        self.title.pack()
        self.sign_in.pack()
        self.form.pack()
        self.btn_quit.pack(side='left', padx=(0, 40))
        self.btn_valid.pack(side='right', padx=(40, 0))
        info.pack()
        buttons.pack(side='bottom')
        self.pack()
        self.update_needed = False

    def info(self, text):
        self.info_label.config(text=text)

    def save(self):
        filename = filedialog.asksaveasfilename(title=_('Save as'),
                                                defaultextension='.csv',
                                                filetypes=(('CSV', '.csv'),
                                                           (_('All files'),
                                                            '*.*')))
        if not filename:
            return
        #with open(filename, 'w', encoding='utf-8') as file:
        #self.tree.print(file)
        fh = open(filename, "w")
        fh.write('personnum')
        fh.write(';')
        fh.write('given names')
        fh.write(';')
        fh.write('surname')
        fh.write(';')
        fh.write('gender')
        fh.write(';')
        fh.write('birthdate')
        fh.write(';')
        fh.write('birthplace')
        fh.write(';')
        fh.write('deathdate')
        fh.write(';')
        fh.write('deathplace')
        fh.write(';')
        fh.write('fathernum')
        fh.write(';')
        fh.write('mothernum')
        fh.write(';')
        fh.write('spousenum')
        fh.write(';')
        fh.write('childnum')
        fh.write(';')
        fh.write('Life Summary')
        fh.write('\n')
        for fid in sorted(self.tree.indi,
                          key=lambda x: self.tree.indi.__getitem__(x).num):
            #person number
            personnum = self.tree.indi[fid].fid
            #name
            givennames = self.tree.indi[fid].name.given
            #surname, all caps
            surname = self.tree.indi[fid].name.surname
            #gender
            gender = self.tree.indi[fid].gender
            #birth and death
            birthstring = 'b. '
            deathstring = 'd. '
            birthdate = ''
            birthplace = ''
            deathdate = ''
            deathplace = ''
            for o in self.tree.indi[fid].facts:
                if o.type == 'http://gedcomx.org/Birth':
                    if o.date:
                        birthdate = o.date
                        birthstring = birthstring + o.date
                    if o.place:
                        birthplace = o.place
                        birthstring = birthstring + ' in ' + o.place
                if o.type == 'http://gedcomx.org/Death':
                    if o.date:
                        deathdate = o.date
                        deathstring = deathstring + o.date
                    if o.place:
                        deathplace = o.place
                        deathstring = deathstring + ' in ' + o.place
            fathernum = ''
            mothernum = ''
            for p in self.tree.indi[fid].parents:
                #father number
                fathernum = p[0]
                #mother number
                mothernum = p[1]
            spousenum = ''
            childnum = ''
            childset = ''
            for husb, wife in sorted(
                    self.tree.fam,
                    key=lambda x: self.tree.fam.__getitem__(x).num):
                if self.tree.fam[(husb, wife)].husb_fid == fid:
                    childnum = self.tree.fam[(husb, wife)].chil_fid.pop()
                    self.tree.fam[(husb, wife)].chil_fid.add(childnum)
                    spousenum = self.tree.fam[(husb, wife)].wife_fid
                elif self.tree.fam[(husb, wife)].wife_fid == fid:
                    childnum = self.tree.fam[(husb, wife)].chil_fid.pop()
                    self.tree.fam[(husb, wife)].chil_fid.add(childnum)
                    spousenum = self.tree.fam[(husb, wife)].husb_fid
                else:
                    continue

            #print('')
            #print(personnum)
            #print(givennames + ' ' + surname)
            #print(surname.upper())
            #print(birthstring)
            #print(deathstring)
            #print(fathernum)
            #print(mothernum)
            #print(spousenum)
            #print(childnum)
            #print('Life Summary ...')

            #Print out in semicolon-csv format
            if personnum:
                fh.write(personnum)
            fh.write(';')
            if givennames:
                fh.write(givennames)
            fh.write(';')
            if surname:
                fh.write(surname)
            fh.write(';')
            if gender:
                fh.write(gender)
            fh.write(';')
            if birthdate:
                fh.write(birthdate)
            fh.write(';')
            if birthplace:
                fh.write(birthplace)
            fh.write(';')
            if deathdate:
                fh.write(deathdate)
            fh.write(';')
            if deathplace:
                fh.write(deathplace)
            fh.write(';')
            if fathernum:
                fh.write(fathernum)
            fh.write(';')
            if mothernum:
                fh.write(mothernum)
            fh.write(';')
            if spousenum:
                fh.write(spousenum)
            fh.write(';')
            if childnum:
                fh.write(childnum)
            fh.write(';')
            fh.write('')
            fh.write('\n')

        fh.close()

    def login(self):
        global _
        username = self.sign_in.username.get()
        password = self.sign_in.password.get()
        if not (username and password):
            messagebox.showinfo(message=_(
                'Please enter your FamilySearch username and password.'))
            return
        self.btn_valid.config(state='disabled')
        self.info(_('Login to FamilySearch...'))
        self.logfile = open('download.log', 'w', encoding='utf-8')
        self.fs = Session(self.sign_in.username.get(),
                          self.sign_in.password.get(),
                          verbose=True,
                          logfile=self.logfile,
                          timeout=1)
        if not self.fs.logged:
            messagebox.showinfo(
                _('Error'),
                message=_('The username or password was incorrect'))
            self.btn_valid.config(state='normal')
            self.info('')
            return
        self.tree = Tree(self.fs)
        _ = self.fs._
        self.title.config(text=_('Options'))
        cache.delete('lang')
        cache.add('lang', self.fs.lang)
        lds_account = self.fs.get_url(
            '/platform/tree/persons/%s/ordinances' % self.fs.fid) != 'error'
        self.options = Options(self.form, lds_account)
        self.info('')
        self.sign_in.destroy()
        self.options.pack()
        self.master.change_lang()
        self.btn_valid.config(command=self.command_in_thread(self.download),
                              state='normal',
                              text=_('Download'))
        self.options.start_indis.add_indi(self.fs.fid)
        self.update_needed = False

    def quit(self):
        self.update_needed = False
        if self.logfile:
            self.logfile.close()
        super(Download, self).quit()
        # prevent exception during download
        os._exit(1)

    def download(self):
        todo = [
            self.options.start_indis.indis[key]
            for key in sorted(self.options.start_indis.indis)
        ]
        for fid in todo:
            if not re.match(r'[A-Z0-9]{4}-[A-Z0-9]{3}', fid):
                messagebox.showinfo(_('Error'),
                                    message=_('Invalid FamilySearch ID: ') +
                                    fid)
                return
        self.start_time = time.time()
        self.options.destroy()
        self.form.destroy()
        self.title.config(text='Ancestor Cards')
        self.btn_valid.config(state='disabled')
        self.info(_('Download starting individuals...'))
        self.info_tree = True
        self.tree.add_indis(todo)

        # download ancestors
        #todo = set(todo)
        todo = set(self.tree.indi.keys())
        done = set()
        for i in range(self.options.ancestors.get()):
            if not todo:
                break
            done |= todo
            #self.info(_('Download ') + str(i + 1) + _('th generation of ancestors...'))
            print(_("Downloading %s. of generations of ancestors...") %
                  (i + 1),
                  file=sys.stderr)
            todo = self.tree.add_parents(todo) - done

        #todo = set(self.tree.indi.keys())
        #done = set()
        #for i in range(self.options.descendants.get()):
        #    if not todo:
        #        break
        #    done |= todo
        #    self.info(_('Download ') + str(i + 1) + _('th generation of descendants...'))
        #    todo = self.tree.add_children(todo) - done

        #if self.options.spouses.get():
        #    self.info(_('Download spouses and marriage information...'))
        #    todo = set(self.tree.indi.keys())
        #    self.tree.add_spouses(todo)

        self.tree.reset_num()
        self.btn_valid.config(command=self.save,
                              state='normal',
                              text=_('Save'))
        self.info(text=_('Success ! Click below to save your CSV file'))
        self.update_info_tree()
        self.update_needed = False

    def command_in_thread(self, func):
        def res():
            self.update_needed = True
            Thread(target=self.update_gui).start()
            Thread(target=func).start()

        return res

    def update_info_tree(self):
        if self.info_tree and self.start_time and self.tree:
            self.info_indis.config(text=_('Individuals: %s') %
                                   len(self.tree.indi))
            self.info_fams.config(text=_('Families: %s') % len(self.tree.fam))
            t = round(time.time() - self.start_time)
            minutes = t // 60
            seconds = t % 60
            self.time.config(text=_('Elapsed time: %s:%s') %
                             (minutes, '00%s'[len(str(seconds)):] % seconds))

    def update_gui(self):
        while self.update_needed:
            self.update_info_tree()
            self.master.update()
            time.sleep(0.1)
Exemple #37
0
class FrameDownload(Frame):

    def __init__(self, master=None, option=()):
        super().__init__(master=master)
        self.master = master
        self.master.title('Download information')
        self.option = option
        self.setupUI()

    def setupUI(self):
        # build UI base on URLS
        if self.option[2] == SEARCH:
            # title window
            label_title = Label(self, text='Search Photos')
            label_title.config(anchor='center', foreground='white', background='#8e44ad')
            label_title.grid(row=0, column=0, columnspan=6, sticky='we')

            # progress
            self.progress = Progressbar(self) 
            self.progress.config(orient='horizontal', length=100, mode='determinate')
            self.progress.grid(row=2, column=0, columnspan=5, sticky='we')

            self.var_progress = StringVar()
            self.var_progress.set('0%')
            self.label_show_progress = Label(self) 
            self.label_show_progress.config(textvariable=self.var_progress, anchor='center')
            self.label_show_progress.var = self.var_progress
            self.label_show_progress.grid(row=2, column=5, sticky='w')

            # query
            self.label_query = Label(self, text='Query')
            self.label_query.grid(row=1, column=0, sticky='e')

            self.var_entry_query = StringVar()
            self.entry_query = Entry(self)
            self.entry_query.config(textvariable=self.var_entry_query, state='readonly')
            self.entry_query.grid(row=1, column=1, sticky='w')

            # total
            self.var_total = StringVar()
            self.var_total.set('Total')
            self.label_total = Label(self, textvariable=self.var_total)
            self.label_total.grid(row=1, column=2, sticky='e')

            self.var_entry_total = IntVar()
            self.entry_total = Entry(self)
            self.entry_total.config(textvariable=self.var_entry_total, state='readonly')
            self.entry_total.grid(row=1, column=3, sticky='w')

            # total pages
            self.label_total_page = Label(self, text='Total pages:')
            self.label_total_page.grid(row=1, column=4, sticky='e')

            self.var_entry_total_pages = IntVar()
            self.entry_total_page = Entry(self)
            self.entry_total_page.config(textvariable=self.var_entry_total_pages, state='readonly')
            self.entry_total_page.grid(row=1, column=5, sticky='w')

            # show image is downloaded
            self.label_image_downloaded = Label(self, anchor='center')
            self.label_image_downloaded.grid(row=3, column=0, columnspan=6, sticky='wesn')
            
            # self.change_ui()

        elif self.option[2] == LIST:
            # title window
            label_title = Label(self, text='List of Photos')
            label_title.config(
                anchor='center', foreground='white', background='#2c3e50')
            label_title.grid(row=0, column=0, columnspan=4, sticky='we')

            # progress
            self.progress = Progressbar(self)
            self.progress.config(orient='horizontal',
                                 length=100, mode='determinate')
            self.progress.grid(row=2, column=0, columnspan=3, sticky='we')

            self.var_progress = StringVar()
            self.var_progress.set('0%')
            self.label_show_progress = Label(self)
            self.label_show_progress.config(
                textvariable=self.var_progress, anchor='center')
            self.label_show_progress.var = self.var_progress
            self.label_show_progress.grid(row=2, column=3, sticky='w')

            # query
            self.label_query = Label(self, text='Query:')
            self.label_query.grid(row=1, column=0, sticky='e')

            self.entry_query = Entry(self)
            self.entry_query.insert(0,'LIST')
            self.entry_query.config(state='readonly')
            self.entry_query.grid(row=1, column=1, sticky='w')

            # amount
            self.label_total = Label(self, text='Amount:')
            self.label_total.grid(row=1, column=2, sticky='e')

            self.entry_total = Entry(self)
            self.entry_total.insert(0,self.option[3]['per_page'])
            self.entry_total.config(state='readonly')
            self.entry_total.grid(row=1, column=3, sticky='w')

            # show image is downloaded
            self.label_image_downloaded = Label(self, anchor='center')
            self.label_image_downloaded.grid(
                row=3, column=0, columnspan=4, sticky='wesn')

            # self.change_ui()

        elif self.option[2] == RANDOM:
            # title window
            label_title = Label(self, text='Random Photos')
            label_title.config(
                anchor='center', foreground='white', background='#16a085')
            label_title.grid(row=0, column=0, columnspan=4, sticky='we')

            # progress
            self.progress = Progressbar(self)
            self.progress.config(orient='horizontal',
                                 length=100, mode='determinate')
            self.progress.grid(row=2, column=0, columnspan=3, sticky='we')

            self.var_progress = StringVar()
            self.var_progress.set('0%')
            self.label_show_progress = Label(self)
            self.label_show_progress.config(
                textvariable=self.var_progress, anchor='center')
            self.label_show_progress.var = self.var_progress
            self.label_show_progress.grid(row=2, column=3, sticky='w')

            # query
            self.label_query = Label(self, text='Query')
            self.label_query.grid(row=1, column=0, sticky='e')

            self.entry_query = Entry(self)
            self.entry_query.insert(0,'RANDOM')
            self.entry_query.config(state='readonly')
            self.entry_query.grid(row=1, column=1, sticky='w')

            # amount
            self.label_total = Label(self, text='Amount')
            self.label_total.grid(row=1, column=2, sticky='e')

            self.var_entry_total = IntVar()
            if self.option[3]['count'] > 30:
                self.var_entry_total.set(30)
            else:
                self.var_entry_total.set(self.option[3]['count'])
            self.entry_total = Entry(self)
            self.entry_total.config(textvariable=self.var_entry_total, state='readonly')
            self.entry_total.grid(row=1, column=3, sticky='w')
            

            # show image is downloaded
            self.label_image_downloaded = Label(self, anchor='center')
            self.label_image_downloaded.grid(
                row=3, column=0, columnspan=4, sticky='wesn')

    def change_ui(self):
        if self.option[2] == SEARCH:
            r = requests.get(self.option[2], params=self.option[3])
            if r.status_code == 200:
                # get urls based on quality
                j = json.loads(r.text)
                total = j['total']
                total_pages = j['total_pages']
                results = j['results']

                self.var_entry_query.set(self.option[3]['query'])
                self.var_entry_total.set(total)
                self.var_entry_total_pages.set(total_pages)

                self.entry_query.update_idletasks()
                self.entry_total.update_idletasks()
                self.entry_total_page.update_idletasks()

        # random photos
        elif self.option[2] == RANDOM:
            r = requests.get(self.option[2], params=self.option[3])
            if r.status_code == 200:

                # get result
                j = json.loads(r.text)
                results = j

        elif self.option[2] == LIST:
            r = requests.get(self.option[2], params=self.option[3])
            if r.status_code == 200:

                # get result
                j = json.loads(r.text)
                results = j

        self.download(results)

    def download(self, results):
        for i in results:
            name = i['id']
            url = i['urls'][self.option[1]]
            time.sleep(1)  # delay time to send request
            try:
                request.urlretrieve(url, self.option[0]+'/'+name+'.jpg')
            except Exception as x:  # re download if have a problem
                print('have problem', x)
                time.sleep(1)

            self.progress['value'] += 100/len(results)
            self.var_progress.set('{}%'.format(self.progress['value']))

            # show image downloaded
            image = Image.open(self.option[0]+'/'+name+'.jpg')
            width = int(self.winfo_width())
            height = int(width*image.height/image.width)
            self.photo = ImageTk.PhotoImage(
                image.resize((width, height), Image.ANTIALIAS))
            self.label_image_downloaded.config(image=self.photo)
            self.label_image_downloaded.image = self.photo

            self.progress.update_idletasks()
            
        self.message_done = messagebox.showinfo('Info', 'Done')
        self.master.destroy()
Exemple #38
0
class MainFrame(Frame):
    ''' This class implements main GUI of the application.

        Attributes:
            parent (Tk object): parent of this frame (Tk()).
            params_frame (ParamsFrame): frame with parameters.
            data_frame (DataFrame): frame with data and solution.
            progress_bar (Progressbar): progress bar widget.
            increment (int): progress bar increment, it is modified
                in other classes that are responsible for solving
                the problem and update progress.
            weights_status_lbl (Label): label that displays if weight
                restrictions are feasible.
            weights_status_str (StringVar): StringVar object used for
                tracking if weight restrictions are feasible.
            current_categories (list of str): list of current categories.

        Args:
            parent (Tk object): parent of this frame (Tk()).
    '''
    def __init__(self, parent, *args, **kwargs):
        Frame.__init__(self, parent, *args, **kwargs)
        self.parent = parent
        self.params_frame = None
        self.data_frame = None
        self.progress_bar = None
        self.increment = 0
        self.weights_status_lbl = None
        self.weights_status_str = StringVar()
        self.weights_status_str.trace('w', self.on_weights_status_change)
        self.current_categories = []
        self.create_widgets()

    def create_widgets(self):
        ''' Creates all widgets that belong to this frame.
        '''
        self.parent.title('pyDEA')
        self.pack(fill=BOTH, expand=1)

        self.columnconfigure(0, weight=1, pad=5)
        self.columnconfigure(1, weight=0, pad=5)
        self.rowconfigure(0, pad=3, weight=1)
        self.rowconfigure(1, pad=3)
        self.rowconfigure(2, pad=3)
        self.rowconfigure(3, pad=3)

        self.current_categories = []
        data_from_params_file = StringVar()
        str_var_for_input_output_boxes = ObserverStringVar()
        self.params_frame = ParamsFrame(self, self.current_categories,
                                        data_from_params_file,
                                        str_var_for_input_output_boxes,
                                        self.weights_status_str)
        data_frame = DataFrame(self, self.params_frame, self.current_categories,
                               data_from_params_file,
                               str_var_for_input_output_boxes)
        self.data_frame = data_frame
        data_frame.grid(row=0, column=0, sticky=N+S+W+E, padx=15, pady=15)

        self.params_frame.grid(row=0, column=1, sticky=W+E+S+N, padx=15,
                               pady=15, columnspan=2)

        lbl_progress = Label(self, text='Progress')
        lbl_progress.grid(row=1, column=0, sticky=W, padx=10, pady=5)

        self.progress_bar = Progressbar(self, mode='determinate', maximum=100)
        self.progress_bar.grid(row=2, column=0, sticky=W+E, padx=10, pady=5)

        run_btn = Button(self, text='Run', command=self.run)
        run_btn.grid(row=2, column=1, sticky=W, padx=10, pady=10)

        self.weights_status_lbl = Label(self, text='', foreground='red')
        self.weights_status_lbl.grid(row=2, column=2, padx=10, pady=5, sticky=W)

    def on_weights_status_change(self, *args):
        ''' This method is called when weight restrictions status is changed.
        '''
        self.weights_status_lbl.config(text=self.weights_status_str.get())

    def run(self):
        ''' This method is called when the user presses Run button.
            Solves the problem and displays solution.
        '''
        clean_up_pickled_files()
        params = self.params_frame.params
        run_method = RunMethodGUI(self)
        run_method.run(params)

    def construct_categories(self):
        ''' Returns current categories.

            Returns:
                (list of str): list of current categories
        '''
        return [category.strip() for category in self.current_categories
                if category]

    def on_dmu_change(self, *args):
        ''' Updates progress bar.
        '''
        self.progress_bar.step(self.increment)
        self.progress_bar.update()
class DialogPluginManager(Toplevel):
    def __init__(self, mainWin, modulesWithNewerFileDates):
        super(DialogPluginManager, self).__init__(mainWin.parent)
        
        self.ENABLE = _("Enable")
        self.DISABLE = _("Disable")
        self.parent = mainWin.parent
        self.cntlr = mainWin
        
        # copy plugins for temporary display
        self.pluginConfig = PluginManager.pluginConfig
        self.pluginConfigChanged = False
        self.uiClassMethodsChanged = False
        self.modelClassesChanged = False
        self.disclosureSystemTypesChanged = False
        self.hostSystemFeaturesChanged = False
        self.modulesWithNewerFileDates = modulesWithNewerFileDates
        
        parentGeometry = re.match("(\d+)x(\d+)[+]?([-]?\d+)[+]?([-]?\d+)", self.parent.geometry())
        dialogX = int(parentGeometry.group(3))
        dialogY = int(parentGeometry.group(4))

        self.title(_("Plug-in Manager"))
        frame = Frame(self)
        
        # left button frame
        buttonFrame = Frame(frame, width=40)
        buttonFrame.columnconfigure(0, weight=1)
        addLabel = Label(buttonFrame, text=_("Find plug-in modules:"), wraplength=60, justify="center")
        addLocalButton = Button(buttonFrame, text=_("Locally"), command=self.findLocally)
        ToolTip(addLocalButton, text=_("File chooser allows selecting python module files to add (or reload) plug-ins, from the local file system."), wraplength=240)
        addWebButton = Button(buttonFrame, text=_("On Web"), command=self.findOnWeb)
        ToolTip(addWebButton, text=_("Dialog to enter URL full path to load (or reload) plug-ins, from the web or local file system."), wraplength=240)
        addLabel.grid(row=0, column=0, pady=4)
        addLocalButton.grid(row=1, column=0, pady=4)
        addWebButton.grid(row=2, column=0, pady=4)
        buttonFrame.grid(row=0, column=0, rowspan=2, sticky=(N, S, W), padx=3, pady=3)
        
        # right tree frame (plugins already known to arelle)
        modulesFrame = Frame(frame, width=700)
        vScrollbar = Scrollbar(modulesFrame, orient=VERTICAL)
        hScrollbar = Scrollbar(modulesFrame, orient=HORIZONTAL)
        self.modulesView = Treeview(modulesFrame, xscrollcommand=hScrollbar.set, yscrollcommand=vScrollbar.set, height=7)
        self.modulesView.grid(row=0, column=0, sticky=(N, S, E, W))
        self.modulesView.bind('<<TreeviewSelect>>', self.moduleSelect)
        hScrollbar["command"] = self.modulesView.xview
        hScrollbar.grid(row=1, column=0, sticky=(E,W))
        vScrollbar["command"] = self.modulesView.yview
        vScrollbar.grid(row=0, column=1, sticky=(N,S))
        modulesFrame.columnconfigure(0, weight=1)
        modulesFrame.rowconfigure(0, weight=1)
        modulesFrame.grid(row=0, column=1, columnspan=4, sticky=(N, S, E, W), padx=3, pady=3)
        self.modulesView.focus_set()

        self.modulesView.column("#0", width=120, anchor="w")
        self.modulesView.heading("#0", text=_("Name"))
        self.modulesView["columns"] = ("author", "ver", "status", "date", "update", "descr", "license")
        self.modulesView.column("author", width=100, anchor="w", stretch=False)
        self.modulesView.heading("author", text=_("Author"))
        self.modulesView.column("ver", width=50, anchor="w", stretch=False)
        self.modulesView.heading("ver", text=_("Version"))
        self.modulesView.column("status", width=50, anchor="w", stretch=False)
        self.modulesView.heading("status", text=_("Status"))
        self.modulesView.column("date", width=70, anchor="w", stretch=False)
        self.modulesView.heading("date", text=_("File Date"))
        self.modulesView.column("update", width=50, anchor="w", stretch=False)
        self.modulesView.heading("update", text=_("Update"))
        self.modulesView.column("descr", width=200, anchor="w", stretch=False)
        self.modulesView.heading("descr", text=_("Description"))
        self.modulesView.column("license", width=70, anchor="w", stretch=False)
        self.modulesView.heading("license", text=_("License"))

        classesFrame = Frame(frame)
        vScrollbar = Scrollbar(classesFrame, orient=VERTICAL)
        hScrollbar = Scrollbar(classesFrame, orient=HORIZONTAL)
        self.classesView = Treeview(classesFrame, xscrollcommand=hScrollbar.set, yscrollcommand=vScrollbar.set, height=5)
        self.classesView.grid(row=0, column=0, sticky=(N, S, E, W))
        hScrollbar["command"] = self.classesView.xview
        hScrollbar.grid(row=1, column=0, sticky=(E,W))
        vScrollbar["command"] = self.classesView.yview
        vScrollbar.grid(row=0, column=1, sticky=(N,S))
        classesFrame.columnconfigure(0, weight=1)
        classesFrame.rowconfigure(0, weight=1)
        classesFrame.grid(row=1, column=1, columnspan=4, sticky=(N, S, E, W), padx=3, pady=3)
        self.classesView.focus_set()
        
        self.classesView.column("#0", width=200, anchor="w")
        self.classesView.heading("#0", text=_("Class"))
        self.classesView["columns"] = ("modules",)
        self.classesView.column("modules", width=500, anchor="w", stretch=False)
        self.classesView.heading("modules", text=_("Modules"))
        
        # bottom frame module info details
        moduleInfoFrame = Frame(frame, width=700)
        moduleInfoFrame.columnconfigure(1, weight=1)
        
        self.moduleNameLabel = Label(moduleInfoFrame, wraplength=600, justify="left", 
                                     font=font.Font(family='Helvetica', size=12, weight='bold'))
        self.moduleNameLabel.grid(row=0, column=0, columnspan=4, sticky=W)
        self.moduleAuthorHdr = Label(moduleInfoFrame, text=_("author:"), state=DISABLED)
        self.moduleAuthorHdr.grid(row=1, column=0, sticky=W)
        self.moduleAuthorLabel = Label(moduleInfoFrame, wraplength=600, justify="left")
        self.moduleAuthorLabel.grid(row=1, column=1, columnspan=3, sticky=W)
        self.moduleDescrHdr = Label(moduleInfoFrame, text=_("description:"), state=DISABLED)
        self.moduleDescrHdr.grid(row=2, column=0, sticky=W)
        self.moduleDescrLabel = Label(moduleInfoFrame, wraplength=600, justify="left")
        self.moduleDescrLabel.grid(row=2, column=1, columnspan=3, sticky=W)
        self.moduleClassesHdr = Label(moduleInfoFrame, text=_("classes:"), state=DISABLED)
        self.moduleClassesHdr.grid(row=3, column=0, sticky=W)
        self.moduleClassesLabel = Label(moduleInfoFrame, wraplength=600, justify="left")
        self.moduleClassesLabel.grid(row=3, column=1, columnspan=3, sticky=W)
        ToolTip(self.moduleClassesLabel, text=_("List of classes that this plug-in handles."), wraplength=240)
        self.moduleUrlHdr = Label(moduleInfoFrame, text=_("URL:"), state=DISABLED)
        self.moduleUrlHdr.grid(row=4, column=0, sticky=W)
        self.moduleUrlLabel = Label(moduleInfoFrame, wraplength=600, justify="left")
        self.moduleUrlLabel.grid(row=4, column=1, columnspan=3, sticky=W)
        ToolTip(self.moduleUrlLabel, text=_("URL of plug-in module (local file path or web loaded file)."), wraplength=240)
        self.moduleDateHdr = Label(moduleInfoFrame, text=_("date:"), state=DISABLED)
        self.moduleDateHdr.grid(row=5, column=0, sticky=W)
        self.moduleDateLabel = Label(moduleInfoFrame, wraplength=600, justify="left")
        self.moduleDateLabel.grid(row=5, column=1, columnspan=3, sticky=W)
        ToolTip(self.moduleDateLabel, text=_("Date of currently loaded module file (with parenthetical node when an update is available)."), wraplength=240)
        self.moduleLicenseHdr = Label(moduleInfoFrame, text=_("license:"), state=DISABLED)
        self.moduleLicenseHdr.grid(row=6, column=0, sticky=W)
        self.moduleLicenseLabel = Label(moduleInfoFrame, wraplength=600, justify="left")
        self.moduleLicenseLabel.grid(row=6, column=1, columnspan=3, sticky=W)
        self.moduleImportsHdr = Label(moduleInfoFrame, text=_("imports:"), state=DISABLED)
        self.moduleImportsHdr.grid(row=7, column=0, sticky=W)
        self.moduleImportsLabel = Label(moduleInfoFrame, wraplength=600, justify="left")
        self.moduleImportsLabel.grid(row=7, column=1, columnspan=3, sticky=W)
        self.moduleEnableButton = Button(moduleInfoFrame, text=self.ENABLE, state=DISABLED, command=self.moduleEnable)
        ToolTip(self.moduleEnableButton, text=_("Enable/disable plug in."), wraplength=240)
        self.moduleEnableButton.grid(row=8, column=1, sticky=E)
        self.moduleReloadButton = Button(moduleInfoFrame, text=_("Reload"), state=DISABLED, command=self.moduleReload)
        ToolTip(self.moduleReloadButton, text=_("Reload/update plug in."), wraplength=240)
        self.moduleReloadButton.grid(row=8, column=2, sticky=E)
        self.moduleRemoveButton = Button(moduleInfoFrame, text=_("Remove"), state=DISABLED, command=self.moduleRemove)
        ToolTip(self.moduleRemoveButton, text=_("Remove plug in from plug in table (does not erase the plug in's file)."), wraplength=240)
        self.moduleRemoveButton.grid(row=8, column=3, sticky=E)
        moduleInfoFrame.grid(row=2, column=0, columnspan=5, sticky=(N, S, E, W), padx=3, pady=3)
        moduleInfoFrame.config(borderwidth=4, relief="groove")
        
        okButton = Button(frame, text=_("Close"), command=self.ok)
        ToolTip(okButton, text=_("Accept and changes (if any) and close dialog."), wraplength=240)
        cancelButton = Button(frame, text=_("Cancel"), command=self.close)
        ToolTip(cancelButton, text=_("Cancel changes (if any) and close dialog."), wraplength=240)
        okButton.grid(row=3, column=3, sticky=(S,E), pady=3)
        cancelButton.grid(row=3, column=4, sticky=(S,E), pady=3, padx=3)
        
        enableDisableFrame = Frame(frame)
        enableDisableFrame.grid(row=3, column=1, sticky=(S,W), pady=3)
        enableAllButton = Button(enableDisableFrame, text=_("Enable All"), command=self.enableAll)
        ToolTip(enableAllButton, text=_("Enable all plug ins."), wraplength=240)
        disableAllButton = Button(enableDisableFrame, text=_("Disable All"), command=self.disableAll)
        ToolTip(disableAllButton, text=_("Disable all plug ins."), wraplength=240)
        enableAllButton.grid(row=1, column=1)
        disableAllButton.grid(row=1, column=2)
        
        self.loadTreeViews()

        self.geometry("+{0}+{1}".format(dialogX+50,dialogY+100))
        frame.grid(row=0, column=0, sticky=(N,S,E,W))
        frame.columnconfigure(0, weight=0)
        frame.columnconfigure(1, weight=1)
        frame.rowconfigure(0, weight=1)
        window = self.winfo_toplevel()
        window.columnconfigure(0, weight=1)
        window.rowconfigure(0, weight=1)
        
        self.bind("<Return>", self.ok)
        self.bind("<Escape>", self.close)
        
        self.protocol("WM_DELETE_WINDOW", self.close)
        self.grab_set()
        self.wait_window(self)
        
    def loadTreeViews(self):
        self.selectedModule = None

        # clear previous treeview entries
        for previousNode in self.modulesView.get_children(""): 
            self.modulesView.delete(previousNode)
            
        def loadSubtree(parentNode, moduleItems):
            for moduleItem in sorted(moduleItems, key=lambda item: item[0]):
                moduleInfo = moduleItem[1]
                if parentNode or not moduleInfo.get("isImported"):
                    nodeName = moduleItem[0]
                    if parentNode:
                        nodeName = parentNode + GROUPSEP + nodeName
                    name = moduleInfo.get("name", nodeName)
                    node = self.modulesView.insert(parentNode, "end", nodeName, text=name)
                    self.modulesView.set(node, "author", moduleInfo.get("author"))
                    self.modulesView.set(node, "ver", moduleInfo.get("version"))
                    self.modulesView.set(node, "status", moduleInfo.get("status"))
                    self.modulesView.set(node, "date", moduleInfo.get("fileDate"))
                    if name in self.modulesWithNewerFileDates:
                        self.modulesView.set(node, "update", _("available"))
                    self.modulesView.set(node, "descr", moduleInfo.get("description"))
                    self.modulesView.set(node, "license", moduleInfo.get("license"))
                    if moduleInfo.get("imports"):
                        loadSubtree(node, [(importModuleInfo["name"],importModuleInfo)
                                           for importModuleInfo in moduleInfo["imports"]])
            
        loadSubtree("", self.pluginConfig.get("modules", {}).items())
        
        # clear previous treeview entries
        for previousNode in self.classesView.get_children(""): 
            self.classesView.delete(previousNode)

        for i, classItem in enumerate(sorted(self.pluginConfig.get("classes", {}).items())):
            className, moduleList = classItem
            node = self.classesView.insert("", "end", className, text=className)
            self.classesView.set(node, "modules", ', '.join(moduleList))
            
        self.moduleSelect()  # clear out prior selection

    def ok(self, event=None):
        if self.pluginConfigChanged:
            PluginManager.pluginConfig = self.pluginConfig
            PluginManager.pluginConfigChanged = True
            PluginManager.reset()  # force reloading of modules
        if self.uiClassMethodsChanged or self.modelClassesChanged or self.disclosureSystemTypesChanged or self.hostSystemFeaturesChanged:  # may require reloading UI
            affectedItems = ""
            if self.uiClassMethodsChanged:
                affectedItems += _("menus of the user interface")
            if self.modelClassesChanged:
                if affectedItems:
                    affectedItems += _(" and ")
                affectedItems += _("model objects of the processor")
            if self.disclosureSystemTypesChanged:
                if affectedItems:
                    affectedItems += _(" and ")
                affectedItems += _("disclosure system types")
            if self.hostSystemFeaturesChanged:
                if affectedItems:
                    affectedItems += _(" and ")
                affectedItems += _("host system features")
            if messagebox.askyesno(_("User interface plug-in change"),
                                   _("A change in plug-in class methods may have affected {0}.  " 
                                     "Please restart Arelle to due to these changes.  \n\n"
                                     "Should Arelle restart itself now "
                                     "(if there are any unsaved changes they would be lost!)?"
                                     ).format(affectedItems),
                                   parent=self):
                self.cntlr.uiThreadQueue.put((self.cntlr.quit, [None, True]))
        self.close()
        
    def close(self, event=None):
        self.parent.focus_set()
        self.destroy()
                
    def moduleSelect(self, *args):
        node = (self.modulesView.selection() or (None,))[0]
        if node:
            node = node.rpartition(GROUPSEP)[2] # drop leading path names for module name
        moduleInfo = self.pluginConfig.get("modules", {}).get(node)
        if moduleInfo:
            self.selectedModule = node
            name = moduleInfo["name"]
            self.moduleNameLabel.config(text=name)
            self.moduleAuthorHdr.config(state=ACTIVE)
            self.moduleAuthorLabel.config(text=moduleInfo["author"])
            self.moduleDescrHdr.config(state=ACTIVE)
            self.moduleDescrLabel.config(text=moduleInfo["description"])
            self.moduleClassesHdr.config(state=ACTIVE)
            self.moduleClassesLabel.config(text=', '.join(moduleInfo["classMethods"]))
            self.moduleUrlHdr.config(state=ACTIVE)
            self.moduleUrlLabel.config(text=moduleInfo["moduleURL"])
            self.moduleDateHdr.config(state=ACTIVE)
            self.moduleDateLabel.config(text=moduleInfo["fileDate"] + " " +
                    (_("(an update is available)") if name in self.modulesWithNewerFileDates else ""))
            self.moduleLicenseHdr.config(state=ACTIVE)
            self.moduleLicenseLabel.config(text=moduleInfo["license"])
            if moduleInfo.get("imports"):
                self.moduleImportsHdr.config(state=ACTIVE)
                _text = ", ".join(mi["name"] for mi in moduleInfo["imports"][:3])
                if len(moduleInfo["imports"]) >= 3:
                    _text += ", ..."
                self.moduleImportsLabel.config(text=_text)
            _buttonState = DISABLED if moduleInfo.get("isImported") else ACTIVE
            self.moduleEnableButton.config(state=_buttonState,
                                           text={"enabled":self.DISABLE,
                                                 "disabled":self.ENABLE}[moduleInfo["status"]])
            self.moduleReloadButton.config(state=_buttonState)
            self.moduleRemoveButton.config(state=_buttonState)
        else:
            self.selectedModule = None
            self.moduleNameLabel.config(text="")
            self.moduleAuthorHdr.config(state=DISABLED)
            self.moduleAuthorLabel.config(text="")
            self.moduleDescrHdr.config(state=DISABLED)
            self.moduleDescrLabel.config(text="")
            self.moduleClassesHdr.config(state=DISABLED)
            self.moduleClassesLabel.config(text="")
            self.moduleUrlHdr.config(state=DISABLED)
            self.moduleUrlLabel.config(text="")
            self.moduleDateHdr.config(state=DISABLED)
            self.moduleDateLabel.config(text="")
            self.moduleLicenseHdr.config(state=DISABLED)
            self.moduleLicenseLabel.config(text="")
            self.moduleImportsHdr.config(state=DISABLED)
            self.moduleImportsLabel.config(text="")
            self.moduleEnableButton.config(state=DISABLED, text=self.ENABLE)
            self.moduleReloadButton.config(state=DISABLED)
            self.moduleRemoveButton.config(state=DISABLED)
        
    def findLocally(self):
        initialdir = self.cntlr.pluginDir # default plugin directory
        if not self.cntlr.isMac: # can't navigate within app easily, always start in default directory
            initialdir = self.cntlr.config.setdefault("pluginOpenDir", initialdir)
        filename = self.cntlr.uiFileDialog("open",
                                           parent=self,
                                           title=_("Choose plug-in module file"),
                                           initialdir=initialdir,
                                           filetypes=[(_("Python files"), "*.py")],
                                           defaultextension=".py")
        if filename:
            # check if a package is selected (any file in a directory containing an __init__.py
            #if (os.path.basename(filename) == "__init__.py" and os.path.isdir(os.path.dirname(filename)) and
            #    os.path.isfile(filename)):
            #    filename = os.path.dirname(filename) # refer to the package instead
            self.cntlr.config["pluginOpenDir"] = os.path.dirname(filename)
            moduleInfo = PluginManager.moduleModuleInfo(filename)
            self.loadFoundModuleInfo(moduleInfo, filename)
                

    def findOnWeb(self):
        url = DialogURL.askURL(self)
        if url:  # url is the in-cache or local file
            moduleInfo = PluginManager.moduleModuleInfo(url)
            self.cntlr.showStatus("") # clear web loading status
            self.loadFoundModuleInfo(moduleInfo, url)
                
    def loadFoundModuleInfo(self, moduleInfo, url):
        if moduleInfo and moduleInfo.get("name"):
            self.addPluginConfigModuleInfo(moduleInfo)
            self.loadTreeViews()
        else:
            messagebox.showwarning(_("Module is not itself a plug-in or in a directory with package __init__.py plug-in.  "),
                                   _("File does not itself contain a python program with an appropriate __pluginInfo__ declaration: \n\n{0}")
                                   .format(url),
                                   parent=self)
        
    def checkIfImported(self, moduleInfo):
        if moduleInfo.get("isImported"):
            messagebox.showwarning(_("Plug-in is imported by a parent plug-in.  "),
                                   _("Plug-in has a parent, please request operation on the parent: \n\n{0}")
                                   .format(moduleInfo.get("name")),
                                   parent=self)
            return True
        return False
    
    def removePluginConfigModuleInfo(self, name):
        moduleInfo = self.pluginConfig["modules"].get(name)
        if moduleInfo:
            if self.checkIfImported(moduleInfo):
                return;
            def _removePluginConfigModuleInfo(moduleInfo):
                _name = moduleInfo.get("name")
                if _name:
                    for classMethod in moduleInfo["classMethods"]:
                        classMethods = self.pluginConfig["classes"].get(classMethod)
                        if classMethods and _name in classMethods:
                            classMethods.remove(_name)
                            if not classMethods: # list has become unused
                                del self.pluginConfig["classes"][classMethod] # remove class
                            if classMethod.startswith("CntlrWinMain.Menu"):
                                self.uiClassMethodsChanged = True  # may require reloading UI
                            elif classMethod == "ModelObjectFactory.ElementSubstitutionClasses":
                                self.modelClassesChanged = True # model object factor classes changed
                            elif classMethod == "DisclosureSystem.Types":
                                self.disclosureSystemTypesChanged = True # disclosure system types changed
                            elif classMethod.startswith("Proxy."):
                                self.hostSystemFeaturesChanged = True # system features (e.g., proxy) changed
                    for importModuleInfo in moduleInfo.get("imports", EMPTYLIST):
                        _removePluginConfigModuleInfo(importModuleInfo)
                    self.pluginConfig["modules"].pop(_name, None)
            _removePluginConfigModuleInfo(moduleInfo)
            self.pluginConfigChanged = True

    def addPluginConfigModuleInfo(self, moduleInfo):
        if self.checkIfImported(moduleInfo):
            return;
        name = moduleInfo.get("name")
        self.removePluginConfigModuleInfo(name)  # remove any prior entry for this module
        def _addPlugin(moduleInfo):
            _name = moduleInfo.get("name")
            if _name:
                self.modulesWithNewerFileDates.discard(_name) # no longer has an update available
                self.pluginConfig["modules"][_name] = moduleInfo
                # add classes
                for classMethod in moduleInfo["classMethods"]:
                    classMethods = self.pluginConfig["classes"].setdefault(classMethod, [])
                    if name not in classMethods:
                        classMethods.append(_name)
                    if classMethod.startswith("CntlrWinMain.Menu"):
                        self.uiClassMethodsChanged = True  # may require reloading UI
                    elif classMethod == "ModelObjectFactory.ElementSubstitutionClasses":
                        self.modelClassesChanged = True # model object factor classes changed
                    elif classMethod == "DisclosureSystem.Types":
                        self.disclosureSystemTypesChanged = True # disclosure system types changed
                    elif classMethod.startswith("Proxy."):
                        self.hostSystemFeaturesChanged = True # system features (e.g., proxy) changed
            for importModuleInfo in moduleInfo.get("imports", EMPTYLIST):
                _addPlugin(importModuleInfo)
        _addPlugin(moduleInfo)
        self.pluginConfigChanged = True

    def moduleEnable(self):
        if self.selectedModule in self.pluginConfig["modules"]:
            moduleInfo = self.pluginConfig["modules"][self.selectedModule]
            if self.checkIfImported(moduleInfo):
                return;
            def _moduleEnable(moduleInfo):
                if self.moduleEnableButton['text'] == self.ENABLE:
                    moduleInfo["status"] = "enabled"
                elif self.moduleEnableButton['text'] == self.DISABLE:
                    moduleInfo["status"] = "disabled"
                for importModuleInfo in moduleInfo.get("imports", EMPTYLIST):
                    _moduleEnable(importModuleInfo)
            _moduleEnable(moduleInfo)
            if self.moduleEnableButton['text'] == self.ENABLE:
                self.moduleEnableButton['text'] = self.DISABLE
            elif self.moduleEnableButton['text'] == self.DISABLE:
                self.moduleEnableButton['text'] = self.ENABLE
            self.pluginConfigChanged = True
            self.loadTreeViews()
            
    def moduleReload(self):
        if self.selectedModule in self.pluginConfig["modules"]:
            url = self.pluginConfig["modules"][self.selectedModule].get("moduleURL")
            if url:
                moduleInfo = PluginManager.moduleModuleInfo(url, reload=True)
                if moduleInfo:
                    if self.checkIfImported(moduleInfo):
                        return;
                    self.addPluginConfigModuleInfo(moduleInfo)
                    self.loadTreeViews()
                    self.cntlr.showStatus(_("{0} reloaded").format(moduleInfo["name"]), clearAfter=5000)
                else:
                    messagebox.showwarning(_("Module error"),
                                           _("File or module cannot be reloaded: \n\n{0}")
                                           .format(url),
                                           parent=self)

    def moduleRemove(self):
        if self.selectedModule in self.pluginConfig["modules"]:
            self.removePluginConfigModuleInfo(self.selectedModule)
            self.pluginConfigChanged = True
            self.loadTreeViews()
                    
    def enableAll(self):
        self.enableDisableAll(True)
                    
    def disableAll(self):
        self.enableDisableAll(False)
                    
    def enableDisableAll(self, doEnable):
        for module in self.pluginConfig["modules"]:
            if not module.get("isImported"):
                moduleInfo = self.pluginConfig["modules"][module]
                def _enableDisableAll(moduleInfo):
                    if doEnable:
                        moduleInfo["status"] = "enabled"
                    else:
                        moduleInfo["status"] = "disabled"
                    for importModuleInfo in moduleInfo.get("imports", EMPTYLIST):
                        _enableDisableAll(importModuleInfo)
                _enableDisableAll(moduleInfo)
                if doEnable:
                    self.moduleEnableButton['text'] = self.DISABLE
                else:
                    self.moduleEnableButton['text'] = self.ENABLE
        self.pluginConfigChanged = True
        self.loadTreeViews()