diff --git a/pype/widgets/project_settings.py b/pype/widgets/project_settings.py new file mode 100644 index 0000000000..98c97b4885 --- /dev/null +++ b/pype/widgets/project_settings.py @@ -0,0 +1,498 @@ + + +from app import style +from avalon.vendor.Qt import QtCore, QtGui, QtWidgets +import os +import getpass +import platform + +import ftrack_api + + +# object symbol + + +class Project_name_getUI(QtWidgets.QWidget): + ''' + Project setting ui: here all the neceserry ui widgets are created + they are going to be used i later proces for dynamic linking of project + in list to project's attributes + ''' + + def __init__(self, parent=None): + super(Project_name_getUI, self).__init__(parent) + + self.platform = platform.system() + self.new_index = 0 + # get projects from ftrack + self.session = ftrack_api.Session() + self.projects_from_ft = self.session.query( + 'Project where status is active') + self.disks_from_ft = self.session.query('Disk') + self.schemas_from_ft = self.session.query('ProjectSchema') + self.projects = self._get_projects_ftrack() + + # define window geometry + self.setWindowTitle('Set project attributes') + self.setWindowFlags(QtCore.Qt.WindowStaysOnTopHint) + self.resize(550, 340) + self.setStyleSheet(style.load_stylesheet()) + + # define disk combobox widget + self.disks = self._get_all_disks() + self.disk_combobox_label = QtWidgets.QLabel('Destination storage:') + self.disk_combobox = QtWidgets.QComboBox() + + # define schema combobox widget + self.schemas = self._get_all_schemas() + self.schema_combobox_label = QtWidgets.QLabel('Project schema:') + self.schema_combobox = QtWidgets.QComboBox() + + # define fps widget + self.fps_label = QtWidgets.QLabel('Fps:') + self.fps_label.setAlignment( + QtCore.Qt.AlignRight | QtCore.Qt.AlignVCenter) + self.fps = QtWidgets.QLineEdit() + + # define project dir widget + self.project_dir_label = QtWidgets.QLabel('Project dir:') + self.project_dir_label.setAlignment( + QtCore.Qt.AlignRight | QtCore.Qt.AlignVCenter) + self.project_dir = QtWidgets.QLineEdit() + + self.project_path_label = QtWidgets.QLabel( + 'Project_path (if not then created):') + self.project_path_label.setAlignment( + QtCore.Qt.AlignHCenter | QtCore.Qt.AlignVCenter) + project_path_font = QtGui.QFont( + "Helvetica [Cronyx]", 12, QtGui.QFont.Bold) + self.project_path = QtWidgets.QLabel() + self.project_path.setObjectName('nom_plan_label') + self.project_path.setStyleSheet( + 'QtWidgets.QLabel#nom_plan_label {color: red}') + self.project_path.setAlignment( + QtCore.Qt.AlignHCenter | QtCore.Qt.AlignVCenter) + self.project_path.setFont(project_path_font) + + # define handles widget + self.handles_label = QtWidgets.QLabel('Handles:') + self.handles_label.setAlignment( + QtCore.Qt.AlignRight | QtCore.Qt.AlignVCenter) + self.handles = QtWidgets.QLineEdit() + + # define resolution widget + self.resolution_w_label = QtWidgets.QLabel('W:') + self.resolution_w = QtWidgets.QLineEdit() + self.resolution_h_label = QtWidgets.QLabel('H:') + self.resolution_h = QtWidgets.QLineEdit() + + devider = QtWidgets.QFrame() + # devider.Shape(QFrame.HLine) + devider.setFrameShape(QtWidgets.QFrame.HLine) + devider.setFrameShadow(QtWidgets.QFrame.Sunken) + + self.generate_lines() + + # define push buttons + self.set_pushbutton = QtWidgets.QPushButton('Set project') + self.cancel_pushbutton = QtWidgets.QPushButton('Cancel') + + # definition of layouts + ############################################ + action_layout = QtWidgets.QHBoxLayout() + action_layout.addWidget(self.set_pushbutton) + action_layout.addWidget(self.cancel_pushbutton) + + # schema property + schema_layout = QtWidgets.QGridLayout() + schema_layout.addWidget(self.schema_combobox, 0, 1) + schema_layout.addWidget(self.schema_combobox_label, 0, 0) + + # storage property + storage_layout = QtWidgets.QGridLayout() + storage_layout.addWidget(self.disk_combobox, 0, 1) + storage_layout.addWidget(self.disk_combobox_label, 0, 0) + + # fps property + fps_layout = QtWidgets.QGridLayout() + fps_layout.addWidget(self.fps, 1, 1) + fps_layout.addWidget(self.fps_label, 1, 0) + + # project dir property + project_dir_layout = QtWidgets.QGridLayout() + project_dir_layout.addWidget(self.project_dir, 1, 1) + project_dir_layout.addWidget(self.project_dir_label, 1, 0) + + # project path property + project_path_layout = QtWidgets.QGridLayout() + spacer_1_item = QtWidgets.QSpacerItem(10, 10) + project_path_layout.addItem(spacer_1_item, 0, 1) + project_path_layout.addWidget(self.project_path_label, 1, 1) + project_path_layout.addWidget(self.project_path, 2, 1) + spacer_2_item = QtWidgets.QSpacerItem(20, 20) + project_path_layout.addItem(spacer_2_item, 3, 1) + + # handles property + handles_layout = QtWidgets.QGridLayout() + handles_layout.addWidget(self.handles, 1, 1) + handles_layout.addWidget(self.handles_label, 1, 0) + + # resolution property + resolution_layout = QtWidgets.QGridLayout() + resolution_layout.addWidget(self.resolution_w_label, 1, 1) + resolution_layout.addWidget(self.resolution_w, 2, 1) + resolution_layout.addWidget(self.resolution_h_label, 1, 2) + resolution_layout.addWidget(self.resolution_h, 2, 2) + + # form project property layout + p_layout = QtWidgets.QGridLayout() + p_layout.addLayout(storage_layout, 1, 0) + p_layout.addLayout(schema_layout, 2, 0) + p_layout.addLayout(project_dir_layout, 3, 0) + p_layout.addLayout(fps_layout, 4, 0) + p_layout.addLayout(handles_layout, 5, 0) + p_layout.addLayout(resolution_layout, 6, 0) + p_layout.addWidget(devider, 7, 0) + spacer_item = QtWidgets.QSpacerItem( + 150, + 40, + QtWidgets.QSizePolicy.Minimum, + QtWidgets.QSizePolicy.Expanding + ) + p_layout.addItem(spacer_item, 8, 0) + + # form with list to one layout with project property + list_layout = QtWidgets.QGridLayout() + list_layout.addLayout(p_layout, 1, 0) + list_layout.addWidget(self.listWidget, 1, 1) + + root_layout = QtWidgets.QVBoxLayout() + root_layout.addLayout(project_path_layout) + root_layout.addWidget(devider) + root_layout.addLayout(list_layout) + root_layout.addLayout(action_layout) + + self.setLayout(root_layout) + + def generate_lines(self): + ''' + Will generate lines of project list + ''' + + self.listWidget = QtWidgets.QListWidget() + for self.index, p in enumerate(self.projects): + item = QtWidgets.QListWidgetItem("{full_name}".format(**p)) + # item.setSelected(False) + self.listWidget.addItem(item) + print(self.listWidget.indexFromItem(item)) + # self.listWidget.setCurrentItem(self.listWidget.itemFromIndex(1)) + + # add options to schemas widget + self.schema_combobox.addItems(self.schemas) + + # add options to disk widget + self.disk_combobox.addItems(self.disks) + + # populate content of project info widgets + self.projects[1] = self._fill_project_attributes_widgets(p, None) + + def _fill_project_attributes_widgets(self, p=None, index=None): + ''' + will generate actual informations wich are saved on ftrack + ''' + + if index is None: + self.new_index = 1 + + if not p: + pass + # change schema selection + for i, schema in enumerate(self.schemas): + if p['project_schema']['name'] in schema: + break + self.schema_combobox.setCurrentIndex(i) + + disk_name, disk_path = self._build_disk_path() + for i, disk in enumerate(self.disks): + if disk_name in disk: + break + # change disk selection + self.disk_combobox.setCurrentIndex(i) + + # change project_dir selection + if "{root}".format(**p): + self.project_dir.setPlaceholderText("{root}".format(**p)) + else: + print("not root so it was replaced with name") + self.project_dir.setPlaceholderText("{name}".format(**p)) + p['root'] = p['name'] + + # set project path to show where it will be created + self.project_path.setText( + os.path.join(self.disks[i].split(' ')[-1], + self.project_dir.text())) + + # change fps selection + self.fps.setPlaceholderText("{custom_attributes[fps]}".format(**p)) + + # change handles selection + self.handles.setPlaceholderText( + "{custom_attributes[handles]}".format(**p)) + + # change resolution selection + self.resolution_w.setPlaceholderText( + "{custom_attributes[resolution_width]}".format(**p)) + self.resolution_h.setPlaceholderText( + "{custom_attributes[resolution_height]}".format(**p)) + + self.update_disk() + + return p + + def fix_project_path_literals(self, dir): + return dir.replace(' ', '_').lower() + + def update_disk(self): + disk = self.disk_combobox.currentText().split(' ')[-1] + + dir = self.project_dir.text() + if not dir: + dir = "{root}".format(**self.projects[self.new_index]) + self.projects[self.new_index]['project_path'] = os.path.normpath( + self.fix_project_path_literals(os.path.join(disk, dir))) + else: + self.projects[self.new_index]['project_path'] = os.path.normpath( + self.fix_project_path_literals(os.path.join(disk, dir))) + + self.projects[self.new_index]['disk'] = self.disks_from_ft[ + self.disk_combobox.currentIndex()] + self.projects[self.new_index]['disk_id'] = self.projects[ + self.new_index]['disk']['id'] + + # set project path to show where it will be created + self.project_path.setText( + self.projects[self.new_index]['project_path']) + + def update_resolution(self): + # update all values in resolution + if self.resolution_w.text(): + self.projects[self.new_index]['custom_attributes'][ + 'resolution_width'] = int(self.resolution_w.text()) + if self.resolution_h.text(): + self.projects[self.new_index]['custom_attributes'][ + 'resolution_height'] = int(self.resolution_h.text()) + + def _update_attributes_by_list_selection(self): + # generate actual selection index + self.new_index = self.listWidget.currentRow() + self.project_dir.setText('') + self.fps.setText('') + self.handles.setText('') + self.resolution_w.setText('') + self.resolution_h.setText('') + + # update project properities widgets and write changes + # into project dictionaries + self.projects[self.new_index] = self._fill_project_attributes_widgets( + self.projects[self.new_index], self.new_index) + + self.update_disk() + + def _build_disk_path(self): + if self.platform == "Windows": + print(self.projects[self.index].keys()) + print(self.projects[self.new_index]['disk']) + return self.projects[self.new_index]['disk'][ + 'name'], self.projects[self.new_index]['disk']['windows'] + else: + return self.projects[self.new_index]['disk'][ + 'name'], self.projects[self.new_index]['disk']['unix'] + + def _get_all_schemas(self): + schemas_list = [] + + for s in self.schemas_from_ft: + # print d.keys() + # if 'Pokus' in s['name']: + # continue + schemas_list.append('{}'.format(s['name'])) + print("\nschemas in ftrack: {}\n".format(schemas_list)) + return schemas_list + + def _get_all_disks(self): + disks_list = [] + for d in self.disks_from_ft: + # print d.keys() + if self.platform == "Windows": + if 'Local drive' in d['name']: + d['windows'] = os.path.join(d['windows'], + os.getenv('USERNAME') + or os.getenv('USER') + or os.getenv('LOGNAME')) + disks_list.append('"{}" at {}'.format(d['name'], d['windows'])) + else: + if 'Local drive' in d['name']: + d['unix'] = os.path.join(d['unix'], getpass.getuser()) + disks_list.append('"{}" at {}'.format(d['name'], d['unix'])) + return disks_list + + def _get_projects_ftrack(self): + + projects_lst = [] + for project in self.projects_from_ft: + # print project.keys() + projects_dict = {} + + for k in project.keys(): + ''' # TODO: delete this in production version ''' + + # if 'test' not in project['name']: + # continue + + # print '{}: {}\n'.format(k, project[k]) + + if '_link' == k: + # print project[k] + content = project[k] + for kc in content[0].keys(): + if content[0]['name']: + content[0][kc] = content[0][kc].encode( + 'ascii', 'ignore').decode('ascii') + print('{}: {}\n'.format(kc, content[0][kc])) + projects_dict[k] = content + print(project[k]) + print(projects_dict[k]) + elif 'root' == k: + print('{}: {}\n'.format(k, project[k])) + projects_dict[k] = project[k] + elif 'disk' == k: + print('{}: {}\n'.format(k, project[k])) + projects_dict[k] = project[k] + elif 'name' == k: + print('{}: {}\n'.format(k, project[k])) + projects_dict[k] = project[k].encode( + 'ascii', 'ignore').decode('ascii') + elif 'disk_id' == k: + print('{}: {}\n'.format(k, project[k])) + projects_dict[k] = project[k] + elif 'id' == k: + print('{}: {}\n'.format(k, project[k])) + projects_dict[k] = project[k] + elif 'full_name' == k: + print('{}: {}\n'.format(k, project[k])) + projects_dict[k] = project[k].encode( + 'ascii', 'ignore').decode('ascii') + elif 'project_schema_id' == k: + print('{}: {}\n'.format(k, project[k])) + projects_dict[k] = project[k] + elif 'project_schema' == k: + print('{}: {}\n'.format(k, project[k])) + projects_dict[k] = project[k] + elif 'custom_attributes' == k: + print('{}: {}\n'.format(k, project[k])) + projects_dict[k] = project[k] + else: + pass + + if projects_dict: + projects_lst.append(projects_dict) + + return projects_lst + + +class Project_name_get(Project_name_getUI): + def __init__(self, parent=None): + super(Project_name_get, self).__init__(parent) + # self.input_project_name.textChanged.connect(self.input_project_name.placeholderText) + + self.set_pushbutton.clicked.connect(lambda: self.execute()) + self.cancel_pushbutton.clicked.connect(self.close) + + self.listWidget.itemSelectionChanged.connect( + self._update_attributes_by_list_selection) + self.disk_combobox.currentIndexChanged.connect(self.update_disk) + self.schema_combobox.currentIndexChanged.connect(self.update_schema) + self.project_dir.textChanged.connect(self.update_disk) + self.fps.textChanged.connect(self.update_fps) + self.handles.textChanged.connect(self.update_handles) + self.resolution_w.textChanged.connect(self.update_resolution) + self.resolution_h.textChanged.connect(self.update_resolution) + + def update_handles(self): + self.projects[self.new_index]['custom_attributes']['handles'] = int( + self.handles.text()) + + def update_fps(self): + self.projects[self.new_index]['custom_attributes']['fps'] = int( + self.fps.text()) + + def update_schema(self): + self.projects[self.new_index]['project_schema'] = self.schemas_from_ft[ + self.schema_combobox.currentIndex()] + self.projects[self.new_index]['project_schema_id'] = self.projects[ + self.new_index]['project_schema']['id'] + + def execute(self): + # import ft_utils + # import hiero + # get the project which has been selected + print("well and what") + # set the project as context and create entity + # entity is task created with the name of user which is creating it + + # get the project_path and create dir if there is not any + print(self.projects[self.new_index]['project_path'].replace( + self.disk_combobox.currentText().split(' ')[-1].lower(), '')) + + # get the schema and recreate a starting project regarding the selection + # set_hiero_template(project_schema=self.projects[self.new_index][ + # 'project_schema']['name']) + + # set all project properities + # project = hiero.core.Project() + # project.setFramerate( + # int(self.projects[self.new_index]['custom_attributes']['fps'])) + # project.projectRoot() + # print 'handles: {}'.format(self.projects[self.new_index]['custom_attributes']['handles']) + # print 'resolution_width: {}'.format(self.projects[self.new_index]['custom_attributes']['resolution_width']) + # print 'resolution_width: {}'.format(self.projects[self.new_index]['custom_attributes']['resolution_height']) + # print "<< {}".format(self.projects[self.new_index]) + + # get path for the hrox file + # root = context.data('ftrackData')['Project']['root'] + # hrox_script_path = ft_utils.getPathsYaml(taskid, templateList=templates, root=root) + + # save the hrox into the correct path + self.session.commit() + self.close() + +# +# def set_hiero_template(project_schema=None): +# import hiero +# hiero.core.closeAllProjects() +# hiero_plugin_path = [ +# p for p in os.environ['HIERO_PLUGIN_PATH'].split(';') +# if 'hiero_plugin_path' in p +# ][0] +# path = os.path.normpath( +# os.path.join(hiero_plugin_path, 'Templates', project_schema + '.hrox')) +# print('---> path to template: {}'.format(path)) +# return hiero.core.openProject(path) + + +# def set_out_ft_session(): +# session = ftrack_api.Session() +# projects_to_ft = session.query('Project where status is active') + + +def main(): + import sys + app = QtWidgets.QApplication(sys.argv) + panel = Project_name_get() + panel.show() + + sys.exit(app.exec_()) + + +if __name__ == "__main__": + main()