예제 #1
0
    def _add_option(self, name, description, value=False):
        var = BooleanVar()
        self._vars[name] = var
        
        var.set(value)
        var.trace('w', self._options_update)

        cb = Checkbutton(self, text=description, variable=var)
        cb.pack(side=LEFT)
예제 #2
0
class RootFrame(Frame):
    def __init__(self, master):
        Frame.__init__(self, master)

        self._value = os.getcwd()
        self._var = StringVar(self)
        self._var.set(self._value)
        self._var.trace('w', self._validate)

        label = Label(self, text="Root:")
        label.pack(side=LEFT)
        self._entry = Entry(self, textvariable=self._var)
        self._entry.pack(side=LEFT, fill=X, expand=True)

        self._recursive_var = BooleanVar()
        recursive_cb = Checkbutton(self, text='Recursive', variable=self._recursive_var)
        recursive_cb.pack(side=LEFT)
        self._recursive_var.trace('w', self._validate)
        
        open_button = Button(self, text="Open", command=self._select_root)
        open_button.pack(side=LEFT)
        
        refresh_button = Button(self, text="Refresh", command=self._refresh)
        refresh_button.pack(side=LEFT)

        repad(self, 'padx', 0, 5)

    def _refresh(self):
        self.event_generate('<<Refresh>>', when='tail')

    def _validate(self, *_):
        res = self._var.get().strip()
        if os.path.isdir(res):
            self._entry.config(fg='black')
            self._value = res
        else:
            self._entry.config(fg='red')
            self._value = None
        self.event_generate('<<RootUpdate>>', when='tail')

    def _select_root(self):
        value = askdirectory()
        if value:
            self._var.set(value)
            self._validate()

    @property
    def root(self):
        return self._value

    
    @property
    def recursive(self):
        return self._recursive_var.get()
예제 #3
0
def validateTableInfosetMenuEntender(cntlr, validateMenu):
    # Extend menu with an item for the save infoset plugin
    cntlr.modelManager.generateTableInfoset = cntlr.config.setdefault("generateTableInfoset",False)
    from tkinter import BooleanVar
    generateTableInfoset = BooleanVar(value=cntlr.modelManager.generateTableInfoset)
    def setTableInfosetOption(*args):
        cntlr.config["generateTableInfoset"] = cntlr.modelManager.generateTableInfoset = generateTableInfoset.get()
    generateTableInfoset.trace("w", setTableInfosetOption)
    validateMenu.add_checkbutton(label=_("Generate table infosets (instead of diffing them)"), 
                                 underline=0, 
                                 variable=generateTableInfoset, onvalue=True, offvalue=False)
예제 #4
0
def validateTableInfosetMenuEntender(cntlr, validateMenu):
    # Extend menu with an item for the save infoset plugin
    cntlr.modelManager.generateTableInfoset = cntlr.config.setdefault("generateTableInfoset",False)
    from tkinter import BooleanVar
    generateTableInfoset = BooleanVar(value=cntlr.modelManager.generateTableInfoset)
    def setTableInfosetOption(*args):
        cntlr.config["generateTableInfoset"] = cntlr.modelManager.generateTableInfoset = generateTableInfoset.get()
    generateTableInfoset.trace("w", setTableInfosetOption)
    validateMenu.add_checkbutton(label=_("Generate table infosets (instead of diffing them)"), 
                                 underline=0, 
                                 variable=generateTableInfoset, onvalue=True, offvalue=False)
예제 #5
0
class Preferences(Frame):
    def __init__(self, client):
        # Basic setup
        super(Preferences, self).__init__()
        self.client = client

        # Setup the variables used
        self.echo_input = BooleanVar()
        self.echo_input.set(self.client.config['UI'].getboolean('echo_input'))
        self.echo_input.trace("w", self.echo_handler)
        self.logging = BooleanVar()
        self.logging.set(
            self.client.config['logging'].getboolean('log_session'))
        self.logging.trace('w', self.logging_handler)
        self.log_dir = self.client.config['logging']['log_directory']

        # Build the actual window and widgets
        prefs = Toplevel(self)
        prefs.wm_title("Preferences")
        echo_input_label = Label(prefs, text="Echo Input:")
        logging_label = Label(prefs, text='Log to file:')
        echo_checkbox = Checkbutton(prefs, variable=self.echo_input)
        logging_checkbox = Checkbutton(prefs, variable=self.logging)
        logging_button_text = 'Choose file...' if self.log_dir == "" else self.log_dir
        logging_button = Button(prefs,
                                text=logging_button_text,
                                command=self.logging_pick_location)

        # Pack 'em in.
        echo_input_label.grid(row=0, column=0)
        echo_checkbox.grid(row=0, column=1)
        logging_label.grid(row=1, column=0)
        logging_checkbox.grid(row=1, column=1)
        logging_button.grid(row=1, column=2)

    def logging_pick_location(self):
        location = askdirectory(initialdir="%UserProfile%\Documents\\")
        self.client.config['logging']['log_directory'] = location
        self.write_config()

    def echo_handler(self, arg1, arg2, mode):
        pprint(self.echo_input.get())
        self.client.config['UI']['echo_input'] = 'yes' if self.echo_input.get(
        ) else 'no'
        self.write_config()

    def logging_handler(self, arg1, arg2, mode):
        self.client.config['logging'][
            'log_session'] = 'yes' if self.logging.get else 'no'
        self.write_config()

    def write_config(self, file='config.ini'):
        self.client.config.write(open(file, 'w'))
예제 #6
0
class Preferences(Frame):
    def __init__(self, client):
        # Basic setup
        super(Preferences, self).__init__()
        self.client = client

        # Setup the variables used
        self.echo_input = BooleanVar()
        self.echo_input.set(self.client.config['UI'].getboolean('echo_input'))
        self.echo_input.trace("w", self.echo_handler)
        self.logging = BooleanVar()
        self.logging.set(self.client.config['logging'].getboolean('log_session'))
        self.logging.trace('w', self.logging_handler)
        self.log_dir = self.client.config['logging']['log_directory']

        # Build the actual window and widgets
        prefs = Toplevel(self)
        prefs.wm_title("Preferences")
        echo_input_label = Label(prefs, text="Echo Input:")
        logging_label = Label(prefs, text='Log to file:')
        echo_checkbox = Checkbutton(prefs, variable=self.echo_input)
        logging_checkbox = Checkbutton(prefs, variable=self.logging)
        logging_button_text = 'Choose file...' if self.log_dir == "" else self.log_dir
        logging_button = Button(prefs, text=logging_button_text, command=self.logging_pick_location)

        # Pack 'em in.
        echo_input_label.grid(row=0, column=0)
        echo_checkbox.grid(row=0, column=1)
        logging_label.grid(row=1, column=0)
        logging_checkbox.grid(row=1, column=1)
        logging_button.grid(row=1, column=2)

    def logging_pick_location(self):
        location = askdirectory(initialdir="%UserProfile%\Documents\\")
        self.client.config['logging']['log_directory'] = location
        self.write_config()

    def echo_handler(self, arg1, arg2, mode):
        pprint(self.echo_input.get())
        self.client.config['UI']['echo_input'] = 'yes' if self.echo_input.get() else 'no'
        self.write_config()

    def logging_handler(self, arg1, arg2, mode):
        self.client.config['logging']['log_session'] = 'yes' if self.logging.get else 'no'
        self.write_config()

    def write_config(self, file='config.ini'):
        self.client.config.write(open(file, 'w'))
예제 #7
0
def weatherprediction():

   frame1.destroy()
   frame2.destroy()
   
   global frame3
   frame3 = Frame(root)
   frame3.pack(side='top',fill='x')

   Label(frame3,text="WEATHER PREDICTION", relief='flat', padx=10,pady=10).grid(row=0,column=0, columnspan=3)
   Label(frame3,text="STEPS", relief='ridge',width=15,bg='white').grid(row=1,column=0)
   Label(frame3,text="PROCESS", relief='ridge',width=25,bg='white').grid(row=1,column=1)
   Label(frame3,text="VALUES", relief='ridge',width=15,bg='white').grid(row=1,column=2)
   steps = ['Step1','Step2','Step3','Step4','Step5','Step6','Step7']
   r = 2
   for c in steps:
     Label(frame3,text=c, relief='ridge',width=15).grid(row=r,column=0)
     r = r + 1

   tr_start1 = tk.Button(frame3, text ="Input Training Set Start Date", command = getTrainSD)
   tr_end1 = tk.Button(frame3, text ="Input Training Set End Date", command = getTrainED)
   test_start1 = tk.Button(frame3, text ="Input Test Set Start Date", command = getTestSD)
   test_end1 = tk.Button(frame3, text ="Input Test Set End Date", command = getTestED)
   dep_var_idx1 = tk.Button(frame3, text ="Choose What to Predict", command = getPredictor)
   indep_var_idx1 = tk.Button(frame3, text ="Choose Plantes", command = getIPredictor)

   def getBool(): # get rid of the event argument
    global feature_scaling
    feature_scaling=boolvar.get()
    Label(frame3,text=feature_scaling, relief='flat',width=15).grid(row=8,column=2)
    print(feature_scaling)

   boolvar = BooleanVar()
   boolvar.set(False)
   boolvar.trace('w', lambda *_: print("The value was changed"))
   cb = tk.Checkbutton(frame3, text = "Is Feature Scaling applicable?", variable = boolvar, command = getBool)
   
   LR = tk.Button(frame3, text = "Run Prediction", command = MLR )

   tr_start1.grid(row=2,column=1)
   tr_end1.grid(row=3,column=1)
   test_start1.grid(row=4,column=1)
   test_end1.grid(row=5,column=1)
   dep_var_idx1.grid(row=6,column=1)
   indep_var_idx1.grid(row=7,column=1)
   cb.grid(row=8,column=1)
   LR.grid(row=9,column=0,columnspan=3)
예제 #8
0
def addValidateMenuTools(cntlr, validateMenu, name, map_name):
    # Extend menu with an item for the save infoset plugin
    attr_name = 'validate{}'.format(name.strip())
    attr_value = cntlr.config.setdefault(attr_name, False)
    setattr(cntlr.modelManager, attr_name, attr_value)
    #cntlr.modelManager.validateDQC = cntlr.config.setdefault("validateDQC",False)
    from tkinter import BooleanVar
    validate_var = BooleanVar(value=getattr(cntlr.modelManager, attr_name))
    
    def setValidateXuleOption(*args):
        setattr(cntlr.modelManager, attr_name, validate_var.get())
        cntlr.config[attr_name] = getattr(cntlr.modelManager, attr_name)
        
    validate_var.trace("w", setValidateXuleOption)
    validateMenu.add_checkbutton(label=_("{} Rules".format(name)), 
                                 underline=0, 
                                 variable=validate_var, onvalue=True, offvalue=False)


    xuleRegisterValidators(name, map_name, validate_var)
예제 #9
0
class _CheckButton(WidgetBase):
    def __init__(self,
                 master,
                 label=None,
                 command=None,
                 default=False,
                 **options):
        super().__init__(master)
        from tkinter import BooleanVar
        from tkinter.ttk import Checkbutton
        self.var = BooleanVar(self.master, value=default)
        self.value = ""
        self.var.trace("w", self.callback)
        self.command = [command]
        if not label is None:
            options.update(text=label)
        self.widget = Checkbutton(self.master, variable=self.var, **options)

    def callback(self, *args):
        self.value = self.var.get()
        if callable(self.command[0]): self.command[0]()
예제 #10
0
class Boolean(Editor):
    def __init__(self, master, style_def=None):
        super().__init__(master, style_def)
        self.config(**self.style.dark, **self.style.dark_highlight_active)
        self._var = BooleanVar()
        self._var.trace('w', self.check_change)
        self._check = Checkbutton(self, text='')
        self._check['variable'] = self._var
        self._check.pack(fill="x")

    def check_change(self, *_):
        self._check.config(text=str(self._var.get()))
        if self._on_change is not None:
            self._on_change(self._var.get())

    def set(self, value):
        self._var.set(bool(value))
        self._check.config(text=str(self._var.get()))

    def get(self):
        return bool(self._var.get())
예제 #11
0
def addValidateMenuTools(cntlr, validateMenu, name, map_name):
    # Extend menu with an item for the save infoset plugin
    attr_name = 'validate{}'.format(name.strip())
    attr_value = cntlr.config.setdefault(attr_name, False)
    setattr(cntlr.modelManager, attr_name, attr_value)
    #cntlr.modelManager.validateDQC = cntlr.config.setdefault("validateDQC",False)
    from tkinter import BooleanVar
    validate_var = BooleanVar(value=getattr(cntlr.modelManager, attr_name))

    def setValidateXuleOption(*args):
        setattr(cntlr.modelManager, attr_name, validate_var.get())
        cntlr.config[attr_name] = getattr(cntlr.modelManager, attr_name)

    validate_var.trace("w", setValidateXuleOption)
    validateMenu.add_checkbutton(label=_("{} Rules".format(name)),
                                 underline=0,
                                 variable=validate_var,
                                 onvalue=True,
                                 offvalue=False)

    xuleRegisterValidators(name, map_name, validate_var)
예제 #12
0
class LoginViewController(GenericController):
    def __init__(self,
                 app: Tk,
                 sock: socket = None,
                 model: User = None,
                 view: LoginView = None):
        super().__init__(app, sock, model, view)
        self.model = model if model is not None else User()
        self.socket = socket(AF_INET, SOCK_STREAM)
        self.sha256 = sha256()
        self.user_logged_state = BooleanVar(app)
        self.user_logged_state.trace('w', self.user_state_changed)

    def connect(self):
        self.socket = socket(AF_INET, SOCK_STREAM)
        self.socket.connect(server_host.host)

    def send_request(self, request: dict):
        serialized_request = json.dumps(request)
        self.socket.sendall(serialized_request.encode())

    def receive_response(self):
        data = bytes()
        while True:
            received = self.socket.recv(4096)
            if not received:
                break
            elif len(received) < 4096:
                data += received
                break
            else:
                data += received

        response = json.loads(data.decode())
        return response

    def hash_password(self, raw_password: str):
        self.sha256.update(raw_password.encode())
        return self.sha256.hexdigest()

    def username_var_changed(self, *args):
        username = self.view.username.get()
        password = self.view.password.get()

        # Unlock the password entry only if there's something in the username entry
        if username != '':
            self.view.pass_entry['state'] = 'normal'
            # Unlock the submit button only if both the username and password typed are at least 8 chars long
            self.view.submit_button['state'] = 'normal' if len(
                username) >= 8 and len(password) >= 8 else 'disabled'
        else:
            self.view.pass_entry['state'] = 'disabled'
            self.view.submit_button['state'] = 'disabled'

    def password_var_changed(self, *args):
        username = self.view.username.get()
        password = self.view.password.get()

        # Unlock the submit button only if both the username and password typed are at least 8 chars long
        if password != '':
            self.view.submit_button['state'] = 'normal' if len(
                username) >= 8 and len(password) >= 8 else 'disabled'
        else:
            self.view.submit_button['state'] = 'disabled'

    def submit(self, *args):
        username = self.view.username.get()
        self.model.username = username
        hashed_password = self.hash_password(self.view.password.get())
        self.model.password = hashed_password

        self.connect()
        request = {
            'request': self.view.action.get(),
            'user': {
                'username': self.model.username,
                'password': self.model.password
            }
        }
        # print(request)
        self.send_request(request)
        response = self.receive_response()

        if response['info'] == 'Logged':
            self.user_logged_state.set(True)
        else:
            messagebox.showwarning('Server says', response['info'])

    def start_main_view(self):
        controller = MainViewController(self.app, self.socket, self.model)
        view = MainView(self.app, controller=controller)
        controller.view = view

    def user_state_changed(self, *args):
        if self.user_logged_state.get() is True:
            for widget in self.app.slaves():
                widget.destroy()

            self.app.geometry('500x400')
            self.start_main_view()
예제 #13
0
class EarthquakeGUI:
    def _quit(self):
        # Quit program
        quit()  # win will exist when this function is called
        Tk.destroy(self)
        exit()

    def _refreshData(self):
        logging.debug("")
        t1 = datetime.now()
        JSONdata = getWebData(urlData)
        t2 = datetime.now()
        tdweb = t2 - t1
        if JSONdata:
            hList = loadHeaderInfo(JSONdata)
            logging.info(f"Web Retrieval - {hList['count']:,} "
                         f"records in {tdweb.total_seconds(): .3}s")
            eList = loadList(JSONdata)
            eList = self.sortData(eList)
            self.updateHeaderFields(hList)
            self.updateFields(eList, self.summarySelected.current())
        else:
            messagebox.showerror(
                "USGS File error", "Error retrieving "
                "data from USGS web site. Check console for error.")
            logging.error("Error retrieving file")

    def _comboCallbackFunc(self, event, data):
        logging.debug("")
        # When combo box changes, updated data with new selection
        self.updateFields(data, self.summarySelected.current())

    def _webCallbackFunc(self, data):
        logging.debug("")
        webbrowser.open_new(data)

    def getNewData(self, timeString):
        logging.debug("")
        global urlData
        x = urlData.find("summary/")
        y = urlData.find(".geojson")
        logging.debug(urlData[x + 8:y])
        urlData = str(urlData.replace(urlData[x + 8:y], timeString, 1))
        logging.debug(urlData)
        self._refreshData()
        # When combo box changes, updated data with new selection
        # self.updateFields(data, self.summarySelected.current())
        # return urlData

    def updateComboBoxData(self, data):
        logging.debug("")
        dropdownlist = []
        self.summarySelected.delete(0)
        if len(data) > 0:
            for n, _ in enumerate(data):
                mag = f"{data[n][1]:.1f}"
                mmi = f"{data[n][8]:.3f}"
                dropdownlist.append(mag + "  -  " + mmi + "  -  " +
                                    str(data[n][2]))
            self.summarySelected["values"] = dropdownlist
            self.summarySelected.current(0)
            self.summarySelected.bind(
                "<<ComboboxSelected>>",
                lambda event, arg=data: self._comboCallbackFunc(event, arg),
            )
        else:
            self.summarySelected["values"] = dropdownlist
            self.summarySelected.set("")

    def sortData(self, data):
        logging.debug(f"{self.sortOption.get()}")
        try:
            if self.sortOption.get() == '2':
                s_eList = sorted(data,
                                 key=lambda x: (x[8], x[1], x[7]),
                                 reverse=True)
            else:
                s_eList = sorted(data,
                                 key=lambda x: (x[1], x[7]),
                                 reverse=True)
            eList = s_eList[:]
        except:
            logging.error("Error sorting list - most likely bad data")
        self.updateComboBoxData(eList)
        return eList

    def __init__(self, data, header):
        self.win = Tk()
        self.win.title("USGS Current Earthquake Data")
        self.checked = BooleanVar()
        self.checked.trace("w", self.mark_checked)
        self.sortOption = StringVar()
        self.sortOption.set("1")
        self.sortOption.trace("w", self.mark_sortOption)

        # ----- Menu Bar - Create the Menu Bar -------------------------
        menuBar = Menu()
        self.win.config(menu=menuBar)
        fileMenu = Menu(menuBar, tearoff=False)
        dataMenu = Menu(menuBar, tearoff=False)
        optionsMenu = Menu(menuBar, tearoff=False)
        helpMenu = Menu(menuBar, tearoff=False)
        menuBar.add_cascade(menu=fileMenu, label="File")
        menuBar.add_cascade(menu=dataMenu, label="Data")
        menuBar.add_cascade(menu=optionsMenu, label="Options")
        menuBar.add_cascade(menu=helpMenu, label="Help")
        # ----- Menu Bar - Create the File Menu ------------------------
        fileMenu.add_separator()
        fileMenu.add_command(label="Exit", command=self._quit)
        # ----- Menu Bar - Create the Options Menu ---------------------
        sortSubMenu = Menu(optionsMenu, tearoff=False)
        optionsMenu.add_cascade(menu=sortSubMenu, label="Sort")
        sortSubMenu.add_radiobutton(label="Sort by Magnitude",
                                    value="1",
                                    variable=self.sortOption)
        sortSubMenu.add_radiobutton(
            label="Sort by Predictive damage or Shake(MMI)",
            value="2",
            variable=self.sortOption)
        # ----- Menu Bar - Create the Data Menu-------------------------
        dataMenu.add_command(label="Refresh current Data source",
                             command=self._refreshData)
        dataMenu.add_separator()
        dataSubMenu = Menu(dataMenu, tearoff=False)
        dataMenu.add_cascade(menu=dataSubMenu, label="New Data Source")
        # ----- Menu Bar - Create the Data submenu ---------------------
        d1 = [
            ["Significant", "significant"],
            ["Magnitude 4.5+", "4.5"],
            ["Magnitude 2.5+", "2.5"],
            ["Magnitude 1.0+", "1.0"],
            ["All Earthquakes+", "all"],
        ]
        d2 = [
            ["hour", "hour"],
            ["day", "day"],
            ["7 days", "week"],
            ["30 days", "month"],
        ]
        for i in range(len(d2)):
            for j in range(len(d1)):
                s1 = str(d1[j][0] + ", past " + d2[i][0])
                s2 = str(d1[j][1] + "_" + d2[i][1])
                dataSubMenu.add_command(
                    label=s1,
                    command=lambda widget=s2: self.getNewData(widget))
                if j == (len(d1) - 1) and i != (len(d2) - 1):
                    dataSubMenu.add_separator()
        # ----- Set up frames and subframes to store widgets -----------
        self.mainFrame = ttk.LabelFrame()
        self.headings_frame = ttk.LabelFrame(self.mainFrame)
        self.headings_frame.grid(row=0)
        self.selection_frame = ttk.LabelFrame(self.headings_frame,
                                              text="selection frame")
        self.selection_frame.configure(text=header["title"])
        self.selection_frame.grid(column=0, columnspan=2, row=0, sticky="NW")
        self.file_frame = ttk.LabelFrame(self.headings_frame, text="File Info")
        self.file_frame.grid(column=2, row=0, rowspan=3, sticky="NW")
        self.details_frame = ttk.LabelFrame(self.mainFrame)
        self.details_frame.grid(row=1)
        self.summary_frame = ttk.LabelFrame(self.details_frame,
                                            text="Event Details")
        self.summary_frame.grid(row=0, columnspan=2)
        self.location_frame = ttk.LabelFrame(self.details_frame,
                                             text="Event Location")
        self.location_frame.grid(row=1, column=0, sticky="NW")
        self.time_frame = ttk.LabelFrame(self.details_frame,
                                         text="Time of Event")
        self.time_frame.grid(row=1, column=1, sticky="NW")
        ttk.Label(self.selection_frame).grid(column=0, row=0, sticky="W")
        # ----- Set up combo box and data to populate it ---------------
        self.summarySelected = ttk.Combobox(self.selection_frame,
                                            width=85,
                                            state="readonly")
        self.summarySelected.grid(column=0, row=1)
        self.updateComboBoxData(data)
        # ----- Add File widget - File delta ---------------------------
        self.fileDelta = StringVar()
        fileDeltaEntry = ttk.Label(self.file_frame,
                                   width=25,
                                   textvariable=self.fileDelta,
                                   state="readonly")
        fileDeltaEntry.grid(column=1, row=0, columnspan=2, sticky="W")
        # ----- Add File widget - File Time ----------------------------
        ttk.Label(self.file_frame, text="File Time:").grid(column=0,
                                                           row=1,
                                                           sticky="E")
        self.fileTime = StringVar()
        fileTimeEntry = ttk.Label(self.file_frame,
                                  width=25,
                                  textvariable=self.fileTime,
                                  state="readonly")
        fileTimeEntry.grid(column=1, row=1, sticky="W")
        # ----- Add File widget - Event count --------------------------
        ttk.Label(self.file_frame, text="Count:").grid(column=0,
                                                       row=2,
                                                       sticky="E")
        self.fileCount = StringVar()
        fileCountEntry = ttk.Label(self.file_frame,
                                   width=25,
                                   textvariable=self.fileCount,
                                   state="readonly")
        fileCountEntry.grid(column=1, row=2, sticky="W")
        # ----- Add Summary widget - Magnitude -------------------------
        ttk.Label(self.summary_frame, text="Magnitude:").grid(column=0,
                                                              row=0,
                                                              sticky="E")
        self.mag = StringVar()
        magEntry = ttk.Label(self.summary_frame,
                             width=7,
                             textvariable=self.mag,
                             state="readonly")
        magEntry.grid(column=1, row=0, sticky="W")
        # ----- Add Summary widget - Alert -----------------------------
        ttk.Label(self.summary_frame, text="Alert:").grid(column=2,
                                                          row=0,
                                                          sticky="E")
        self.alert = StringVar()
        alertEntry = ttk.Label(self.summary_frame,
                               width=7,
                               textvariable=self.alert,
                               state="readonly")
        alertEntry.grid(column=3, row=0, sticky="W")
        # ----- Add Summary widget - Shake -----------------------------
        ttk.Label(self.summary_frame, text="Shake (MMI):").grid(column=4,
                                                                row=0,
                                                                sticky="E")
        self.shake = StringVar()
        shakeEntry = ttk.Label(self.summary_frame,
                               width=7,
                               textvariable=self.shake,
                               state="readonly")
        shakeEntry.grid(column=5, row=0, sticky="W")
        # ----- Add Summary widget - Report Felt -----------------------
        ttk.Label(self.summary_frame, text="Reported felt:").grid(column=6,
                                                                  row=0,
                                                                  sticky="E")
        self.felt = StringVar()
        feltEntry = ttk.Label(self.summary_frame,
                              width=7,
                              textvariable=self.felt,
                              state="readonly")
        feltEntry.grid(column=7, row=0, sticky="W")
        # ----- Add Summary widget - Url/More Info ---------------------
        ttk.Label(self.summary_frame, text="More info:").grid(column=0,
                                                              row=1,
                                                              sticky="E")
        self.urlName = StringVar()
        self.urlEntry = ttk.Button(self.summary_frame)
        self.urlEntry.grid(column=1, row=1, columnspan=8, sticky="W")
        # ----- Add Location widget - Place ----------------------------
        ttk.Label(self.location_frame, text="Place:").grid(column=0,
                                                           row=4,
                                                           sticky="E")
        self.place = StringVar()
        locEntry = ttk.Label(self.location_frame,
                             width=45,
                             textvariable=self.place,
                             state="readonly")
        locEntry.grid(column=1, row=4, sticky="W")
        # ----- Add Location widget - Latitude -------------------------
        ttk.Label(self.location_frame, text="Latitude:").grid(column=0,
                                                              row=10,
                                                              sticky="E")
        self.lat = StringVar()
        latEntry = ttk.Label(self.location_frame,
                             width=25,
                             textvariable=self.lat,
                             state="readonly")
        latEntry.grid(column=1, row=10, sticky="W")
        # ----- Add Location widget - Longitude ------------------------
        ttk.Label(self.location_frame, text="Longitude:").grid(column=0,
                                                               row=11,
                                                               sticky="E")
        self.lon = StringVar()
        longEntry = ttk.Label(self.location_frame,
                              width=25,
                              textvariable=self.lon,
                              state="readonly")
        longEntry.grid(column=1, row=11, sticky="W")
        # ----- Add Location widget - Depth ----------------------------
        ttk.Label(self.location_frame, text="Depth:").grid(column=0,
                                                           row=12,
                                                           sticky="E")
        self.depth = StringVar()
        depthEntry = ttk.Label(self.location_frame,
                               width=25,
                               textvariable=self.depth,
                               state="readonly")
        depthEntry.grid(column=1, row=12, sticky="W")
        # ----- Add Time widget - Event delta --------------------------
        self.deltaEntry = StringVar()
        deltaEntry = ttk.Label(self.time_frame,
                               width=25,
                               textvariable=self.deltaEntry,
                               state="readonly")
        deltaEntry.grid(column=1, row=0, sticky="W")
        # ----- Add Time widget - Event Time ---------------------------
        ttk.Label(self.time_frame, text="Time:").grid(column=0,
                                                      row=1,
                                                      sticky="E")
        self.time = StringVar()
        timeEntry = ttk.Label(self.time_frame,
                              width=25,
                              textvariable=self.time,
                              state="readonly")
        timeEntry.grid(column=1, row=1, sticky="W")
        # ----- Add Time widget - Event Local Time ---------------------
        ttk.Label(self.time_frame, text="Your local time:").grid(column=0,
                                                                 row=2,
                                                                 sticky="E")
        self.tz = StringVar()
        tzEntry = ttk.Label(self.time_frame,
                            width=25,
                            textvariable=self.tz,
                            state="readonly")
        tzEntry.grid(column=1, row=2, sticky="W")
        # ----- Add padding around fields
        self.mainFrame.grid_configure(padx=8, pady=4)
        for child in self.mainFrame.winfo_children():
            child.grid_configure(padx=8, pady=4)
            for grandChild in child.winfo_children():
                grandChild.grid_configure(padx=8, pady=4)
                for widget in grandChild.winfo_children():
                    widget.grid_configure(padx=8, pady=4)

        # ----- Call funtion to update fields --------------------------
        data = self.sortData(data)
        self.updateHeaderFields(header)
        self.updateFields(data, self.summarySelected.current())

    def mark_checked(self, *args):
        logging.debug("")
        print(self.checked.get())

    def mark_sortOption(self, *args):
        logging.debug("")
        print(self.sortOption.get())
        JSONdata = getDataFile()
        if not JSONdata:
            self._refreshData()
        else:
            hList = loadHeaderInfo(JSONdata)
            eList = loadList(JSONdata)
            eList = self.sortData(eList)
            self.updateHeaderFields(hList)
            self.updateFields(eList, self.summarySelected.current())

    def updateHeaderFields(self, header):
        # Update header fields for the file
        logging.debug("")
        global urlData
        urlData = header["url"]
        self.selection_frame.configure(text=header["title"])
        self.fileCount.set(header["count"])
        utc_time = datetime.utcfromtimestamp(header["timeStamp"] /
                                             1000).replace(tzinfo=pytz.utc)
        self.fileTime.set(utc_time.strftime("%Y-%m-%d %H:%M:%S %Z"))
        self.fileDelta.set(deltaTime(self, utc_time))

    def updateFields(self, data, rec):
        logging.debug("")
        if len(data) > 0:
            # Update fields in the display from the data record
            self.mag.set(f"{data[rec][1]:.1f}")
            self.place.set(data[rec][2])
            utc_time = datetime.utcfromtimestamp(data[rec][3] /
                                                 1000).replace(tzinfo=pytz.utc)
            self.time.set(utc_time.strftime("%Y-%m-%d %H:%M:%S %Z"))
            current_tz = utc_time.astimezone(get_localzone())
            self.tz.set(current_tz.strftime("%Y-%m-%d %H:%M:%S %Z"))
            self.urlName.set(data[rec][5])
            self.felt.set(data[rec][6])
            self.alert.set(data[rec][7])
            self.shake.set(f"{data[rec][8]:.3f}")
            tmpLat = data[rec][10]
            if tmpLat == 0:
                self.lat.set("{} \xb0".format(tmpLat))
            elif tmpLat > 0:
                self.lat.set("{} \xb0 N".format(tmpLat))
            else:
                tmpLat *= -1
                self.lat.set("{} \xb0 S".format(tmpLat))
            tmpLong = data[rec][9]
            if tmpLong == 0:
                self.lon.set("{} \xb0".format(tmpLong))
            elif tmpLong > 0:
                self.lon.set("{} \xb0 E".format(tmpLong))
            else:
                tmpLong *= -1
                self.lon.set("{} \xb0 W".format(tmpLong))
            self.depth.set("{} km".format(data[rec][11]))
            # self.lon.set(data[rec][5])
            self.deltaEntry.set(deltaTime(self, utc_time))
        else:
            self.mag.set(None)
            self.place.set(None)
            self.time.set(None)
            self.tz.set(None)
            self.urlName.set(None)
            self.felt.set(None)
            self.alert.set(None)
            self.shake.set(None)
            self.lat.set(None)
            self.lon.set(None)
            self.depth.set(None)
            self.deltaEntry.set(None)
        self.urlEntry.config(
            text=self.urlName.get(),
            command=lambda arg=self.urlName.get(): self._webCallbackFunc(arg))
