class StrategyShareToplevel(Parent): """ Toplevel to display a list of strategy with checkboxes to allow selecting which should be shared. """ def __init__(self, master, client, database, strategy_frame, **kwargs): """ :param master: master widget :param client: network.strategy.client.StrategyClient :param database: results.strategies.StrategyDataBase :param strategy_frame: frames.strategy.StrategyFrame :param kwargs: SnapToplevel keyword arguments """ resizable = kwargs.pop("resizable", False) self._client = client self._database = database self._frame = strategy_frame Parent.__init__(self, master, **kwargs) self.wm_title("GSF Parser: Strategy Sharing") self.wm_resizable(resizable, resizable) # Configure the Treeview self.tree = CheckboxTreeview(master=self, height=16) self.tree.column("#0", width=200) self.tree.heading("#0", text="Strategy") self.tree.config(show=("headings", "tree")) self.scroll_bar = ttk.Scrollbar(self, orient=tk.VERTICAL, command=self.tree.yview) self.tree.config(yscrollcommand=self.scroll_bar.set) self.update_strategy_tree() self.share_button = ttk.Button(self, text="Share Strategies", command=self.share_strategies) self.grid_widgets() def grid_widgets(self): self.tree.grid(row=1, column=1, sticky="nswe", padx=5, pady=5) self.scroll_bar.grid(row=1, column=2, sticky="ns", padx=(0, 5), pady=5) self.share_button.grid(row=2, column=1, columnspan=2, sticky="nswe", padx=5, pady=(0, 5)) def share_strategies(self): for strategy in self.strategies_to_share: self._client.send_strategy(strategy) messagebox.showinfo("Info", "Selected Strategies sent.") def update_strategy_tree(self): self.tree.delete(*self.tree.get_children("")) for strategy in sorted(self._database.keys()): self.tree.insert("", tk.END, iid=strategy, text=strategy) @property def strategies_to_share(self): for strategy in self.tree.get_checked(): yield self._database[strategy]
def test_checkboxtreeview_methods(self): tree = CheckboxTreeview(self.window) tree.pack() self.window.update() tree.insert("", "end", "1", text="1") tree.insert("1", "end", "11", text="11") tree.insert("11", "end", "111", text="111") tree.insert("11", "end", "112", text="112") self.window.update() tree.state() self.window.update() tree.state(['disabled']) self.window.update() tree.state(['!disabled']) self.window.update() tree.collapse_all() self.window.update() tree.expand_all() self.window.update() tree.tag_add("1", "item") self.assertTrue(tree.tag_has("item", "1")) self.window.update() tree.change_state("1", "checked") self.assertTrue(tree.tag_has("checked", "1")) self.assertFalse(tree.tag_has("unchecked", "1")) self.assertFalse(tree.tag_has("tristate", "1")) self.assertTrue(tree.tag_has("item", "1")) self.window.update() tree.tag_del("1", "item") self.assertFalse(tree.tag_has("item", "1")) self.window.update() tree._check_descendant("1") self.assertTrue(tree.tag_has("checked", "11")) self.assertTrue(tree.tag_has("checked", "111")) self.assertTrue(tree.tag_has("checked", "112")) self.window.update() tree._uncheck_descendant("1") self.assertTrue(tree.tag_has("unchecked", "11")) self.assertTrue(tree.tag_has("unchecked", "111")) self.assertTrue(tree.tag_has("unchecked", "112")) self.window.update() tree._check_ancestor("111") self.assertTrue(tree.tag_has("tristate", "11")) self.window.update() tree._check_ancestor("112") self.assertTrue(tree.tag_has("checked", "11")) self.window.update() tree._uncheck_ancestor("111") self.assertTrue(tree.tag_has("tristate", "11")) self.window.update() tree._uncheck_ancestor("112") self.assertTrue(tree.tag_has("unchecked", "11")) self.window.update() tree._tristate_parent("111") self.assertTrue(tree.tag_has("tristate", "11")) self.assertTrue(tree.tag_has("tristate", "1")) self.window.update() tree.change_state("1", "checked") tree._check_descendant("1") self.assertEqual(tree.get_checked(), ["111", "112"]) self.window.update()
class ScriptManager: """ Open the scripts window manager """ folder_icon = None def __init__(self, parent): """ parent: the tkinter parent view to use for this window construction. """ self.parent = parent self.app = tk.Toplevel(parent) self.app.title("Scripts Manager") self.app.resizable(True, True) self.rvalue = None appFrame = ttk.Frame(self.app) #PANED PART self.paned = tk.PanedWindow(appFrame, height=300) #RIGHT PANE : TAble self.viewframe = ttk.Frame(self.paned) self.file_tree = CheckboxTreeview(self.viewframe) self.file_tree['columns'] = ('name', 'category') self.file_tree.heading('#0', text='Name') self.file_tree.column("#0", stretch=tk.YES, minwidth=300, width=300) self.file_tree.heading('#1', text='Category') self.file_tree.column("#1", stretch=tk.YES, minwidth=300, width=300) self.file_tree.pack(fill=tk.BOTH, expand=True) btn_pane = ttk.Frame(self.viewframe) self.execute_icone = tk.PhotoImage(file = Utils.getIcon("execute.png")) btn_execute = ttk.Button(btn_pane, text="Execute", image=self.execute_icone, command=self.executedSelectedScripts, tooltip="Execute all selected scripts", style="Toolbutton") btn_execute.pack(side=tk.RIGHT, padx=3, pady=5) self.open_folder_icone = tk.PhotoImage(file = Utils.getIcon("folder.png")) btn_openPathForUser = ttk.Button(btn_pane, text="Execute", image=self.open_folder_icone, command=self.openPathForUser, tooltip="Open scripts folder", style="Toolbutton") btn_openPathForUser.pack(side=tk.RIGHT, padx=3, pady=5) btn_pane.pack(fill=tk.X, side=tk.BOTTOM, anchor=tk.E) #LEFT PANE : Treeview self.frameTw = ttk.Frame(self.paned) self.treevw = ttk.Treeview(self.frameTw) self.treevw.pack() scbVSel = ttk.Scrollbar(self.frameTw, orient=tk.VERTICAL, command=self.treevw.yview) self.treevw.configure(yscrollcommand=scbVSel.set) self.treevw.grid(row=0, column=0, sticky=tk.NSEW) scbVSel.grid(row=0, column=1, sticky=tk.NS) self.treevw.grid(row=0, column=0, sticky=tk.NSEW) scbVSel.grid(row=0, column=1, sticky=tk.NS) self.paned.add(self.frameTw) self.paned.add(self.viewframe) self.paned.pack(fill=tk.BOTH, expand=1) self.frameTw.rowconfigure(0, weight=1) # Weight 1 sur un layout grid, sans ça le composant ne changera pas de taille en cas de resize self.frameTw.columnconfigure(0, weight=1) # Weight 1 sur un layout grid, sans ça le composant ne changera pas de taille en cas de resize appFrame.pack(fill=tk.BOTH, ipady=10, ipadx=10, expand=True) self.treevw.bind("<<TreeviewSelect>>", self.onTreeviewSelect) try: self.app.wait_visibility() self.app.focus_force() self.app.lift() except tk.TclError: pass self.refreshUI() def refreshUI(self): for widget in self.treevw.winfo_children(): widget.destroy() script_dir = self.getScriptsDir() if self.__class__.folder_icon is None: self.__class__.folder_icon = ImageTk.PhotoImage(Image.open(Utils.getIcon("folder.png"))) parent = self.treevw.insert("", "end", " ", text="Scripts", image=self.__class__.folder_icon, open=True) self.treevw.focus(parent) self.treevw.selection_set(parent) for root, subFolders, files in os.walk(script_dir): root_name = root.replace(script_dir, "") for folder in subFolders: if folder.startswith("__") or folder.endswith("__"): continue folder_iid = os.path.join(root_name, folder) parent_node = parent if root_name == "" else root_name self.treevw.insert(parent_node, "end", folder_iid, text=folder, image=self.__class__.folder_icon) self.openScriptFolderView() def getScriptsDir(self): return os.path.join(Utils.getMainDir(), "scripts/") def onTreeviewSelect(self, _event=None): selec = self.treevw.selection() if len(selec) == 0: return None item = selec[0] self.openScriptFolderView(str(item)) def openScriptFolderView(self, script_folder=""): full_script_path = os.path.join(self.getScriptsDir(), script_folder.strip()) script_shown = set() self.file_tree.delete(*self.file_tree.get_children()) for root, _, files in os.walk(full_script_path): for file in files: filepath = root + '/' + file if file.endswith(".py"): script_shown.add(filepath) scripts_list = sorted(script_shown) script_dir = self.getScriptsDir() for script in scripts_list: scriptName = os.path.basename(script) category_name = os.path.dirname(script.replace(script_dir, "")) self.file_tree.insert("", "end", script, text=scriptName, values=(category_name)) def executedSelectedScripts(self): for selected in self.file_tree.get_checked(): self.executeScript(selected) def executeScript(self, script_path): script_dir = self.getScriptsDir() category_name = os.path.dirname(script_path.replace(script_dir, "")) script_name = ".".join(os.path.splitext(os.path.basename(script_path))[:-1]) module = os.path.join("pollenisatorgui/scripts/",category_name, script_name).replace("/", '.') imported = importlib.import_module(module) success, res = imported.main(APIClient.getInstance()) if success: tk.messagebox.showinfo("Script finished", f"Script {script_name} finished.\n{res}") else: tk.messagebox.showwarning("Script failed", f"Script {script_name} failed.\n{res}") def openPathForUser(self): selection = self.treevw.selection() if selection: folder = os.path.join(self.getScriptsDir(), selection[0]) else: folder = self.getScriptsDir() Utils.openPathForUser(folder)