def confirm(self, title, ui_components, show_buttons=True): """Show a popup dialogue with default 'ok' and 'cancel' button. Contents of the window will be in order of whats passed in 'ui_components' param. :param title: Custom title to appear in titlebar. :type: str :param ui_components: UI components and values to display, in order. :type: dict :returns: td.containerCOMP instance used as the confirm dialog. """ confirm = td.op(self.app_tdpath + "/controls/confirm") confirm_titlebar_define = td.op(self.app_tdpath + "/controls/confirm/titlebar/define") # set display on all ui components by cross-referencing 'ui_components' [self.__set_display(name, confirm) for name in ui_components.keys()] # populate all ui components self.__populate(ui_components, confirm) # set title confirm_titlebar_define["dialogname", 1] = title # set window height confirm.par.h = self.__calculate_window_height(ui_components, confirm) return confirm.openViewer(unique=False, borders=False)
def _set_pars_from_data(op_path, op_data): """Set target op's parameters from json data. :param op_path: TD path to the target op. :type: str :param op_data: Op data from json. :type: dict :returns: recreation of the original td.OP from current json. """ if isinstance(op_path, td.OP): op_ = op_path else: op_ = td.op(op_path) for par in op_.pars(): # set pars if par.name in op_data["pars"]: par.val = op_data["pars"][par.name] # set nodeCenter op_.nodeCenterX = op_data["nodeCenter"][0] op_.nodeCenterY = op_data["nodeCenter"][1] # set connections for i, output_dict in enumerate(op_data["outputs"]): op_.outputConnectors[i].connect(td.op(output_dict["path"])) for i, input_dict in enumerate(op_data["inputs"]): op_.inputConnectors[i].connect(td.op(input_dict["path"])) return op_
def set_component_remote(): """Open a confirm dialogue to add a new git repo URL to this component.""" remote_name = td.op(UI.app_tdpath + "/controls/confirm/null_name").text remote_url = td.op(UI.app_tdpath + "/controls/confirm/null_url").text title, ui_components = CMPT_UI.set_component_remote( remote_name, remote_url) UI.confirm(title, ui_components)
def _assertWasCreated(self, name, class_): """Return True if a node with the given name exists at the project root. :param class_: <cls> td.Op Class type to create. :param name: <str> Name of the op to look for. """ td.op("/").create(class_, name) op_names = [child.name for child in td.op("/").children] return name in op_names
def _destroy_op(op_tdpath): """Destroy a single op. :param op_tdpath: path to the op to destroy. :type op_tdpath: str """ try: td.op(op_tdpath).destroy() except AttributeError: logging.exception( "{} was missing, skipping delete!".format(op_tdpath))
def __setup(self): """Creates all necessary td-related ops.""" self.placeholder = td.op(str(Path("<user_components>"))).create( td.containerCOMP, self.c.name) self.placeholder.par.clone = str(Path("<placeholder_template>")) self.placeholder.par.align = "verttb" # create a td.tableDAT from selection inside placeholder self.stash_dat = \ self.create_stash_dat(td.op(str(Path("<user_components>")))) self.stash_dat.outputConnectors[0].connect( self.placeholder.inputConnectors[0]) # set dat comment self.stash_dat.comment = 'Created on {0}'.format(self.c.timestamp) # create a selectCOMP where the user made the selection self.select_placeholder = self.parent_op.create( td.selectCOMP, self.c.name) self.select_placeholder.par.selectpanel = \ str(Path("<user_components>")) \ + "/" \ + self.c.name self.select_placeholder.par.selectpanel.readOnly = True self.select_placeholder.viewer = 1 # set the select_placeholder position x, y = self.calculate_placeholder_position() self.select_placeholder.nodeCenterX = x self.select_placeholder.nodeCenterY = y # destroy originally selected ops for data_pack in self.c.selection: self._destroy_op(data_pack["path"]) # assign all controller tableDAT's self.controllers = { "tracked_files": self.placeholder.findChildren(name="tbl_tracked_files")[0], "untracked_files": self.placeholder.findChildren(name="tbl_untracked_files")[0], "modified_files": self.placeholder.findChildren(name="tbl_modified_files")[0], "ops": self.placeholder.findChildren(name="tbl_ops")[0], "git_log": self.placeholder.findChildren(name="tbl_git_log")[0], "git_branches": self.placeholder.findChildren(name="tbl_git_branches")[0], "remotes": self.placeholder.findChildren(name="tbl_remotes")[0] }
def __recursive_recreate(self, target_op, selection): """Recreate new op and nested children-ops from selection-data. :param target_op: Parent to create inside. :type target: td.OP :param data: Data from the json for this op. :type date: dict of properties originally saved to json. :return: A list of recreated op instances. :rtype: list """ import td recreated_list = [] for op_data in selection: op_parent_path = "/".join(op_data["path"].split("/")[:-1]) op_parent = td.op(op_parent_path) # parent recreated_op = self._recreate(op_parent, op_data)[0] # op if op_data.get("children", False): self.__recursive_recreate(recreated_op, op_data["children"]) recreated_list.append(recreated_op) else: recreated_list.append(recreated_op) return recreated_list
def _dock_op(self, op_data): """Dock an op to it's placeholder. :param op_data: the op data dict for the op to dock. :type op_data: ParDict """ op_ = td.op(op_data["path"]) op_.dock = self.select_placeholder
def __populate(self, ui_components, parent): """Set all labels and values for ui components. :param name: <str> Name of ui component. :param dict_: <dict> Dict containing 'label' and 'value' properties. :param parent: <td.Op> Parent Op containing the children to work on. """ if "message" in ui_components: text_dat = td.op(self.app_tdpath + "/controls/confirm/message/text2") text_dat.text = ui_components["message"]["val"] if "ok" in ui_components: define = td.op(self.app_tdpath + "/controls/confirm/ok/define") # bind and call ok button with args define["buttonlabel", 1] = ui_components["ok"]["label"] # store as local variabls to confirm comp self.confirm_locals.update({ "ok": { "callback": ui_components["ok"]["callback"], "args": ui_components["ok"]["args"] } }) if "list": table_list = td.op(self.app_tdpath + "/controls/confirm/table_list") table_list.setSize(0, 1) [ table_list.appendRow(dict__["label"]) for dict__ in ui_components["list"] ] for ui_c_name in ["stringfield_url", "stringfield_name"]: if ui_c_name in ui_components: define = td.op(self.app_tdpath + "/controls/confirm/{}/define".format(ui_c_name)) define["label", 1] = ui_components[ui_c_name]["label"] td.op(self.app_tdpath + "/controls/confirm/{}/string".format(ui_c_name) ).text = ui_components[ui_c_name]["val"]
def staging_area(): """Show the 'staging area' tab.""" LIST_SELECT.par.display = 0 LIST_STAGING_AREA.par.display = 1 LIST_OPS.par.display = 0 LIST_BRANCHES.par.display = 0 # populate tracked files __set_table(td.op("../tbl_tracked_files"), [[osp.basename(f), f] for f in CMPNT.retrieve_tracked_files()]) # populate untracked files __set_table(td.op("../tbl_untracked_files"), [[osp.basename(f), f] for f in CMPNT.retrieve_untracked_files()]) # populate modified files __set_table(td.op("../tbl_modified_files"), [[entry[0], entry[1]] for entry in CMPNT.retrieve_modified_files()])
def __rebuild_connections(selection): """Rebuild the connections of ops from resding the selection ParDict's. :param selection: the selection data to recreate the connections from. :type selection: list """ import td for op_data in selection: op_ = td.op(op_data["path"]) for i, input_tdpath in enumerate(op_data["inputs"]): op_.inputConnectors[i] = td.op(input_tdpath) for i, output_tdpath in enumerate(op_data["outputs"]): op_.outputConnectors[i] = td.op(output_tdpath)
def onOffToOn(panelValue): # very ugly here... tbl_untracked_files = td.op("../../../tbl_untracked_files") full_path = tbl_untracked_files[0, 1].val rel_path = full_path.replace(CMPT_UI.c.repo.working_dir, "") # rel_path = rel_path.replace("\\", "/") if rel_path[0] == os.sep: rel_path = rel_path[1:] return gitAdd(rel_path)
def __set_select(name): """Set the 'select1' selectDAT's 'select' attribute. :param name: the op name to set to. :type name: str """ td.op("../select1").par.dat = name LIST_SELECT.par.display = 1 LIST_STAGING_AREA.par.display = 0 LIST_OPS.par.display = 0 LIST_BRANCHES.par.display = 0
def test_create_op(self): """Test various default Touch Designer op-creation scenarios.""" # validate by searching the root for the op self.assertIsInstance( td.op("/").create(td.containerCOMP), td.containerCOMP) # single character name self.assertTrue( self._assertWasCreated(self._id_generator(1, 1), td.containerCOMP)) # # rediculously large name (using Windows path length limit) self.assertTrue( self._assertWasCreated(self._id_generator(1000, 1000), td.containerCOMP))
def __set_table(table_name, list_): """Map iterable to table rows. :param table_name: the table to map. :type table_name: str :param list_: the list of data to map to the tableDAT rows. :type list_: list """ table = td.op(table_name) table.setSize(0, 1) for item in list_: table.appendRow(item)
def __update_project_preferences_dialogue(self): """needs to be cleaned up.""" # tbl_git_branches self.tbl_git_branches.setSize(0, 1) # reset all btns to hidden for btn in self.branch_btn_grp.values(): btn.par.display = 0 # portion of the row with the branch's name branch_name = td.op(self.app_tdpath + "/controls/list/list/list") if not self.project.repo: self.tbl_git_branches.appendRow("No Repo...") # init self.branch_btn_grp["init"].par.display = 1 branch_name.par.w = branch_name.parent().width \ - self.branch_btn_grp["init"].par.w elif not len(self.project.repo.branches): self.tbl_git_branches.appendRow( self.project.repo.active_branch.name) self.branch_btn_grp["create_branch"].par.display = 1 self.branch_btn_grp["create_branch"].par.w = 128 # change button label self.branch_btn_grp["create_branch"].op( "eval2").par.expr = "\'make initial commit.\'" branch_name.par.w = branch_name.parent().width \ - self.branch_btn_grp["create_branch"].par.w else: # append rows for each branch for branch in self.project.repo.branches: self.tbl_git_branches.appendRow(str(branch)) # turn on button display button_grp_width = 0 for btn_name in ["checkout", "delete"]: btn = self.branch_btn_grp[btn_name] btn.par.display = 1 button_grp_width += btn.par.w # set width branch_name.par.w = branch_name.parent().width \ - button_grp_width
def calculate_placeholder_position(self): """Calculate a position for the placeholder by averaging selected ops. :return: x, y positions :rtype: tuple """ x_sum = 0 y_sum = 0 leftmost = 0 topmost = 0 for op_data in self.c.selection: op_ = td.op(op_data["path"]) x_sum += op_.nodeCenterX y_sum += op_.nodeCenterY leftmost = leftmost if leftmost > op_.nodeX else op_.nodeX topmost = topmost if topmost > op_.nodeY else op_.nodeY mean_x = x_sum / len(self.c.selection) mean_y = y_sum / len(self.c.selection) return int(mean_x), int(mean_y)
"""Set Project Preferences""" import os import re import td tdgam_path = td.op("/local").fetch("tdgam_path") app_ui = td.op(tdgam_path).extensions[1] new_project_folder = td.op("nul_project_root_path").text.strip() new_remote_repo = td.op("nul_project_remote_url").text.strip() # handle relative path if not re.search(r"[a-z]\:", new_remote_repo): new_remote_repo = os.path.join(td.project.folder, new_remote_repo) new_remote_repo = os.path.normpath(new_remote_repo) settings = { "project_folder": new_project_folder, "project_remote_repo_url": new_remote_repo } app_ui.update_settings(settings)
"""Add a remote origin for component repo.""" import td from tdgam import Path # TDGamProjectUI instance UI = td.op(Path("<tdgam>")).ext.UI def onOffToOn(channel, sampleIndex, val, prev): callback = UI.confirm_locals["ok"]["callback"] ok_args = UI.confirm_locals["ok"]["args"] callback(ok_args[0], ok_args[1])
"""Create new git branch.""" import td from tdgam import Path UI = td.op(Path("<tdgam>")).ext.UI CMPT_UI = UI.retrieve_component(td.op("../../..").name) # origin = repo.create_remote('origin', repository) # origin.fetch() UI.git_initial_commit()
def __init__(self, TDGamProject): """Ititialize default UI instance with project repo.""" self.project = TDGamProject self.app_tdpath = td.op("/local").fetch("app_tdpath", "/ui/dialogs/mainmenu/TDGam") btn_row_tdpath = self.app_tdpath + "/controls/list/list/" self.branch_btn_grp = { "checkout": td.op(btn_row_tdpath + "checkout"), "push": td.op(btn_row_tdpath + "push"), "pull": td.op(btn_row_tdpath + "pull"), "delete": td.op(btn_row_tdpath + "delete"), "create_branch": td.op(btn_row_tdpath + "create_branch"), "init": td.op(btn_row_tdpath + "init"), } # data tables used by UI self.tbl_git_branches = td.op("tbl_git_branches") self.tbl_gitLog = td.op("tbl_gitLog") self.tbl_ops = td.op("tbl_ops") self.tbl_preferences = td.op("tbl_preferences") self.confirm_locals = {"ok": None, "cancel": None} self.component_uis = []
"""panelexecuteDAT /ui/dialogs/mainmenu/TDGam/controls/TDGamComponent_ui/menu1/buttontoggle/script """ import td APP = td.op("/ui/dialogs/mainmenu/TDGam").extensions[1] CMPNT = APP.retrieve_component(td.op("../../..").name) def onOffToOn(panel_value): """Commit the added files to this Component's repo.""" message = str(panel_value) commit = None try: commit = CMPNT.repo.git.commit('-m', message) APP.log(commit, "info") except Exception: APP.log("Nothing to commit!", "warning") return commit
"""Menu Handler for components. This script runs each time a user clicks on a menu item. /ui/dialogs/mainmenu/TDGam/controls/TDGamComponent_ui/menu1/script """ import td from tdgam import Path # TDGamProjectUI instance UI = td.op(Path("<tdgam>")).ext.UI # TDGamComponentUI instance CMPT_UI = UI.retrieve_component(td.op("../..").name) # args passed to this textDAT ARGS = globals()["args"] MENU_ID = td.op("id")[0, 0].val SUBMENU_ID = ARGS[0] def set_component_remote(): """Open a confirm dialogue to add a new git repo URL to this component.""" remote_name = td.op(UI.app_tdpath + "/controls/confirm/null_name").text remote_url = td.op(UI.app_tdpath + "/controls/confirm/null_url").text title, ui_components = CMPT_UI.set_component_remote( remote_name, remote_url) UI.confirm(title, ui_components)
args = globals()["args"] SELECTION = args[0] KEY = { "0": "production", "1": "development", "tdpath": { "0": "/ui/dialogs/mainmenu/TDGam", "1": "/TDGam" } } APP_MODE = KEY[SELECTION] APP_TDPATH = KEY["tdpath"][SELECTION] root = td.op("/local") root.store("app_mode", APP_MODE) root.store("tdgam_path", APP_TDPATH) # check if a model instance is present app_model = None if td.op(APP_TDPATH) and td.op(APP_TDPATH).extensions: app_model = td.op(APP_TDPATH).extensions[0] app_model.log("TDGam App Mode set to: {}\n\n\tNow using tdpath: {}".format( td.op("/local").fetch("app_mode").upper(), td.op("/local").fetch("tdgam_path") ), "warning") else: print("TDGam Could not be initialized at: {}!".format(APP_TDPATH))
"""Tabhandler for components. /ui/dialogs/mainmenu/TDGam/controls/TDGamComponent_ui/text_tabhandler """ import os.path as osp import td from tdgam import Path # args given to this textDAT ARGS = globals()["args"] SELECTED_TAB_INDEX = ARGS[0] # tableDAT controllers for the ui LIST_SELECT = td.op("../list") LIST_STAGING_AREA = td.op("../list_staging_area") LIST_OPS = td.op("../list_ops") LIST_BRANCHES = td.op("../list_branches") # TDGamProjectUI instance UI = td.op(Path("<tdgam>")).ext.UI # current component's TDGamComponent instance CMPNT = UI.retrieve_component(td.op("../..").name) def __set_select(name): """Set the 'select1' selectDAT's 'select' attribute. :param name: the op name to set to. :type name: str