예제 #14
0
class GraphyInspector:

    def __init__(self, parent):

        self.parent = parent

        self.width = self.parent.right_frame_width
        self.padding = self.parent.right_frame_padding

        self.frame = Frame(master=self.parent.right_frame)
        self.frame.pack(side='top', fill='y', )

        # "Inspector" title bar
        self.title_frame = Frame(master=self.frame)
        self.title_frame.pack(side='top')
        self.title_label = Label(master=self.title_frame, text="Inspector", width=self.width, bg='lightgray')
        self.title_label.pack()

        # identifier for type of object selected
        self.type_frame = Frame(master=self.frame, relief='sunken')
        self.type_frame.pack(side='top', fill='x', pady=self.padding, padx=self.padding)
        self.type_label1 = Label(master=self.type_frame, width=int(self.width/2)-self.padding, text='Object:')
        self.type_label1.pack(side='left', padx=self.padding, pady=self.padding)
        self.type_label2 = Label(master=self.type_frame, width=int(self.width / 2) - self.padding, text='', bg='white')
        self.type_label2.pack(side='right', padx=self.padding, pady=self.padding)

        # label of selected object (i.e. name user gives them, no canvas IDs here)
        self.label_frame = Frame(master=self.frame, relief='sunken')
        self.label_frame.pack(side='top', fill='x', pady=self.padding, padx=self.padding)
        self.label_label = Label(master=self.label_frame, width=int(self.width/2)-self.padding, text="Label:")
        self.label_label.pack(side='left', padx=self.padding, pady=self.padding)
        self.label_var = StringVar()
        self.label_var.set('')
        self.label_entry = Entry(self.label_frame, width=int(self.width/2)-self.padding, textvariable=self.label_var)
        self.label_entry.pack(side='right', padx=self.padding, pady=self.padding)
        self.label_entry.bind('<Button-1>', self.select_label_text)
        self.label_entry.bind('<Return>', self.drop_widget_focus)

        # status identifier (for vertices and layers)
        self.status_frame = Frame(master=self.frame, relief='sunken')
        self.status_frame.pack(side='top', fill='x', pady=self.padding, padx=self.padding)
        self.status_label1 = Label(master=self.status_frame, width=int(self.width/2)-self.padding, text='Status:')
        self.status_label1.pack(side='left', padx=self.padding, pady=self.padding)
        self.status_label2 = Label(master=self.status_frame, width=int(self.width/2)-self.padding, text='', bg='white')
        self.status_label2.pack(side='right', padx=self.padding, pady=self.padding)
        self.activation_var = StringVar()
        self.activation_var.set('')
        self.activation_menu = OptionMenu(self.status_frame, self.activation_var, "Identity", "Sigmoid", "ReLU", "Logarithmic", "Exponential")
        self.activation_menu.pack(side='right', padx=self.padding, pady=self.padding)

        # weight identifier (for edges only)
        self.weight_frame = Frame(master=self.frame, relief='sunken')
        self.weight_frame.pack(side='top', fill='x', pady=self.padding, padx=self.padding)
        self.weight_label = Label(master=self.weight_frame, width=int(self.width/2)-self.padding, text="Weight:")
        self.weight_label.pack(side='left', padx=self.padding, pady=self.padding)
        self.weight_var = DoubleVar()
        self.weight_entry = Entry(self.weight_frame, width=int(self.width / 2) - self.padding, textvariable=self.weight_var)
        self.weight_entry.pack(side='right', padx=self.padding, pady=self.padding)
        self.weight_entry.bind('<Button-1>', self.select_weight_text)
        self.weight_entry.bind('<Return>', self.drop_widget_focus)

        # node count identifier (for layers only)
        self.node_frame = Frame(master=self.frame, relief='sunken')
        self.node_frame.pack(side='top', fill='x', pady=self.padding, padx=self.padding)
        self.node_label = Label(master=self.node_frame, width=int(self.width/2)-self.padding, text="Node Count:")
        self.node_label.pack(side='left', padx=self.padding, pady=self.padding)
        self.node_var = IntVar()
        self.node_entry = Entry(self.node_frame, width=int(self.width / 2) - self.padding, textvariable=self.node_var)
        self.node_entry.pack(side='right', padx=self.padding, pady=self.padding)
        self.node_entry.bind('<Button-1>', self.select_node_text)
        self.node_entry.bind('<Return>', self.drop_widget_focus)

        # leakiness
        self.leakiness_frame = Frame(master=self.frame, relief='sunken')
        self.leakiness_frame.pack(side='top', fill='x', pady=self.padding, padx=self.padding)
        self.leakiness_label = Label(master=self.leakiness_frame, width=int(self.width/2)-self.padding, text="Leakiness")
        self.leakiness_label.pack(side='left', padx=self.padding, pady=self.padding)
        self.leakiness_var = DoubleVar()
        self.leakiness_entry = Entry(self.leakiness_frame, width=int(self.width / 2) - self.padding, textvariable=self.leakiness_var)
        self.leakiness_entry.pack(side='right', padx=self.padding, pady=self.padding)
        self.leakiness_entry.bind('<Button-1>', self.select_leakiness_text)
        self.leakiness_entry.bind('<Return>', self.drop_widget_focus)

        # bias
        self.bias_frame = Frame(master=self.frame, relief='sunken')
        self.bias_frame.pack(side='top', fill='x', pady=self.padding, padx=self.padding)
        self.bias_label = Label(master=self.bias_frame, width=int(self.width/2)-self.padding, text="Bias:")
        self.bias_label.pack(side='left', padx=self.padding, pady=self.padding)
        self.bias_var = DoubleVar()
        self.bias_entry = Entry(self.bias_frame, width=int(self.width / 2) - self.padding, textvariable=self.bias_var)
        self.bias_entry.pack(side='right', padx=self.padding, pady=self.padding)
        self.bias_entry.bind('<Button-1>', self.select_bias_text)
        self.bias_entry.bind('<Return>', self.drop_widget_focus)

        # output bound
        self.bound_frame = Frame(master=self.frame, relief='sunken')
        self.bound_frame.pack(side='top', fill='x', pady=self.padding, padx=self.padding)
        self.bound_label = Label(master=self.bound_frame, width=int(self.width/2)-self.padding, text="Output Bound:")
        self.bound_label.pack(side='left', padx=self.padding, pady=self.padding)
        self.bound_var = DoubleVar()
        self.bound_entry = Entry(self.bound_frame, width=int(self.width / 2) - self.padding, textvariable=self.bound_var)
        self.bound_entry.pack(side='right', padx=self.padding, pady=self.padding)
        self.bound_entry.bind('<Button-1>', self.select_bound_text)
        self.bound_entry.bind('<Return>', self.drop_widget_focus)

        # noise
        self.noise_frame = Frame(master=self.frame, relief='sunken')
        self.noise_frame.pack(side='top', fill='x', pady=self.padding, padx=self.padding)
        self.noise_label = Label(master=self.noise_frame, width=int(self.width/2)-self.padding, text="Weight Noise:")
        self.noise_label.pack(side='left', padx=self.padding, pady=self.padding)
        self.noise_var = DoubleVar()
        self.noise_entry = Entry(self.noise_frame, width=int(self.width / 2) - self.padding, textvariable=self.noise_var)
        self.noise_entry.pack(side='right', padx=self.padding, pady=self.padding)
        self.noise_entry.bind('<Button-1>', self.select_noise_text)
        self.noise_entry.bind('<Return>', self.drop_widget_focus)

        # input / output
        self.input_output_frame = Frame(master=self.frame, relief='sunken')
        self.input_output_frame.pack(side='top', fill='x', pady=self.padding, padx=self.padding)
        self.input_var = BooleanVar()
        self.input_var.set(False)
        self.output_var = BooleanVar()
        self.output_var.set(False)
        self.input_toggle = Checkbutton(master=self.input_output_frame, text="Is Input", variable=self.input_var)
        self.output_toggle = Checkbutton(master=self.input_output_frame, text="Is Output", variable=self.output_var)
        self.input_toggle.pack(side='left', padx=self.padding, pady=self.padding)
        self.output_toggle.pack(side='left', padx=self.padding, pady=self.padding)

        self.selected = None
        self.selected_type = None
        self.set_unselected()

        self.label_var.trace('w', self.set_selected_label)
        self.weight_var.trace('w', self.set_selected_weight)
        self.activation_var.trace('w', self.set_selected_activation)
        self.leakiness_var.trace('w', self.set_selected_leakiness)
        self.node_var.trace('w', self.set_selected_node_count)
        self.bias_var.trace('w', self.set_selected_bias)
        self.bound_var.trace('w', self.set_selected_bound)
        self.noise_var.trace('w', self.set_selected_noise)
        self.input_var.trace('w', self.set_input)
        self.output_var.trace('w', self.set_output)

        # mode
        self.mode = parent.mode
        self.set_mode(parent.mode)

    # object is a vertex or edge, type is 'vertex' or 'edge'...
    def set_selected(self, selected_object, selected_object_type):

        self.selected = selected_object
        self.selected_type = selected_object_type

        if self.mode == "Graph":
            if selected_object_type == 'vertex':
                self.type_label2.config(text="Vertex")
                self.status_label2.config(text=selected_object.status)

                self.type_frame.pack(side='top', fill='x', pady=self.padding, padx=self.padding)
                self.label_frame.pack(side='top', fill='x', pady=self.padding, padx=self.padding)
                self.status_frame.pack(side='top', fill='x', pady=self.padding, padx=self.padding)

                self.label_var.set(selected_object.label)

            elif selected_object_type == 'edge':
                self.type_label2.config(text="Edge")

                self.type_frame.pack(side='top', fill='x', pady=self.padding, padx=self.padding)
                self.label_frame.pack(side='top', fill='x', pady=self.padding, padx=self.padding)
                self.weight_frame.pack(side='top', fill='x', pady=self.padding, padx=self.padding)

                self.label_var.set(selected_object.label)
                self.weight_var.set(selected_object.weight)

            else:
                print('dafuq is going on')

        elif self.mode == "Net":
            if selected_object_type == 'vertex':
                self.type_label2.config(text="Layer")
                self.status_label2.config(text=selected_object.status)

                self.type_frame.pack(side='top', fill='x', pady=self.padding, padx=self.padding)
                self.label_frame.pack(side='top', fill='x', pady=self.padding, padx=self.padding)
                self.status_frame.pack(side='top', fill='x', pady=self.padding, padx=self.padding)
                self.node_frame.pack(side='top', fill='x', pady=self.padding, padx=self.padding)
                self.leakiness_frame.pack(side='top', fill='x', pady=self.padding, padx=self.padding)
                self.bias_frame.pack(side='top', fill='x', pady=self.padding, padx=self.padding)
                self.bound_frame.pack(side='top', fill='x', pady=self.padding, padx=self.padding)
                self.input_output_frame.pack(side='top', fill='x', pady=self.padding, padx=self.padding)

                self.label_var.set(selected_object.label)
                self.node_var.set(selected_object.node_count)
                self.activation_var.set(selected_object.status)
                self.leakiness_var.set(selected_object.leakiness)
                self.bias_var.set(selected_object.bias)
                self.bound_var.set(selected_object.bound)
                self.input_var.set(selected_object.is_input_layer)
                self.output_var.set(selected_object.is_output_layer)

            elif selected_object_type == 'edge':
                self.type_label2.config(text="Weights")

                self.type_frame.pack(side='top', fill='x', pady=self.padding, padx=self.padding)
                self.label_frame.pack(side='top', fill='x', pady=self.padding, padx=self.padding)
                self.weight_frame.pack(side='top', fill='x', pady=self.padding, padx=self.padding)
                self.noise_frame.pack(side='top', fill='x', pady=self.padding, padx=self.padding)

                self.label_var.set(selected_object.label)
                self.weight_var.set(selected_object.weight)
                self.noise_var.set(selected_object.noise)

        else:
            print('This will never happen.')

    # nothing is selected
    def set_unselected(self):
        self.type_frame.pack_forget()
        self.label_frame.pack_forget()
        self.status_frame.pack_forget()
        self.weight_frame.pack_forget()
        self.node_frame.pack_forget()
        self.bias_frame.pack_forget()
        self.bound_frame.pack_forget()
        self.noise_frame.pack_forget()
        self.input_output_frame.pack_forget()
        self.leakiness_frame.pack_forget()
        self.selected = None
        self.selected_type = None

    # set label of selected object
    def set_selected_label(self, *args):
        self.selected.set_label(self.label_var.get())

    # set weight of selected object
    def set_selected_weight(self, *args):
        self.selected.set_weight(self.weight_var.get())

    def set_selected_activation(self, *args):
        self.selected.set_status(self.activation_var.get())

    def set_selected_node_count(self, *args):
        self.selected.set_node_count(self.node_var.get())

    def set_selected_bias(self, *args):
        self.selected.set_bias(self.bias_var.get())

    def set_selected_bound(self, *args):
        self.selected.set_bound(self.bound_var.get())

    def set_selected_noise(self, *args):
        self.selected.set_noise(self.noise_var.get())

    def set_input(self, *args):
        self.selected.set_input_layer(self.input_var.get())

    def set_output(self, *args):
        self.selected.set_output_layer(self.output_var.get())

    def set_selected_leakiness(self, *args):
        self.selected.set_leakiness(self.leakiness_var.get())

    def update(self):
        if self.selected:
            selected = self.selected
            type = self.selected_type
            self.set_unselected()
            self.set_selected(selected, type)

    def select_label_text(self, event):
        if event:
            # delay so the default click doesn't undo selection, then recall and fall through to "else"
            self.parent.tk.after(50, self.select_label_text, False)
        else:
            self.label_entry.select_range(0, 'end')
            self.label_entry.icursor(0)

    def select_weight_text(self, event):
        if event:
            # delay so the default click doesn't undo selection, then recall and fall through to "else"
            self.parent.tk.after(50, self.select_weight_text, False)
        else:
            self.weight_entry.select_range(0, 'end')
            self.weight_entry.icursor(0)

    def select_node_text(self, event):
        if event:
            self.parent.tk.after(50, self.select_node_text, False)
        else:
            self.node_entry.select_range(0, 'end')
            self.node_entry.icursor(0)

    def select_bias_text(self, event):
        if event:
            self.parent.tk.after(50, self.select_bias_text, False)
        else:
            self.bias_entry.select_range(0, 'end')
            self.bias_entry.icursor(0)

    def select_noise_text(self, event):
        if event:
            self.parent.tk.after(50, self.select_noise_text, False)
        else:
            self.noise_entry.select_range(0, 'end')
            self.noise_entry.icursor(0)

    def select_bound_text(self, event):
        if event:
            self.parent.tk.after(50, self.select_bound_text, False)
        else:
            self.bound_entry.select_range(0, 'end')
            self.bound_entry.icursor(0)

    def select_leakiness_text(self, event):
        if event:
            self.parent.tk.after(50, self.select_leakiness_text, False)
        else:
            self.leakiness_entry.select_range(0, 'end')
            self.leakiness_entry.icursor(0)

    def drop_widget_focus(self, event):
        self.frame.focus()

    def set_mode(self, mode):
        if mode == "Graph":
            self.mode = mode
            self.weight_label.config(text="Weight:")
            self.status_label1.config(text="Status:")
            self.activation_menu.pack_forget()
            self.input_output_frame.pack_forget()
            self.status_label2.pack(side='right', padx=self.padding, pady=self.padding)
        elif mode == "Net":
            self.mode = mode
            self.weight_label.config(text="Start Weight:")
            self.status_label1.config(text="Activation:")
            self.status_label2.pack_forget()
            self.activation_menu.pack(side='right', padx=self.padding, pady=self.padding)
        else:
            print("This will never happen.")
