Esempio n. 1
0
    def create_gui(app):

        f1 = PanedWindow(
            app,
            orient='horizontal',
            width=800,
            height=600,
            sashrelief='ridge',
            sashwidth=4,
        )
        f1.grid(
            row=0,
            column=0,
            sticky="nesw",
        )
        f2 = PanedWindow(f1, orient='vertical')
        canvW = Canvas(f2, bg='#113333')
        f2.add(canvW)
        logW = scrolledtext.ScrolledText(f2,
                                         bg='#223399',
                                         fg='#cccc99',
                                         font=font.nametofont('TkDefaultFont'))
        f2.add(logW)
        bodyW = makeBodyW(f1)
        f1.add(f2)
        f1.add(bodyW)
        return f1, f2, bodyW, canvW, logW
Esempio n. 2
0
 def resize_paned_window(self, tk_paned_window: tkinter.PanedWindow):
     column, row = tk_paned_window.grid_info()['column'], tk_paned_window.grid_info()['row']
     tk_paned_window.grid_forget()
     p_pane_list = []
     for pane_index in range(len(tk_paned_window.panes())):
         p_pane_list.append(self.widgets.find_pyte_widget_from_tk(str(tk_paned_window.panes()[0])))
         tk_paned_window.forget(p_pane_list[-1].tk_name)
         tk_widget_list = []
         tk_widget_row = []
         # tk_widget_column = []
         for tk_widget in p_pane_list[-1].tk_name.winfo_children():
             tk_widget_list.append(tk_widget)
             # print(tk_widget)
             tk_widget_row.append(tk_widget.grid_info()['row'])
         # print(p_pane_list[-1])
     for p_pane in p_pane_list:
         tk_paned_window.add(p_pane.tk_name)
     tk_paned_window.grid(row=row, column=column)