예제 #15
0
class GeoDemonstrator(Tk, GeoMixinTrans, GeoMixinHelp):
    # Konstruktor aplikacije
    def __init__(self):
        # Log poruka o pokretanju aplikacije
        print('Dobro došli u aplikaciju GeoDemonstrator!')

        # Pozivanje konstruktora roditeljske klase
        super().__init__()

        # Postavljanje naziva aplikacije
        self.title('GeoDemonstrator')

        # Inicijalizacija liste tačaka
        self.tačke = []
        self.ttačke = []

        # Inicijalizacija liste identifikatora
        # na platnu trenutno iscrtanih tačaka
        self.id_tač = []

        # Inicijalizacija figure
        self.figura = None

        # Inicijalizacija transformacija iz platna
        # u iscrtani koordinatni sistem i obrnuto
        self.puk = Skal(1 / 7, -1 / 7) * Trans(-204, -132)
        self.kup = Trans(204, 132) * Skal(7, -7)

        # Inicijalizacija elemenata GKI
        self.init_gki()

    # Inicijalizacija elemenata GKI
    def init_gki(self):
        # Postavljanje veličine i pozicije prozora
        self.geometry('450x450+75+75')

        # Onemogućavanje promene veličine prozora,
        # pošto je Tk prilično plastičan, pa promene
        # ugrožavaju zamišljeni izgled aplikacije
        self.resizable(False, False)

        # Inicijalizacija glavnog menija
        self.init_meni()

        # Inicijalizacija platna
        self.init_platno()

        # Kontrola unosa tačaka
        self.init_unos()

    # Inicijalizacija glavnog menija
    def init_meni(self):
        # Pravljenje glavnog menija
        meni = Menu(self)

        # Postavljanje sporednog padajućeg menija
        self.umeni = Menu(meni)
        self.umeni.add_command(label='Zaključi unos',
                               command=self.promena_unosa)
        self.umeni.add_command(label='Ispravi figuru', command=self.ispravi)
        self.umeni.add_command(label='Očisti platno',
                               command=partial(self.novo_platno, True))

        # Postavljanje glavnog menija i vezivanje
        # komandi za odgovarajuće funkcionalnosti
        meni.add_cascade(label='Opcije', menu=self.umeni)
        meni.add_command(label='Pomoć (H)', command=self.pomoć)
        meni.add_command(label='Info (G)', command=self.info)
        self.config(menu=meni)

        # Vezivanje tipki za akcije analogne
        # onima iz prethodno postavljenog menija;
        # od F1 se odustalo jer se ne ponaša kako
        # treba na operativnom sistemu Windows
        self.bind('<H>', self.pomoć)
        self.bind('<h>', self.pomoć)
        self.bind('<G>', self.info)
        self.bind('<g>', self.info)
        self.bind('<Escape>', self.kraj)

        # Vezivanje protokola zatvaranja prozora
        # za istu akciju kao za Kraj i Escape
        self.protocol('WM_DELETE_WINDOW', self.kraj)

    # Inicijalizacija platna
    def init_platno(self):
        # Pravljenje okvira za platno
        okvir_p = LabelFrame(self,
                             text='Zakoračite u svet geometrijskih'
                             ' transformacija',
                             padx=10,
                             pady=10)
        okvir_p.place(x=10, y=10, height=300, width=430)

        # Postavljanje platna unutar okvira
        self.platno = Canvas(okvir_p, height=261, width=405)
        self.platno.place(x=0, y=0)

        # Postavljanje koordinatnog sistema na platno;
        # slika nije lokalna promenljiva, pošto bi je u
        # tom slučaju 'pojeo' sakupljač otpadaka
        self.slika = self.učitaj_sliku('koord.gif')
        self.platno.create_image(203, 131, image=self.slika)

        # Vezivanje čuvanja tačke za klik na platno
        self.unos = True
        self.platno.bind('<Button-1>', self.dodaj_tačku)

        # Vezivanje promene unosa za desni klik,
        # a ispravljanja figure za srednji, prema
        # sugestiji asistenta, čime se dobija na
        # lakoći korišćenja, bez potrebe za menijem
        self.platno.bind('<Button-2>', self.ispravi)
        self.platno.bind('<Button-3>', self.promena_unosa)

    # Okvir za magični svet transformacija
    def init_unos(self):
        # Pravljenje okvira za elemente
        self.okvir_d = LabelFrame(self,
                                  text='Unosite tačke klikovima'
                                  ' po platnu',
                                  padx=10,
                                  pady=10)
        self.okvir_d.place(x=10, y=315, height=128, width=430)

        # Inicijalizacija polja sa transformacijama
        self.init_trans()

        # Oznake parametara koje korisnik unosi
        x_koord_labela = Label(self, text='x:')
        y_koord_labela = Label(self, text='y:')
        ugao_labela = Label(self, text='\u03b8:')

        # Postavljanje oznaka na prozor
        x_koord_labela.place(x=185, y=348)
        y_koord_labela.place(x=185, y=375)
        ugao_labela.place(x=185, y=403)

        # Polja za unos vrednosti transformacija
        self.x_koord = Entry(self, width=4, state='disabled')
        self.y_koord = Entry(self, width=4, state='disabled')
        self.ugao = Entry(self, width=4, state='disabled')

        # Postavljanje polja na prozor
        self.x_koord.place(x=200, y=348)
        self.y_koord.place(x=200, y=375)
        self.ugao.place(x=200, y=403)

        # Postavljanje ostalih elemenata
        self.init_centar()
        self.init_inverz()

    # Transformacijski okvir
    def init_trans(self):
        # Mapa za preslikavanje niske u
        # odgavarajuću klasu transformacije
        self.funkcije = {
            'translacija': Trans,
            'skaliranje': Skal,
            'smicanje': Smic,
            'rotacija': Rot,
            'refleksija': Refl
        }

        # Pravljenje okvira za odabir transformacije
        okvir_t = LabelFrame(self,
                             text='Izaberite transformaciju',
                             padx=23,
                             pady=7)
        okvir_t.place(x=18, y=337, height=95, width=158)

        # U zavisnosti od vrednosti var koju pročitamo iz
        # padajućeg menija, poziva se prava transformacija
        self.tr = StringVar(self)
        self.tr.set('')

        # Funkcija za praćenje promenljive; izveštava o odabiru
        # transformacije i kontroliše pristup poljima za unos
        # parametara u zavisnosti od odabira; nepakovana lista
        # argumenata *args je neophodna kako bi se prosledili
        # (i zanemarili) dodatni podaci o promeni odabira, slično
        # kao što npr. kolbek funkcije u GLUT-u obavezno primaju
        # koordinate događaja, iako one često nisu nužan podatak
        self.tr.trace(
            'w',
            lambda *args: print('Odabrana transformacija:'
                                ' {}.'.format(self.tr.get())) or self.kontrola(
                                ))

        # Padajuća lista geometrijskih transformacija;
        # umesto dosad korišćene fje place za postavljanje
        # objekta na tačno određeno mesto na prozoru, ovde
        # se koristi pack, koji objekat optimalno spakuje
        # na raspoloživom prostoru; iz tog razloga je i
        # roditeljski element upravo transformacioni okvir,
        # u koji se pakuje, a ne self, kako je dosad bilo
        OptionMenu(okvir_t, self.tr, 'translacija', 'skaliranje', 'smicanje',
                   'rotacija', 'refleksija').pack(fill='x')

        # Dugme za pokretanje transformacije
        self.dugme_t = Button(okvir_t,
                              text='Transformiši',
                              command=self.transformiši,
                              state='disabled')
        self.dugme_t.pack(fill='x')

    # Odabir centra transformacije
    def init_centar(self):
        # Promenljiva za praćenje
        self.centar = StringVar(self)
        self.centar.set(None)
        self.centar.trace(
            'w', lambda *args: print('Odabran {}'
                                     ' za centar transformacije.'.format(
                                         self.centar.get()))
            if self.centar.get() != 'None' else None)

        # Oznaka za odabir centra
        odabir_centra = Label(self, text='Centar transformacije:')
        odabir_centra.place(x=265, y=330)

        # Dugme za transformaciju sa centrom
        # u koordinatnom početku
        self.radio1 = Radiobutton(self,
                                  text='centar platna',
                                  padx=3,
                                  variable=self.centar,
                                  value='centar platna',
                                  state='disabled',
                                  command=partial(self.kontrola, True))
        self.radio1.place(x=242, y=350)

        # Dugme za transformaciju sa centrom
        # u centru mase (baricentru) figure
        self.radio2 = Radiobutton(self,
                                  text='centar mase',
                                  padx=3,
                                  variable=self.centar,
                                  value='centar mase',
                                  state='disabled',
                                  command=partial(self.kontrola, True))
        self.radio2.place(x=242, y=370)

        # Dugme za transformaciju sa centrom
        # u korisnički unetoj tački
        self.radio3 = Radiobutton(self,
                                  text='uneta tačka',
                                  padx=3,
                                  variable=self.centar,
                                  value='korisnički unos',
                                  state='disabled',
                                  command=partial(self.kontrola, True))
        self.radio3.place(x=242, y=390)

        # Oznake za unos centra transformacija
        t1_labela = Label(self, text='t1:')
        t2_labela = Label(self, text='t2:')

        # Postavljanje oznaka na prozor
        t1_labela.place(x=360, y=358)
        t2_labela.place(x=360, y=385)

        # Polja za unos centra transformacija
        self.t1_koord = Entry(self, width=4, state='disabled')
        self.t2_koord = Entry(self, width=4, state='disabled')

        # Postavljanje polja na prozor
        self.t1_koord.place(x=380, y=358)
        self.t2_koord.place(x=380, y=385)

    # Funkcija za praćenje inverza
    def init_inverz(self):
        self.inv = BooleanVar(self)
        self.inv.trace(
            'w', lambda *args: print('Odabrana inverzna'
                                     ' transformacija.')
            if self.inv.get() else print('Odabrana klasična transformacija.'))

        # Dugme za odabir inverza
        self.inverz = Checkbutton(self,
                                  text='Invertuj promenu',
                                  variable=self.inv,
                                  state='disabled')
        self.inverz.place(x=262, y=410)
예제 #16
0
class Statistics(ttk.Frame):
    data = dict()

    def __init__(self, master, axis):
        ttk.Frame.__init__(self, master, padding="5")

        self.axis = axis

        self.is_gaussian = BooleanVar(value=False)
        self.is_gaussian.trace("w", self.replot)

        self.fig = Figure(figsize=(5, 4), dpi=100)
        self.plot = self.fig.add_subplot(111)

        self._create_widgets()

    def replot(self, *args):
        self.plot.clear()
        if self.is_gaussian.get():
            for name, errors in self.data.iter():
                self.plot_probability(name, errors[1])

            self.plot.set_xlabel("Error (microns)")
            self.plot.set_ylabel("Probability")
        else:
            for name, errors in self.data.iter():
                self.plot.plot(errors[0], errors[1], label=name)

            self.plot.set_xlabel("Encoder Value")
            self.plot.set_ylabel("Error (microns)")

        self.plot.legend()
        self.fig.canvas.draw()

    def plot_probability(self, label, errors):
        hist, bins = np.histogram(errors, bins=50, density=True)
        centers = (bins[:-1] + bins[1:]) / 2

        prob = interpolate.InterpolatedUnivariateSpline(centers, hist)

        color = (random(), random(), random())
        xp = np.linspace(centers[0], centers[-1], 100)
        self.plot.plot(centers, hist, '.', color=color)
        self.plot.plot(xp, prob(xp), '-', color=color, label=label)

    def analyse_data(self, name, data):
        i = 0
        temp_name = name
        while temp_name in self.data.keys():
            i += 1
            temp_name = name + "_{}".format(i)
        name = temp_name

        errors = self.get_errors(data)

        self.data[name] = np.array([data[0], errors])

    def analyse_data_from_file(self, filename):
        data = np.loadtxt(filename, delimiter=",")
        filename = os.path.split(filename)[1].split(".")[0]
        self.analyse_data(filename, data)

    def more_details(self):
        window = Toplevel(self)
        u = " (" + chr(181) + "m)"
        columns = ("Min Error" + u, "Max Error" + u, "Mean Error" + u,
                   "Standard Deviation" + u)

        data_grid = ttk.Treeview(window, columns=columns)

        i = 0
        data_grid.heading('#{}'.format(i), text="File")

        for c in columns:
            i += 1
            data_grid.heading('#{}'.format(i), text=c)

        for name, errors in self.data.iteritems():
            err = errors[1]
            data_grid.insert('', 0, iid=name, text=name)
            i = 0
            for v in [np.min(err), np.max(err), np.mean(err), np.std(err)]:
                data_grid.set(name, column=i, value="{:.3g}".format(v))
                i += 1

        data_grid.pack()

    def get_errors(self, data):
        b, c = np.polyfit(data[0], data[1], 1)

        b = self.axis.microstep.get() / (self.axis.motor_res.get() *
                                         self.axis.enc_res.get())

        # Calculate the error from the theoretical value and convert to microns
        vfunc = np.vectorize(lambda x, y: ((b * x + c) - y) * self.axis.
                             motor_res.get() / self.axis.microstep.get())

        return vfunc(data[0], data[1])

    def change_axis(self, axis):
        self.axis = axis

    def _load_data(self):
        files = filedialog.askopenfilename(initialdir=os.getcwd(),
                                           filetypes=[("Text", "*.txt")],
                                           multiple=1)
        for f in files:
            self.analyse_data_from_file(f)
        self.replot()

    def _clear(self):
        self.data = dict()
        self.plot.clear()
        self.fig.canvas.draw()

    def _create_widgets(self):
        canvas = FigureCanvasTkAgg(self.fig, master=self)
        canvas.show()
        canvas.get_tk_widget().pack(side=TOP, fill=BOTH, expand=1)

        toolbar = NavigationToolbar2TkAgg(canvas, self)
        toolbar.update()
        toolbar.pack(side=BOTTOM)

        ttk.Separator(toolbar).pack(side=LEFT, fill=Y, padx="10")
        ttk.Button(toolbar, text="Load",
                   command=self._load_data).pack(side=LEFT, fill=Y)
        ttk.Button(toolbar, text="Clear", command=self._clear).pack(side=LEFT,
                                                                    fill=Y)
        ttk.Button(toolbar, text="More Details",
                   command=self.more_details).pack(side=LEFT, fill=Y)
        ttk.Checkbutton(toolbar, text="Prob. Dist.",
                        variable=self.is_gaussian).pack(side=LEFT, fill=Y)

        canvas._tkcanvas.pack(side=TOP)
예제 #17
0
    def __init__(self, master, par=False):
        """
        GUI for selecting default parameters - will write parameters to file \
        of users choosing.

        :type master: Tk
        :param master: Tkinter window
        :type par: EQcorrscanParameters
        :param par: Default parameters to start-up with.
        """
        from tkinter import Label, Button, Entry, DoubleVar, StringVar, IntVar
        from tkinter import BooleanVar, OptionMenu, Checkbutton
        import tkMessageBox
        from eqcorrscan.utils import parameters
        from obspy import UTCDateTime
        import warnings

        # Set the default par, only if they don't already exist.
        if not par:
            par = parameters.EQcorrscanParameters([''], 2, 10, 4, 100, 2,
                                                  '1900-01-01', '2300-01-01',
                                                  '', 'seishub', 4, False, '',
                                                  'jpg', False, 8, 'MAD', 6)
        # Callback functions for all variables (ugly)

        def update_template_names(*args):
            par.template_names = [name.strip() for name in
                                  template_names.get().split(',')]
            template_names.set(', '.join(par.template_names))

        def update_lowcut(*args):
            par.lowcut = lowcut.get()
            lowcut.set(par.lowcut)

        def update_highcut(*args):
            par.highcut = highcut.get()
            if par.highcut >= 0.5 * par.samp_rate:
                msg = ('Highcut must be less than the Nyquist, setting to ' +
                       str((par.samp_rate / 2.0) - 1))
                tkMessageBox.showwarning(title="Nyquist error",
                                         message=msg)
                par.highcut = (par.samp_rate / 2.0) - 1
            highcut.set(par.highcut)

        def update_filt_order(*args):
            par.filt_order = filt_order.get()
            filt_order.set(par.filt_order)

        def update_samp_rate(*args):
            par.samp_rate = samp_rate.get()
            if par.highcut >= 0.5 * par.samp_rate:
                msg = ('Highcut must be less than the Nyquist, setting to ' +
                       str((par.samp_rate / 2.0) - 1))
                tkMessageBox.showwarning(title="Nyquist error",
                                         message=msg)
                par.highcut = (par.samp_rate / 2.0) - 1
                highcut.set(par.highcut)
            samp_rate.set(par.samp_rate)

        def update_debug(*args):
            par.debug = debug.get()
            debug.set(par.debug)

        def update_startdate(*args):
            par.startdate = UTCDateTime(startdate.get())
            startdate.set(str(par.startdate))

        def update_enddate(*args):
            par.enddate = UTCDateTime(enddate.get())
            enddate.set(str(par.enddate))

        def update_archive(*args):
            par.archive = archive.get()
            archive.set(par.archive)

        def update_arc_type(*args):
            par.arc_type = arc_type.get()
            arc_type.set(par.arc_type)

        def update_cores(*args):
            par.cores = cores.get()
            cores.set(par.cores)

        def update_plotvar(*args):
            par.plotvar = plotvar.get()
            plotvar.set(par.plotvar)

        def update_plot_format(*args):
            par.plot_format = plot_format.get()
            plot_format.set(par.plot_format)

        def update_tempdir(*args):
            par.tempdir = tempdir.get()
            tempdir.set(par.tempdir)

        def update_threshold(*args):
            par.threshold = threshold.get()
            threshold.set(par.threshold)

        def update_threshold_type(*args):
            par.threshold_type = threshold_type.get()
            threshold_type.set(par.threshold_type)

        def update_plotdir(*args):
            par.plotdir = plotdir.get()
            plotdir.set(par.plotdir)

        def update_trigger_interval(*args):
            par.trigger_interval = trigger_interval.get()
            trigger_interval.set(par.trigger_interval)
        # Set some grid parameters
        nrows = 25
        ncolumns = 3
        self.master = master
        master.title("EQcorrscan parameter setup")
        self.label = Label(master, text="Alpha GUI for default setup")
        self.label.grid(column=0, columnspan=ncolumns, row=0)

        # Set up parameter input
        self.t_names_label = Label(master, text="Template names", anchor='e')
        self.t_names_label.grid(column=0, row=1, sticky='e')
        template_names = StringVar()
        template_names.set(', '.join(par.template_names))
        self.t_names_box = Entry(master, bd=2, textvariable=template_names)
        self.t_names_box.grid(column=1, row=1)
        template_names.trace("w", update_template_names)
        self.t_names_lookup = Button(master, text="Lookup",
                                     command=lambda: self.get_template_names(par))
        self.t_names_lookup.grid(column=2, row=1)

        self.lowcut_label = Label(master, text="Lowcut (Hz)", anchor='e')
        self.lowcut_label.grid(column=0, row=2, sticky='e')
        lowcut = DoubleVar()
        lowcut.set(par.lowcut)
        self.lowcut_box = Entry(master, bd=2, textvariable=lowcut)
        self.lowcut_box.grid(column=1, row=2)
        lowcut.trace("w", update_lowcut)

        self.highcut_label = Label(master, text="Highcut (Hz)", anchor='e')
        self.highcut_label.grid(column=0, row=3, sticky='e')
        highcut = DoubleVar()
        highcut.set(par.highcut)
        self.highcut_box = Entry(master, bd=2, textvariable=highcut)
        self.highcut_box.grid(column=1, row=3)
        highcut.trace("w", update_highcut)

        self.filt_order_label = Label(master, text="Filter order")
        self.filt_order_label.grid(column=0, row=4, sticky='e')
        filt_order = DoubleVar()
        filt_order.set(par.filt_order)
        self.filt_order_box = Entry(master, bd=2, textvariable=filt_order)
        self.filt_order_box.grid(column=1, row=4)
        filt_order.trace("w", update_filt_order)

        self.samp_rate_label = Label(master, text="Sample rate (Hz)")
        self.samp_rate_label.grid(column=0, row=5, sticky='e')
        samp_rate = DoubleVar()
        samp_rate.set(par.samp_rate)
        self.samp_rate_box = Entry(master, bd=2, textvariable=samp_rate)
        self.samp_rate_box.grid(column=1, row=5)
        samp_rate.trace("w", update_samp_rate)

        self.debug_label = Label(master, text="Debug")
        self.debug_label.grid(column=0, row=6, sticky='e')
        debug = IntVar()
        debug.set(par.debug)
        self.debug_box = Entry(master, bd=2, textvariable=debug)
        self.debug_box.grid(column=1, row=6)
        debug.trace("w", update_debug)

        self.startdate_label = Label(master, text="Start date (yyyy-mm-dd)")
        self.startdate_label.grid(column=0, row=6, sticky='e')
        startdate = StringVar()
        startdate.set(par.startdate)
        self.startdate_box = Entry(master, bd=2, textvariable=startdate)
        self.startdate_box.grid(column=1, row=6)
        startdate.trace("w", update_startdate)

        self.enddate_label = Label(master, text="End date (yyyy-mm-dd)")
        self.enddate_label.grid(column=0, row=8, sticky='e')
        enddate = StringVar()
        enddate.set(par.enddate)
        self.enddate_box = Entry(master, bd=2, textvariable=enddate)
        self.enddate_box.grid(column=1, row=8)
        enddate.trace("w", update_enddate)

        self.archive_label = Label(master, text="Archive")
        self.archive_label.grid(column=0, row=9, sticky='e')
        archive = StringVar()
        archive.set(par.archive)
        self.archive_box = Entry(master, bd=2, textvariable=archive)
        self.archive_box.grid(column=1, row=9)
        archive.trace("w", update_archive)
        self.archive_lookup = Button(master, text="Lookup",
                                     command=lambda: self.get_archive(par))
        self.archive_lookup.grid(column=2, row=9)


        self.arc_type_label = Label(master, text="Archive type")
        self.arc_type_label.grid(column=0, row=10, sticky='e')
        arc_type = StringVar()
        arc_type.set(par.arc_type)
        self.arc_type_box = OptionMenu(master, arc_type,
                                       "seishub", "fdsn", "day_vols")
        self.arc_type_box.grid(column=1, row=10, sticky='w,e')
        arc_type.trace("w", update_arc_type)

        self.cores_label = Label(master, text="Number of cores")
        self.cores_label.grid(column=0, row=11, sticky='e')
        cores = IntVar()
        cores.set(par.cores)
        self.cores_box = Entry(master, bd=2, textvariable=cores)
        self.cores_box.grid(column=1, row=11)
        cores.trace("w", update_cores)

        self.plotvar_label = Label(master, text="Plotting on/off")
        self.plotvar_label.grid(column=0, row=12, sticky='e')
        plotvar = BooleanVar()
        plotvar.set(par.plotvar)
        self.plotvar_box = Checkbutton(master, text='Plot on', var=plotvar,
                                       onvalue=True, offvalue=False)
        self.plotvar_box.grid(column=1, row=12)
        plotvar.trace("w", update_plotvar)

        self.plotdir_label = Label(master, text="Plot directory")
        self.plotdir_label.grid(column=0, row=13, sticky='e')
        plotdir = StringVar()
        plotdir.set(par.plotdir)
        self.plotdir_box = Entry(master, bd=2, textvariable=plotdir)
        self.plotdir_box.grid(column=1, row=13)
        plotdir.trace("w", update_plotdir)
        self.plotdir_lookup = Button(master, text="Lookup",
                                     command=lambda: self.get_plotdir(par))
        self.plotdir_lookup.grid(column=2, row=13)

        self.plot_format_label = Label(master, text="Plot format")
        self.plot_format_label.grid(column=0, row=14, sticky='e')
        plot_format = StringVar()
        plot_format.set(par.plot_format)
        self.plot_format_box = OptionMenu(master, plot_format,
                                          "jpg", "eps", "pdf", "png")
        self.plot_format_box.grid(column=1, row=14, sticky='w,e')
        plot_format.trace("w", update_plot_format)

        self.tempdir_label = Label(master, text="Temporary directory")
        self.tempdir_label.grid(column=0, row=15, sticky='e')
        tempdir = StringVar()
        tempdir.set(par.tempdir)
        self.tempdir_box = Entry(master, bd=2, textvariable=tempdir)
        self.tempdir_box.grid(column=1, row=15)
        tempdir.trace("w", update_tempdir)
        self.tempdir_lookup = Button(master, text="Lookup",
                                     command=lambda: self.get_tempdir(par))
        self.tempdir_lookup.grid(column=2, row=15)

        self.threshold_label = Label(master, text="Threshold")
        self.threshold_label.grid(column=0, row=16, sticky='e')
        threshold = DoubleVar()
        threshold.set(par.threshold)
        self.threshold_box = Entry(master, bd=2, textvariable=threshold)
        self.threshold_box.grid(column=1, row=16)
        threshold.trace("w", update_threshold)

        self.threshold_type_label = Label(master, text="Threshold type")
        self.threshold_type_label.grid(column=0, row=17, sticky='e')
        threshold_type = StringVar()
        threshold_type.set(par.threshold_type)
        self.threshold_type_box = OptionMenu(master, threshold_type,
                                             "MAD", "absolute", "av_chan_corr")
        self.threshold_type_box.grid(column=1, row=17, sticky='w,e')
        threshold_type.trace("w", update_threshold_type)

        self.trigger_interval_label = Label(master,
                                            text="Minimum trigger " +
                                            "interval (s)")
        self.trigger_interval_label.grid(column=0, row=18, sticky='e')
        trigger_interval = DoubleVar()
        trigger_interval.set(par.trigger_interval)
        self.trigger_interval_box = Entry(master, bd=2,
                                          textvariable=trigger_interval)
        self.trigger_interval_box.grid(column=1, row=18)
        trigger_interval.trace("w", update_trigger_interval)

        # End of user editable section, now we have read/write buttons
        self.read_button = Button(master, text="Read parameters",
                                  command=lambda: self.read_par(master))
        self.read_button.grid(column=0, row=nrows-2, sticky='w,e')

        self.write_button = Button(master, text="Write parameters",
                                   command=lambda: self.write_par(par))
        self.write_button.grid(column=1, row=nrows-2, sticky='w,e')
예제 #18
0
class App(Tk):
    def __init__(self):
        super().__init__()
        self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        self.sock.connect(communication.SERVER_ADDRESS)
        self.sock.setblocking(False)
        self.title('OnlineDrive - Welcome')
        # Informa à aplicação qual método chamar ao fechar.
        self.protocol('WM_DELETE_WINDOW', self.on_close)
        self.current_frame = Frame()
        self.user_logged = BooleanVar()
        self.user_logged.set(False)
        self.user_logged.trace('w', self.user_state_changed)
        # Inicia o thread que recebe dados do servidor.
        Thread(target=self.get_server_response).start()

    def run(self):
        self.current_frame = LoginViewController.Controller(self).view
        self.mainloop()

    def on_close(self):
        # Abre um pop-up para confirmar se o usuário realmente deseja fechar a aplicação
        if messagebox.askquestion('Quit', 'Você deseja mesmo sair?') == 'yes':
            # Manda uma mensagem para o servidor informando-o para desconectar o cliente
            self.sock.sendall(
                json.dumps({
                    'action': communication.ACTIONS[2]
                }).encode())
            self.sock.close()
            # Fecha a aplicação
            self.destroy()

    def send_request(self, request: dict):
        serialized_request = json.dumps(request)
        Thread(target=self.sock.sendall,
               args=(serialized_request.encode(), )).start()

    def get_server_response(self):
        while True:
            data = self.sock.recv(communication.BUFFSIZE)
            response = json.loads(data.decode())

            if 'file_name' in response:
                # Recebe o nome do arquivo.
                print('Received file name. Preparing to receive file data.')
                self.recv_file_data(response['file_name'])
            else:
                if response == communication.RESULTS[0]:
                    print('response:', response['message'])

    def recv_file_data(self, file_name):
        # Recebe os dados do arquivo.
        with open(os.path.join('downloads', file_name), 'wb') as file:
            while True:
                print('Recebendo dados do arquivo.')
                data = self.sock.recv(communication.BUFFSIZE)
                file.write(data)

    def user_state_changed(self, *args):
        if self.user_logged.get() is True:
            # Remove o frame atual da tela.
            for widget in self.slaves():
                widget.destroy()

            # Abre um pop-up que informa que o usuário está logado.
            messagebox.showinfo('UHUU', 'Você está logado')