Esempio n. 3
0
    def __init__(self, master, appWidth, appHeight):
        self.master = master
        geo = "%dx%d" % (appWidth, appHeight)
        master.geometry(geo)
        master.title("Smacket")
        self.videoPath = ""

        bcg = "#0A8049"
        topLeft = PanedWindow(master, orient=tk.VERTICAL)
        topLeft.config(bg = bcg)
        topLeft.grid(row = 0, column = 0)
        topLeftTitle = tk.Message(master, text = "Timestamps")
        topLeftTitle.config(anchor = "center", aspect = 500, font = ("consolas", 20, "bold"), bg = bcg, relief = "sunken")
        timeStamps = TextScrollCombo(master)
        timeStamps.config(width=appWidth // 10, height= appHeight // 2)
        timeStamps.txt.config(font=("consolas", 12), undo=True, wrap='word', borderwidth=3, relief="sunken")
        topLeft.add(topLeftTitle)
        topLeft.add(timeStamps)

        bottomLeft = PanedWindow(master, orient=tk.VERTICAL)
        bottomLeft.config(bg = bcg)
        bottomLeft.grid(row = 1, column = 0)
        bottomLeftTitle = tk.Message(master, text = "Matches")
        bottomLeftTitle.config(anchor = "center", aspect = 500, font = ("consolas", 20, "bold"), bg = bcg, relief = "sunken")
        matches = TextScrollCombo(master)
        matches.config(width= appWidth// 10 , height=appHeight // 2)
        matches.txt.config(font=("consolas", 12), undo=True, wrap='word', borderwidth=3, relief="sunken")
        bottomLeft.add(bottomLeftTitle)
        bottomLeft.add(matches)

        videoPlayer = Label(master, 
                            height = 20,
                            width = appWidth - (appWidth // 10),
                            bg = 'red',
                            text = "VideoPlayer",)
        videoPlayer.grid(row=0, column=1)

        videoSkimmer = Label(master, 
                            height = 20,
                            width = appWidth - (appWidth // 10),
                            bg = 'yellow',
                            text = "VideoSkimmer",)
        videoSkimmer.grid(row=1, column=1)
Esempio n. 4
0
 def show_paned_window_parent(self, tk_paned_window: tkinter.PanedWindow):
     p_paned_window = self.widgets.find_pyte_parent(tk_paned_window)
     tk_paned_window.grid(row=p_paned_window.row, column=p_paned_window.column)
Esempio n. 5
0
class PyLatency:
    """Ping tool visualization with tkinter"""
    def __init__(self, root):
        """Setup window geometry & widgets + layout, init counters"""

        self.master = root
        self.master.title("pyLatency")
        self.appdata_dir = getenv("APPDATA") + "/pyLatency"
        self.options_path = self.appdata_dir + "/options.json"
        self.log_dir = self.appdata_dir + "/logs"
        self.logfile = None

        self.options_logging = BooleanVar()
        self.options_geometry = ""

        self.options = self.init_options()
        if self.options:
            self.options_geometry = self.options["geometry"]
            self.options_logging.set(self.options["logging"])

        if self.options_geometry:
            self.master.geometry(self.options_geometry)
        else:
            self.master.geometry("400x200")

        self.master.minsize(width=400, height=200)
        self.master.update()

        self.running = False
        self.hostname = None
        self.RECT_SCALE_FACTOR = 2
        self.TIMEOUT = 5000
        self.minimum = self.TIMEOUT
        self.maximum = 0
        self.average = 0
        self.SAMPLE_SIZE = 1000
        self.sample = deque(maxlen=self.SAMPLE_SIZE)
        self.pcount = 0
        self.max_bar = None
        self.min_bar = None

        # Widgets:
        self.frame = Frame(self.master)

        self.lbl_entry = Label(self.frame, text="Host:")
        self.lbl_status_1 = Label(self.frame, text="Ready")
        self.lbl_status_2 = Label(self.frame, fg="red")
        self.entry = Entry(self.frame)

        self.btn_start = Button(self.frame, text="Start", command=self.start)

        self.btn_stop = Button(self.frame, text="Stop", command=self.stop)

        self.chk_log = Checkbutton(self.frame,
                                   text="Enable log",
                                   variable=self.options_logging)

        self.delay_scale = Scale(
            self.frame,
            label="Interval (ms)",
            orient="horizontal",
            from_=100,
            to=self.TIMEOUT,
            resolution=100,
        )
        self.delay_scale.set(1000)

        self.paneview = PanedWindow(self.master, sashwidth=5, bg="#cccccc")
        self.left_pane = PanedWindow(self.paneview)
        self.right_pane = PanedWindow(self.paneview)
        self.paneview.add(self.left_pane)
        self.paneview.add(self.right_pane)

        self.canvas_scroll_y = Scrollbar(self.left_pane)
        self.canvas = Canvas(self.left_pane,
                             bg="#FFFFFF",
                             yscrollcommand=self.canvas_scroll_y.set)
        self.canvas_scroll_y.config(command=self.canvas.yview)
        self.left_pane.add(self.canvas_scroll_y)

        self.ping_list_scroll = Scrollbar(self.master)
        self.ping_list = Listbox(self.right_pane,
                                 highlightthickness=0,
                                 font=14,
                                 selectmode="disabled",
                                 yscrollcommand=self.ping_list_scroll.set)
        self.ping_list_scroll.config(command=self.ping_list.yview)
        self.right_pane.add(self.ping_list_scroll)

        self.left_pane.add(self.canvas)
        self.right_pane.add(self.ping_list)

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

        self.frame.columnconfigure(1, weight=1)

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

        self.lbl_entry.grid(row=0, column=0)
        self.lbl_status_1.grid(row=1, column=0, columnspan=4)
        self.lbl_status_2.grid(row=2, column=0, columnspan=4)
        self.entry.grid(row=0, column=1, sticky="ew")
        self.btn_start.grid(row=0, column=2)
        self.btn_stop.grid(row=0, column=3)
        self.chk_log.grid(row=1, column=2, columnspan=2)
        self.delay_scale.grid(row=0, column=4, rowspan=2)

        # self.canvas_scroll_y.grid(row=1, column=2, sticky="ns")
        self.paneview.grid(row=1, column=0, sticky="nsew")
        # self.ping_list_scroll.grid(row=1, column=1, sticky="ns")

        self.paneview.paneconfigure(
            self.left_pane,
            width=(self.master.winfo_width() -
                   self.delay_scale.winfo_reqwidth()),
        )

        #Bindings:
        self.canvas.bind("<MouseWheel>", self.scroll_canvas)

        self.master.bind("<Return>", self.start)
        self.master.bind("<Escape>", self.stop)
        self.master.bind("<Control-w>", lambda event: self.master.destroy())
        self.master.bind(
            "<Up>",
            lambda event: self.delay_scale.set(self.delay_scale.get() + 100))
        self.master.bind(
            "<Down>",
            lambda event: self.delay_scale.set(self.delay_scale.get() - 100))

        self.master.protocol("WM_DELETE_WINDOW", self.master_close)

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

        return f"pyLatency GUI @ {hex(id(self))}"

    def start(self, event=None):
        """
            Reset the GUI, create & start a thread so we don't block
            the mainloop during each poll. 
        """

        if not self.running:
            self.hostname = self.entry.get()
            if self.hostname:
                self.ping_list.delete(0, "end")
                self.canvas.delete("all")
                self.lbl_status_1.config(text="Running", fg="green")
                self.lbl_status_2.config(text="")

                self.sample.clear()

                (self.minimum, self.maximum, self.average,
                 self.pcount) = self.TIMEOUT, 0, 0, 0

                self.running = True
                self.thread = Thread(target=self.run, daemon=True)
                self.thread.start()
            else:
                self.lbl_status_2.config(text="Missing Hostname")

    def logged(fn):
        """
            decorates self.run(), create a log directory if one doesn't
            exist, create a filename with a date & timestamp, call self.run()
            with logging enabled or disabled
        """
        @wraps(fn)
        def inner(self):
            if self.options_logging.get():
                if not exists(self.log_dir):
                    mkdir(self.log_dir)

                timestamp = datetime.now()
                fname = timestamp.strftime("%a %b %d @ %H-%M-%S")

                with open(self.log_dir + f"/{fname}.txt",
                          "w+") as self.logfile:
                    self.logfile.write(f"pyLatency {fname}\n")
                    self.logfile.write(f"Host: {self.hostname}\n")
                    self.logfile.write("-" * 40 + "\n")
                    start = default_timer()
                    fn(self)
                    end = default_timer()
                    elapsed = end - start
                    self.logfile.write("-" * 40 + "\n")
                    self.logfile.write(
                        f"Logged {self.pcount} pings over {int(elapsed)} seconds"
                    )
            else:
                fn(self)

        return inner

    @logged
    def run(self):
        """
            Continuously shell out to ping, get an integer result, 
            update the GUI, and wait. 
        """

        while self.running:
            latency = self.ping(self.hostname)
            self.pcount += 1

            if latency is None:
                self.stop()
                self.lbl_status_2.config(text="Unable to ping host")
                return
            if latency > self.maximum:
                self.maximum = latency
            if latency < self.minimum:
                self.minimum = latency

            self.sample.append(latency)
            self.average = sum(self.sample) / len(self.sample)

            if self.logfile:
                self.logfile.write(str(latency) + "\n")

            self.update_gui(latency)
            sleep(self.delay_scale.get() / 1000)

    def update_gui(self, latency):
        """
            Update the listbox, shift all existing rectangles, draw the latest
            result from self.ping(), cleanup unused rectangles, update the mainloop
        """

        if self.ping_list.size() >= self.SAMPLE_SIZE:
            self.ping_list.delete(self.SAMPLE_SIZE - 1, "end")

        self.ping_list.insert(0, str(latency) + "ms")

        self.canvas.move("rect", 10, 0)
        self.canvas.create_rectangle(0,
                                     0,
                                     10,
                                     int(latency * self.RECT_SCALE_FACTOR),
                                     fill="#333333",
                                     tags="rect",
                                     width=0)

        self.canvas.delete(self.max_bar)
        self.max_bar = self.canvas.create_line(
            0,
            self.maximum * self.RECT_SCALE_FACTOR,
            self.canvas.winfo_width(),
            self.maximum * self.RECT_SCALE_FACTOR,
            fill="red",
        )
        self.canvas.delete(self.min_bar)
        self.min_bar = self.canvas.create_line(
            0,
            self.minimum * self.RECT_SCALE_FACTOR,
            self.canvas.winfo_width(),
            self.minimum * self.RECT_SCALE_FACTOR,
            fill="green",
        )

        # canvas scrollable region is not updated automatically
        self.canvas.configure(scrollregion=self.canvas.bbox("all"))

        self.lbl_status_2.config(fg="#000000",
                                 text=f"Min: {self.minimum} "
                                 f"Max: {self.maximum} "
                                 f"Avg: {round(self.average,2):.2f}")

        self.cleanup_rects()
        self.master.update()

    def scroll_canvas(self, event):
        """
            Bound to <MouseWheel> tkinter event on self.canvas.
            Respond to Linux or Windows mousewheel event, and scroll
            the canvas accordingly
        """

        count = None
        if event.num == 5 or event.delta == -120:
            count = 1
        if event.num == 4 or event.delta == 120:
            count = -1
        self.canvas.yview_scroll(count, "units")

    def cleanup_rects(self):
        """Delete rectangles that are outside the bbox of the canvas"""

        for rect in self.canvas.find_withtag("rect"):
            if self.canvas.coords(rect)[0] > self.canvas.winfo_width():
                self.canvas.delete(rect)

    def stop(self, event=None):
        """Satisfy the condition in which self.thread exits"""

        if self.running:
            self.running = False
            self.lbl_status_1.config(text="Stopped", fg="red")

    def master_close(self, event=None):
        """Writes window geometry/options to the disk."""

        options = dumps({
            "geometry": self.master.geometry(),
            "logging": self.options_logging.get()
        })

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

        with open(self.options_path, "w+") as options_file:
            options_file.write(options)

        self.master.destroy()

    def init_options(self):
        """Called on startup, loads, parses, and returns options from json."""

        if exists(self.options_path):
            with open(self.options_path, "r") as options_file:
                options_json = options_file.read()

            return loads(options_json)
        else:
            return None

    @staticmethod
    def ping(url):
        """
            Shell out to ping and return an integer result.
            Returns None if ping fails for any reason: timeout, bad hostname, etc.
        """

        flag = "-n" if platform == "win32" else "-c"
        result = run(["ping", flag, "1", "-w", "5000", url],
                     capture_output=True,
                     creationflags=DETACHED_PROCESS)
        output = result.stdout.decode("utf-8")
        try:
            duration = findall("\\d+ms", output)[0]
            return int(duration[:-2])
        except IndexError:
            return None
Esempio n. 6
0
class PreferencesFrame(FrameTemplate):
    """Used to set decision maker's preferences for use in prioritization."""

    # Label used for button to select frame in the main program.
    buttonLabel = 'Prioritization'
    # Image used on button to select frame, when frame is active.
    activeIcon = 'icons/Prioritization_ON.gif'
    # Image used on button to select frame, when frame is inactive.
    inactiveIcon = 'icons/Prioritization_OFF.gif'
    # Help text to be displayed when screen is active.
    helpText = ("Select a decision maker from the column at left by clicking "
                "its 'Edit' button.  Enter preferred conditions using the "
                "inputs to the right.  Preferred conditions for the selected "
                "decision maker are shown at the far right, from most "
                "important at the top, to least important at the bottom.")

    # ########################     INITIALIZATION  ################################
    def __init__(self, master, conflict, *args):
        """Initialize the Frame. Does not build widgets."""
        FrameTemplate.__init__(self, master, conflict, self.buttonLabel,
                               self.activeIcon, self.inactiveIcon,
                               self.helpText)

        self.lastBuildDMs = None
        self.lastBuildOptions = None
        self.lastBuildInfeasibles = None
        self.lastBuildRanking = None

# ############################     METHODS  ###################################

    def hasRequiredData(self):
        """Check that minimum data required to render the frame exists."""
        if len(self.conflict.decisionMakers) < 1:
            return False
        if len(self.conflict.options) < 1:
            return False
        if len(self.conflict.feasibles) < 1:
            self.conflict.recalculateFeasibleStates()
            if len(self.conflict.feasibles) < 1:
                return False
        else:
            return True

    def dataChanged(self):
        """Check if data has changed since the last build of the Frame."""
        if self.lastBuildDMs != self.conflict.decisionMakers.export_rep():
            return True
        if self.lastBuildOptions != self.conflict.options.export_rep():
            return True
        if self.lastBuildInfeasibles != self.conflict.infeasibles.export_rep():
            return True
        if self.lastBuildRanking != self.conflict.useManualPreferenceRanking:
            return True
        else:
            return False

    def buildFrame(self):
        """Contruct frame widgets and initialize data."""
        if self.built:
            return

        # Ensure all required parts of the conflict model are properly set-up.
        self.conflict.reorderOptionsByDM()
        self.conflict.options.set_indexes()
        self.conflict.infeasibles.validate()
        self.conflict.recalculateFeasibleStates()

        for dm in self.conflict.decisionMakers:
            dm.calculatePerceived()
            dm.calculatePreferences()

        self.lastBuildDMs = self.conflict.decisionMakers.export_rep()
        self.lastBuildOptions = self.conflict.options.export_rep()
        self.lastBuildInfeasibles = self.conflict.infeasibles.export_rep()
        self.lastBuildRanking = self.conflict.useManualPreferenceRanking

        # Define variables that will display in the infoFrame
        numD = len(self.conflict.decisionMakers)
        self.infoText = StringVar(
            value='Valid Preferences set for {0}/{0} DMs.'.format(numD))

        # Define frame-specific variables
        self.dm = None

        # infoFrame: frame and label definitions (with master 'self.infoFrame')
        self.infoLabel = ttk.Label(self.infoFrame, textvariable=self.infoText)

        # helpFrame: frame and label definitions (with master 'self.helpFrame')
        self.helpLabel = ttk.Label(self.helpFrame,
                                   textvariable=self.helpVar,
                                   wraplength=150)

        # Define frame-specific input widgets (with 'self' as master)
        self.paneMaster = PanedWindow(self,
                                      orient=VERTICAL,
                                      sashwidth=5,
                                      sashrelief="raised",
                                      sashpad=2,
                                      relief="sunken")

        self.paneTop = ttk.Frame(self.paneMaster)
        self.rankings = PreferenceRankingMaster(self.paneTop, self.conflict)
        self.editor = RadiobuttonEntry(self.paneTop, self.conflict)
        self.paneTopRightMaster = PanedWindow(self.paneTop,
                                              orient=HORIZONTAL,
                                              sashwidth=5,
                                              sashrelief="raised",
                                              sashpad=2,
                                              relief="sunken")
        self.staging = PreferenceStaging(self.paneTopRightMaster,
                                         self.conflict)
        self.preferenceDisp = PreferenceListDisplay(self.paneTopRightMaster,
                                                    self.conflict)

        self.paneBottom = ttk.Frame(self.paneMaster)
        self.optionTable = OptionFormTable(self.paneBottom, self.conflict)

        self.usePrioritizationButton = ttk.Button(
            self,
            text=("Use preference prioritization. Any manually set "
                  "preference rankings will be lost."),
            command=self.usePrioritization)

        # ########  preliminary gridding and option configuration

        # configuring the input frame
        self.grid(column=0, row=0, rowspan=5, sticky=NSEW)
        self.columnconfigure(0, weight=1)
        self.rowconfigure(1, weight=1)
        self.grid_remove()

        # configuring infoFrame & infoFrame widgets
        self.infoFrame.grid(column=2, row=0, sticky=NSEW, padx=3, pady=3)
        self.infoFrame.grid_remove()
        self.infoLabel.grid(column=0, row=1, sticky=NSEW)

        # configuring helpFrame & helpFrame widgets
        self.helpFrame.grid(column=2, row=1, sticky=NSEW, padx=3, pady=3)
        self.helpFrame.grid_remove()
        self.helpLabel.grid(column=0, row=0, sticky=NSEW)

        # configuring frame-specific options
        self.paneMaster.grid(column=0, row=1, sticky=NSEW)
        self.paneMaster.add(self.paneTop, minsize=200)
        self.rankings.grid(column=0, row=1, sticky=NSEW)
        ttk.Separator(self.paneTop, orient=VERTICAL).grid(column=1,
                                                          row=1,
                                                          sticky=NSEW,
                                                          padx=3)
        self.editor.grid(column=2, row=1, sticky=NSEW)
        ttk.Separator(self.paneTop, orient=VERTICAL).grid(column=3,
                                                          row=1,
                                                          sticky=NSEW,
                                                          padx=3)
        self.paneTopRightMaster.grid(column=4, row=1, sticky=NSEW)
        self.paneTop.columnconfigure(0, weight=0)
        self.paneTop.columnconfigure(2, weight=0)
        self.paneTop.columnconfigure(4, weight=1)
        self.paneTop.rowconfigure(1, weight=1)

        self.usePrioritizationButton.grid(column=0,
                                          row=0,
                                          columnspan=5,
                                          sticky=NSEW)

        self.paneTopRightMaster.add(self.staging)
        self.paneTopRightMaster.add(self.preferenceDisp)

        self.paneMaster.add(self.paneBottom)
        self.optionTable.grid(column=0, row=0, sticky=NSEW)
        self.paneBottom.columnconfigure(0, weight=1)
        self.paneBottom.rowconfigure(0, weight=1)

        # bindings
        self.rankings.bind('<<DMchg>>', self.dmChgHandler)
        self.editor.bind('<<AddPref>>', self.addPref)
        self.editor.bind('<<StagePref>>', self.stagePref)
        self.staging.bind('<<SelCond>>', self.selCondChg)
        self.staging.bind('<<PullFromStage>>', self.pullFromStage)
        self.preferenceDisp.bind('<<SelPref>>', self.selPrefChg)
        self.preferenceDisp.bind('<<ValueChange>>', self.refresh)

        self.dmChgHandler()

        self.built = True

    def enter(self, *args):
        """Re-grid the screen into the master. Perform required updates."""
        if self.dataChanged():
            self.clearFrame()

        FrameTemplate.enter(self)

    def refresh(self, *args):
        """Refresh data in all active display widgets."""
        for dm in self.conflict.decisionMakers:
            dm.calculatePreferences()
        self.editor.reloadOpts()
        self.rankings.refresh()
        self.preferenceDisp.refresh()
        self.optionTable.buildTable(self.dm)

        self.checkIfUsingRankings()

    def checkIfUsingRankings(self, event=None):
        """Disable screen if Manual Ranking has been assigned."""
        if self.conflict.useManualPreferenceRanking:
            self.usePrioritizationButton.grid()
            self.rankings.disable()
            self.editor.disable()
            self.staging.disable()
            self.preferenceDisp.disable()
        else:
            self.usePrioritizationButton.grid_remove()

    def usePrioritization(self):
        """Reactivate the screen if user decides to use prioritization."""
        self.conflict.useManualPreferenceRanking = False
        self.conflict.preferenceErrors = None
        self.refresh()

    def dmChgHandler(self, event=None):
        """Bound to <<DMchg>>."""
        self.dm = self.rankings.dm
        self.preferenceDisp.changeDM(self.dm)
        self.optionTable.buildTable(self.dm)
        self.staging.clear()
        self.editor.setStates('clear')
        if self.dm is None:
            self.preferenceDisp.disable()
            self.editor.disable()
            self.staging.disable()
        else:
            self.preferenceDisp.enable()
            self.editor.enable()

    def addPref(self, event=None):
        """Add a preference for the active decision maker."""
        pref = self.editor.getStates()
        self.dm.preferences.append(pref)
        self.refresh()

    def stagePref(self, event=None):
        """Send a condition to the staging area."""
        if self.editor.hasValidIf:
            for cond in self.editor.ifCond:
                self.staging.addCondition(cond)
        else:
            condData = self.editor.getStates()
            newCond = self.conflict.newCondition(condData)
            self.staging.addCondition(newCond)

        self.editor.setStates('clear')

    def pullFromStage(self, event=None):
        """Move a compound condition from Staging to Preferences."""
        newPref = self.staging.conditionList
        self.staging.clear()
        self.dm.preferences.append(newPref)
        self.refresh()

    def selCondChg(self, event=None):
        """Triggered when a condition is selected in staging."""
        condition = self.staging.conditionList[event.x]
        self.editor.setStates(condition.ynd())

    def selPrefChg(self, event=None):
        """Triggered when a preference is select from preferences."""
        condition = self.dm.preferences[event.x]
        self.staging.setList(condition)
class StabilityFrame(FrameTemplate):
    """Frame used to for Stability Analysis."""

    # Label used for button to select frame in the main program.
    buttonLabel = 'Post Analysis'
    # Image used on button to select frame, when frame is active.
    activeIcon = 'icons/Post_Analysis_ON.gif'
    # Image used on button to select frame, when frame is inactive.
    inactiveIcon = 'icons/Post_Analysis_OFF.gif'
    # Help text to be displayed when screen is active.
    helpText = ("Selecting coalitions, status quo and goals at the top left"
                "will generate a reachability tree below the status quo, and "
                "detail the patterns that preferences must match for the goal "
                "state to be reached.")

    # ########################     INITIALIZATION  ################################
    def __init__(self, master, conflict, *args):
        """Initialize the Frame. Does not build widgets."""
        FrameTemplate.__init__(self, master, conflict, self.buttonLabel,
                               self.activeIcon, self.inactiveIcon,
                               self.helpText)

        self.lastBuildConflict = None

# ############################     METHODS  ###################################

    def hasRequiredData(self):
        """Check that minimum data required to render the frame exists."""
        if len(self.conflict.decisionMakers) < 1:
            return False
        if len(self.conflict.options) < 1:
            return False
        if len(self.conflict.feasibles) < 1:
            return False
        if self.conflict.preferenceErrors:
            return False
        else:
            return True

    def dataChanged(self):
        """Check if data has changed since the last build of the Frame."""
        if self.lastBuildConflict != self.conflict.export_rep():
            return True
        else:
            return False

    def buildFrame(self):
        """Contruct frame widgets and initialize data."""
        if self.built:
            return

        # Ensure all required parts of the conflict model are properly set-up.
        self.conflict.reorderOptionsByDM()
        self.conflict.options.set_indexes()
        self.conflict.infeasibles.validate()
        self.conflict.recalculateFeasibleStates()

        for dm in self.conflict.decisionMakers:
            dm.calculatePerceived()
            dm.calculatePreferences()

        self.lastBuildConflict = self.conflict.export_rep()

        # Define frame-specific variables
        self.sol = GoalSeeker(self.conflict)

        # infoFrame: frame and label definitions (with master 'self.infoFrame')
        self.infoLabel = ttk.Label(self.infoFrame, text="")

        # helpFrame: frame and label definitions (with master 'self.helpFrame')
        self.helpLabel = ttk.Label(self.helpFrame,
                                   textvariable=self.helpVar,
                                   wraplength=150)

        # Define frame-specific input widgets (with 'self' as master)
        self.paneMaster = PanedWindow(self,
                                      orient=HORIZONTAL,
                                      sashwidth=10,
                                      sashrelief="raised",
                                      sashpad=3,
                                      relief="sunken")

        self.paneLeft = PanedWindow(self.paneMaster,
                                    orient=VERTICAL,
                                    sashwidth=10,
                                    sashrelief="raised",
                                    sashpad=3,
                                    relief="sunken")

        self.paneLeftTop = ttk.Frame(self.paneLeft)
        self.coalitionSelector = CoalitionSelector(self.paneLeftTop,
                                                   self.conflict, self)
        self.statusQuoAndGoals = StatusQuoAndGoals(self.paneLeftTop,
                                                   self.conflict)
        self.reachableTree = ReachableTreeViewer(self.paneLeftTop,
                                                 self.conflict, self)

        self.paneLeftBottom = ttk.Frame(self.paneLeft)
        self.optionFormTable = OptionFormTable(self.paneLeftBottom,
                                               self.conflict)

        self.paneRight = ttk.Frame(self.paneMaster)
        self.patternNarrator = PatternNarrator(self.paneRight, self.conflict,
                                               self)

        # ########  preliminary gridding and option configuration

        # configuring the input frame
        self.grid(column=0, row=0, rowspan=5, sticky=NSEW)
        self.grid_remove()
        self.columnconfigure(0, weight=1)
        self.rowconfigure(0, weight=1)

        # configuring infoFrame & infoFrame widgets
        self.infoFrame.grid(column=2, row=0, sticky=NSEW, padx=3, pady=3)
        self.infoFrame.grid_remove()
        self.infoLabel.grid(column=0, row=1, sticky=NSEW)

        # configuring helpFrame & helpFrame widgets
        self.helpFrame.grid(column=2, row=1, sticky=NSEW, padx=3, pady=3)
        self.helpFrame.grid_remove()
        self.helpLabel.grid(column=0, row=0, sticky=NSEW)

        # configuring frame-specific options
        self.paneMaster.grid(row=0, column=0, sticky=NSEW)

        self.paneMaster.add(self.paneLeft)

        self.paneLeft.add(self.paneLeftTop)
        self.paneLeftTop.columnconfigure(1, weight=1)
        self.paneLeftTop.rowconfigure(2, weight=1)
        self.coalitionSelector.grid(row=0, column=0, sticky=NSEW)
        ttk.Separator(self, orient=HORIZONTAL).grid(row=1,
                                                    column=0,
                                                    sticky=NSEW,
                                                    pady=3)
        self.statusQuoAndGoals.grid(row=2, column=0, sticky=NSEW)
        self.reachableTree.grid(row=0, column=1, rowspan=3, sticky=NSEW)

        self.paneLeft.add(self.paneLeftBottom)
        self.paneLeftBottom.rowconfigure(0, weight=1)
        self.paneLeftBottom.columnconfigure(0, weight=1)
        self.optionFormTable.grid(row=0, column=0, sticky=NSEW)

        self.paneMaster.add(self.paneRight)
        self.paneRight.rowconfigure(0, weight=1)
        self.paneRight.columnconfigure(0, weight=1)
        self.patternNarrator.grid(row=0, column=0, sticky=NSEW)

        # bindings
        self.statusQuoAndGoals.bind("<<StatusQuoChanged>>", self.refresh)
        self.statusQuoAndGoals.bind("<<GoalChanged>>", self.refresh)
        self.coalitionSelector.bind("<<CoalitionsChanged>>", self.refresh)

        self.built = True

    def refresh(self):
        """Refresh data in all active display widgets."""
        sq = self.statusQuoAndGoals.statusQuoSelector.current()
        goals = self.statusQuoAndGoals.getGoals()
        if len(goals) > 0:
            self.sol = GoalSeeker(self.conflict, goals)
        else:
            self.sol = GoalSeeker(self.conflict)
        self.reachableTree.buildTree(sq, watchFor=[x[0] for x in goals])
        self.patternNarrator.updateNarration(
            goalInfo=self.reachableTree.goalInfo())
Esempio n. 8
0
class PicasaView():
    """ Interface to the view class """
    def __init__(self, controller):
        self.controller = controller  # function to call

        self.root = Tk()  # create main window called root
        self.root.state('zoomed')  # have root be full screen
        self.root.title('Picasa')  # name the display
        self.root.protocol(
            'WM_DELETE_WINDOW',
            lambda: self.controller('stop'))  # Trap close window

        self.menu = PicasaMenu(self.root, controller)  # create main menu
        self.root.config(menu=self.menu)  # add menu to window

        self.TAB = PanedWindow(self.root, orient=VERTICAL)  # Top And Bottom
        self.TAB.grid(sticky='nsew')
        self.LAR = PanedWindow(self.root, orient=HORIZONTAL)  # Left And Right
        self.LAR.grid(sticky='nsew')
        self.TAB.add(self.LAR)

        self.tree = Tree(self.root, controller)  # create tree
        self.LAR.add(self.tree)

        self.gallery = Gallery(self.root, controller)  # create all pics
        self.LAR.add(self.gallery)

        self.status = Status(self.TAB, controller)  # create status text
        self.TAB.add(self.status)

        self.TAB.config(sashrelief='raised')  # make sash visible
        self.LAR.config(sashrelief='raised')

        self.root.grid_columnconfigure(0, weight=1)  # make all resizeable
        self.root.grid_rowconfigure(0, weight=1)

        self.TAB.sash_place(0, 1, 1000)
        #self.TAB.sash('dragto', 0, 1, 1000)

    def start(self):
        """ start the main window """
        self.root.mainloop()  # display root

    def stop(self):
        """ quit Picasa and close down cleanly """
        self.root.destroy()  # Quit the application
        #self.root.quit()

    def addstatus(self, text):
        """ add a comment to the status log """
        txt = ""
        for msg in text:
            txt += msg
        self.status.text.insert((1.0), txt + '\n')

    def clearstatus(self):
        """ clear the contents of the status area """
        self.status.text.delete((1.0), 'end')

    def getdir(self):
        """ Get the user to choose a folder to watch """
        return filedialog.askdirectory()

    def build(self, album):
        """ build tree structure and gallery from list of folders """
        self.tree.build(album)
        self.gallery.build(album)
Esempio n. 9
0
def main(fname):
    tstart = time.monotonic()
    #@+others
    #@+node:vitalije.20180518114840.1: *3* 1. load xml
    ltm = load_leo(fname)
    ltm.selectedPosition = ltm.data.positions[1]
    ltmbytes = ltm.to_bytes()
    #@+node:vitalije.20180518114847.1: *3* 2. create app
    app = Tk()
    app.columnconfigure(0, weight=1)
    app.rowconfigure(0, weight=1)
    #@+node:vitalije.20180518114857.1: *3* 3. adjust fonts
    font.nametofont('TkFixedFont').config(size=18)
    font.nametofont('TkTextFont').config(size=18)
    font.nametofont('TkDefaultFont').config(size=18)
    #@+node:vitalije.20180518114953.1: *3* 4. create gui
    f1 = PanedWindow(app,
                     orient='horizontal',
                     width=800,
                     height=600,
                     sashrelief='ridge',
                     sashwidth=4)
    f1.grid(
        row=0,
        column=0,
        sticky="nesw",
    )
    f2 = PanedWindow(f1, orient='vertical')
    canvW = Canvas(f2, bg='#113333')
    f2.add(canvW)
    logW = scrolledtext.ScrolledText(f2,
                                     bg='#223399',
                                     fg='#cccc99',
                                     font=font.nametofont('TkDefaultFont'))
    f2.add(logW)
    bodyW = makeBodyW(f1)
    f1.add(f2)
    f1.add(bodyW)

    #@+node:vitalije.20180518115000.1: *3* 5. f_later
    def f_later():
        f1.sash_place(0, 270, 1)
        f2.sash_place(0, 1, 350)
        app.geometry("800x600+720+50")
        app.wm_title(fname)
        app.after_idle(update_model)

    #@+node:vitalije.20180518115003.1: *3* 6. loadex
    def loadex():
        ltm2 = LeoTreeModel.from_bytes(ltmbytes)
        loaddir = os.path.dirname(fname)
        load_external_files(ltm2, loaddir)
        G.q.put(ltm2)

    #@+node:vitalije.20180518115010.1: *3* 7. update_model
    def update_model():
        try:
            m = G.q.get(False)
            ltm.data = m.data
            draw_tree(G.tree, ltm)
            tend = time.monotonic()
            t1 = (tend - tstart)
            logW.insert('end', 'External files loaded in %.3fs\n' % t1)
        except queue.Empty:
            app.after(100, update_model)

    #@+node:vitalije.20180518115038.1: *3* 8. start loading thread
    threading.Thread(target=loadex, name='externals-loader').start()
    app.after_idle(f_later)
    #@-others
    return bunch(ltm=ltm,
                 app=app,
                 tree=canvW,
                 body=bodyW,
                 log=logW,
                 q=queue.Queue(1),
                 topIndex=IntVar(),
                 search=SearchState(str_to_fa(''), ltm.data.positions[1], 0, 0,
                                    False))
Esempio n. 10
0
    font=('calibri', '11'), bg='#ffffff', relief=FLAT, bd=0)
profiles_adjust_ROI_text.pack(side=TOP, padx=(0, 0))

global profiles_redefine_film_ROI_frame
profiles_redefine_film_ROI_frame = tk.Frame(profiles_adjust_ROI_canvas)
profiles_redefine_film_ROI_frame.pack(side=BOTTOM, padx=(0, 0))
profiles_redefine_film_ROI_frame.config(bg='#ffffff')
global profiles_adjust_button_left
global profiles_adjust_button_right
global profiles_adjust_button_down
global profiles_adjust_button_up

global profiles_film_panedwindow
profiles_film_panedwindow = \
    PanedWindow(profiles_view_film_doseplan_ROI, orient='horizontal')
profiles_film_panedwindow.grid(row=1, column=0, \
    columnspan=3, rowspan=5, sticky=N+W)
profiles_film_panedwindow.configure(sashrelief=RAISED, showhandle=True)

global profiles_scanned_image_text_image
global profiles_film_dose_map_text_image
global profiles_doseplan_text_image

global doseplan_write_image
global film_write_image
global doseplan_write_image_width
global doseplan_write_image_height
global doseplan_write_image_var_x
doseplan_write_image_var_x = 0
global doseplan_write_image_var_y
doseplan_write_image_var_y = 0
global profiles_coordinate_in_dataset
Esempio n. 11
0
class StabilityFrame(FrameTemplate):
    """Frame used to for Stability Analysis."""

    # Label used for button to select frame in the main program.
    buttonLabel = 'Post Analysis'
    # Image used on button to select frame, when frame is active.
    activeIcon = 'icons/Post_Analysis_ON.gif'
    # Image used on button to select frame, when frame is inactive.
    inactiveIcon = 'icons/Post_Analysis_OFF.gif'
    # Help text to be displayed when screen is active.
    helpText = ("Selecting coalitions, status quo and goals at the top left"
                "will generate a reachability tree below the status quo, and "
                "detail the patterns that preferences must match for the goal "
                "state to be reached.")

# ########################     INITIALIZATION  ################################
    def __init__(self, master, conflict, *args):
        """Initialize the Frame. Does not build widgets."""
        FrameTemplate.__init__(self, master, conflict, self.buttonLabel,
                               self.activeIcon, self.inactiveIcon,
                               self.helpText)

        self.lastBuildConflict = None


# ############################     METHODS  ###################################

    def hasRequiredData(self):
        """Check that minimum data required to render the frame exists."""
        if len(self.conflict.decisionMakers) < 1:
            return False
        if len(self.conflict.options) < 1:
            return False
        if len(self.conflict.feasibles) < 1:
            return False
        if self.conflict.preferenceErrors:
            return False
        else:
            return True

    def dataChanged(self):
        """Check if data has changed since the last build of the Frame."""
        if self.lastBuildConflict != self.conflict.export_rep():
            return True
        else:
            return False

    def buildFrame(self):
        """Contruct frame widgets and initialize data."""
        if self.built:
            return

        # Ensure all required parts of the conflict model are properly set-up.
        self.conflict.reorderOptionsByDM()
        self.conflict.options.set_indexes()
        self.conflict.infeasibles.validate()
        self.conflict.recalculateFeasibleStates()

        for dm in self.conflict.decisionMakers:
            dm.calculatePerceived()
            dm.calculatePreferences()

        self.lastBuildConflict = self.conflict.export_rep()

        # Define frame-specific variables
        self.sol = GoalSeeker(self.conflict)

        # infoFrame: frame and label definitions (with master 'self.infoFrame')
        self.infoLabel = ttk.Label(self.infoFrame, text="")

        # helpFrame: frame and label definitions (with master 'self.helpFrame')
        self.helpLabel = ttk.Label(self.helpFrame, textvariable=self.helpVar,
                                   wraplength=150)

        # Define frame-specific input widgets (with 'self' as master)
        self.paneMaster = PanedWindow(self, orient=HORIZONTAL, sashwidth=10,
                                      sashrelief="raised", sashpad=3,
                                      relief="sunken")

        self.paneLeft = PanedWindow(self.paneMaster, orient=VERTICAL,
                                    sashwidth=10, sashrelief="raised",
                                    sashpad=3, relief="sunken")

        self.paneLeftTop = ttk.Frame(self.paneLeft)
        self.coalitionSelector = CoalitionSelector(self.paneLeftTop,
                                                   self.conflict, self)
        self.statusQuoAndGoals = StatusQuoAndGoals(self.paneLeftTop,
                                                   self.conflict)
        self.reachableTree = ReachableTreeViewer(self.paneLeftTop,
                                                 self.conflict, self)

        self.paneLeftBottom = ttk.Frame(self.paneLeft)
        self.optionFormTable = OptionFormTable(self.paneLeftBottom,
                                               self.conflict)

        self.paneRight = ttk.Frame(self.paneMaster)
        self.patternNarrator = PatternNarrator(self.paneRight, self.conflict,
                                               self)

        # ########  preliminary gridding and option configuration

        # configuring the input frame
        self.grid(column=0, row=0, rowspan=5, sticky=NSEW)
        self.grid_remove()
        self.columnconfigure(0, weight=1)
        self.rowconfigure(0, weight=1)

        # configuring infoFrame & infoFrame widgets
        self.infoFrame.grid(column=2, row=0, sticky=NSEW, padx=3, pady=3)
        self.infoFrame.grid_remove()
        self.infoLabel.grid(column=0, row=1, sticky=NSEW)

        # configuring helpFrame & helpFrame widgets
        self.helpFrame.grid(column=2, row=1, sticky=NSEW, padx=3, pady=3)
        self.helpFrame.grid_remove()
        self.helpLabel.grid(column=0, row=0, sticky=NSEW)

        # configuring frame-specific options
        self.paneMaster.grid(row=0, column=0, sticky=NSEW)

        self.paneMaster.add(self.paneLeft)

        self.paneLeft.add(self.paneLeftTop)
        self.paneLeftTop.columnconfigure(1, weight=1)
        self.paneLeftTop.rowconfigure(2, weight=1)
        self.coalitionSelector.grid(row=0, column=0, sticky=NSEW)
        ttk.Separator(self, orient=HORIZONTAL).grid(row=1, column=0,
                                                    sticky=NSEW, pady=3)
        self.statusQuoAndGoals.grid(row=2, column=0, sticky=NSEW)
        self.reachableTree.grid(row=0, column=1, rowspan=3, sticky=NSEW)

        self.paneLeft.add(self.paneLeftBottom)
        self.paneLeftBottom.rowconfigure(0, weight=1)
        self.paneLeftBottom.columnconfigure(0, weight=1)
        self.optionFormTable.grid(row=0, column=0, sticky=NSEW)

        self.paneMaster.add(self.paneRight)
        self.paneRight.rowconfigure(0, weight=1)
        self.paneRight.columnconfigure(0, weight=1)
        self.patternNarrator.grid(row=0, column=0, sticky=NSEW)

        # bindings
        self.statusQuoAndGoals.bind("<<StatusQuoChanged>>",
                                    self.refresh)
        self.statusQuoAndGoals.bind("<<GoalChanged>>",
                                    self.refresh)
        self.coalitionSelector.bind("<<CoalitionsChanged>>",
                                    self.refresh)

        self.built = True

    def refresh(self, *args):
        """Refresh data in all active display widgets."""
        sq = self.statusQuoAndGoals.statusQuoSelector.current()
        goals = self.statusQuoAndGoals.getGoals()
        if len(goals) > 0:
            self.sol = GoalSeeker(self.conflict, goals)
        else:
            self.sol = GoalSeeker(self.conflict)
        self.reachableTree.buildTree(sq, watchFor=[x[0] for x in goals])
        self.patternNarrator.updateNarration(
            goalInfo=self.reachableTree.goalInfo())
Esempio n. 12
0
    def BuildMainFrame(self): 
        from tkinter import Menu, IntVar, StringVar, Toplevel, Listbox, Frame, PanedWindow, Text, Scrollbar, Entry
        from tkinter import X, N, S, W, E, VERTICAL, TOP, END, DISABLED, RAISED

        menu = Menu(self.master,activeborderwidth=0,bd=0)
        self.master.config(menu=menu)
  
        filemenu = Menu(menu,tearoff=0,bd=1,activeborderwidth=0)
        menu.add_cascade(label="File", underline=0,  menu=filemenu)
        filemenu.add_command(label="New", accelerator='Ctrl+N',command=self.NewCommand)
        filemenu.add_command(label="Open...",accelerator='Ctrl+O', command=self.OpenCommand)
        filemenu.add_command(label="Save as...",accelerator='Ctrl+S', command=self.SaveCommand)
        filemenu.add_separator()
        filemenu.add_command(label="Quit",accelerator='Ctrl+Q', command=self.QuitCommand)

        self.log_on = IntVar()
        self.log_on.set(1)
  
        self.output_to_file = StringVar()
        self.output_to_file.set('n')
 
        scriptmenu = Menu(menu,tearoff=0,bd=1,activeborderwidth=0)
        modulenames = ['vmtkscripts']
        for modulename in modulenames:
            scriptsubmenu = self.BuildScriptMenu(menu,modulename)
            if scriptsubmenu:
                scriptmenu.add_cascade(label=modulename,menu=scriptsubmenu)
 
        editmenu = Menu(menu,tearoff=0,bd=1,activeborderwidth=0)
        menu.add_cascade(label="Edit",underline=0,  menu=editmenu)
        editmenu.add_cascade(label="Insert script",menu=scriptmenu)
        editmenu.add_command(label="Insert file name", accelerator='Ctrl+F',command=self.InsertFileName)
        editmenu.add_separator()
        editmenu.add_command(label="Clear input", command=self.ClearInputCommand)
        editmenu.add_command(label="Clear output", command=self.ClearOutputCommand)
        editmenu.add_command(label="Clear all", command=self.ClearAllCommand)
        editmenu.add_separator()
        editmenu.add_checkbutton(label="Log", variable=self.log_on)
        editmenu.add_separator()
        editmenu.add_radiobutton(label="No output to file", variable=self.output_to_file,value='n')
        editmenu.add_radiobutton(label="Write output to file", variable=self.output_to_file,value='w')
        editmenu.add_radiobutton(label="Append output to file", variable=self.output_to_file,value='a')
        editmenu.add_command(label="Output file...", command=self.OutputFileCommand)

        runmenu = Menu(menu,tearoff=0,bd=1,activeborderwidth=0)
        menu.add_cascade(label="Run", underline=0, menu=runmenu)
        runmenu.add_command(label="Run all", command=self.RunAllCommand)
        runmenu.add_command(label="Run current line", command=self.RunLineCommand)
        runmenu.add_command(label="Run selection", command=self.RunSelectionCommand)
       
        helpmenu = Menu(menu,tearoff=0,bd=1,activeborderwidth=0)
        menu.add_cascade(label="Help", underline=0, menu=helpmenu)
        helpmenu.add_command(label="Help", underline=0, accelerator='F1',command=self.ShowHelpCommand)
        helpmenu.add_command(label="About", underline=0, command=self.AboutCommand)

        self.master.bind("<Control-KeyPress-q>", self.QuitHandler)
        self.master.bind("<Control-KeyPress-n>", self.NewHandler)
        self.master.bind("<Control-KeyPress-o>", self.OpenHandler)
        self.master.bind("<Control-KeyPress-s>", self.SaveHandler)
        self.master.bind("<Control-KeyPress-f>", self.InsertFileNameHandler)
        self.master.bind("<KeyPress-F1>", self.ShowHelpHandler)
        self.master.bind("<KeyPress>", self.KeyPressHandler)
        
        self.wordIndex = ['1.0','1.0']
               
        self.suggestionswindow = Toplevel(bg='#ffffff',bd=0,height=50,width=600,highlightthickness=0,takefocus=True)
        self.suggestionswindow.overrideredirect(1)
        self.suggestionslist = Listbox(self.suggestionswindow,bg='#ffffff',bd=1,fg='#336699',activestyle='none',highlightthickness=0,height=9)
        self.suggestionslist.insert(END,"foo")
        self.suggestionslist.pack(side=TOP,fill=X)
        self.suggestionswindow.bind("<KeyPress>", self.TopKeyPressHandler)
        self.suggestionswindow.withdraw()

        self.master.rowconfigure(0,weight=1)
        self.master.columnconfigure(0,weight=1)
        content = Frame(self.master,bd=0,padx=2,pady=2) 
        content.grid(row=0,column=0,sticky=N+S+W+E)
        content.rowconfigure(0,weight=1,minsize=50)
        content.rowconfigure(1,weight=0)
        content.columnconfigure(0,weight=1)

        panes = PanedWindow(content,orient=VERTICAL,bd=1,sashwidth=8,sashpad=0,sashrelief=RAISED,showhandle=True)
        panes.grid(row=0,column=0,sticky=N+S+W+E)

        frame1 = Frame(panes,bd=0) 
        frame1.grid(row=0,column=0,sticky=N+S+W+E)
        frame1.columnconfigure(0,weight=1)
        frame1.columnconfigure(1,weight=0)
        frame1.rowconfigure(0,weight=1)

        panes.add(frame1,height=300,minsize=20)        

        frame2 = Frame(panes,bd=0) 
        frame2.grid(row=1,column=0,sticky=N+S+W+E)
        frame2.columnconfigure(0,weight=1)
        frame2.columnconfigure(1,weight=0)
        frame2.rowconfigure(0,weight=1)
        
        panes.add(frame2,minsize=20) 
 
        self.text_input = Text(frame1, bg='#ffffff',bd=1,highlightthickness=0)

        self.text_input.bind("<KeyPress>", self.KeyPressHandler)
        self.text_input.bind("<Button-3>", self.PopupHandler)
        self.text_input.bind("<Control-Return>", self.RunKeyboardHandler)
 
        self.input_scrollbar = Scrollbar(frame1,orient=VERTICAL,command=self.text_input.yview)
        self.text_input["yscrollcommand"] = self.input_scrollbar.set    

        self.text_output = Text(frame2,state=DISABLED,bd=1,bg='#ffffff',highlightthickness=0)
        
        self.output_scrollbar = Scrollbar(frame2,orient=VERTICAL,command=self.text_output.yview)
        self.text_output["yscrollcommand"] = self.output_scrollbar.set    
      
        self.text_entry = Entry(content,bd=1,bg='#ffffff',state=DISABLED,highlightthickness=0)

        self.text_input.focus_set()

        self.text_input.grid(row=0,column=0,sticky=N+S+W+E)
        self.input_scrollbar.grid(row=0,column=1,sticky=N+S+W+E)
        self.text_output.grid(row=0,column=0,sticky=N+S+W+E)
        self.output_scrollbar.grid(row=0,column=1,sticky=N+S+W+E)
        self.text_entry.grid(row=1,column=0,sticky=N+S+W+E)

        self.popupmenu = Menu(self.text_input, tearoff=1, bd=0)
        self.popupmenu.add_command(label="Context help", command=self.ShowHelpCommand)
        self.popupmenu.add_cascade(label="Insert script",menu=scriptmenu)
        self.popupmenu.add_command(label="Insert file name...", command=self.InsertFileName)
        self.popupmenu.add_separator()
        self.popupmenu.add_command(label="Run all", command=self.RunAllCommand)
        self.popupmenu.add_command(label="Run current line", command=self.RunLineCommand)
        self.popupmenu.add_command(label="Run selection", command=self.RunSelectionCommand)

        self.output_stream = TkPadOutputStream(self.text_output)
        self.input_stream = TkPadInputStream(self.text_entry,self.output_stream)
class PreferencesFrame(FrameTemplate):
    """Used to set decision maker's preferences for use in prioritization."""

    # Label used for button to select frame in the main program.
    buttonLabel = 'Prioritization'
    # Image used on button to select frame, when frame is active.
    activeIcon = 'icons/Prioritization_ON.gif'
    # Image used on button to select frame, when frame is inactive.
    inactiveIcon = 'icons/Prioritization_OFF.gif'
    # Help text to be displayed when screen is active.
    helpText = ("Select a decision maker from the column at left by clicking "
                "its 'Edit' button.  Enter preferred conditions using the "
                "inputs to the right.  Preferred conditions for the selected "
                "decision maker are shown at the far right, from most "
                "important at the top, to least important at the bottom.")

# ########################     INITIALIZATION  ################################
    def __init__(self, master, conflict, *args):
        """Initialize the Frame. Does not build widgets."""
        FrameTemplate.__init__(self, master, conflict, self.buttonLabel,
                               self.activeIcon, self.inactiveIcon,
                               self.helpText)

        self.lastBuildDMs = None
        self.lastBuildOptions = None
        self.lastBuildInfeasibles = None
        self.lastBuildRanking = None


# ############################     METHODS  ###################################

    def hasRequiredData(self):
        """Check that minimum data required to render the frame exists."""
        if len(self.conflict.decisionMakers) < 1:
            return False
        if len(self.conflict.options) < 1:
            return False
        if len(self.conflict.feasibles) < 1:
            self.conflict.recalculateFeasibleStates()
            if len(self.conflict.feasibles) < 1:
                return False
        else:
            return True

    def dataChanged(self):
        """Check if data has changed since the last build of the Frame."""
        if self.lastBuildDMs != self.conflict.decisionMakers.export_rep():
            return True
        if self.lastBuildOptions != self.conflict.options.export_rep():
            return True
        if self.lastBuildInfeasibles != self.conflict.infeasibles.export_rep():
            return True
        if self.lastBuildRanking != self.conflict.useManualPreferenceRanking:
            return True
        else:
            return False

    def buildFrame(self):
        """Contruct frame widgets and initialize data."""
        if self.built:
            return

        # Ensure all required parts of the conflict model are properly set-up.
        self.conflict.reorderOptionsByDM()
        self.conflict.options.set_indexes()
        self.conflict.infeasibles.validate()
        self.conflict.recalculateFeasibleStates()

        for dm in self.conflict.decisionMakers:
            dm.calculatePerceived()
            dm.calculatePreferences()

        self.lastBuildDMs = self.conflict.decisionMakers.export_rep()
        self.lastBuildOptions = self.conflict.options.export_rep()
        self.lastBuildInfeasibles = self.conflict.infeasibles.export_rep()
        self.lastBuildRanking = self.conflict.useManualPreferenceRanking

        # Define variables that will display in the infoFrame
        numD = len(self.conflict.decisionMakers)
        self.infoText = StringVar(
            value='Valid Preferences set for {0}/{0} DMs.'.format(numD))

        # Define frame-specific variables
        self.dm = None

        # infoFrame: frame and label definitions (with master 'self.infoFrame')
        self.infoLabel = ttk.Label(self.infoFrame, textvariable=self.infoText)

        # helpFrame: frame and label definitions (with master 'self.helpFrame')
        self.helpLabel = ttk.Label(self.helpFrame, textvariable=self.helpVar,
                                   wraplength=150)

        # Define frame-specific input widgets (with 'self' as master)
        self.paneMaster = PanedWindow(self, orient=VERTICAL, sashwidth=5,
                                      sashrelief="raised", sashpad=2,
                                      relief="sunken")

        self.paneTop = ttk.Frame(self.paneMaster)
        self.rankings = PreferenceRankingMaster(self.paneTop, self.conflict)
        self.editor = RadiobuttonEntry(self.paneTop, self.conflict)
        self.paneTopRightMaster = PanedWindow(self.paneTop, orient=HORIZONTAL,
                                              sashwidth=5, sashrelief="raised",
                                              sashpad=2, relief="sunken")
        self.staging = PreferenceStaging(self.paneTopRightMaster,
                                         self.conflict)
        self.preferenceDisp = PreferenceListDisplay(self.paneTopRightMaster,
                                                    self.conflict)

        self.paneBottom = ttk.Frame(self.paneMaster)
        self.optionTable = OptionFormTable(self.paneBottom, self.conflict)

        self.usePrioritizationButton = ttk.Button(
            self,
            text=("Use preference prioritization. Any manually set "
                  "preference rankings will be lost."),
            command=self.usePrioritization)

        # ########  preliminary gridding and option configuration

        # configuring the input frame
        self.grid(column=0, row=0, rowspan=5, sticky=NSEW)
        self.columnconfigure(0, weight=1)
        self.rowconfigure(1, weight=1)
        self.grid_remove()

        # configuring infoFrame & infoFrame widgets
        self.infoFrame.grid(column=2, row=0, sticky=NSEW, padx=3, pady=3)
        self.infoFrame.grid_remove()
        self.infoLabel.grid(column=0, row=1, sticky=NSEW)

        # configuring helpFrame & helpFrame widgets
        self.helpFrame.grid(column=2, row=1, sticky=NSEW, padx=3, pady=3)
        self.helpFrame.grid_remove()
        self.helpLabel.grid(column=0, row=0, sticky=NSEW)

        # configuring frame-specific options
        self.paneMaster.grid(column=0, row=1, sticky=NSEW)
        self.paneMaster.add(self.paneTop, minsize=200)
        self.rankings.grid(column=0, row=1, sticky=NSEW)
        ttk.Separator(self.paneTop, orient=VERTICAL).grid(
            column=1, row=1, sticky=NSEW, padx=3)
        self.editor.grid(column=2, row=1, sticky=NSEW)
        ttk.Separator(self.paneTop, orient=VERTICAL).grid(
            column=3, row=1, sticky=NSEW, padx=3)
        self.paneTopRightMaster.grid(column=4, row=1, sticky=NSEW)
        self.paneTop.columnconfigure(0, weight=0)
        self.paneTop.columnconfigure(2, weight=0)
        self.paneTop.columnconfigure(4, weight=1)
        self.paneTop.rowconfigure(1, weight=1)

        self.usePrioritizationButton.grid(column=0, row=0, columnspan=5,
                                          sticky=NSEW)

        self.paneTopRightMaster.add(self.staging)
        self.paneTopRightMaster.add(self.preferenceDisp)

        self.paneMaster.add(self.paneBottom)
        self.optionTable.grid(column=0, row=0, sticky=NSEW)
        self.paneBottom.columnconfigure(0, weight=1)
        self.paneBottom.rowconfigure(0, weight=1)

        # bindings
        self.rankings.bind('<<DMchg>>', self.dmChgHandler)
        self.editor.bind('<<AddPref>>', self.addPref)
        self.editor.bind('<<StagePref>>', self.stagePref)
        self.staging.bind('<<SelCond>>', self.selCondChg)
        self.staging.bind('<<PullFromStage>>', self.pullFromStage)
        self.preferenceDisp.bind('<<SelPref>>', self.selPrefChg)
        self.preferenceDisp.bind('<<ValueChange>>', self.refresh)

        self.dmChgHandler()

        self.built = True

    def enter(self, *args):
        """Re-grid the screen into the master. Perform required updates."""
        if self.dataChanged():
            self.clearFrame()

        FrameTemplate.enter(self)

    def refresh(self, *args):
        """Refresh data in all active display widgets."""
        for dm in self.conflict.decisionMakers:
            dm.calculatePreferences()
        self.editor.reloadOpts()
        self.rankings.refresh()
        self.preferenceDisp.refresh()
        self.optionTable.buildTable(self.dm)

        self.checkIfUsingRankings()

    def checkIfUsingRankings(self, event=None):
        """Disable screen if Manual Ranking has been assigned."""
        if self.conflict.useManualPreferenceRanking:
            self.usePrioritizationButton.grid()
            self.rankings.disable()
            self.editor.disable()
            self.staging.disable()
            self.preferenceDisp.disable()
        else:
            self.usePrioritizationButton.grid_remove()

    def usePrioritization(self):
        """Reactivate the screen if user decides to use prioritization."""
        self.conflict.useManualPreferenceRanking = False
        self.conflict.preferenceErrors = None
        self.refresh()

    def dmChgHandler(self, event=None):
        """Bound to <<DMchg>>."""
        self.dm = self.rankings.dm
        self.preferenceDisp.changeDM(self.dm)
        self.optionTable.buildTable(self.dm)
        self.staging.clear()
        self.editor.setStates('clear')
        if self.dm is None:
            self.preferenceDisp.disable()
            self.editor.disable()
            self.staging.disable()
        else:
            self.preferenceDisp.enable()
            self.editor.enable()

    def addPref(self, event=None):
        """Add a preference for the active decision maker."""
        pref = self.editor.getStates()
        self.dm.preferences.append(pref)
        self.refresh()

    def stagePref(self, event=None):
        """Send a condition to the staging area."""
        if self.editor.hasValidIf:
            for cond in self.editor.ifCond:
                self.staging.addCondition(cond)
        else:
            condData = self.editor.getStates()
            newCond = self.conflict.newCondition(condData)
            self.staging.addCondition(newCond)

        self.editor.setStates('clear')

    def pullFromStage(self, event=None):
        """Move a compound condition from Staging to Preferences."""
        newPref = self.staging.conditionList
        self.staging.clear()
        self.dm.preferences.append(newPref)
        self.refresh()

    def selCondChg(self, event=None):
        """Triggered when a condition is selected in staging."""
        condition = self.staging.conditionList[event.x]
        self.editor.setStates(condition.ynd())

    def selPrefChg(self, event=None):
        """Triggered when a preference is select from preferences."""
        condition = self.dm.preferences[event.x]
        self.staging.setList(condition)
Esempio n. 14
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)
Esempio n. 15
0
class ResultFrame(FrameTemplate):
    """Frame for display of equilibria in the conflict."""

    # Label used for button to select frame in the main program.
    buttonLabel = 'Equilibria Results'
    # Image used on button to select frame, when frame is active.
    activeIcon = 'icons/Equilibria_Results_ON.gif'
    # Image used on button to select frame, when frame is inactive.
    inactiveIcon = 'icons/Equilibria_Results_OFF.gif'
    # Help text to be displayed when screen is active.
    helpText = ("The stability of each state in the conflict is shown in the "
                "table on the left, giving results under a number of different"
                " stability criterion. The display on the right allows the "
                "logic which defines the stability or instability of each "
                "option to be examined.")

    # ########################     INITIALIZATION  ################################
    def __init__(self, master, conflict, *args):
        """Initialize the Frame. Does not build widgets."""
        FrameTemplate.__init__(self, master, conflict, self.buttonLabel,
                               self.activeIcon, self.inactiveIcon,
                               self.helpText)

        self.lastBuildConflict = None

# ############################     METHODS  ###################################

    def hasRequiredData(self):
        """Check that minimum data required to render the frame exists."""
        if len(self.conflict.decisionMakers) < 1:
            return False
        if len(self.conflict.options) < 1:
            return False
        if len(self.conflict.feasibles) < 1:
            return False
        if self.conflict.preferenceErrors:
            return False
        else:
            return True

    def dataChanged(self):
        """Check if data has changed since the last build of the Frame."""
        if self.lastBuildConflict != self.conflict.export_rep():
            return True
        else:
            return False

    def buildFrame(self):
        """Contruct frame widgets and initialize data."""
        if self.built:
            return

        # Ensure all required parts of the conflict model are properly set-up.
        self.conflict.reorderOptionsByDM()
        self.conflict.options.set_indexes()
        self.conflict.infeasibles.validate()
        self.conflict.recalculateFeasibleStates()
        self.conflict.coalitions.validate()

        for dm in self.conflict.decisionMakers:
            dm.calculatePerceived()
            dm.calculatePreferences()

        self.lastBuildConflict = self.conflict.export_rep()

        # Define variables that will display in the infoFrame
        self.infoText = StringVar(value='')

        # Define frame-specific variables
        self.sol = LogicalSolver(self.conflict)
        self.sol.findEquilibria()

        # infoFrame: frame and label definitions (with master 'self.infoFrame')
        self.infoLabel = ttk.Label(self.infoFrame, textvariable=self.infoText)

        # helpFrame: frame and label definitions (with master 'self.helpFrame')
        self.helpLabel = ttk.Label(self.helpFrame,
                                   textvariable=self.helpVar,
                                   wraplength=150)

        # Define frame-specific input widgets (with 'self' as master)
        self.paneMaster = PanedWindow(self,
                                      orient=HORIZONTAL,
                                      sashwidth=10,
                                      sashrelief="raised",
                                      sashpad=3,
                                      relief="sunken")

        self.pane1 = ttk.Frame(self.paneMaster)
        self.coalitionSelector = CoalitionSelector(self.pane1, self.conflict,
                                                   self)
        self.solutionTable = OptionFormSolutionTable(self.pane1, self.conflict,
                                                     self)
        self.exporter = Exporter(self.pane1, self.conflict, self)

        self.pane2 = ttk.Frame(self.paneMaster)
        self.narrator = LogNarrator(self.pane2, self.conflict, self)

        # ########  preliminary gridding and option configuration

        # configuring the input frame
        self.grid(column=0, row=0, rowspan=5, sticky=NSEW)
        self.grid_remove()
        self.columnconfigure(0, weight=1)
        self.rowconfigure(1, weight=1)

        # configuring infoFrame & infoFrame widgets
        self.infoFrame.grid(column=2, row=0, sticky=NSEW, padx=3, pady=3)
        self.infoFrame.grid_remove()
        self.infoLabel.grid(column=0, row=1, sticky=NSEW)

        # configuring helpFrame & helpFrame widgets
        self.helpFrame.grid(column=2, row=1, sticky=NSEW, padx=3, pady=3)
        self.helpFrame.grid_remove()
        self.helpLabel.grid(column=0, row=0, sticky=NSEW)

        # configuring frame-specific options
        self.paneMaster.grid(column=0, row=1, sticky=NSEW)
        self.paneMaster.add(self.pane1, width=600, stretch='always')
        self.pane1.rowconfigure(1, weight=1)
        self.pane1.columnconfigure(0, weight=1)
        self.coalitionSelector.grid(row=0, column=0, sticky=NSEW)
        self.solutionTable.grid(row=1, column=0, sticky=NSEW)
        self.exporter.grid(row=2, column=0, sticky=NSEW)

        self.paneMaster.add(self.pane2, width=250, stretch='always')
        self.pane2.rowconfigure(0, weight=1)
        self.pane2.columnconfigure(0, weight=1)
        self.narrator.grid(row=0, column=0, sticky=NSEW)

        # bindings
        self.coalitionSelector.bind("<<CoalitionsChanged>>", self.refresh)

        self.built = True

    def refresh(self, *args):
        """Refresh data in all active display widgets."""
        self.sol = LogicalSolver(self.conflict)
        self.sol.findEquilibria()
        self.coalitionSelector.refresh()
        self.solutionTable.refresh()
        self.narrator.refresh()
Esempio n. 16
0
        self.config(bg='blue')
        bp_label = Label(self)
        bp_label.config(text='Barplot Controls')
        bp_label.grid(row=0, column=0, sticky='ew')
        window_prop = Frame(self)
        window_prop.config(width=10, height=150, bg='cyan')
        window_prop.grid(row=0, column=1, sticky='nsew')


EDA_Bottom_Pane = PanedWindow(root,
                              orient=VERTICAL,
                              bd=0,
                              bg='yellow',
                              sashwidth=4)
EDA_Bottom_Pane.grid(sticky='nsew')

EDA_Top_Pane = PanedWindow(EDA_Bottom_Pane,
                           orient=HORIZONTAL,
                           bd=0,
                           bg='black',
                           sashwidth=4)
EDA_Top_Pane.grid(sticky='nsew')
EDA_Bottom_Pane.add(EDA_Top_Pane, stretch='always')

EDA_Controls_Frame = Frame(EDA_Bottom_Pane)
EDA_Controls_Frame.config(bg='red', width=200, height=100)
EDA_Controls_Frame.grid(sticky='nsew')
EDA_Controls_Frame.grid_columnconfigure(0, weight=1)
EDA_Controls_Frame.grid_columnconfigure(2, weight=1)
EDA_Bottom_Pane.add(EDA_Controls_Frame, stretch='never')
Esempio n. 17
0
menu2.add_command(label="Help")
menu_area.add_cascade(label="Help", menu=menu2)

label_frame = LabelFrame(win, text='label frame')
label_frame.grid(row=0, column=0, padx=5, pady=5)

lbl_name = Label(label_frame, text="성명: ")
lbl_phone = Label(label_frame, text="전화번호: ")
lbl_email = Label(label_frame, text="이메일: ")

entry_name = Entry(label_frame)
entry_phone = Entry(label_frame)
entry_email = Entry(label_frame)

lbl_name.grid(row=0, column=0)
entry_name.grid(row=0, column=1, padx=5, pady=5)
lbl_phone.grid(row=1, column=0)
entry_phone.grid(row=1, column=1, padx=5, pady=5)
lbl_email.grid(row=2, column=0)
entry_email.grid(row=2, column=1, padx=5, pady=5)

penedwindow = PanedWindow(relief="raised", bd=0)
penedwindow.grid(row=3, column=0, columnspan=2)

btn_ok = Button(penedwindow, text="확인")
btn_cancel = Button(penedwindow, text="취소")
penedwindow.add(btn_ok)
penedwindow.add(btn_cancel)

if __name__ == '__main__':
    win.mainloop()
Esempio n. 18
0
class Ufd:
    """
        Universal File Dialog - "UFD"
        
        Unopinionated, minimalist, reusable, slightly configurable,
        general-purpose file-dialog.
    """
    def __init__(self,
                 title: str = "Universal File Dialog",
                 icon: str = "",
                 show_hidden: bool = False,
                 include_files: bool = True,
                 multiselect: bool = True,
                 select_dirs: bool = True,
                 select_files: bool = True,
                 unix_delimiter: bool = True,
                 stdout: bool = False):
        """
            Init kwargs as object attributes, save references to 
            Tk PhotoImages, & define the widgets + layout
        """

        if not isinstance(title, str):
            raise TypeError("Argument title must be type string.")

        self.title = title

        if icon:
            if not isinstance(icon, str):
                raise TypeError("Argument icon must be type string.")

            if not isfile(icon):
                raise FileNotFoundError(f"File not found: {icon}")

            self.icon = icon

        else:
            self.icon = ""

        if show_hidden:
            self.show_hidden = True
        else:
            self.show_hidden = False

        if include_files:
            self.include_files = True
        else:
            self.include_files = False

        if multiselect:
            self.multiselect = True
        else:
            self.multiselect = False

        if select_dirs:
            self.select_dirs = True
        else:
            self.select_dirs = False

        if select_files:
            self.select_files = True
        else:
            self.select_files = False

        if unix_delimiter:
            self.unix_delimiter = True
        else:
            self.unix_delimiter = False

        if stdout:
            self.stdout = True
        else:
            self.stdout = False

        # Tkinter:
        self.dialog = Tk()
        self.dialog.withdraw()
        self.dialog.title(self.title)
        self.dialog.minsize(width=300, height=200)
        self.dialog.geometry("500x300")
        self.dialog.update_idletasks()

        self.file_icon = PhotoImage(file=f"{dirname(__file__)}/file.gif",
                                    master=self.dialog).subsample(50)

        self.folder_icon = PhotoImage(file=f"{dirname(__file__)}/folder.gif",
                                      master=self.dialog).subsample(15)

        self.disk_icon = PhotoImage(file=f"{dirname(__file__)}/disk.gif",
                                    master=self.dialog).subsample(15)

        if self.icon:
            self.dialog.iconbitmap(self.icon)
        else:
            self.dialog.iconbitmap(f"{dirname(__file__)}/icon.ico")

        # Widgets:
        self.paneview = PanedWindow(
            self.dialog,
            sashwidth=7,
            bg="#cccccc",
            bd=0,
        )

        self.left_pane = PanedWindow(self.paneview)
        self.right_pane = PanedWindow(self.paneview)
        self.paneview.add(self.left_pane)
        self.paneview.add(self.right_pane)

        self.treeview_x_scrollbar = Scrollbar(self.left_pane,
                                              orient="horizontal")
        self.treeview_y_scrollbar = Scrollbar(self.left_pane,
                                              orient="vertical")
        self.list_box_x_scrollbar = Scrollbar(self.right_pane,
                                              orient="horizontal")
        self.list_box_y_scrollbar = Scrollbar(self.right_pane,
                                              orient="vertical")

        # tstyle = Style().configure(".", )

        self.treeview = Treeview(
            self.left_pane,
            xscrollcommand=self.treeview_x_scrollbar.set,
            yscrollcommand=self.treeview_y_scrollbar.set,
            show="tree",
            selectmode="browse",
            # style=tstyle
        )

        self.list_box = Listbox(self.right_pane,
                                xscrollcommand=self.list_box_x_scrollbar.set,
                                yscrollcommand=self.list_box_y_scrollbar.set,
                                width=34,
                                highlightthickness=0,
                                bd=2,
                                relief="ridge")

        if self.multiselect:
            self.list_box.config(selectmode="extended")
        else:
            self.list_box.config(selectmode="browse")

        self.cancel_button = Button(self.left_pane,
                                    text="Cancel",
                                    command=self.cancel)

        self.submit_button = Button(self.right_pane,
                                    text="Submit",
                                    command=self.submit)

        self.treeview_x_scrollbar.config(command=self.treeview.xview)
        self.treeview_y_scrollbar.config(command=self.treeview.yview)
        self.list_box_x_scrollbar.config(command=self.list_box.xview)
        self.list_box_y_scrollbar.config(command=self.list_box.yview)

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

        self.left_pane.grid_rowconfigure(0, weight=1)
        self.left_pane.grid_columnconfigure(0, weight=1)
        self.right_pane.grid_rowconfigure(0, weight=1)
        self.right_pane.grid_columnconfigure(0, weight=1)

        self.paneview.paneconfigure(
            self.left_pane,
            minsize=100,
            #Start off w/ the sash centered in the GUI:
            width=(self.dialog.winfo_width() / 2) - ceil(
                (self.paneview.cget("sashwidth") * 1.5)),
        )
        self.paneview.paneconfigure(self.right_pane, minsize=100)

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

        self.treeview.grid(row=0, column=0, sticky="nsew")
        self.treeview_y_scrollbar.grid(row=0, column=1, sticky="ns")
        self.treeview_x_scrollbar.grid(row=1,
                                       column=0,
                                       columnspan=2,
                                       sticky="ew")

        self.list_box.grid(row=0, column=0, sticky="nsew")
        self.list_box_y_scrollbar.grid(row=0, column=1, sticky="ns")
        self.list_box_x_scrollbar.grid(row=1,
                                       column=0,
                                       columnspan=2,
                                       sticky="ew")

        self.cancel_button.grid(row=2, column=0, sticky="w", padx=10, pady=10)
        self.submit_button.grid(row=2,
                                column=0,
                                columnspan=2,
                                sticky="e",
                                padx=10,
                                pady=10)

        #Bindings, Protocols, & Misc:
        self.dialog.bind("<Control-w>", self.cancel)
        self.treeview.bind("<<TreeviewSelect>>", self.treeview_select)
        self.treeview.bind("<Double-Button-1>", self.dialog_populate)
        self.treeview.bind("<Return>", self.dialog_populate)
        self.treeview.bind("<Right>", self.dialog_populate)
        self.list_box.bind("<<ListboxSelect>>", self.list_box_select)
        self.list_box.bind("<Return>", self.submit)
        self.dialog.protocol("WM_DELETE_WINDOW", self.cancel)

        self.dialog_selection = deque()
        self.selection_paths = deque()

        for disk in self.get_disks():
            self.treeview.insert(
                "",
                index="end",
                text=disk,
                image=self.disk_icon,
            )

        self.dialog.focus()

    def __call__(self):
        """
            Display dialog & return selection
        """

        (width_offset, height_offset) = self.get_offset(self.dialog)
        self.dialog.geometry(f"+{width_offset}+{height_offset}")
        self.dialog.update_idletasks()
        self.dialog.deiconify()

        self.dialog.wait_window()

        for i, path in enumerate(self.dialog_selection):
            if self.unix_delimiter:
                self.dialog_selection[i] = sub("\\\\", "/", path)
            else:
                self.dialog_selection[i] = sub("/", "\\\\", path)

        if self.stdout:
            [print(item) for item in self.dialog_selection]

        return list(self.dialog_selection)

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

        return "Universal File Dialog"\
        f" @ {hex(id(self))}"

    def __repr__(self):
        """
            Return full string representation of constructor signature
        """

        return f"Ufd("\
        f"title=\"{self.title}\","\
        f" icon=\"{self.icon}\","\
        f" show_hidden={self.show_hidden},"\
        f" include_files={self.include_files},"\
        f" multiselect={self.multiselect},"\
        f" select_dirs={self.select_dirs},"\
        f" select_files={self.select_files},"\
        f" unix_delimiter={self.unix_delimiter})"\
        f" stdout={self.stdout})"\
        f" @ {hex(id(self))}"

    @staticmethod
    def get_offset(tk_window):
        """
            Returns an appropriate offset for a given tkinter toplevel,
            such that it always is created center screen on the primary display.
        """

        width_offset = int((tk_window.winfo_screenwidth() / 2) -
                           (tk_window.winfo_width() / 2))

        height_offset = int((tk_window.winfo_screenheight() / 2) -
                            (tk_window.winfo_height() / 2))

        return (width_offset, height_offset)

    @staticmethod
    def get_disks():
        """
            Returns all mounted disks (for Windows)

            >> ["A:", "B:", "C:"]
        """

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

        logicaldisks = run(["wmic", "logicaldisk", "get", "name"],
                           capture_output=True)

        return findall("[A-Z]:", str(logicaldisks.stdout))

    @staticmethod
    def list_dir(path, force=False):
        """
            Reads a directory with a shell call to dir.
            Truthiness of bool force determines whether 
            hidden items are returned or not. (For Windows)
        """

        path = sub("/", "\\\\", path)

        if force:
            dir_listing = run(["dir", path, "/b", "/a"],
                              shell=True,
                              capture_output=True)

        else:
            dir_listing = run(["dir", path, "/b"],
                              shell=True,
                              capture_output=True)

        output = dir_listing.stdout
        err = dir_listing.stderr

        if not output:
            return []

        if err:
            err = err.decode("utf-8")
            raise Exception(err)

        str_output = output.decode("utf-8")
        list_output = re_split("\r\n", str_output)

        return sorted([item for item in list_output if item])

    def climb(self, item):
        """
            Builds & returns a complete path to root directory,
            including the item name itself as the path tail.
            An extra delimiter is appeneded for the subsequent
            child node, which is normalized in dialog_populate()
        """

        item_text = self.treeview.item(item)["text"]
        parent = self.treeview.parent(item)
        path = ""
        parents = deque()

        while parent:
            parents.append(self.treeview.item(parent)["text"] + "/")
            parent = self.treeview.parent(parent)

        for parent in reversed(parents):
            path += parent

        path += item_text + "/"
        return path

    def dialog_populate(self, event=None):
        """
            Dynamically populates & updates the treeview, listbox,
            and keeps track of the full paths corresponding to each
            item in the listbox
        """
        if not self.treeview.focus():
            return

        self.treeview.column("#0", width=1000)

        existing_children = self.treeview.get_children(self.treeview.focus())
        [self.treeview.delete(child) for child in existing_children]

        self.list_box.delete(0, "end")
        self.selection_paths.clear()

        focus_item = self.treeview.focus()
        path = self.climb(focus_item)

        if self.show_hidden:
            children = self.list_dir(path, force=True)
        else:
            children = self.list_dir(path)

        for child in children:
            if isdir(path + child):

                self.treeview.insert(focus_item,
                                     index="end",
                                     text=child,
                                     image=self.folder_icon)

                if self.select_dirs:
                    self.list_box.insert("end", child)
                    self.selection_paths.append(path + child)

            elif isfile(path + child):

                if self.include_files:
                    self.treeview.insert(focus_item,
                                         index="end",
                                         text=child,
                                         image=self.file_icon)

                if self.select_files:
                    self.list_box.insert("end", child)
                    self.list_box.itemconfig("end", {"bg": "#EAEAEA"})
                    self.selection_paths.append(path + child)

        if isfile(normpath(path)):
            (head, tail) = path_split(normpath(path))
            head = sub("\\\\", "/", head)

            self.list_box.insert("end", tail)
            self.selection_paths.append(head + "/" + tail)
            self.list_box.itemconfig("end", {"bg": "#EAEAEA"})

    def list_box_select(self, event=None):
        """
            Dynamically refresh the dialog selection with
            what's selected in the listbox
            (Callback for <<ListboxSelect>>).
        """

        self.dialog_selection.clear()

        for i in self.list_box.curselection():
            self.dialog_selection.append(self.selection_paths[i])

    def treeview_select(self, event=None):
        """
            Dynamically refresh the dialog selection with
            what's selected in the treeview
            (Callback for <<TreeviewSelect>>).
        """

        for i in self.list_box.curselection():
            self.list_box.selection_clear(i)

        self.dialog_selection.clear()

        item = normpath(self.climb(self.treeview.focus()))
        self.dialog_selection.append(item)

    def submit(self, event=None):
        """
            Satisfies wait_window() in self.__call__() and validates selection

            (Callback for <Return>, <Button-1> on file_list, submit_button)
        """

        if self.select_dirs == False:
            for item in self.dialog_selection:
                if isdir(item):
                    messagebox.showwarning(
                        "Error - Invalid Selection",
                        "Unable to select directory. Please select a file(s).")
                    return

        if self.select_files == False:
            for item in self.dialog_selection:
                if isfile(item):
                    messagebox.showwarning(
                        "Error - Invalid Selection",
                        "Unable to select file. Please select a folder(s)")
                    return

        self.dialog.destroy()

    def cancel(self, event=None):
        """
            Satisfies wait_window() in self.__call__() 

            (Callback for <Button-1> on cancel_button)
            (Callback for protocol "WM_DELETE_WINDOW" on self.dialog)
        """

        self.dialog_selection.clear()
        self.dialog.destroy()
Esempio n. 19
0
class ResultFrame(FrameTemplate):
    """Frame for display of equilibria in the conflict."""

    # Label used for button to select frame in the main program.
    buttonLabel = 'Equilibria Results'
    # Image used on button to select frame, when frame is active.
    activeIcon = 'icons/Equilibria_Results_ON.gif'
    # Image used on button to select frame, when frame is inactive.
    inactiveIcon = 'icons/Equilibria_Results_OFF.gif'
    # Help text to be displayed when screen is active.
    helpText = ("The stability of each state in the conflict is shown in the "
                "table on the left, giving results under a number of different"
                " stability criterion. The display on the right allows the "
                "logic which defines the stability or instability of each "
                "option to be examined.")

# ########################     INITIALIZATION  ################################
    def __init__(self, master, conflict, *args):
        """Initialize the Frame. Does not build widgets."""
        FrameTemplate.__init__(self, master, conflict, self.buttonLabel,
                               self.activeIcon, self.inactiveIcon,
                               self.helpText)

        self.lastBuildConflict = None

# ############################     METHODS  ###################################

    def hasRequiredData(self):
        """Check that minimum data required to render the frame exists."""
        if len(self.conflict.decisionMakers) < 1:
            return False
        if len(self.conflict.options) < 1:
            return False
        if len(self.conflict.feasibles) < 1:
            return False
        if self.conflict.preferenceErrors:
            return False
        else:
            return True

    def dataChanged(self):
        """Check if data has changed since the last build of the Frame."""
        if self.lastBuildConflict != self.conflict.export_rep():
            return True
        else:
            return False

    def buildFrame(self):
        """Contruct frame widgets and initialize data."""
        if self.built:
            return

        # Ensure all required parts of the conflict model are properly set-up.
        self.conflict.reorderOptionsByDM()
        self.conflict.options.set_indexes()
        self.conflict.infeasibles.validate()
        self.conflict.recalculateFeasibleStates()
        self.conflict.coalitions.validate()

        for dm in self.conflict.decisionMakers:
            dm.calculatePerceived()
            dm.calculatePreferences()

        self.lastBuildConflict = self.conflict.export_rep()

        # Define variables that will display in the infoFrame
        self.infoText = StringVar(value='')

        # Define frame-specific variables
        self.sol = LogicalSolver(self.conflict)
        self.sol.findEquilibria()

        # infoFrame: frame and label definitions (with master 'self.infoFrame')
        self.infoLabel = ttk.Label(self.infoFrame, textvariable=self.infoText)

        # helpFrame: frame and label definitions (with master 'self.helpFrame')
        self.helpLabel = ttk.Label(self.helpFrame, textvariable=self.helpVar,
                                   wraplength=150)

        # Define frame-specific input widgets (with 'self' as master)
        self.paneMaster = PanedWindow(self, orient=HORIZONTAL, sashwidth=10,
                                      sashrelief="raised", sashpad=3,
                                      relief="sunken")

        self.pane1 = ttk.Frame(self.paneMaster)
        self.coalitionSelector = CoalitionSelector(self.pane1, self.conflict,
                                                   self)
        self.solutionTable = OptionFormSolutionTable(self.pane1, self.conflict,
                                                     self)
        self.exporter = Exporter(self.pane1, self.conflict, self)

        self.pane2 = ttk.Frame(self.paneMaster)
        self.narrator = LogNarrator(self.pane2, self.conflict, self)

        # ########  preliminary gridding and option configuration

        # configuring the input frame
        self.grid(column=0, row=0, rowspan=5, sticky=NSEW)
        self.grid_remove()
        self.columnconfigure(0, weight=1)
        self.rowconfigure(1, weight=1)

        # configuring infoFrame & infoFrame widgets
        self.infoFrame.grid(column=2, row=0, sticky=NSEW, padx=3, pady=3)
        self.infoFrame.grid_remove()
        self.infoLabel.grid(column=0, row=1, sticky=NSEW)

        # configuring helpFrame & helpFrame widgets
        self.helpFrame.grid(column=2, row=1, sticky=NSEW, padx=3, pady=3)
        self.helpFrame.grid_remove()
        self.helpLabel.grid(column=0, row=0, sticky=NSEW)

        # configuring frame-specific options
        self.paneMaster.grid(column=0, row=1, sticky=NSEW)
        self.paneMaster.add(self.pane1, width=600, stretch='always')
        self.pane1.rowconfigure(1, weight=1)
        self.pane1.columnconfigure(0, weight=1)
        self.coalitionSelector.grid(row=0, column=0, sticky=NSEW)
        self.solutionTable.grid(row=1, column=0, sticky=NSEW)
        self.exporter.grid(row=2, column=0, sticky=NSEW)

        self.paneMaster.add(self.pane2, width=250, stretch='always')
        self.pane2.rowconfigure(0, weight=1)
        self.pane2.columnconfigure(0, weight=1)
        self.narrator.grid(row=0, column=0, sticky=NSEW)

        # bindings
        self.coalitionSelector.bind("<<CoalitionsChanged>>",
                                    self.refresh)

        self.built = True

    def refresh(self, *args):
        """Refresh data in all active display widgets."""
        self.sol = LogicalSolver(self.conflict)
        self.sol.findEquilibria()
        self.coalitionSelector.refresh()
        self.solutionTable.refresh()
        self.narrator.refresh()