예제 #19
0
class MyApp(Tk):
    """
    This class serves as a central control.
    Where are all process are launched and variables are set and shared.
    """

    __title__ = "Senior"

    def __init__(self, *args, **kwargs):
        Tk.__init__(self, *args, **kwargs)

        container = Frame(self)
        container.grid()

        self.serial = SerialComm()

        self.frames = {}
        self.q = LifoQueue()
        self.eye_tracker = EyeTracker(self.q)

        self.variables = {}

        self.fps = IntVar()
        self.fps.set(20)

        self.temp = IntVar()
        self.temp.set(20)
        self.temp.trace("w", self.send_command)
        self.variables[self.temp.__str__()] = 't', self.temp

        self.temp_current = StringVar()
        self.temp_current.set('Temperature')

        self.tts = StringVar()
        self.tts.set('Type and Play')

        self.temp_offset = IntVar()
        self.temp_offset.set(5)
        self.temp_offset.trace("w", self.send_command)
        self.variables[self.temp_offset.__str__()] = 'o', self.temp_offset

        self.samples = 9

        self.window = IntVar()
        self.window.trace("w", self.send_command)
        self.variables[self.window.__str__()] = 'w', self.window

        self.mouse_control = BooleanVar()
        self.mouse_control.set(False)

        self.talk = BooleanVar()
        self.talk.set(True)

        self.alarm = BooleanVar()
        self.alarm.set(False)
        self.alarm.trace("w", self.send_command)
        self.variables[self.alarm.__str__()] = 'a', self.alarm

        self.light = BooleanVar()
        self.light.set(False)
        self.light.trace("w", self.send_command)
        self.variables[self.light.__str__()] = 'l', self.light

        self.heater = BooleanVar()
        self.heater.set(False)
        self.heater.trace("w", self.send_command)
        self.variables[self.heater.__str__()] = 'h', self.heater

        self.ac = BooleanVar()
        self.ac.set(False)
        self.ac.trace("w", self.send_command)
        self.variables[self.ac.__str__()] = 'f', self.ac

        self.move = BooleanVar()
        self.move.set(False)

        self.w, self.h = pyautogui.size()

        self.hor_div = DoubleVar()
        self.hor_div.set(5)
        self.hor_div.trace("w", self.send_command)
        self.variables[self.hor_div.__str__()] = 'hor', self.hor_div

        self.ver_div = DoubleVar()
        self.ver_div.set(5)
        self.ver_div.trace("w", self.send_command)
        self.variables[self.ver_div.__str__()] = 'ver', self.ver_div

        self.mouse_directions = []

        self.mouse = MouseAndSpeech(self)
        self.t = Thread(target=self.mouse.process)
        self.t.start()

        self.frame = None
        self.draw = False

        frame = Preview(container, self)
        self.frames[Preview] = frame
        frame.grid(row=0, column=1, sticky="nsew", rowspan=100)
        self.current_frame = frame

        frame = Settings(container, self)
        self.frames[Settings] = frame
        frame.grid(row=0, column=0, sticky="nsew", pady=10, padx=10)
        frame.grid_remove()

        frame = Applications(container, self)
        self.frames[Applications] = frame
        frame.grid(row=0, column=0, sticky="nsew", pady=10, padx=10)
        frame.grid_remove()

        # Menu Bar
        menu = MyMenu(self)
        self.config(menu=menu)

        Tk.iconbitmap(self, default=resource_path('icon.ico'))
        Tk.wm_title(self, "Senior")
        w = (self.winfo_screenwidth() - self.eye_tracker.window_size) // 2
        self.geometry('+{}+{}'.format(w, 0))
        self.protocol("WM_DELETE_WINDOW", lambda: self.close())

    def show_frame(self, cont):
        """
        This method is used to switch betwen views.
        """
        if self.current_frame is not None:
            self.current_frame.grid_remove()
        frame = self.frames[cont]
        frame.grid()
        self.current_frame = frame

        if cont is Applications:
            frame.button_alarm.focus()

    def send_command(self, widget, *args):
        """
        This method send data to the Arduino whenever a button is clicked.
        """
        w = self.variables[widget]
        try:
            indicator = w[0]
            value = str(int(w[1].get()))
            if indicator == 'f' and value == '1':
                self.heater.set(False)
                self.serial.send_serial('h0')
            elif indicator == 'h' and value == '1':
                self.ac.set(False)
                self.serial.send_serial('f0')
            elif indicator == 't':
                self.heater.set(False)
                self.ac.set(False)

            s = indicator + value
            self.serial.send_serial(s)

            if len(value) > 0:
                value = float(w[1].get())
                if indicator in ['ver', 'hor']:
                    x_offset = self.ver_div.get()
                    y_offset = self.hor_div.get()
                    if indicator == 'ver':
                        y_offset = value * (self.h // 100)
                    elif indicator == 'hor':
                        x_offset = value * (self.w // 100)

                    self.mouse_directions = [(-x_offset, -y_offset),
                                             (0, -y_offset),
                                             (x_offset, -y_offset),
                                             (-x_offset, 0), 0, (x_offset, 0),
                                             (-x_offset, y_offset),
                                             (0, y_offset),
                                             (x_offset, y_offset), 0]
        except:
            pass

    def close(self):
        """
        Method used to to close the program orderly so no threads are left hanging.
        """

        print(self.__title__)
        while self.mouse.isTalking:
            print('Is Talking')

        self.eye_tracker.video_capture.release()
        clear_queue(self.q)
        self.q.put(False)
        self.q.join()
        self.t.join()
        self.destroy()
예제 #20
0
파일: viewer.py 프로젝트: izag/imgviewer
class MainWindow:
    def __init__(self):
        global root

        self.provider = None
        self.session = None
        self.show_image = False
        self.original_image = None
        self.original_image_name = None
        self.main_image = None
        self.main_image_orig = None
        self.resized = False
        self.thumb_prefix = None
        self.proxies = None
        self.gallery_url = None
        self.hist_stack = []
        self.fwd_stack = []
        self.interrupt = False
        self.thumb_url = None
        self.image_url = None

        self.menu_bar = Menu(root)
        self.menu_bar.add_command(label="<< Back",
                                  command=self.back_in_history)
        self.menu_bar.add_command(label="Forward >>",
                                  command=self.forward_in_history)
        self.menu_bar.add_command(label="View gallery",
                                  command=self.view_gallery_url)
        self.menu_bar.add_command(label="Cancel", command=self.calcel)
        root.config(menu=self.menu_bar)

        frm_top = Frame(root)
        self.frm_main = ScrollFrame(root)
        frm_status = Frame(root)

        frm_center = Frame(self.frm_main.view_port)
        frm_left = Frame(self.frm_main.view_port)
        frm_right = Frame(self.frm_main.view_port)

        frm_caption = Frame(frm_center)
        frm_image = Frame(frm_center)

        self.btn_prev = LinkButton(self, frm_caption, text="Previous")
        self.btn_prev.link = "prev link"
        self.btn_prev.pack(side=LEFT)

        self.btn_save = Button(frm_caption,
                               text="Save",
                               command=self.save_image)
        self.btn_save.pack(side=LEFT)

        self.btn_next = LinkButton(self, frm_caption, text="Next")
        self.btn_next.link = "next link"
        self.btn_next.pack(side=LEFT)

        self.btn_paste = Button(frm_top,
                                text="Paste",
                                command=self.paste_from_clipboard)
        self.btn_paste.pack(side=LEFT)

        self.btn_update = Button(frm_top,
                                 text="Load image",
                                 command=self.load_image_from_input)
        self.btn_update.pack(side=LEFT)

        self.sv_url = StringVar()
        self.entry_url = Entry(frm_top, textvariable=self.sv_url, width=100)
        self.entry_url.bind("<FocusIn>", self.focus_callback)
        self.entry_url.bind('<Return>', self.enter_callback)
        self.entry_url.pack(side=LEFT)

        self.use_proxy = BooleanVar()
        self.use_proxy.set(False)
        self.use_proxy.trace('w', self.on_use_proxy_change)

        self.chk_use_proxy = Checkbutton(frm_top,
                                         text='Use proxy',
                                         variable=self.use_proxy)
        self.chk_use_proxy.pack(side=LEFT)

        self.sv_proxy = StringVar()
        self.entry_proxy = Entry(frm_top,
                                 textvariable=self.sv_proxy,
                                 width=30,
                                 state=DISABLED)
        self.entry_proxy.pack(side=LEFT)

        self.btn_force = Button(frm_top,
                                text="Force load",
                                command=self.force_load_image)
        self.btn_force.pack(side=LEFT)

        try:
            with open("proxy.txt") as f:
                self.sv_proxy.set(f.readline().strip())
        except BaseException as error:
            print(error)
            traceback.print_exc()

        self.btn_image = Button(frm_image, command=self.resize_image)
        self.btn_image.bind("<Button-3>", self.load_original_image_in_thread)
        self.btn_image.pack()

        self.left_buttons = self.fill_panel(frm_left)
        self.right_buttons = self.fill_panel(frm_right)

        self.status = StringVar()
        self.status_label = Label(frm_status,
                                  bd=1,
                                  relief=SUNKEN,
                                  anchor=W,
                                  textvariable=self.status)
        self.status_label.pack(side=LEFT, fill=BOTH, expand=1)
        self.status.set('Status Bar')

        self.progress_bar = ttk.Progressbar(frm_status,
                                            orient=HORIZONTAL,
                                            length=200,
                                            mode='indeterminate')

        root.bind("<FocusIn>", self.focus_callback)
        root.bind("<BackSpace>", self.backspace_callback)
        root.bind("<space>", self.space_callback)
        root.protocol("WM_DELETE_WINDOW", self.on_close)

        frm_caption.pack()
        frm_image.pack()

        frm_left.pack(side=LEFT, fill=BOTH, expand=1)
        frm_center.pack(side=LEFT)
        frm_right.pack(side=RIGHT, fill=BOTH, expand=1)

        frm_top.pack()
        self.frm_main.pack(fill=BOTH, expand=1)
        frm_status.pack(fill=X)

        self.hist_logger = logging.getLogger('history')
        self.hist_logger.setLevel(logging.INFO)

        self.fh_hist = logging.FileHandler(
            os.path.join(LOGS, f'hist_{int(time.time())}.log'))
        self.fh_hist.setLevel(logging.INFO)
        self.hist_logger.addHandler(self.fh_hist)

    def force_load_image(self):
        self.load_page_in_thread(self.sv_url.get().strip(), True, True)

    def load_image_from_input(self):
        self.load_page_in_thread(self.sv_url.get().strip())

    def load_page_in_thread(self,
                            input_url,
                            remember=True,
                            ignore_cache=False):
        self.set_controls_state(DISABLED)
        self.interrupt = False
        future = executor.submit(self.load_image_retry, input_url, remember,
                                 ignore_cache)
        future.add_done_callback(lambda f: self.set_controls_state(NORMAL))

    def load_image_retry(self, input_url, remember, ignore_cache):
        global root

        try:
            err_count = 0
            while err_count < MAX_ERRORS:
                root.after_idle(self.set_undefined_state)
                if self.load_image(input_url, remember, ignore_cache):
                    break

                if self.interrupt:
                    break

                err_count += 1
        except BaseException as error:
            print("Exception URL: " + input_url)
            print(error)
            traceback.print_exc()

    def load_image(self, input_url, remember, ignore_cache):
        global root

        if len(input_url) == 0:
            return False

        root.after_idle(self.sv_url.set, input_url)

        self.provider = self.get_provider()
        if self.provider is None:
            return False

        cache_path = os.path.join(CACHE, self.provider.get_domen())
        if not os.path.exists(cache_path):
            os.mkdir(cache_path)

        proxy = self.sv_proxy.get().strip()
        if self.use_proxy.get() and len(proxy.strip()) > 0:
            self.proxies = {
                "http": "http://" + proxy,
                "https": "https://" + proxy
            }
            with open("proxy.txt", "w") as f:
                f.write(proxy)
        else:
            self.proxies = None

        http_session = requests.Session()
        http_session.headers.update(HEADERS)

        ident = self.get_id(input_url)
        if ident is None:
            print("ident is None")
            return False

        input_url = "https://" + self.provider.get_host() + "/" + ident

        root.after_idle(root.title, input_url)

        try:
            html = self.get_from_cache(ident)
            if ignore_cache or (html is None) or (len(html) == 0):
                html = self.get_final_page(ident, input_url, http_session)

            if (html is None) or (len(html) == 0):
                return False

            html = html.decode('utf-8')

            if not self.render_page(ident, html, http_session):
                return False

            if remember and (input_url is not None):
                if len(self.hist_stack) == 0 or (input_url !=
                                                 self.hist_stack[-1]):
                    self.hist_stack.append(input_url)
                    self.hist_logger.info(f'{input_url}\t{self.thumb_url}')
                if len(self.fwd_stack) > 0 and (input_url
                                                == self.fwd_stack[-1]):
                    self.fwd_stack.pop()
                else:
                    self.fwd_stack.clear()

        except BaseException as error:
            print("Exception URL: " + input_url)
            print(error)
            traceback.print_exc()
            return False
        finally:
            http_session.close()

        return True

    def get_final_page(self, ident, input_url, http_session):
        global root

        response = http_session.get(input_url,
                                    proxies=self.proxies,
                                    timeout=TIMEOUT)
        if response.status_code == 404:
            print("input_url response.status_code == 404")
            return None

        html = response.content.decode('utf-8')

        if DEBUG:
            with open('1.html', 'w') as f:
                f.write(html)

        # sometimes this functions fails (i don't want to tamper with this)
        redirect_url = self.provider.get_redirect_url(html)
        if redirect_url is not None:
            if len(redirect_url) == 0:
                print("(redirect_url is None) or (len(redirect_url) == 0)")
                return None

            http_session.headers.update({'Referer': input_url})
            response = http_session.get(redirect_url,
                                        proxies=self.proxies,
                                        timeout=TIMEOUT)
            if response.status_code == 404:
                print("redirect_url response.status_code == 404")
                return None

            html = response.content.decode('utf-8')

            if DEBUG:
                with open('2.html', 'w') as f:
                    f.write(html)

        pos = html.find('File Not Found')
        if pos >= 0:
            print("File Not Found: " + input_url)
            return None

        param = self.provider.get_post_param(html)
        if len(param) == 0:
            print("len(param) == 0")
            return None

        post_fields = {'op': 'view', 'id': ident, 'pre': 1, param: 1}
        response = http_session.post(redirect_url,
                                     data=post_fields,
                                     proxies=self.proxies,
                                     timeout=TIMEOUT)
        if response.status_code == 404:
            print("POST: redirect_url response.status_code == 404")
            return None

        html = response.content

        if DEBUG:
            with open('3.html', 'wb') as f:
                f.write(html)

        self.put_to_cache(ident, html)

        return html

    def render_page(self, ident, html, http_session):
        self.thumb_url = get_thumb(html)
        if (self.thumb_url is None) or (len(self.thumb_url) == 0):
            print("len(thumb_url) == 0")
            return False

        slash_pos = self.thumb_url.rfind('/')
        self.thumb_prefix = self.thumb_url[:slash_pos + 1]
        thumb_filename = self.thumb_url[slash_pos + 1:]
        dot_pos = thumb_filename.rfind('.')
        thumb_filename = thumb_filename[:dot_pos]

        self.gallery_url = search('href="([^"]*)">More from gallery</a>', html)

        self.reconfigure_prev_button(http_session, html)
        self.reconfigure_next_button(http_session, html)

        executor.submit(self.reconfigure_left_buttons, html)
        executor.submit(self.reconfigure_right_buttons, html)

        self.image_url = self.provider.get_image_url(html)

        fname = get_filename(self.image_url)
        dot_pos = fname.rfind('.')
        self.original_image_name = fname[:dot_pos] + '_' + ident
        self.original_image = self.get_from_cache(self.original_image_name)

        bg_color = 'green'
        self.resized = True
        if (self.original_image is None) or (len(self.original_image) == 0):
            self.original_image = self.get_from_cache(thumb_filename)
            self.resized = False

        if (self.original_image is None) or (len(self.original_image) == 0):
            response = http_session.get(self.thumb_url,
                                        proxies=self.proxies,
                                        timeout=TIMEOUT)
            if response.status_code == 404:
                print("image_url response.status_code == 404")
                return False

            self.original_image = response.content

            # if DEBUG:
            #     with open(self.original_image_name, 'wb') as f:
            #         f.write(self.original_image)

            self.put_to_cache(thumb_filename, self.original_image)
            bg_color = 'red'
            self.resized = False

        img = Image.open(io.BytesIO(self.original_image))
        w, h = img.size
        k = MAIN_IMG_WIDTH / w
        img_resized = img.resize((MAIN_IMG_WIDTH, int(h * k)))

        root.after_idle(root.title, f"{root.title()} ({w}x{h})")

        self.main_image_orig = ImageTk.PhotoImage(img)
        self.main_image = ImageTk.PhotoImage(img_resized)

        photo_image = self.main_image if self.resized else self.main_image_orig
        root.after_idle(self.btn_image.config, {
            'image': photo_image,
            'background': bg_color
        })

        if os.path.exists(os.path.join(OUTPUT, self.original_image_name)):
            root.after_idle(self.btn_save.config, {'background': 'green'})

        return True

    def focus_callback(self, event):
        self.entry_url.selection_range(0, END)

    def enter_callback(self, event):
        self.load_image_from_input()

    def backspace_callback(self, event):
        self.back_in_history()

    def space_callback(self, event):
        self.forward_in_history()

    def on_close(self):
        global root

        root.update_idletasks()
        root.destroy()
        self.fh_hist.close()
        self.hist_logger.removeHandler(self.fh_hist)

    def calcel(self):
        self.interrupt = True

    def set_undefined_state(self):
        global root

        self.main_image = None
        self.main_image_orig = None
        self.original_image = None
        self.original_image_name = None
        self.btn_image.config(image='', background="SystemButtonFace")
        self.btn_save.config(background="SystemButtonFace")
        root.title(None)
        self.btn_prev.reset()
        self.btn_next.reset()
        for btn in self.left_buttons:
            btn.reset()
        for btn in self.right_buttons:
            btn.reset()

        self.frm_main.scroll_top_left()

    def paste_from_clipboard(self):
        self.sv_url.set(clipboard.paste())
        self.entry_url.selection_range(0, END)

    def save_image(self):
        if self.original_image is None:
            return

        filename = self.original_image_name
        i = 1
        while os.path.exists(os.path.join(OUTPUT, filename)):
            filename = f'{self.original_image_name}_{i:04}'
            i += 1

        with open(os.path.join(OUTPUT, filename), 'wb') as f:
            f.write(self.original_image)

        self.btn_save.config(background="green")

    def on_enter(self, event):
        self.status.set(event.widget.link)

    def on_leave(self, enter):
        self.status.set("")

    def fill_panel(self, panel):
        buttons = []
        for i in range(4):
            Grid.columnconfigure(panel, i, weight=1)
            for j in range(2):
                Grid.rowconfigure(panel, j, weight=1)
                btn = LinkButton(self, panel, text=f"({i}, {j})")
                btn.link = None
                btn.grid(row=i, column=j, sticky=NSEW, padx=PAD, pady=PAD)
                buttons.append(btn)

        return buttons

    def resize_image(self):
        self.btn_image.config(
            image=(self.main_image_orig if self.resized else self.main_image))
        self.resized = not self.resized
        self.frm_main.scroll_top_left()

    def get_id(self, url):
        found = re.search(
            r"https?://" + self.provider.get_domen() +
            r"\.[a-z]+/(.+?)(?:/|$)", url)
        if (found is None) or (found.group(0) is None):
            return None

        return found.group(1)

    def reconfigure_left_buttons(self, html):
        tab = get_more_from_author(html)
        self.reconfigure_buttons(self.left_buttons, tab)

    def reconfigure_right_buttons(self, html):
        tab = get_more_from_gallery(html)
        self.reconfigure_buttons(self.right_buttons, tab)

    def reconfigure_prev_button(self, http_session, html):
        url = get_prev_url(html)
        if len(url) == 0:
            return

        ident = self.get_id(url)
        img_url = self.thumb_prefix + ident + '_t.jpg'
        self.reconfigure_button(http_session, self.btn_prev, url, img_url)

    def reconfigure_next_button(self, http_session, html):
        url = get_next_url(html)
        if len(url) == 0:
            return

        ident = self.get_id(url)
        img_url = self.thumb_prefix + ident + '_t.jpg'
        self.reconfigure_button(http_session, self.btn_next, url, img_url)

    def reconfigure_button(self, http_session, btn, url, img_url):
        global root

        filename = get_filename(img_url)
        dot_pos = filename.rfind('.')
        filename = filename[:dot_pos]
        bg_color = "green"
        image = self.get_from_cache(filename)
        if (image is None) or (len(image) == 0):
            image = download_image(http_session, img_url)
            self.put_to_cache(filename, image)
            bg_color = "red"

        if (image is None) or (len(image) == 0):
            return

        img = Image.open(io.BytesIO(image))
        w, h = img.size
        k = IMG_WIDTH / w
        img_resized = img.resize((IMG_WIDTH, int(h * k)))
        photo_image = ImageTk.PhotoImage(img_resized)
        if photo_image is None:
            return

        root.after_idle(btn.set_values, url,
                        partial(self.load_page_in_thread, url), photo_image,
                        bg_color)

    def reconfigure_buttons(self, buttons, html):
        http_session = requests.Session()
        http_session.headers.update(HEADERS)

        try:
            for btn in buttons:
                btn.reset()

            i = 0
            for m in re.finditer('<td>.*?href="(.*?)".*?src="(.*?)".*?</td>',
                                 html, re.MULTILINE | re.DOTALL):
                self.reconfigure_button(http_session, buttons[i], m.group(1),
                                        m.group(2))
                i += 1
        except BaseException as error:
            print(error)
            traceback.print_exc()
        finally:
            http_session.close()

    def on_use_proxy_change(self, *args):
        if self.use_proxy.get():
            self.entry_proxy.config(state=NORMAL)
            self.entry_proxy.focus_set()
            self.entry_proxy.selection_range(0, END)
        else:
            self.entry_proxy.config(state=DISABLED)

    def get_provider(self):
        input_url = self.sv_url.get()

        pos = input_url.find(ImgRock.DOMEN)
        if pos >= 0:
            return ImgRock()

        pos = input_url.find(ImgView.DOMEN)
        if pos >= 0:
            return ImgView()

        pos = input_url.find(ImgTown.DOMEN)
        if pos >= 0:
            return ImgTown()

        pos = input_url.find(ImgOutlet.DOMEN)
        if pos >= 0:
            return ImgOutlet()

        pos = input_url.find(ImgMaze.DOMEN)
        if pos >= 0:
            return ImgMaze()

        pos = input_url.find(ImgDew.DOMEN)
        if pos >= 0:
            return ImgDew()

        return None

    def view_gallery_url(self):
        if (self.gallery_url is None) or (len(self.gallery_url) == 0):
            return

        clipboard.copy(self.gallery_url)
        GalleryWindow(self, Toplevel(root))

    def back_in_history(self):
        if len(self.hist_stack) < 2:
            return

        self.fwd_stack.append(self.hist_stack.pop())

        self.load_page_in_thread(self.hist_stack[-1], False)

    def forward_in_history(self):
        if len(self.fwd_stack) == 0:
            return

        self.load_page_in_thread(self.fwd_stack[-1])

    def get_from_cache(self, filename):
        full_path = os.path.join(CACHE, self.provider.get_domen(), filename)
        if not os.path.exists(full_path):
            return None

        mod_time = time.time()
        os.utime(full_path, (mod_time, mod_time))

        with open(full_path, 'rb') as f:
            return f.read()[::-1]

    def put_to_cache(self, filename, data):
        if (data is None) or (len(data) == 0):
            return

        full_path = os.path.join(CACHE, self.provider.get_domen(), filename)

        with open(full_path, 'wb') as f:
            f.write(data[::-1])

    def set_controls_state(self, status):
        self.btn_prev.config(state=status)
        self.btn_next.config(state=status)
        self.btn_update.config(state=status)
        self.btn_force.config(state=status)
        self.entry_url.config(state=status)
        self.btn_paste.config(state=status)
        self.chk_use_proxy.config(state=status)
        self.entry_proxy.config(state=status)
        self.menu_bar.entryconfig("<< Back", state=status)
        self.menu_bar.entryconfig("Forward >>", state=status)

        for btn in self.left_buttons:
            btn.config(state=status)
        for btn in self.right_buttons:
            btn.config(state=status)

        if status == DISABLED:
            self.progress_bar.pack(side=LEFT)
            self.progress_bar.start()
        else:
            self.progress_bar.pack_forget()
            self.progress_bar.stop()

    def load_original_image_in_thread(self, event):
        executor.submit(self.load_original_image)

    def load_original_image(self):
        response = requests.get(self.image_url,
                                proxies=self.proxies,
                                timeout=TIMEOUT)
        if response.status_code == 404:
            print("image_url response.status_code == 404")
            return

        self.original_image = response.content

        # if DEBUG:
        #     with open(self.original_image_name, 'wb') as f:
        #         f.write(self.original_image)

        self.put_to_cache(self.original_image_name, self.original_image)
        bg_color = 'red'

        self.resized = True

        img = Image.open(io.BytesIO(self.original_image))
        w, h = img.size
        k = MAIN_IMG_WIDTH / w
        img_resized = img.resize((MAIN_IMG_WIDTH, int(h * k)))

        root.after_idle(root.title, f"{root.title()} ({w}x{h})")

        self.main_image_orig = ImageTk.PhotoImage(img)
        self.main_image = ImageTk.PhotoImage(img_resized)

        root.after_idle(self.btn_image.config, {
            'image': self.main_image,
            'background': bg_color
        })
예제 #21
0
class CurrencyEditor(Frame):
    def __init__(self, master, **kwargs):
        super().__init__(master, **kwargs)

        self.bvar_modified = BooleanVar()
        self.create_currency_ui()

    def create_currency_ui(self):
        self.rowconfigure(0, weight=1)
        self.columnconfigure(0, weight=1)
        self.frm_currency = Frame(self)
        self.frm_currency.rowconfigure(2, weight=1)
        self.frm_currency.columnconfigure(0, weight=1)
        self.frm_currency.grid(padx=10, pady=10, sticky='nsew')

        # Tree Frame
        self.frm_tree = Frame(self.frm_currency)
        self.frm_tree.grid(row=2, sticky='nsew')
        self.frm_tree.rowconfigure(0, weight=1)
        self.frm_tree.columnconfigure(0, weight=1)

        self.tree = EditableTreeview(self.frm_tree,
                                     on_cell_update=self.onCellUpdate)
        scrly = AutoScrollbar(self.frm_tree, command=self.tree.yview)
        scrlx = AutoScrollbar(self.frm_tree,
                              command=self.tree.xview,
                              orient=HORIZONTAL)
        self.tree.config(yscrollcommand=scrly.set, xscrollcommand=scrlx.set)
        self.tree.grid(row=0, column=0, sticky='nsew')
        scrly.grid(row=0, column=1, sticky='nsew')
        scrlx.grid(row=1, column=0, sticky='nsew')

        self.tree.insert('', 0, text='Exalted Orb', values=('90', '85'))

        frm = Frame(self.frm_currency, relief=SOLID, borderwidth=2)
        frm.columnconfigure(10, weight=1)
        frm.grid(row=1, column=0, pady=(0, 5), sticky='nsew')
        # self.entry_currency = \
        #     Combobox_Autocomplete(frm, list_of_items=['one of many currencies'], startswith_match=False)

        self.search_var = StringVar()
        self.entry_search = PlaceholderEntry(frm,
                                             'Search..',
                                             style='Default.TEntry',
                                             textvariable=self.search_var)

        self.search_var.trace_variable(
            'w',
            lambda a, b, c: self.tree.search(self.entry_search.get_value()))
        self.entry_search.bind(
            '<Return>',
            lambda event: self.tree.search(self.entry_search.get_value(),
                                           find_next=True))
        # self.btn_currency_search = Button(frm, text='Search', command=lambda event: self.tree_currency.search(self.entry_currency_search.get_value(), find_next=True))
        self.btn_apply = Button(frm, text='Apply', command=self.applyChanges)
        self.btn_reload = Button(
            frm,
            text='Reload',
            command=lambda: self.loadCurrency(force_reload=True))

        self.entry_search.grid(row=2, column=0, pady=5, padx=5)
        # self.btn_currency_search.grid(row=2, column=1, pady=5)
        self.btn_apply.grid(row=2, column=2, pady=5)
        # frm.columnconfigure(3, weight=1)
        self.btn_reload.grid(row=2, column=3, sticky='e', pady=5)

        # Confidence Level
        lbl = Label(frm, text="Confidence level:")
        lbl.grid(row=2, column=10, padx=5, sticky='nse', pady=(3, 5))
        self.lbl_confidence_lvl = lbl
        self.var_confidence_lvl = IntVar()
        self.entry_confidence_lvl = ConfidenceScale(
            frm, variable=self.var_confidence_lvl)
        self.entry_confidence_lvl.grid(row=2, column=11, padx=5, pady=5)
        self.var_confidence_lvl.trace(
            'w',
            lambda a, b, c: self.on_entry_change(self.entry_confidence_lvl))

        # Tree Config
        tree = self.tree
        tree['columns'] = currencyColumns[1:]
        tree.register_column(
            'Override',
            ColEntry(TooltipEntry(tree),
                     func_validate=_validate_price_override))

        def init_tree_column(col):
            col_name = currencyColumns[0] if col == '#0' else col
            tree.heading(col,
                         text=CurrencyColumn[col_name].value,
                         anchor=W,
                         command=lambda col=col: tree.sort_col(col))
            tree.column(col, width=140, stretch=False)

        for col in ('#0', ) + tree['columns']:
            init_tree_column(col)

        tree.heading('#0', anchor=CENTER)
        tree.column('#0', width=250, stretch=False)
        tree.column(CurrencyColumn.Filler.name, stretch=True)

        tree.heading(CurrencyColumn.Rate.name,
                     command=lambda col=CurrencyColumn.Rate.name: tree.
                     sort_col(col, key=float, default=0))
        tree.heading(CurrencyColumn.EffectiveRate.name,
                     command=lambda col=CurrencyColumn.EffectiveRate.name: tree
                     .sort_col(col, key=float, default=0))
        tree.heading(CurrencyColumn.Override.name,
                     command=lambda col=CurrencyColumn.Override.name: tree.
                     sort_col(col, key=self._price_key))

        self.bvar_modified.trace('w', lambda a, b, c: self._updateApplyState())

    def _price_key(self, key):
        if key == '':
            return None  # this means it will be ignored while sorting
        try:
            return cm.compilePrice(key, base_price=0)
        except Exception:
            return 0

    def _updateApplyState(self):
        if self.bvar_modified.get():
            self.btn_apply.config(state=NORMAL)
        else:
            self.btn_apply.config(state=DISABLED)

    def loadCurrency(self, force_reload=False):
        if not cm.initialized:
            return
        if not force_reload and self.bvar_modified.get():
            return

        self.var_confidence_lvl.set(cm.confidence_level)

        tree = self.tree
        tree.clear()

        table = {}
        for curr in cm.shorts:
            effective_rate = cm.crates.get(curr, '0')
            table[curr] = (_to_display_rate(cm.rates.get(curr, '')),
                           cm.overrides.get(curr, ''),
                           _to_display_rate(effective_rate))

        for curr in table:
            tree.insert('', END, '', text=curr, values=table[curr])

        tree.sort_col(CurrencyColumn.EffectiveRate.name, key=float, default=0)

        self.bvar_modified.set(False)

    def applyChanges(self, event=None):
        if not self.bvar_modified.get() or not cm.initialized:
            return

        overrides = {}

        for iid in self.tree.get_children():
            #TODO: hide #0 col and move names to a value column
            currency_name_col = '#0'  # CurrencyColumn.Currency.name
            # id = self.tree.set(iid, currency_name_col)
            id = self.tree.item(iid, 'text')
            override = self.tree.set(iid, CurrencyColumn.Override.name)

            if override:
                overrides[id] = override

        # ids = set([self.tree.set(iid, currency_name_col) for iid in self.tree.get_children()])
        ids = set(
            [self.tree.item(iid, 'text') for iid in self.tree.get_children()])

        # preserve unhandled ids configuration
        for key in (set(cm.overrides) - ids):
            overrides[key] = cm.overrides[key]

        cm.confidence_level = self.entry_confidence_lvl.get()

        try:
            cm.compile(overrides=overrides)
            if fm.initialized:
                threading.Thread(target=fm.compileFilters).start()
            self.bvar_modified.set(False)
        except AppException as e:
            messagebox.showerror('Update error',
                                 e,
                                 parent=self.winfo_toplevel())
        except Exception as e:
            logexception()
            messagebox.showerror(
                'Update error',
                'Failed to apply changes, unexpected error:\n{}'.format(e),
                parent=self.winfo_toplevel())

    def onCellUpdate(self, iid, col, old, new):
        if not self.bvar_modified.get() and old != new:
            self.bvar_modified.set(True)

    def on_entry_change(self, entry):
        self.bvar_modified.set(True)
예제 #22
0
class PricesEditor(Frame):
    def __init__(self, master, **kwargs):
        super().__init__(master, **kwargs)

        self.create_prices_ui()
        self.initial_values = {}
        self.table_modified = False

    def create_prices_ui(self):
        self.rowconfigure(0, weight=1)
        self.columnconfigure(0, weight=1)
        self.frm_prices = Frame(self)
        self.frm_prices.rowconfigure(2, weight=1)
        self.frm_prices.columnconfigure(0, weight=1)
        self.frm_prices.grid(padx=10, pady=10, sticky='nsew')

        # Button Frame
        frm_btns = Frame(self.frm_prices, relief=SOLID, borderwidth=2)
        frm_btns.grid(row=0, column=0, pady=(0, 5), sticky='nsew')
        frm_btns.columnconfigure(10, weight=1)
        # self.entry_currency = \
        #     Combobox_Autocomplete(frm, list_of_items=['one of many currencies'], startswith_match=False)

        self.search_var = StringVar()
        self.entry_search = PlaceholderEntry(frm_btns,
                                             'Search..',
                                             style='Default.TEntry',
                                             textvariable=self.search_var)

        self.search_var.trace_variable(
            'w',
            lambda a, b, c: self.tree.search(self.entry_search.get_value()))
        self.entry_search.bind(
            '<Return>',
            lambda event: self.tree.search(self.entry_search.get_value(),
                                           find_next=True))
        self.btn_apply = Button(frm_btns,
                                text='Apply',
                                command=self.applyChanges)
        self.btn_reload = Button(
            frm_btns,
            text='Reload',
            command=lambda: self.loadPrices(force_reload=True))

        self.entry_search.grid(row=2, column=0, pady=5, padx=5)
        self.btn_apply.grid(row=2, column=2, pady=5)
        # frm.columnconfigure(3, weight=1)
        self.btn_reload.grid(row=2, column=3, sticky='e', pady=5)

        self.var_advanced = BooleanVar(False)
        self.var_advanced.trace_variable(
            'w', lambda a, b, c: self._on_view_option_change())
        self.cb_advanced = Checkbutton(frm_btns,
                                       text='Advanced',
                                       variable=self.var_advanced)
        self.cb_advanced.grid(row=2, column=10, sticky='e', padx=10)

        frm_border = Frame(self.frm_prices, relief=SOLID, borderwidth=2)
        frm_border.grid(row=2, column=0, sticky='nsew')
        frm_border.rowconfigure(2, weight=1)
        frm_border.columnconfigure(0, weight=1)
        # Tree Frame
        self.frm_tree = Frame(frm_border)
        self.frm_tree.grid(row=2, column=0, sticky='nsew', padx=5, pady=(0, 0))
        self.frm_tree.rowconfigure(0, weight=1)
        self.frm_tree.columnconfigure(0, weight=1)

        self.tree = EditableTreeview(self.frm_tree,
                                     on_cell_update=self.onCellUpdate)
        scrly = AutoScrollbar(self.frm_tree, command=self.tree.yview)
        scrlx = AutoScrollbar(self.frm_tree,
                              command=self.tree.xview,
                              orient=HORIZONTAL)
        self.tree.config(yscrollcommand=scrly.set, xscrollcommand=scrlx.set)
        self.tree.grid(row=0, column=0, sticky='nsew')
        scrly.grid(row=0, column=1, sticky='nsew')
        scrlx.grid(row=1, column=0, sticky='nsew')

        # Button Frame
        frm = Frame(frm_border)  #, relief=SOLID, borderwidth=1)
        # frm = Frame(self.frm_prices)
        frm.grid(row=0, column=0, sticky='nsew')
        # self.entry_currency = \
        #     Combobox_Autocomplete(frm, list_of_items=['one of many currencies'], startswith_match=False)

        lbl = Label(frm, text='Item value threshold:')
        lbl.grid(row=0, column=0, padx=5, pady=5, sticky='w')
        self.var_threshold = StringVar()
        self.entry_threshold = TooltipEntry(frm,
                                            textvariable=self.var_threshold)
        self.entry_threshold.bind(
            '<FocusOut>', lambda event: self._validate_threshold_entry())
        self.entry_threshold.grid(row=0, column=1, padx=5, pady=5)
        self.var_threshold.trace(
            'w', lambda a, b, c: self.on_entry_change(self.entry_threshold))

        lbl = Label(frm, text='Budget:')
        lbl.grid(row=0, column=2, padx=5, pady=5)
        self.var_budget = StringVar()
        self.entry_budget = TooltipEntry(frm, textvariable=self.var_budget)
        self.entry_budget.bind('<FocusOut>',
                               lambda event: self._validate_budget_entry())
        self.entry_budget.grid(row=0, column=3, padx=5, pady=5)
        self.var_budget.trace(
            'w', lambda a, b, c: self.on_entry_change(self.entry_budget))

        lbl = Label(frm, text='Minimum price:')
        lbl.grid(row=0, column=4, padx=5, pady=5)
        self.var_min_price = StringVar()
        self.entry_min_price = TooltipEntry(frm,
                                            textvariable=self.var_min_price)
        self.entry_min_price.bind(
            '<FocusOut>', lambda event: self._validate_min_price_entry())
        self.entry_min_price.grid(row=0, column=5, padx=5, pady=5)
        self.var_min_price.trace(
            'w', lambda a, b, c: self.on_entry_change(self.entry_min_price))

        lbl = Label(frm, text='Default filter override:')
        lbl.grid(row=0, column=6, padx=5, pady=5)
        self.lbl_fprice_override = lbl
        self.var_fprice_override = StringVar()
        self.entry_fprice_override = TooltipEntry(
            frm, textvariable=self.var_fprice_override)
        self.entry_fprice_override.bind(
            '<FocusOut>', lambda event: self._validate_fprice_override_entry())
        self.entry_fprice_override.grid(row=0, column=7, padx=5, pady=5)
        self.var_fprice_override.trace(
            'w',
            lambda a, b, c: self.on_entry_change(self.entry_fprice_override))

        # Advanced

        lbl = Label(frm, text='Default item value override:')
        lbl.grid(row=1, column=0, padx=5, pady=(2, 5), sticky='w')
        self.lbl_price_override = lbl
        self.var_price_override = StringVar()
        self.entry_price_override = TooltipEntry(
            frm, textvariable=self.var_price_override)
        self.entry_price_override.bind(
            '<FocusOut>', lambda event: self._validate_price_override_entry())
        self.entry_price_override.grid(row=1, column=1, padx=5, pady=(2, 5))
        self.var_price_override.trace(
            'w',
            lambda a, b, c: self.on_entry_change(self.entry_price_override))

        # Confidence Level
        lbl = Label(frm, text="Confidence level:")
        lbl.grid(row=1, column=2, padx=5, pady=(2, 5), sticky='w')
        self.lbl_confidence_lvl = lbl
        self.var_confidence_lvl = IntVar()
        self.entry_confidence_lvl = ConfidenceScale(
            frm, variable=self.var_confidence_lvl)
        self.entry_confidence_lvl.grid(row=1, column=3, padx=5, pady=(2, 5))
        self.var_confidence_lvl.trace(
            'w',
            lambda a, b, c: self.on_entry_change(self.entry_confidence_lvl))

        self.var_5l_filters = BooleanVar(False)
        self.cb_5l_filters = VarCheckbutton(frm,
                                            text='Enable 5L filters',
                                            variable=self.var_5l_filters)
        self.cb_5l_filters.var = self.var_5l_filters
        self.cb_5l_filters.grid(row=1,
                                column=4,
                                padx=5,
                                pady=(2, 5),
                                columnspan=1)
        self.var_5l_filters.trace_variable(
            'w', lambda a, b, c: self.on_entry_change(self.cb_5l_filters))

        # Tree Config
        tree = self.tree

        def init_tree_column(col):
            col_name = pricesColumns[0] if col == '#0' else col
            tree.heading(col,
                         text=PricesColumn[col_name].value,
                         anchor=W,
                         command=lambda col=col: tree.sort_col(col))
            tree.column(col, width=140, stretch=False)

        # self.tree['columns'] = ('ID', 'Item Price', 'Override', 'Filter Price', 'Filter Override', 'Effective Filter Price', 'Filter State Override', '')
        self.tree['columns'] = pricesColumns[1:]

        self.tree.register_column(
            PricesColumn.Override.name,
            ColEntry(TooltipEntry(self.tree),
                     func_validate=_validate_price_override))
        self.tree.register_column(
            PricesColumn.FilterOverride.name,
            ColEntry(TooltipEntry(self.tree),
                     func_validate=_validate_price_override))
        self.tree.register_column(
            PricesColumn.FilterStateOverride.name,
            ColEntry(Combobox(self.tree,
                              values=filterStateOptions,
                              state=READONLY),
                     accept_events=('<<ComboboxSelected>>', '<Return>')))

        for col in (('#0', ) + tree['columns']):
            init_tree_column(col)

        tree.heading('#0', anchor=CENTER)
        tree.column('#0', width=200, stretch=False)
        tree.column(PricesColumn.Filler.name, stretch=True)

        tree.heading(PricesColumn.ItemPrice.name,
                     command=lambda col=PricesColumn.ItemPrice.name: tree.
                     sort_col(col, key=self._price_key))
        tree.heading(PricesColumn.Override.name,
                     command=lambda col=PricesColumn.Override.name: tree.
                     sort_col(col, key=self._price_key))
        tree.heading(PricesColumn.FilterOverride.name,
                     command=lambda col=PricesColumn.FilterOverride.name: tree.
                     sort_col(col, key=self._price_key))

        tree.heading(PricesColumn.FilterPrice.name,
                     command=lambda col=PricesColumn.FilterPrice.name: tree.
                     sort_col(col, key=self._rate_key, default=0))
        tree.heading(PricesColumn.EffectiveFilterPrice.name,
                     command=lambda col=PricesColumn.EffectiveFilterPrice.name:
                     tree.sort_col(col, key=self._rate_key, default=0))

        self.bvar_modified = BooleanVar()
        self.bvar_modified.trace('w', lambda a, b, c: self._updateApplyState())
        self.bvar_modified.set(False)
        self.var_advanced.set(False)

    def _rate_key(self, key):
        if key == 'N/A':
            return 0
        return float(key)

    def _price_key(self, key):
        if key == '':
            return None  # this means it will be ignored while sorting
        try:
            return cm.compilePrice(key, base_price=0)
        except Exception:
            return 0

    def on_entry_change(self, entry):
        val = entry.get()

        if self.initial_values[entry] != val:
            self.bvar_modified.set(True)

    # def on_price_entry_focusout(self, widget):
    #     valid = _validate_price(widget, accept_empty=False)
    #     if valid and not self.bvar_modified.get() and self.initial_values[widget] != widget.get():
    #         self.bvar_modified.set(True)
    #     return valid
    #
    # def on_override_entry_focusout(self, widget):
    #     valid = _validate_price_override(widget, accept_empty=False)
    #     if valid and not self.bvar_modified.get() and self.initial_values[widget] != widget.get():
    #         self.bvar_modified.set(True)
    #     return valid

    def _validate_threshold_entry(self):
        return _validate_price(self.entry_threshold, accept_empty=False)

    def _validate_budget_entry(self):
        return _validate_price(self.entry_budget, accept_empty=True)

    def _validate_min_price_entry(self):
        return _validate_price(self.entry_min_price, accept_empty=True)

    def _validate_price_override_entry(self):
        return _validate_price_override(self.entry_price_override,
                                        accept_empty=False)

    def _validate_fprice_override_entry(self):
        return _validate_price_override(self.entry_fprice_override,
                                        accept_empty=False)

    def _update_modified(self):
        modified = any(entry.get() != self.initial_values[entry]
                       for entry in self.initial_values) or self.table_modified

        self.bvar_modified.set(modified)

    def _updateApplyState(self):
        if self.bvar_modified.get():
            self.btn_apply.config(state=NORMAL)
        else:
            self.btn_apply.config(state=DISABLED)

    def _validateForm(self):
        if not self._validate_threshold_entry():
            return False
        if not self._validate_budget_entry():
            return False
        if not self._validate_min_price_entry():
            return False
        if not self._validate_price_override_entry():
            return False
        if not self._validate_fprice_override_entry():
            return False
        return True

    def applyChanges(self, event=None):
        if not self.bvar_modified.get() or not fm.initialized:
            return
        if not self._validateForm():
            return

        price_threshold = self.entry_threshold.get()
        default_price_override = self.entry_price_override.get()
        default_fprice_override = self.entry_fprice_override.get()
        budget = self.entry_budget.get()
        min_price = self.entry_min_price.get()
        confidence_lvl = self.entry_confidence_lvl.get(
        ) or fm.DEFAULT_CONFIDENCE_LEVEL
        enable_5l_filters = self.var_5l_filters.get()

        price_overrides = {}
        filter_price_overrides = {}
        filter_state_overrides = {}

        for iid in self.tree.get_children():
            id = self.tree.set(iid, PricesColumn.ID.name)
            iprice = self.tree.set(iid, PricesColumn.Override.name)

            if iprice:
                price_overrides[id] = iprice

            fprice = self.tree.set(iid, PricesColumn.FilterOverride.name)
            if fprice:
                filter_price_overrides[id] = fprice

            fstate = self.tree.set(iid, PricesColumn.FilterStateOverride.name)
            try:
                filter_state_overrides[id] = FilterStateOption[fstate].value
            except KeyError:
                pass

        ids = set([
            self.tree.set(iid, PricesColumn.ID.name)
            for iid in self.tree.get_children()
        ])

        # preserve unhandled ids configuration
        for key in (set(fm.price_overrides) - ids):
            price_overrides[key] = fm.price_overrides[key]

        for key in (set(fm.filter_price_overrides) - ids):
            filter_price_overrides[key] = fm.filter_price_overrides[key]

        for key in (set(fm.filter_state_overrides) - ids):
            filter_state_overrides[key] = fm.filter_state_overrides[key]

        try:
            fm.updateConfig(default_price_override, default_fprice_override,
                            price_threshold, budget, min_price,
                            price_overrides,
                            filter_price_overrides, filter_state_overrides,
                            int(confidence_lvl), enable_5l_filters)
        except AppException as e:
            messagebox.showerror(
                'Validation error',
                'Failed to update configuration:\n{}'.format(e),
                parent=self.winfo_toplevel())
        except Exception as e:
            logexception()
            messagebox.showerror(
                'Update error',
                'Failed to apply changes, unexpected error:\n{}'.format(e),
                parent=self.winfo_toplevel())
        else:
            # SHOULD always work since config is valid, main console will report any failures
            # background thread because schema validating takes a bit of time
            threading.Thread(target=fm.compileFilters).start()
            self._initFormState()

    def loadPrices(self, force_reload=False):
        if not cm.initialized or not fm.initialized:
            return

        if not force_reload:
            self._update_modified()  # in case of reverted changes
            if self.bvar_modified.get():  # dont interrupt user changes
                return

        tree = self.tree
        tree.clear()

        table = {}
        for fltr in fm.autoFilters:
            # effective_rate = cm.crates.get(curr, '')
            # if effective_rate != '':
            #     effective_rate = round(effective_rate, 3)

            fid = fltr.id

            fstate_override = fm.filter_state_overrides.get(fid, '')
            try:
                fstate_override = FilterStateOption(fstate_override).name
            except ValueError:
                fstate_override = ''

            table[fid] = (fltr.title, fid, fm.item_prices[fid],
                          fm.price_overrides.get(fid, ''),
                          _to_display_rate(
                              fm.compiled_item_prices.get(fid, 'N/A')),
                          fm.filter_price_overrides.get(fid, ''),
                          _to_display_rate(
                              fm.compiled_filter_prices.get(fid, 'N/A')),
                          fstate_override)

        for fid in table:
            tree.insert('', END, '', text=table[fid][0], values=table[fid][1:])

        # tree.sort_by('#0', descending=True)
        tree.sort_col('#0', reverse=False)

        self._initFormState()

    # def onItemPriceUpdate(self, iid, col, old, new):
    #     print('IPrice update: iid {}, col {}'.format(iid, col))

    def onCellUpdate(self, iid, col, old, new):
        if old != new:
            self.table_modified = True
            self.bvar_modified.set(True)
            # self._update_modified()

    def _initFormState(self):
        self.table_modified = False
        self.initial_values[self.entry_threshold] = fm.price_threshold
        self.initial_values[self.entry_budget] = fm.budget
        self.initial_values[self.entry_min_price] = fm.default_min_price
        self.initial_values[
            self.entry_price_override] = fm.default_price_override
        self.initial_values[
            self.entry_fprice_override] = fm.default_fprice_override
        self.initial_values[self.entry_confidence_lvl] = fm.confidence_level
        self.initial_values[self.cb_5l_filters] = fm.enable_5l_filters

        self.var_threshold.set(fm.price_threshold)
        self.var_budget.set(fm.budget)
        self.var_min_price.set(fm.default_min_price)
        self.var_price_override.set(fm.default_price_override)
        self.var_fprice_override.set(fm.default_fprice_override)
        self.var_confidence_lvl.set(fm.confidence_level)
        self.var_5l_filters.set(fm.enable_5l_filters)

        self.bvar_modified.set(False)

    def _on_view_option_change(self):
        advanced_widgets = [
            self.entry_price_override, self.lbl_price_override,
            self.lbl_confidence_lvl, self.entry_confidence_lvl,
            self.cb_5l_filters
        ]
        if not self.var_advanced.get():
            for w in advanced_widgets:
                w.grid_remove()
            self.tree.config(displaycolumn=[
                PricesColumn.FilterPrice.name, PricesColumn.FilterOverride.
                name, PricesColumn.EffectiveFilterPrice.name,
                PricesColumn.Filler.name
            ])
        else:
            for w in advanced_widgets:
                w.grid()
            self.tree.config(displaycolumn='#all')
        self.tree.on_entry_close()
예제 #23
0
class MainWindow:
    def __init__(self):
        global root

        self.http_session = requests.Session()
        self.http_session.headers.update(HEADERS)

        self.menu_bar = Menu(root)
        self.menu_bar.add_command(label="Back", command=self.back_in_history)
        self.menu_bar.add_command(label="Toggle image",
                                  command=self.toggle_image)

        hist_menu = Menu(self.menu_bar, tearoff=0)
        hist_menu.add_command(label="All time",
                              command=lambda: self.show_full_history(ALL_TIME))
        hist_menu.add_command(label="Last day",
                              command=lambda: self.show_full_history(DAY))
        hist_menu.add_command(label="Two days",
                              command=lambda: self.show_full_history(TWO_DAYS))
        hist_menu.add_command(label="Week",
                              command=lambda: self.show_full_history(WEEK))
        hist_menu.add_command(label="Month",
                              command=lambda: self.show_full_history(MONTH))
        hist_menu.add_command(
            label="Three months",
            command=lambda: self.show_full_history(THREE_MONTHS))
        self.menu_bar.add_cascade(label="History", menu=hist_menu)

        root.config(menu=self.menu_bar)

        self.session = None
        self.show_image = False
        self.hist_window = None
        self.proxies = None

        self.model_name = None
        self.update_title()

        self.level = 0

        self.image_label = Label(root)

        self.level += 1
        self.cb_model = ttk.Combobox(root, width=60)
        self.cb_model.bind("<FocusIn>", self.focus_callback)
        self.cb_model.bind("<Button-1>", self.drop_down_callback)
        self.cb_model.bind('<Return>', self.enter_callback)
        self.cb_model.focus_set()
        self.cb_model.grid(row=self.level,
                           column=0,
                           columnspan=4,
                           sticky=W + E,
                           padx=PAD,
                           pady=PAD)

        self.btn_remove = Button(root,
                                 text="-",
                                 command=self.remove_from_favorites)
        self.btn_remove.grid(row=self.level,
                             column=4,
                             sticky=W + E,
                             padx=PAD,
                             pady=PAD)

        self.level += 1
        self.btn_update = Button(root,
                                 text="Update info",
                                 command=lambda: self.update_model_info(True))
        self.btn_update.grid(row=self.level,
                             column=0,
                             sticky=W + E,
                             padx=PAD,
                             pady=PAD)

        self.cb_resolutions = ttk.Combobox(root, state="readonly", values=[])
        self.cb_resolutions.grid(row=self.level,
                                 column=1,
                                 columnspan=4,
                                 sticky=W + E,
                                 padx=PAD,
                                 pady=PAD)
        self.cb_resolutions['values'] = ['1080', '720', '480', '240']

        self.level += 1
        self.btn_show_recording = Button(root,
                                         text="Show recording model",
                                         command=self.show_recording_model,
                                         state=DISABLED)
        self.btn_show_recording.grid(row=self.level,
                                     column=0,
                                     sticky=W + E,
                                     padx=PAD,
                                     pady=PAD)

        self.use_proxy = BooleanVar()
        self.use_proxy.set(False)
        self.use_proxy.trace('w', self.on_use_proxy_change)

        self.chk_use_proxy = Checkbutton(root,
                                         text='Use proxy',
                                         variable=self.use_proxy)
        self.chk_use_proxy.grid(row=self.level,
                                column=1,
                                sticky=W,
                                padx=PAD,
                                pady=PAD)

        self.cb_proxy = ttk.Combobox(root, width=30, state=DISABLED)
        self.cb_proxy.grid(row=self.level,
                           column=2,
                           columnspan=3,
                           sticky=W + E,
                           padx=PAD,
                           pady=PAD)

        self.level += 1
        self.btn_start = Button(root, text="Start", command=self.on_btn_start)
        self.btn_start.grid(row=self.level,
                            column=0,
                            sticky=W + E,
                            padx=PAD,
                            pady=PAD)

        self.btn_stop = Button(root,
                               text="Stop",
                               command=self.on_btn_stop,
                               state=DISABLED)
        self.btn_stop.grid(row=self.level,
                           column=1,
                           sticky=W + E,
                           padx=PAD,
                           pady=PAD)

        self.copy_button = Button(root,
                                  text="Copy",
                                  command=self.copy_model_name)
        self.copy_button.grid(row=self.level,
                              column=2,
                              sticky=W + E,
                              padx=PAD,
                              pady=PAD)

        self.paste_button = Button(root,
                                   text="Paste",
                                   command=self.paste_model_name)
        self.paste_button.grid(row=self.level,
                               column=3,
                               columnspan=2,
                               sticky=W + E,
                               padx=PAD,
                               pady=PAD)

        self.level += 1
        self.progress = ttk.Progressbar(root,
                                        orient=HORIZONTAL,
                                        length=120,
                                        mode='indeterminate')

        root.bind("<FocusIn>", self.focus_callback)
        root.protocol("WM_DELETE_WINDOW", self.on_close)

        self.play_list_url = None
        self.base_url = None
        self.model_image = None
        self.img_url = None

        self.hist_logger = logging.getLogger('history')
        self.hist_logger.setLevel(logging.INFO)

        self.fh_hist = logging.FileHandler(
            os.path.join(LOGS, f'hist_{int(time.time())}.log'))
        self.fh_hist.setLevel(logging.INFO)
        self.hist_logger.addHandler(self.fh_hist)

        self.proxy_logger = logging.getLogger('proxy')
        self.proxy_logger.setLevel(logging.INFO)

        self.fh_proxy = logging.FileHandler(
            os.path.join(LOGS, f'proxy_{int(time.time())}.log'))
        self.fh_proxy.setLevel(logging.INFO)
        self.proxy_logger.addHandler(self.fh_proxy)

        self.proxy_dict = {}
        self.load_proxy_dict()

        self.hist_stack = []

        self.load_image()

    def on_btn_start(self):
        self.btn_start.config(state=DISABLED)

        self.stop()

        idx = self.cb_resolutions.current()

        success = self.update_model_info(True)
        if not success:
            self.set_default_state()
            return

        items_count = len(self.cb_resolutions['value'])
        if items_count == 0:
            return

        if items_count <= idx or idx < 0:
            idx = 0

        self.cb_resolutions.current(idx)

        self.session = RecordSession(self, self.base_url, self.model_name,
                                     "chunks.m3u8")
        self.session.start()

        self.btn_stop.config(state=NORMAL)
        self.btn_show_recording.config(state=NORMAL)
        self.progress.grid(row=self.level,
                           column=0,
                           columnspan=5,
                           sticky=W + E,
                           padx=PAD,
                           pady=PAD)
        self.progress.start()

        self.update_title()

        root.configure(background='green')

    def on_btn_stop(self):
        self.stop()
        self.set_default_state()

    def stop(self):
        if self.session is None:
            return

        self.session.stop()
        self.session = None

    def copy_model_name(self):
        clipboard.copy(self.cb_model.get())

    def paste_model_name(self):
        self.cb_model.set(clipboard.paste())
        self.cb_model.selection_range(0, END)

    def update_model_info(self, remember):
        if remember and (self.model_name is not None):
            if len(self.hist_stack) == 0 or (self.model_name !=
                                             self.hist_stack[-1]):
                self.hist_stack.append(self.model_name)

        self.set_undefined_state()

        input_url = self.cb_model.get().strip()

        if len(input_url) == 0:
            self.set_undefined_state()
            return False

        proxy = self.cb_proxy.get().strip()
        if self.use_proxy.get() and len(proxy.strip()) != 0:
            self.proxies = {
                "http": "http://" + proxy,
                "https": "https://" + proxy
            }
        else:
            self.proxies = None

        ## https://live-edge66.bcvcdn.com/hls/stream_-icebabyice-/public/stream_-icebabyice-/chunks.m3u8
        ## https://live-edge3.bcvcdn.com/hls/stream_TemariShi/public-aac/stream_TemariShi/chunks.m3u8
        self.base_url = None
        if input_url.startswith('https://ded'):
            public_pos = input_url.rfind('public')
            self.base_url = input_url[:public_pos + 7]

            stream_pos = self.base_url.find('stream_')
            slash_pos = self.base_url.find('/', stream_pos)

            self.model_name = self.base_url[stream_pos + 7:slash_pos]
        elif input_url.startswith('https://live-edge'):
            slash_pos = input_url[:-1].rfind('/')
            self.base_url = input_url[:slash_pos + 1]

            stream_pos = self.base_url.find('stream_')
            slash_pos = self.base_url.find('/', stream_pos)

            self.model_name = self.base_url[stream_pos + 7:slash_pos]
        elif input_url.startswith('http'):
            slash_pos = input_url[:-1].rfind('/')
            self.model_name = input_url[slash_pos +
                                        1:-1] if input_url.endswith(
                                            '/') else input_url[slash_pos + 1:]
        else:
            self.model_name = input_url

        if self.base_url is None:
            info = self.get_model_info()
            print(info)
            if 'localData' not in info:
                self.set_undefined_state()
                return False

            server_url = info['localData']['videoServerUrl']
            self.model_name = info['performerData']['username']
            self.cb_resolutions.set(info['performerData']['videoQuality'])
            self.base_url = f"https:{server_url}/hls/stream_{self.model_name}/public-aac/stream_{self.model_name}/"

        if self.use_proxy.get() and len(proxy) != 0:
            self.add_to_proxies(proxy)

        self.get_image_url()
        self.add_to_history(self.model_name)

        self.update_title()

        return True

    def add_to_history(self, name):
        if name not in self.cb_model['values']:
            self.cb_model['values'] = (name, *self.cb_model['values'])

        self.hist_logger.info(name)

    def remove_from_favorites(self):
        name = self.cb_model.get().strip()
        values = list(self.cb_model['values'])
        if name not in values:
            return

        values.remove(name)
        self.cb_model['values'] = tuple(values)
        if len(values) == 0:
            self.cb_model.set('')
        else:
            self.cb_model.set(values[0])

    def add_to_proxies(self, proxy):
        if len(self.cb_proxy['values']) == 0:
            self.cb_proxy['values'] = proxy
        elif proxy not in self.cb_proxy['values']:
            self.cb_proxy['values'] = (proxy, *self.cb_proxy['values'])

        self.proxy_logger.info(proxy)
        count = self.proxy_dict.get(proxy, 0)
        self.proxy_dict[proxy] = count + 1

    def focus_callback(self, event):
        self.cb_model.selection_range(0, END)
        if self.hist_window is not None:
            self.hist_window.lift()

    def drop_down_callback(self, event):
        self.cb_model.focus_set()
        self.cb_model.selection_range(0, END)
        self.cb_model.event_generate('<Down>')

    def enter_callback(self, event):
        self.update_model_info(True)

    def get_image_url(self):
        edge_pos = self.base_url.find('-edge')
        point_pos = self.base_url.find('.', edge_pos)
        # hyphen_pos = self.base_url.find('-', edge_pos + 1)
        # if point_pos > hyphen_pos:
        #     point_pos = hyphen_pos
        vsid = self.base_url[edge_pos + 5:point_pos]
        self.img_url = f"https://mobile-edge{vsid}.bcvcdn.com/stream_{self.model_name}.jpg"

    def get_model_info(self):
        post_fields = {
            'method': 'getRoomData',
            'args[]': [self.model_name, "", ""]
        }

        headers = {
            'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8',
            'X-Requested-With': 'XMLHttpRequest'
        }

        try:
            response = self.http_session.post(
                "https://rt.chat-s-devushkami.com/tools/amf.php?x-country=a1",
                data=post_fields,
                headers=headers,
                proxies=self.proxies,
                timeout=TIMEOUT)
        except RequestException as error:
            print("GetRoomData exception model: " + self.model_name)
            print(error)
            traceback.print_exc()
            return {}

        return response.json()

    def load_image(self):
        global executor
        global root

        if (self.img_url is not None) or self.show_image:
            executor.submit(self.fetch_image)

        root.update_idletasks()
        root.after(DELAY, self.load_image)

    def fetch_image(self):
        global root

        try:
            response = self.http_session.get(self.img_url, timeout=TIMEOUT)
            img = Image.open(io.BytesIO(response.content))
            w, h = img.size
            k = 200 / w
            img_resized = img.resize((200, int(h * k)))
            root.after_idle(self.update_image, img_resized)
        except BaseException as error:
            root.after_idle(self.set_undefined_state)
            print("Exception URL: " + self.img_url)
            print(error)
            traceback.print_exc()

    def update_image(self, img):
        self.model_image = ImageTk.PhotoImage(img)
        self.image_label.config(image=self.model_image)

    def on_close(self):
        global root

        self.stop()
        root.update_idletasks()
        root.destroy()
        self.fh_hist.close()
        self.hist_logger.removeHandler(self.fh_hist)
        self.fh_proxy.close()
        self.proxy_logger.removeHandler(self.fh_proxy)
        self.http_session.close()

    def set_default_state(self):
        global root

        self.session = None
        self.btn_stop.config(state=DISABLED)
        self.btn_start.config(state=NORMAL)
        self.btn_show_recording.config(state=DISABLED)
        self.progress.stop()
        self.progress.grid_forget()
        self.update_title()
        root.configure(background='SystemButtonFace')

    def update_title(self):
        global root

        root.title(self.model_name or '<Undefined>')

        if self.session is None:
            return

        if not self.session.is_alive():
            return

        if self.session.model_name != root.title():
            return

        root.title(root.title() + " - Recording")

    def set_undefined_state(self):
        self.model_image = None
        self.image_label.config(image=None)
        self.model_name = None
        self.img_url = None
        self.update_title()

    def show_recording_model(self):
        if self.session is None:
            return

        self.cb_model.set(self.session.model_name)
        self.cb_model.selection_range(0, END)
        self.update_model_info(True)

    def on_use_proxy_change(self, *args):
        if self.use_proxy.get():
            self.cb_proxy.config(state=NORMAL)
            self.cb_proxy.focus_set()
            self.cb_proxy.selection_range(0, END)
        else:
            self.cb_proxy.config(state=DISABLED)

    def toggle_image(self):
        if self.show_image:
            self.model_image = None
            self.image_label.config(image=None)
            self.img_url = None
            self.image_label.grid_forget()
            self.show_image = False
        else:
            self.show_image = True
            self.image_label.grid(row=0,
                                  column=0,
                                  columnspan=5,
                                  sticky=W + E,
                                  padx=PAD,
                                  pady=PAD)
            self.update_model_info(True)

    def show_full_history(self, period):
        if self.hist_window is not None:
            self.hist_window.on_close()

        self.hist_window = HistoryWindow(self, Toplevel(root),
                                         load_hist_dict(period))

    def back_in_history(self):
        if len(self.hist_stack) == 0:
            return

        self.cb_model.set(self.hist_stack.pop())
        self.update_model_info(False)

    def load_proxy_dict(self):
        for file in os.listdir(LOGS):
            if not file.startswith('proxy_'):
                continue

            full_path = os.path.join(LOGS, file)
            if os.path.getsize(full_path) == 0:
                continue

            with open(full_path) as f:
                for line in f.readlines():
                    name = line.strip()
                    count = self.proxy_dict.get(name, 0)
                    self.proxy_dict[name] = count + 1

        hist = sorted(self.proxy_dict.items(),
                      key=lambda x: x[1],
                      reverse=True)
        self.cb_proxy.configure(values=[x[0] for x in hist[:10]])
예제 #24
0
class Assembly(Frame):
    def __init__(self, parent):
        Frame.__init__(self, parent, background="white")
        self.parent = parent
        self.parent.title("SMBP_logs")
        self.pack(fill='both', expand=True)

        panelFrame = Frame(self)
        textFrame = Frame(self)
        """ создаем фреймы верх-низ и далее в каждом фрейме создаем лево-право 
			или верх=низ фреймы, к которым будут привязаны объекты, чтобы
			в случае расширения формы нормально отображалось и перемещалось все
		"""
        panelFrame.pack(side='top', fill='both')
        textFrame.pack(side='bottom', fill='both', expand=True)

        panelFrameUp = Frame(panelFrame)
        panelFrameDown = Frame(panelFrame)

        panelFrameUp.pack(side='top', fill='both', expand=True)
        panelFrameDown.pack(side='bottom', fill='both', expand=True)

        panelFrameUpTop = Frame(panelFrameUp)
        panelFrameUpBottom = Frame(panelFrameUp)

        panelFrameUpTop.pack(side='top', fill='both', expand=True)
        panelFrameUpBottom.pack(side='bottom', fill='both', expand=True)

        panelFrameTop = Frame(panelFrameDown)
        panelFrameBottom = Frame(panelFrameDown,
                                 relief='raised',
                                 borderwidth=1)

        panelFrameTop.pack(side='top', fill='both', expand=True)
        panelFrameBottom.pack(side='bottom', fill='both', expand=True)

        textFrameLeft = Frame(textFrame)
        textFrameRight = Frame(textFrame)

        textFrameLeft.pack(side='left', fill='both', expand=True)
        textFrameRight.pack(side='right', fill='both', expand=True)

        textFrameRightTop = Frame(textFrameRight)
        textFrameRightBottom = Frame(textFrameRight)

        textFrameRightTop.pack(side='top', fill='both', expand=True)
        textFrameRightBottom.pack(side='bottom', fill='both', expand=True)

        # создаем экземпляры класса текстбокса передаем нужный фрейм
        self.txtBox_left = TxtBox(textFrameLeft)
        self.txtBox_rtop = TxtBox(textFrameRightTop)
        self.txtBox_rbottom = TxtBox(textFrameRightBottom)

        label_param = Label(panelFrameBottom, text="Параметры поиска. Маска: ")
        label_param.pack(side='left', padx=5, pady=5)

        mask_entry = Entry(panelFrameBottom, width=15)
        mask_entry.pack(side='left', padx=5, pady=5)
        mask_entry.insert('end', date_mask)

        label_delta = Label(panelFrameBottom, text="Дельта в минутах: ")
        label_delta.pack(side='left', padx=5, pady=5)

        def def_delta():
            if str(delta_btn['text']) == '0':
                delta_btn['text'] = '10'
            else:
                delta_btn['text'] = '0'

        delta_btn = Button(panelFrameBottom,
                           text=delta,
                           width=3,
                           command=def_delta)
        delta_btn.pack(side='left', padx=5, pady=5)

        # чекбокс проверки поиска по ТД
        self.check_on_td_var = BooleanVar()
        check_on_td = Checkbutton(panelFrameBottom,
                                  text='Поиск по TD',
                                  variable=self.check_on_td_var)
        self.check_on_td_var.set(True)
        check_on_td.pack(side='left', padx=5, pady=5)

        btn_run = Button(panelFrameBottom, text='Поиск по файлам',
                         width=15)  #, command=pass)
        btn_run.pack(side='right', pady=1)

        btn_find_files = Button(panelFrameBottom,
                                text='Поиск файлов',
                                width=15)  #, command=pass)
        btn_find_files.pack(side='right', padx=3, pady=1)

        # строка поиска
        label_find = Label(panelFrameTop, text="Строка поиска: ")
        label_find.pack(side='left', padx=5, pady=5)

        find_entry = Entry(panelFrameTop)
        find_entry.pack(fill='x', padx=5, expand=True)
        find_entry.insert('end', search_word)

        # если строка не изменялась при нажатии мышкой должна быть очищена
        def clean_find_entry(*args):
            if str(find_entry.get()) == search_word:
                find_entry.delete(0, 'end')

        find_entry.bind('<Button-1>', clean_find_entry)

        # textbox
        txt_mr = Text(panelFrameUpBottom, width=1, height=8)
        scrollbar_mr = Scrollbar(panelFrameUpBottom)
        scrollbar_mr['command'] = txt_mr.yview
        txt_mr['yscrollcommand'] = scrollbar_mr.set
        scrollbar_mr.pack(side='right', fill='y')
        txt_mr.pack(fill='both', expand=True)

        # для передачи аргументов при нажатии кнопки поиска файлов
        btn_find_files.bind(
            '<Button-1>', lambda _: find_files(
                txt_mr, self.txtBox_rbottom.txt_box, self.txtBox_rtop.txt_box,
                self.txtBox_left.txt_box, mask_entry, delta_btn))

        btn_run.bind(
            '<Button-1>', lambda _:
            find_session(self.txtBox_rtop.txt_box, self.txtBox_rbottom.txt_box,
                         self.txtBox_left.txt_box, find_entry, mask_entry, self
                         .check_on_td_var, btn_run))

        def select_mr(self, btn_mr):
            # все кнопки закрашиваем в цвет по умолчанию
            btn_mr1['bg'] = btn_mr2['bg'] = btn_mr3['bg'] = btn_mr4[
                'bg'] = btn_mr5['bg'] = 'SystemButtonFace'
            # подкрашиваем только ту кнопку, что нажата
            btn_mr['bg'] = 'gray75'
            global mr
            # меняем регион с которым работаем
            mr = btn_mr['text']
            # при смене мр меняем список серверов
            print_mr_list()  #(btn_mr['text'])

        def print_mr_list(*args):
            # очищаем текстбокс и выводим новый список серверов исходя из МР
            txt_mr.delete('1.0', 'end')
            # mr = args[0]
            for host in mr_dict[mr]['hosts']:
                for path in mr_dict[mr]['paths']:
                    txt_mr.insert('end', host + ' | ' + path + '\n')
            for host in mr_dict[mr]['new_hosts']:
                for path in mr_dict[mr]['new_paths']:
                    txt_mr.insert('end', host + ' | ' + path + '\n')
            # если чекбокс стоит на архивных серверах - добавляем их
            if self.check_arch_var.get():
                for path in mr_dict[mr]['arch_paths']:
                    txt_mr.insert(
                        'end',
                        str(mr_dict[mr]['arch_host']) + ' | ' + path + '\n')

        label_mr = Label(panelFrameUpTop, text="Выбор МР: ")
        label_mr.pack(side='left', padx=5, pady=5)

        btn_mr1 = Button(panelFrameUpTop, text='МРЮг', width=10, bg='gray75')
        btn_mr1.pack(side='left', padx=1, pady=1)
        # при нажатии кнопки вызываем процедуру перекраски мр
        btn_mr1.bind('<Button-1>', lambda _: select_mr(self, btn_mr1))

        btn_mr2 = Button(panelFrameUpTop, text='МРМосква', width=10)
        btn_mr2.pack(side='left', padx=1, pady=1)
        btn_mr2.bind('<Button-1>', lambda _: select_mr(self, btn_mr2))

        btn_mr3 = Button(panelFrameUpTop, text='МРСибирь', width=10)
        btn_mr3.pack(side='left', padx=1, pady=1)
        btn_mr3.bind('<Button-1>', lambda _: select_mr(self, btn_mr3))

        btn_mr4 = Button(panelFrameUpTop, text='МРСЗ', width=10)
        btn_mr4.pack(side='left', padx=1, pady=1)
        btn_mr4.bind('<Button-1>', lambda _: select_mr(self, btn_mr4))

        btn_mr5 = Button(panelFrameUpTop, text='МРПоволжье', width=10)
        btn_mr5.pack(side='left', padx=1, pady=1)
        btn_mr5.bind('<Button-1>', lambda _: select_mr(self, btn_mr5))

        self.check_arch_var = BooleanVar()
        check_arch = Checkbutton(panelFrameUpTop,
                                 text='Поиск по архивным серверам',
                                 variable=self.check_arch_var)
        self.check_arch_var.set(True)
        check_arch.pack(side='left', padx=5, pady=5)
        self.check_arch_var.trace('w', print_mr_list)
        # один разок надо вызвать эту процедуру при инициализации
        select_mr(self, btn_mr1)
예제 #25
0
class CopyToMoveTo:
    """
        Minimalist file manager intended to be used independently
        or alongside Windows Explorer
    """
    def __init__(self, root):
        """
            Setup window geometry, init settings, define widgets + layout
        """
        self.master = root
        self.master.title("CopyTo-MoveTo")
        self.master.iconbitmap(f"{dirname(__file__)}/icon.ico")

        if system() != "Windows":
            self.master.withdraw()
            messagebox.showwarning(
                "Incompatible platform",
                "CopyTo-MoveTo currently supports Windows platforms only.")
            raise SystemExit

        #Settings:
        self.settings_show_hidden = BooleanVar()
        self.settings_include_files = BooleanVar(value=True)
        self.settings_ask_overwrite = BooleanVar()
        self.settings_ask_overwrite.trace("w", self.settings_exclusives)
        self.settings_rename_dupes = BooleanVar(value=True)
        self.settings_rename_dupes.trace("w", self.settings_exclusives)
        self.settings_multiselect = BooleanVar(value=True)
        self.settings_select_dirs = BooleanVar(value=True)
        self.settings_select_dirs.trace("w", self.settings_mutuals)
        self.settings_select_files = BooleanVar(value=True)
        self.settings_select_files.trace("w", self.settings_mutuals)
        self.settings_geometry = None

        self.appdata_dir = getenv("APPDATA") + "/CopyTo-MoveTo"
        self.appdata_path = self.appdata_dir + "/settings.json"
        self.settings = self.init_settings()

        if self.settings:
            self.settings_geometry = self.settings["geometry"]
            self.settings_show_hidden.set(self.settings["show_hidden"])
            self.settings_include_files.set(self.settings["include_files"])
            self.settings_ask_overwrite.set(self.settings["ask_overwrite"])
            self.settings_rename_dupes.set(self.settings["rename_dupes"])
            self.settings_multiselect.set(self.settings["multiselect"])
            self.settings_select_dirs.set(self.settings["select_dirs"])
            self.settings_select_files.set(self.settings["select_files"])

        self.dialog_showing = BooleanVar()
        self.help_showing = BooleanVar()
        self.about_showing = BooleanVar()

        self.master.protocol("WM_DELETE_WINDOW", self.master_close)
        self.master.bind("<Control-w>", self.master_close)

        #Geometry:
        self.master.minsize(width=450, height=200)

        if self.settings_geometry:
            self.master.geometry(self.settings_geometry)
            self.master.update()
        else:
            self.master.geometry("600x400")
            self.master.update_idletasks()
            (width_offset, height_offset) = Ufd.get_offset(self.master)
            self.master.geometry(f"+{width_offset}+{height_offset}")
            self.master.update_idletasks()

        # Menu:
        self.main_menu = Menu(self.master)
        self.master.config(menu=self.main_menu)

        self.file_menu = Menu(self.main_menu, tearoff=0)
        self.settings_menu = Menu(self.main_menu, tearoff=0)
        self.main_menu.add_cascade(label="File", menu=self.file_menu)
        self.main_menu.add_cascade(label="Settings", menu=self.settings_menu)

        self.file_menu.add_command(label="Open Source(s)",
                                   accelerator="Ctrl+O",
                                   command=lambda: self.show_ufd(source=True))
        self.master.bind("<Control-o>",
                         lambda event: self.show_ufd(source=True))

        self.file_menu.add_command(label="Open Destination(s)",
                                   accelerator="Ctrl+K+O",
                                   command=lambda: self.show_ufd(source=False))
        self.master.bind("<Control-k>o",
                         lambda event: self.show_ufd(source=False))

        self.file_menu.add_separator()
        self.file_menu.add_command(label="Help / Commands",
                                   command=self.show_help)
        self.file_menu.add_command(label="About", command=self.show_about)

        #Settings menu:
        self.settings_menu.add_checkbutton(label="Show Hidden Files & Folders",
                                           variable=self.settings_show_hidden,
                                           onvalue=True,
                                           offvalue=False)

        self.settings_menu.add_checkbutton(
            label="Include Files in Tree",
            variable=self.settings_include_files,
            onvalue=True,
            offvalue=False)

        self.settings_menu.add_separator()

        self.settings_menu.add_checkbutton(
            label="Ask Overwrite",
            variable=self.settings_ask_overwrite,
            onvalue=True,
            offvalue=False)

        self.settings_menu.add_checkbutton(label="Rename Duplicates",
                                           variable=self.settings_rename_dupes,
                                           onvalue=True,
                                           offvalue=False)

        self.settings_menu.add_separator()

        self.settings_menu.add_checkbutton(label="Multiselect",
                                           variable=self.settings_multiselect,
                                           onvalue=True,
                                           offvalue=False)

        self.settings_menu.add_checkbutton(label="Select Folders",
                                           variable=self.settings_select_dirs,
                                           onvalue=True,
                                           offvalue=False)

        self.settings_menu.add_checkbutton(label="Select Files",
                                           variable=self.settings_select_files,
                                           onvalue=True,
                                           offvalue=False)

        self.main_menu.add_separator()

        #Menu commands:
        self.main_menu.add_command(label="Swap Selected",
                                   command=self.swap_selected)
        self.master.bind("<Control-s>", lambda event: self.swap_selected())

        self.main_menu.add_command(label="Clear Selected",
                                   command=self.clear_selected)
        self.master.bind("<Control-x>", lambda event: self.clear_selected())

        self.main_menu.add_command(label="Clear All", command=self.clear_all)
        self.master.bind("<Control-Shift-X>", lambda event: self.clear_all())

        self.main_menu.add_separator()

        self.main_menu.add_command(label="COPY",
                                   command=lambda: self._submit(copy=True))
        self.master.bind("<Control-Shift-Return>",
                         lambda event: self._submit(copy=True))

        self.main_menu.add_command(label="MOVE",
                                   command=lambda: self._submit(copy=False))
        self.master.bind("<Control-Return>",
                         lambda event: self._submit(copy=False))

        # Body:
        self.paneview = PanedWindow(self.master,
                                    sashwidth=7,
                                    bg="#cccccc",
                                    bd=0,
                                    orient="vertical")

        self.top_pane = PanedWindow(self.paneview)
        self.bottom_pane = PanedWindow(self.paneview)
        self.paneview.add(self.top_pane)
        self.paneview.add(self.bottom_pane)

        self.label_source = Label(self.top_pane, text="Source(s):")
        self.label_dest = Label(self.bottom_pane, text="Destination(s):")

        self.y_scrollbar_source = Scrollbar(self.top_pane, orient="vertical")
        self.x_scrollbar_source = Scrollbar(self.top_pane, orient="horizontal")
        self.y_scrollbar_dest = Scrollbar(self.bottom_pane, orient="vertical")
        self.x_scrollbar_dest = Scrollbar(self.bottom_pane,
                                          orient="horizontal")

        self.list_box_source = Listbox(
            self.top_pane,
            selectmode="extended",
            yscrollcommand=self.y_scrollbar_source.set,
            xscrollcommand=self.x_scrollbar_source.set)

        self.list_box_dest = Listbox(self.bottom_pane,
                                     selectmode="extended",
                                     yscrollcommand=self.y_scrollbar_dest.set,
                                     xscrollcommand=self.x_scrollbar_dest.set)

        self.x_scrollbar_source.config(command=self.list_box_source.xview)
        self.y_scrollbar_source.config(command=self.list_box_source.yview)
        self.x_scrollbar_dest.config(command=self.list_box_dest.xview)
        self.y_scrollbar_dest.config(command=self.list_box_dest.yview)

        # Layout:
        self.master.rowconfigure(0, weight=1)
        self.master.columnconfigure(0, weight=1)

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

        self.paneview.paneconfigure(self.top_pane, minsize=100)
        self.paneview.paneconfigure(self.bottom_pane, minsize=100)

        self.paneview.grid(row=0, column=0, sticky="nsew")

        self.label_source.grid(row=0, column=0, sticky="w")
        self.list_box_source.grid(row=1, column=0, sticky="nsew")
        self.y_scrollbar_source.grid(row=1, column=1, sticky="ns")
        self.x_scrollbar_source.grid(row=2, column=0, sticky="ew")

        self.label_dest.grid(row=0, column=0, sticky="w", columnspan=2)
        self.list_box_dest.grid(row=1, column=0, sticky="nsew")
        self.y_scrollbar_dest.grid(row=1, column=1, sticky="ns")
        self.x_scrollbar_dest.grid(row=2, column=0, sticky="ew")

    def __str__(self):
        """Return own address"""

        return f"CopyTo-MoveTo @ {hex(id(self))}"

    def init_settings(self):
        """Called on startup, loads, parses, and returns json settings."""

        if exists(self.appdata_path):
            with open(self.appdata_path, "r") as settings_file:
                settings_json = settings_file.read()

            settings = loads(settings_json)
            return settings
        else:
            return None

    def settings_exclusives(self, *args):
        """
            Callback assigned to settings that are mutually exclusive, 
            to prevent logical/runtime errors or unexpected behavior.
        """

        if args[0] == "PY_VAR2":
            if self.settings_ask_overwrite.get() == 1:
                self.settings_rename_dupes.set(0)
                return

        elif args[0] == "PY_VAR3":
            if self.settings_rename_dupes.get() == 1:
                self.settings_ask_overwrite.set(0)
                return

    def settings_mutuals(self, *args):
        """
            Prevent select folders & select files from being disabled concurrently

            If both are unselected, reselect the one we didn't just deselect on.
        """

        if self.settings_select_dirs.get() == 0 \
        and self.settings_select_files.get() == 0:

            if args[0] == "PY_VAR5":
                self.settings_select_files.set(1)

            elif args[0] == "PY_VAR6":
                self.settings_select_dirs.set(1)

    def master_close(self, event=None):
        """
            Similar to utils.toplevel_close().
            writes settings to the disk as json.
        """

        settings = {
            "geometry": self.master.geometry(),
            "show_hidden": self.settings_show_hidden.get(),
            "include_files": self.settings_include_files.get(),
            "ask_overwrite": self.settings_ask_overwrite.get(),
            "rename_dupes": self.settings_rename_dupes.get(),
            "multiselect": self.settings_multiselect.get(),
            "select_dirs": self.settings_select_dirs.get(),
            "select_files": self.settings_select_files.get(),
        }

        settings_json = dumps(settings)

        if not exists(self.appdata_dir):
            mkdir(self.appdata_dir)

        with open(self.appdata_path, "w+") as settings_file:
            settings_file.write(settings_json)

        if self.dialog_showing.get() == 1:
            self.ufd.cancel()

        self.master.destroy()

    def toplevel_close(self, dialog, boolean):
        """
            This callback flips the value for a given toplevel_showing boolean
            to false, before disposing of the toplevel.
        """

        boolean.set(0)
        dialog.destroy()

    def swap_selected(self):
        """Swap list entries between source & destination"""

        source_selection = list(self.list_box_source.curselection())
        dest_selection = list(self.list_box_dest.curselection())

        for i in reversed(source_selection):
            item = self.list_box_source.get(i)
            self.list_box_source.delete(i)
            self.list_box_dest.insert("0", item)

        for i in reversed(dest_selection):
            item = self.list_box_dest.get(i)
            self.list_box_dest.delete(i)
            self.list_box_source.insert("0", item)

    def clear_selected(self):
        """Removes selected (highlighted) item(s) from a given listbox"""

        source_selection = list(self.list_box_source.curselection())
        dest_selection = list(self.list_box_dest.curselection())

        if source_selection:
            for i in reversed(source_selection):
                self.list_box_source.delete(i)

            self.list_box_source.selection_set(source_selection[0])

        if dest_selection:
            for i in reversed(dest_selection):
                self.list_box_dest.delete(i)

            self.list_box_dest.selection_set(dest_selection[0])

    def clear_all(self):
        """Clears both listboxes in the main UI, resetting the form."""

        self.list_box_source.delete(0, "end")
        self.list_box_dest.delete(0, "end")

    def handled(fn):
        """Filesystem operations are wrapped here for error handling"""
        @wraps(fn)
        def inner(self, *args, **kwargs):
            try:
                fn(self, *args, **kwargs)
                return True
            except (PermissionError, FileNotFoundError) as err:
                self.skipped_err.append(f"{err.args[1]}:\n" +
                                        (" => ".join(args)))
                return False

        return inner

    @handled
    def _copy(self, path, destination):
        """Wrapper for shutil.copy2() || shutil.copytree()"""

        if isfile(path):
            copy2(path, destination)
        else:
            copytree(path, destination)

    @handled
    def _move(self, path, destination):
        """Wrapper for shutil.move()"""

        move(path, destination)

    @handled
    def _delete(self, path):
        """Wrapper for os.remove() || shutil.rmtree()"""

        if isfile(path):
            remove(path)
        elif isdir(path):
            rmtree(path)

    def disabled_ui(fn):
        """Menubar is disabled during operations"""
        @wraps(fn)
        def inner(self, *args, **kwargs):
            self.main_menu.entryconfig("File", state="disabled")
            self.main_menu.entryconfig("Settings", state="disabled")
            self.main_menu.entryconfig("Clear Selected", state="disabled")
            self.main_menu.entryconfig("Clear All", state="disabled")
            self.main_menu.entryconfig("COPY", state="disabled")
            self.main_menu.entryconfig("MOVE", state="disabled")

            fn(self, *args, **kwargs)

            self.main_menu.entryconfig("File", state="normal")
            self.main_menu.entryconfig("Settings", state="normal")
            self.main_menu.entryconfig("Clear Selected", state="normal")
            self.main_menu.entryconfig("Clear All", state="normal")
            self.main_menu.entryconfig("COPY", state="normal")
            self.main_menu.entryconfig("MOVE", state="normal")

        return inner

    def _submit(self, copy):
        """Thread/wrapper for submit() so we don't block the UI during operations"""

        self.thread = Thread(target=self.submit, args=(copy, ), daemon=True)
        self.thread.start()

    @disabled_ui
    def submit(self, copy):
        """
            Move or copy each item in the origin list to the path in the
            destination list. Supports no more than one destination directory
            where copy == False.

            Ask Overwrite and Rename Dupes will alter the way we handle 
            existing data standing in the way. By default, duplicates are 
            renamed with an index. A messagebox can complain to the user
            if shutil raises a PermissionError, and the operation is skipped.
        """

        if (self.list_box_dest.size() > 1) and not copy:
            messagebox.showwarning(
                "Invalid Operation",
                "Move operation only supports a single destination directory.")
            return

        sources = self.list_box_source.get(0, "end")
        destinations = self.list_box_dest.get(0, "end")

        self.skipped_err = []

        for j, destination in enumerate(destinations):

            if isfile(destination):
                self.skipped_err.append(f"Invalid destination: {destination}")
                continue

            for i, source in enumerate(sources):
                self.progress(i, j)

                (_, filename) = split(source)
                future_destination = join(destination + sep, filename)

                if exists(future_destination):
                    if not self.settings_ask_overwrite.get() \
                    and not self.settings_rename_dupes.get():

                        if not self._delete(future_destination):
                            continue

                    if self.settings_ask_overwrite.get():

                        if self.ask_overwrite(future_destination):
                            if not self._delete(future_destination):
                                continue

                        else:
                            continue

                    if self.settings_rename_dupes.get():
                        future_destination = self.name_dupe(future_destination)

                if copy:
                    if not self._copy(source, future_destination):
                        continue
                else:
                    if not self._move(source, future_destination):
                        continue

        self.list_box_source.delete(0, "end")
        self.list_box_dest.delete(0, "end")

        if self.skipped_err:
            messagebox.showerror(title="Error(s)",
                                 message="\n\n".join(self.skipped_err))

    @staticmethod
    def name_dupe(path):
        """
            Renames the file or directory until it doesn't exist
            in the destination with that name anymore, by appending
            the filename with an index wrapped in parenthesis.
            (Windows platforms)
            file.txt => file (1).txt => file (2).txt
        """

        if system() != "Windows":
            raise OSError("For use with Windows filesystems.")

        path_ = path
        (root, filename) = split(path_)

        if isdir(path_):
            title = filename
            ext = None
        else:
            (title, ext) = splitext(filename)

        filecount = 0
        while exists(path_):
            filecount += 1
            new_title = title + " (" + str(filecount) + ")"
            if ext:
                new_title = new_title + ext
            path_ = join(root, new_title)

        return path_

    def ask_overwrite(self, future_destination):
        """Messagebox result returned as truth value"""

        return messagebox.askyesno(
            title="Path Conflict",
            message=f"Overwrite:\n\n{future_destination}?\n\n" \
            f"YES - Overwrite\nNO - Skip"
        )

    def progress(self, i, j):
        """
            Visualize operands in GUI during operations

            i = current source operand index
            j = current destination operand index
        """

        for y, _ in enumerate(self.list_box_source.get(0, "end")):
            if y != i:
                self.list_box_source.itemconfigure(y,
                                                   bg="#FFFFFF",
                                                   fg="#000000")
            else:
                self.list_box_source.itemconfigure(y,
                                                   bg="#cccccc",
                                                   fg="#000000")

        for x, _ in enumerate(self.list_box_dest.get(0, "end")):
            if x != j:
                self.list_box_dest.itemconfigure(x, bg="#FFFFFF", fg="#000000")
            else:
                self.list_box_dest.itemconfigure(x, bg="#cccccc", fg="#000000")

        self.master.update()

    #Toplevels:
    def show_about(self):
        """
            Displays a static dialog that doesn't allow additional
            instances of itself to be created while showing.
        """

        if self.about_showing.get() == 0:
            self.about_showing.set(1)

            try:
                with open(f"{dirname(__file__)}/about.txt", "r") as aboutfile:
                    about_info = aboutfile.read()
            except FileNotFoundError:
                messagebox.showerror("Error", "File not found")
                self.about_showing.set(0)
                return

            else:
                self.about = Toplevel()
                self.about.title("About")
                self.about.iconbitmap(f"{dirname(__file__)}/icon.ico")

                self.about.geometry("600x400")
                self.about.resizable(0, 0)
                self.about.update_idletasks()
                (width_offset, height_offset) = Ufd.get_offset(self.about)
                self.about.geometry(f"+{width_offset-75}+{height_offset-75}")
                self.about.update_idletasks()

                self.about_message = Label(
                    self.about,
                    text=about_info,
                    justify="left",
                    wraplength=(self.about.winfo_width() - 25))

                self.about_message.grid(sticky="nsew")

                self.about.protocol(
                    "WM_DELETE_WINDOW", lambda: self.toplevel_close(
                        self.about, self.about_showing))

    def show_help(self):
        """
            Displays a scrollable dialog that doesn't allow additional
            instances of itself to be created while showing.
        """

        if self.help_showing.get() == 0:
            self.help_showing.set(1)

            try:
                with open(f"{dirname(__file__)}/help.txt", "r") as helpfile:
                    help_info = helpfile.read()
            except FileNotFoundError:
                messagebox.showerror("Error", "File not found")
                self.help_showing.set(0)
                return

            else:
                self.help_window = Toplevel()
                self.help_window.title("Help")
                self.help_window.iconbitmap(f"{dirname(__file__)}/icon.ico")

                self.help_window.geometry("500x300")
                self.help_window.update_idletasks()
                (width_offset,
                 height_offset) = Ufd.get_offset(self.help_window)
                self.help_window.geometry(
                    f"+{width_offset+75}+{height_offset-75}")
                self.help_window.update_idletasks()

                self.message_y_scrollbar = Scrollbar(self.help_window,
                                                     orient="vertical")

                self.help_text = Text(
                    self.help_window,
                    wrap="word",
                    yscrollcommand=self.message_y_scrollbar.set)

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

                self.help_text.grid(row=0, column=0, sticky="nsew")
                self.message_y_scrollbar.grid(row=0, column=1, sticky="nse")

                self.message_y_scrollbar.config(command=self.help_text.yview)

                self.help_text.insert("end", help_info)
                self.help_text.config(state="disabled")

                self.help_window.protocol(
                    "WM_DELETE_WINDOW", lambda: self.toplevel_close(
                        self.help_window, self.help_showing))

    def show_ufd(self, source=True):
        """ Display Ufd w/ appropriate kwargs => Populate GUI w/ result"""

        if self.dialog_showing.get() == 0:
            self.dialog_showing.set(1)

            self.ufd = Ufd(title="Add Items",
                           show_hidden=self.settings_show_hidden.get(),
                           include_files=self.settings_include_files.get(),
                           multiselect=self.settings_multiselect.get(),
                           select_dirs=self.settings_select_dirs.get(),
                           select_files=self.settings_select_files.get(),
                           unix_delimiter=False,
                           stdout=False)

            for result in self.ufd():
                if source:
                    self.list_box_source.insert("end", result)
                else:
                    self.list_box_dest.insert("end", result)

            self.dialog_showing.set(0)
예제 #26
0
파일: LURKc.py 프로젝트: jmsimons/LURKc
input_user = StringVar()
input_type = 0


def join_recv(*args):
    print(exit_flag.get(), recv_thread.is_alive())
    if exit_flag.get() and recv_thread.is_alive():
        print('Attempting to Join recv_thread')
        recv_thread.join()
        print('Thread joined succesfully!')


exit_flag = BooleanVar()
exit_flag.set(False)
exit_flag.trace('w', join_recv)

### Function Definitions ###


def console(message, sender=None, recipient=None, end='\n', level=0):
    global text
    if level:  # TODO: Set color formatting on [sender]
        if level == 1: color = 'Green'  # Successful Action
        elif level == 2: color = 'Yellow'  # Unsuccessful action
        elif level == 3: color = 'Red'  # Server Critical Issue
        elif level == 4: color = 'blue'  # Private Message
    # TODO: set bold formatting on [sender]
    if not sender:
        sender = 'LURKle'
    if not recipient:
예제 #27
0
class MainFrame(Frame):
    def set_saved_title(self, fpath):
        fname = split(fpath)[-1].replace('.json', '')
        self.master.title('{}  -  {}'.format(fname, _title))

    def set_unsaved_title(self, *args):
        if len(roller_groups) < 1:
            return
        if self.autosave.get():
            self.save_config(self.fpath)
            return
        title = self.master.title()
        if title == _title:
            title = '{}  -  {}'.format('Unsaved', title)
        if '*' not in title:
            title = '*' + title

        self.master.title(title)

    def __init__(self, master):
        Frame.__init__(self, master)

        self.master = master

        self.use_random_org = BooleanVar()
        self.allow_odd = IntVar()
        self.always_on_top = BooleanVar()
        self.autosave = BooleanVar()

        self.use_random_org.trace('w', self.set_unsaved_title)
        self.allow_odd.trace('w', self.set_unsaved_title)
        self.always_on_top.trace('w', self.set_unsaved_title)

        self.set_defaults()

        self.menubar = Menu(master)

        self.filemenu = Menu(self.menubar,
                             tearoff=0,
                             postcommand=maintain_group_indices)
        self.filemenu.add_command(label='New',
                                  underline=0,
                                  command=self.reset_default_group,
                                  accelerator='Ctrl+N')
        self.filemenu.add_command(label='Load',
                                  underline=3,
                                  command=self.load_config,
                                  accelerator='Ctrl+D')
        self.filemenu.add_command(
            label='Save',
            underline=1,
            command=lambda: self.save_config(fpath=self.fpath),
            accelerator='Ctrl+S')
        self.filemenu.add_command(label='Save as...',
                                  underline=4,
                                  command=self.save_config,
                                  accelerator='Ctrl+Shift+S')

        self.editmenu = Menu(self.menubar, tearoff=0)
        self.editmenu.add_checkbutton(label='Use random.org',
                                      underline=0,
                                      variable=self.use_random_org)
        self.editmenu.add_checkbutton(label='Allow odd dice',
                                      underline=6,
                                      variable=self.allow_odd,
                                      command=self.toggle_odd,
                                      onvalue=1,
                                      offvalue=2)
        self.editmenu.add_separator()  #      ------------------
        self.editmenu.add_checkbutton(label='Always on top',
                                      underline=10,
                                      variable=self.always_on_top,
                                      command=self.pin)
        self.editmenu.add_checkbutton(label='Autosave',
                                      underline=4,
                                      variable=self.autosave,
                                      command=self.toggle_autosave)
        self.editmenu.add_separator()  #      ------------------
        self.editmenu.add_command(label='Repeat last action',
                                  underline=0,
                                  accelerator='Ctrl+R')

        self.menubar.add_cascade(label='File', underline=0, menu=self.filemenu)
        self.menubar.add_cascade(label='Edit', underline=0, menu=self.editmenu)

        self.menubar.config(relief='flat')

        master.config(menu=self.menubar)

        self.reset_default_group()

        self.bind_all('<Control-n>', lambda e: self.reset_default_group())
        self.bind_all('<Control-d>', lambda e: self.load_config())
        self.bind_all('<Control-s>',
                      lambda e: self.save_config(fpath=self.fpath))
        self.bind_all('<Control-Shift-S>', lambda e: self.save_config())

    def ask_proceed(self):
        if '*' in self.master.title():
            if not askyesno(
                    'Unsaved changes!',
                    'There are unsaved changes!\r\nWould you like to proceed anyway?'
            ):
                return False
        return True

    def pin(self):
        self.master.wm_attributes('-topmost', self.always_on_top.get())

    def toggle_odd(self):
        for group in roller_groups:
            for roller in group.rollers:
                roller.die_faces_spin.interval = self.allow_odd.get()
                num = roller.die_faces.get()
                if num % 2 != 0:
                    roller.die_faces.set(num - 1)

    def toggle_autosave(self):
        if self.autosave.get():
            self.save_config(self.fpath)
        else:
            self.set_unsaved_title()

    def set_defaults(self):
        self.master.title(_title)
        self.fpath = ''
        self.use_random_org.set(False)
        self.allow_odd.set(2)
        self.always_on_top.set(False)
        self.autosave.set(False)

    def reset_default_group(self):
        if self.ask_proceed():
            self.autosave.set(False)
            self.clear_groups()
            self.set_defaults()
            self.create_group(0, 1)

    @staticmethod
    def clear_groups():
        temp_groups = list(roller_groups)
        for group in temp_groups:
            group.remove_group(override=True)

    def create_group(self, index, rollers):
        default_group = RollerGroup(self, index)
        for i in range(rollers):
            default_group.rollers.append(Roller(default_group, i))
        roller_groups.append(default_group)

    def load_config(self):
        autosave = False
        self.autosave.set(autosave)
        if not self.ask_proceed():
            return

        fpath = askopenfilename(filetypes=[('JSON', '*.json'), ('All', '*.*')],
                                defaultextension='.json')
        if not fpath or not isfile(fpath):
            return
        self.fpath = fpath

        self.clear_groups()

        with open(fpath, 'r') as f:
            group_dict = load(f)

        try:
            settings_dict = group_dict.pop('settings')
            autosave = (settings_dict['autosave'])
            self.use_random_org.set(settings_dict['use_random_org'])
            self.allow_odd.set(settings_dict['allow_odd'])
            self.always_on_top.set(settings_dict['always_on_top'])
        except KeyError:
            pass

        g = 0
        for group_name, group_settings in group_dict.items():
            self.create_group(g, len(group_settings['rollers']))

            group = roller_groups[g]
            group.name.set(group_name)
            group.index = group_settings['index']

            r = 0
            h = 0
            for roller_name, roller_settings in group_settings[
                    'rollers'].items():
                roller = group.rollers[r]
                roller.name.set(roller_name)
                for attr, value in roller_settings.items():
                    try:
                        getattr(roller, attr).set(value)
                    except AttributeError:
                        setattr(roller, attr, value)
                roller.reset(loading=True)
                h = len(roller.history) - 1
                r += 1

            group.navigate_history(desired_index=h)
            g += 1

        roller_groups.sort(key=lambda x: x.index)

        maintain_group_indices()
        for group in roller_groups:
            group.rollers.sort(key=lambda x: x.index)
            group.maintain_roller_indices()
            for roller in group.rollers:
                roller.apply_modifiers()

        maintain_tabstops()

        self.pin()
        self.autosave.set(autosave)
        self.set_saved_title(fpath)

    def save_config(self, fpath=''):
        if not fpath:
            fpath = asksaveasfilename(filetypes=[('JSON', '*.json'),
                                                 ('All', '*.*')],
                                      defaultextension='.json')
        if not fpath:
            if '*' in self.master.title():
                self.autosave.set(False)
            return
        self.fpath = fpath

        d1 = {}
        d1['settings'] = {
            'use_random_org': self.use_random_org.get(),
            'allow_odd': self.allow_odd.get(),
            'always_on_top': self.always_on_top.get(),
            'autosave': self.autosave.get()
        }
        for group in roller_groups:
            group.maintain_roller_indices()
            d2 = {}
            d2['index'] = group.index
            d2['rollers'] = {}
            for roller in group.rollers:
                name = roller.name.get()
                while name in d2['rollers']:
                    name += '!'
                d2['rollers'][name] = {
                    'index': roller.index,
                    'history': roller.history,
                    'dice_qty': roller.dice_qty.get(),
                    'die_faces': roller.die_faces.get(),
                    'modifier': roller.modifier.get(),
                    'finalmod': roller.finalmod.get()
                }
            name = group.name.get()
            if name in d1:
                name += '!'
            d1[name] = d2

        with open(fpath, 'w') as f:
            f.write(dumps(d1, indent=2, separators=(',', ': ')))

        self.set_saved_title(fpath)
예제 #28
0
    def __init__(self, master, par=False):
        """
        GUI for selecting default parameters - will write parameters to file \
        of users choosing.

        :type master: Tk
        :param master: Tkinter window
        :type par: EQcorrscanParameters
        :param par: Default parameters to start-up with.
        """
        from tkinter import Label, Button, Entry, DoubleVar, StringVar, IntVar
        from tkinter import BooleanVar, OptionMenu, Checkbutton
        import tkMessageBox
        from eqcorrscan.utils import parameters
        from obspy import UTCDateTime
        import warnings

        # Set the default par, only if they don't already exist.
        if not par:
            par = parameters.EQcorrscanParameters([''], 2, 10, 4, 100, 2,
                                                  '1900-01-01', '2300-01-01',
                                                  '', 'seishub', 4, False, '',
                                                  'jpg', False, 8, 'MAD', 6)
        # Callback functions for all variables (ugly)

        def update_template_names(*args):
            par.template_names = [
                name.strip() for name in template_names.get().split(',')
            ]
            template_names.set(', '.join(par.template_names))

        def update_lowcut(*args):
            par.lowcut = lowcut.get()
            lowcut.set(par.lowcut)

        def update_highcut(*args):
            par.highcut = highcut.get()
            if par.highcut >= 0.5 * par.samp_rate:
                msg = ('Highcut must be less than the Nyquist, setting to ' +
                       str((par.samp_rate / 2.0) - 1))
                tkMessageBox.showwarning(title="Nyquist error", message=msg)
                par.highcut = (par.samp_rate / 2.0) - 1
            highcut.set(par.highcut)

        def update_filt_order(*args):
            par.filt_order = filt_order.get()
            filt_order.set(par.filt_order)

        def update_samp_rate(*args):
            par.samp_rate = samp_rate.get()
            if par.highcut >= 0.5 * par.samp_rate:
                msg = ('Highcut must be less than the Nyquist, setting to ' +
                       str((par.samp_rate / 2.0) - 1))
                tkMessageBox.showwarning(title="Nyquist error", message=msg)
                par.highcut = (par.samp_rate / 2.0) - 1
                highcut.set(par.highcut)
            samp_rate.set(par.samp_rate)

        def update_debug(*args):
            par.debug = debug.get()
            debug.set(par.debug)

        def update_startdate(*args):
            par.startdate = UTCDateTime(startdate.get())
            startdate.set(str(par.startdate))

        def update_enddate(*args):
            par.enddate = UTCDateTime(enddate.get())
            enddate.set(str(par.enddate))

        def update_archive(*args):
            par.archive = archive.get()
            archive.set(par.archive)

        def update_arc_type(*args):
            par.arc_type = arc_type.get()
            arc_type.set(par.arc_type)

        def update_cores(*args):
            par.cores = cores.get()
            cores.set(par.cores)

        def update_plotvar(*args):
            par.plotvar = plotvar.get()
            plotvar.set(par.plotvar)

        def update_plot_format(*args):
            par.plot_format = plot_format.get()
            plot_format.set(par.plot_format)

        def update_tempdir(*args):
            par.tempdir = tempdir.get()
            tempdir.set(par.tempdir)

        def update_threshold(*args):
            par.threshold = threshold.get()
            threshold.set(par.threshold)

        def update_threshold_type(*args):
            par.threshold_type = threshold_type.get()
            threshold_type.set(par.threshold_type)

        def update_plotdir(*args):
            par.plotdir = plotdir.get()
            plotdir.set(par.plotdir)

        def update_trigger_interval(*args):
            par.trigger_interval = trigger_interval.get()
            trigger_interval.set(par.trigger_interval)

        # Set some grid parameters
        nrows = 25
        ncolumns = 3
        self.master = master
        master.title("EQcorrscan parameter setup")
        self.label = Label(master, text="Alpha GUI for default setup")
        self.label.grid(column=0, columnspan=ncolumns, row=0)

        # Set up parameter input
        self.t_names_label = Label(master, text="Template names", anchor='e')
        self.t_names_label.grid(column=0, row=1, sticky='e')
        template_names = StringVar()
        template_names.set(', '.join(par.template_names))
        self.t_names_box = Entry(master, bd=2, textvariable=template_names)
        self.t_names_box.grid(column=1, row=1)
        template_names.trace("w", update_template_names)
        self.t_names_lookup = Button(
            master,
            text="Lookup",
            command=lambda: self.get_template_names(par))
        self.t_names_lookup.grid(column=2, row=1)

        self.lowcut_label = Label(master, text="Lowcut (Hz)", anchor='e')
        self.lowcut_label.grid(column=0, row=2, sticky='e')
        lowcut = DoubleVar()
        lowcut.set(par.lowcut)
        self.lowcut_box = Entry(master, bd=2, textvariable=lowcut)
        self.lowcut_box.grid(column=1, row=2)
        lowcut.trace("w", update_lowcut)

        self.highcut_label = Label(master, text="Highcut (Hz)", anchor='e')
        self.highcut_label.grid(column=0, row=3, sticky='e')
        highcut = DoubleVar()
        highcut.set(par.highcut)
        self.highcut_box = Entry(master, bd=2, textvariable=highcut)
        self.highcut_box.grid(column=1, row=3)
        highcut.trace("w", update_highcut)

        self.filt_order_label = Label(master, text="Filter order")
        self.filt_order_label.grid(column=0, row=4, sticky='e')
        filt_order = DoubleVar()
        filt_order.set(par.filt_order)
        self.filt_order_box = Entry(master, bd=2, textvariable=filt_order)
        self.filt_order_box.grid(column=1, row=4)
        filt_order.trace("w", update_filt_order)

        self.samp_rate_label = Label(master, text="Sample rate (Hz)")
        self.samp_rate_label.grid(column=0, row=5, sticky='e')
        samp_rate = DoubleVar()
        samp_rate.set(par.samp_rate)
        self.samp_rate_box = Entry(master, bd=2, textvariable=samp_rate)
        self.samp_rate_box.grid(column=1, row=5)
        samp_rate.trace("w", update_samp_rate)

        self.debug_label = Label(master, text="Debug")
        self.debug_label.grid(column=0, row=6, sticky='e')
        debug = IntVar()
        debug.set(par.debug)
        self.debug_box = Entry(master, bd=2, textvariable=debug)
        self.debug_box.grid(column=1, row=6)
        debug.trace("w", update_debug)

        self.startdate_label = Label(master, text="Start date (yyyy-mm-dd)")
        self.startdate_label.grid(column=0, row=6, sticky='e')
        startdate = StringVar()
        startdate.set(par.startdate)
        self.startdate_box = Entry(master, bd=2, textvariable=startdate)
        self.startdate_box.grid(column=1, row=6)
        startdate.trace("w", update_startdate)

        self.enddate_label = Label(master, text="End date (yyyy-mm-dd)")
        self.enddate_label.grid(column=0, row=8, sticky='e')
        enddate = StringVar()
        enddate.set(par.enddate)
        self.enddate_box = Entry(master, bd=2, textvariable=enddate)
        self.enddate_box.grid(column=1, row=8)
        enddate.trace("w", update_enddate)

        self.archive_label = Label(master, text="Archive")
        self.archive_label.grid(column=0, row=9, sticky='e')
        archive = StringVar()
        archive.set(par.archive)
        self.archive_box = Entry(master, bd=2, textvariable=archive)
        self.archive_box.grid(column=1, row=9)
        archive.trace("w", update_archive)
        self.archive_lookup = Button(master,
                                     text="Lookup",
                                     command=lambda: self.get_archive(par))
        self.archive_lookup.grid(column=2, row=9)

        self.arc_type_label = Label(master, text="Archive type")
        self.arc_type_label.grid(column=0, row=10, sticky='e')
        arc_type = StringVar()
        arc_type.set(par.arc_type)
        self.arc_type_box = OptionMenu(master, arc_type, "seishub", "fdsn",
                                       "day_vols")
        self.arc_type_box.grid(column=1, row=10, sticky='w,e')
        arc_type.trace("w", update_arc_type)

        self.cores_label = Label(master, text="Number of cores")
        self.cores_label.grid(column=0, row=11, sticky='e')
        cores = IntVar()
        cores.set(par.cores)
        self.cores_box = Entry(master, bd=2, textvariable=cores)
        self.cores_box.grid(column=1, row=11)
        cores.trace("w", update_cores)

        self.plotvar_label = Label(master, text="Plotting on/off")
        self.plotvar_label.grid(column=0, row=12, sticky='e')
        plotvar = BooleanVar()
        plotvar.set(par.plotvar)
        self.plotvar_box = Checkbutton(master,
                                       text='Plot on',
                                       var=plotvar,
                                       onvalue=True,
                                       offvalue=False)
        self.plotvar_box.grid(column=1, row=12)
        plotvar.trace("w", update_plotvar)

        self.plotdir_label = Label(master, text="Plot directory")
        self.plotdir_label.grid(column=0, row=13, sticky='e')
        plotdir = StringVar()
        plotdir.set(par.plotdir)
        self.plotdir_box = Entry(master, bd=2, textvariable=plotdir)
        self.plotdir_box.grid(column=1, row=13)
        plotdir.trace("w", update_plotdir)
        self.plotdir_lookup = Button(master,
                                     text="Lookup",
                                     command=lambda: self.get_plotdir(par))
        self.plotdir_lookup.grid(column=2, row=13)

        self.plot_format_label = Label(master, text="Plot format")
        self.plot_format_label.grid(column=0, row=14, sticky='e')
        plot_format = StringVar()
        plot_format.set(par.plot_format)
        self.plot_format_box = OptionMenu(master, plot_format, "jpg", "eps",
                                          "pdf", "png")
        self.plot_format_box.grid(column=1, row=14, sticky='w,e')
        plot_format.trace("w", update_plot_format)

        self.tempdir_label = Label(master, text="Temporary directory")
        self.tempdir_label.grid(column=0, row=15, sticky='e')
        tempdir = StringVar()
        tempdir.set(par.tempdir)
        self.tempdir_box = Entry(master, bd=2, textvariable=tempdir)
        self.tempdir_box.grid(column=1, row=15)
        tempdir.trace("w", update_tempdir)
        self.tempdir_lookup = Button(master,
                                     text="Lookup",
                                     command=lambda: self.get_tempdir(par))
        self.tempdir_lookup.grid(column=2, row=15)

        self.threshold_label = Label(master, text="Threshold")
        self.threshold_label.grid(column=0, row=16, sticky='e')
        threshold = DoubleVar()
        threshold.set(par.threshold)
        self.threshold_box = Entry(master, bd=2, textvariable=threshold)
        self.threshold_box.grid(column=1, row=16)
        threshold.trace("w", update_threshold)

        self.threshold_type_label = Label(master, text="Threshold type")
        self.threshold_type_label.grid(column=0, row=17, sticky='e')
        threshold_type = StringVar()
        threshold_type.set(par.threshold_type)
        self.threshold_type_box = OptionMenu(master, threshold_type, "MAD",
                                             "absolute", "av_chan_corr")
        self.threshold_type_box.grid(column=1, row=17, sticky='w,e')
        threshold_type.trace("w", update_threshold_type)

        self.trigger_interval_label = Label(master,
                                            text="Minimum trigger " +
                                            "interval (s)")
        self.trigger_interval_label.grid(column=0, row=18, sticky='e')
        trigger_interval = DoubleVar()
        trigger_interval.set(par.trigger_interval)
        self.trigger_interval_box = Entry(master,
                                          bd=2,
                                          textvariable=trigger_interval)
        self.trigger_interval_box.grid(column=1, row=18)
        trigger_interval.trace("w", update_trigger_interval)

        # End of user editable section, now we have read/write buttons
        self.read_button = Button(master,
                                  text="Read parameters",
                                  command=lambda: self.read_par(master))
        self.read_button.grid(column=0, row=nrows - 2, sticky='w,e')

        self.write_button = Button(master,
                                   text="Write parameters",
                                   command=lambda: self.write_par(par))
        self.write_button.grid(column=1, row=nrows - 2, sticky='w,e')
예제 #29
0
class BIDSFile(FileInfo):
    """
    BIDSFiles are the main files which will contain the data that is to be
    converted to BIDS format.
    For KIT data this is the .con file.
    For Elekta data this is the .fif file.

    """
    def __init__(self, id_=None, file=None, settings=dict(), parent=None):
        super(BIDSFile, self).__init__(id_, file, parent)

        self._settings = settings

        self._create_vars()

        if 'emptyroom' in self.file.lower():
            self.is_empty_room.set(True)

    def _create_vars(self):
        # TODO: Fix
        # This is called multiple times...
        FileInfo._create_vars(self)
        self.run = StringVar(value='1')
        self.run.trace("w", self.validate)
        self.task = OptionsVar(options=['None'])
        self.task.trace("w", self._update_tasks)
        self.is_junk = BooleanVar()
        self.is_empty_room = BooleanVar()
        self.is_empty_room.trace("w", self.propagate_emptyroom_data)
        self.has_empty_room = BooleanVar()

        self.hpi = list()

        self.loaded = False

        self.extra_data = dict()

        # event info: a list of lists. The sub-lists contains the event number
        # and the event description
        self.event_info = list()
        # channel info: key - channel name (?), value - something
        self.channel_info = dict()

        self.raw = None
        self.container = None

        # Set all BIDS files to be saved by default
        self.requires_save = True

    def load_data(self):
        pass

    def validate(self, validate_container=True, *args):
        """
        Check whether the file is valid (ie. contains all the required info for
        BIDS exporting).

        """
        self.valid = self.check_valid()
        if self.container is not None and validate_container:
            self.container.validate()

    def check_valid(self):
        """
        Go over all the required settings and determine whether the file is
        ready to be exported to the bids format.

        """
        is_valid = super(BIDSFile, self).check_valid()
        # if empty room or junk we consider them good
        if self.is_empty_room.get() or self.is_junk.get():
            return is_valid
        is_valid &= self.run.get() != ''
        is_valid &= (self.hpi != list())
        return is_valid

    def get_event_data(self):
        return ['', '']

    def propagate_emptyroom_data(self, *args):
        """ Callback to propagate the empty room state

        This is used to tell the container object that the empty room status
        of this file has changed and change the 'has empty room' state of any
        other files in the same folder (for KIT).

        """
        if self.container is not None:
            emptyroom_set = self.container.autodetect_emptyroom()
            if not emptyroom_set:
                self.is_empty_room.set(False)
                self.associated_tab.is_emptyroom_info.value = self.is_empty_room  # noqa

    def _update_tasks(self, *args):
        """Update the EntryChoice that contains the task options"""
        if self.associated_tab is not None:
            self.associated_tab.task_info.value = self.task

    def __getstate__(self):
        data = super(BIDSFile, self).__getstate__()

        data['run'] = self.run.get()                                      # run
        data['tsk'] = self.task.get()                                    # task
        # marker coils:
        data['hpi'] = [hpi.file for hpi in self.hpi]
        data['ier'] = self.is_empty_room.get()            # is empty room data?
        data['her'] = self.has_empty_room.get()          # has empty room data?

        return data

    def __setstate__(self, state):
        super(BIDSFile, self).__setstate__(state)
        self.run.set(state.get('run', 0))
        task = state.get('tsk', '')
        self.task.options = [task]
        self.task.set(task)
        # support old and new format hpi storage
        self.hpi = state.get('hpi', list())
        self.is_empty_room.set(state.get('ier', False))
        self.has_empty_room.set(state.get('her', False))