Exemple #1
0
 def fbx_choose_button_clicked(self):
     """runs when the FBX push button is clicked
     """
     dialog = QtWidgets.QFileDialog(self.parent, "Choose FBX File")
     result = dialog.getOpenFileName()
     file_path = result[0]
     if file_path:
         self.fbx_file_field.setText(file_path)
Exemple #2
0
 def tde4_lens_distort_node_creator(cls, parent):
     """creates lens distort nodes from the given 3de4 lens file
     """
     # show a file browser
     dialog = QtWidgets.QFileDialog(parent, "Choose file")
     dialog.setNameFilter("3DE4 Lens Files (*.txt)")
     dialog.setFileMode(QtWidgets.QFileDialog.ExistingFile)
     if dialog.exec_():
         file_path = dialog.selectedFiles()[0]
         if not file_path:
             return
         from anima.env.fusion.utils import TDE4LensDistortionImporter
         lens_importer = TDE4LensDistortionImporter()
         lens_importer.import_(file_path)
Exemple #3
0
    def show_context_menu(self, position):
        """the custom context menu
        """
        # convert the position to global screen position
        global_position = self.mapToGlobal(position)

        index = self.indexAt(position)
        model = self.model()
        item = model.itemFromIndex(index)
        logger.debug('itemAt(position) : %s' % item)
        task_id = None
        entity = None

        # if not item:
        #     return

        # if item and not hasattr(item, 'task'):
        #     return

        # from anima.ui.models.task import TaskItem
        # if not isinstance(item, TaskItem):
        #     return

        if item:
            try:
                if item.task:
                    task_id = item.task.id
            except AttributeError:
                return

        # if not task_id:
        #     return

        from anima import utils
        file_browser_name = utils.file_browser_name()

        # create the menu
        menu = QtWidgets.QMenu()  # Open in browser

        # -----------------------------------
        # actions created in different scopes
        create_time_log_action = None
        create_project_action = None
        update_task_action = None
        upload_thumbnail_action = None
        create_child_task_action = None
        duplicate_task_hierarchy_action = None
        delete_task_action = None
        export_to_json_action = None
        import_from_json_action = None
        no_deps_action = None
        create_project_structure_action = None
        create_task_structure_action = None
        update_project_action = None
        assign_users_action = None
        open_in_web_browser_action = None
        open_in_file_browser_action = None
        copy_url_action = None
        copy_id_to_clipboard = None
        fix_task_status_action = None
        change_status_menu_actions = []

        from anima import defaults
        from stalker import LocalSession
        local_session = LocalSession()
        logged_in_user = local_session.logged_in_user

        from stalker import SimpleEntity, Task, Project
        # TODO: Update this to use only task_id
        if task_id:
            entity = SimpleEntity.query.get(task_id)

        reload_action = menu.addAction(u'\uf0e8 Reload')

        # sub menus
        create_sub_menu = menu.addMenu('Create')
        update_sub_menu = menu.addMenu('Update')

        if defaults.is_power_user(logged_in_user):
            # create the Create Project menu item
            create_project_action = \
                create_sub_menu.addAction(u'\uf0e8 Create Project...')

            if isinstance(entity, Project):
                # this is a project!
                if defaults.is_power_user(logged_in_user):
                    update_project_action = \
                        update_sub_menu.addAction(u'\uf044 Update Project...')
                    assign_users_action = \
                        menu.addAction(u'\uf0c0 Assign Users...')
                    create_project_structure_action = \
                        create_sub_menu.addAction(
                            u'\uf115 Create Project Structure'
                        )
                    create_child_task_action = \
                        create_sub_menu.addAction(
                            u'\uf0ae Create Child Task...'
                        )
                    # Export and Import JSON
                    create_sub_menu.addSeparator()
                    # export_to_json_action = \
                    #     create_sub_menu.addAction(u'\uf1f8 Export To JSON...')

                    import_from_json_action = \
                        create_sub_menu.addAction(u'\uf1f8 Import From JSON...')

        if entity:
            # separate the Project and Task related menu items
            menu.addSeparator()

            open_in_web_browser_action = \
                menu.addAction(u'\uf14c Open In Web Browser...')
            open_in_file_browser_action = \
                menu.addAction(u'\uf07c Browse Folders...')
            copy_url_action = menu.addAction(u'\uf0c5 Copy URL')
            copy_id_to_clipboard = \
                menu.addAction(u'\uf0c5 Copy ID to clipboard')

            if isinstance(entity, Task):
                # this is a task
                create_task_structure_action = \
                    create_sub_menu.addAction(
                        u'\uf115 Create Task Folder Structure'
                    )

                task = entity
                from stalker import Status
                status_wfd = Status.query.filter(Status.code == 'WFD').first()
                status_prev = \
                    Status.query.filter(Status.code == 'PREV').first()
                status_cmpl = \
                    Status.query.filter(Status.code == 'CMPL').first()
                if logged_in_user in task.resources \
                        and task.status not in [status_wfd, status_prev,
                                                status_cmpl]:
                    create_sub_menu.addSeparator()
                    create_time_log_action = \
                        create_sub_menu.addAction(u'\uf073 Create TimeLog...')

                # Add Depends To menu
                menu.addSeparator()
                depends = task.depends
                if depends:
                    depends_to_menu = menu.addMenu(u'\uf090 Depends To')

                    for dTask in depends:
                        action = depends_to_menu.addAction(dTask.name)
                        action.task = dTask

                # Add Dependent Of Menu
                dependent_of = task.dependent_of
                if dependent_of:
                    dependent_of_menu = menu.addMenu(u'\uf08b Dependent Of')

                    for dTask in dependent_of:
                        action = dependent_of_menu.addAction(dTask.name)
                        action.task = dTask

                if not depends and not dependent_of:
                    no_deps_action = menu.addAction(u'\uf00d No Dependencies')
                    no_deps_action.setEnabled(False)

                # update task and create child task menu items
                menu.addSeparator()
                if defaults.is_power_user(logged_in_user):
                    create_sub_menu.addSeparator()
                    update_task_action = \
                        update_sub_menu.addAction(u'\uf044 Update Task...')

                    upload_thumbnail_action = \
                        update_sub_menu.addAction(
                            u'\uf03e Upload Thumbnail...'
                        )

                    # Export and Import JSON
                    create_sub_menu.addSeparator()
                    export_to_json_action = \
                        create_sub_menu.addAction(u'\uf1f8 Export To JSON...')

                    import_from_json_action = \
                        create_sub_menu.addAction(u'\uf1f8 Import From JSON...')
                    create_sub_menu.addSeparator()

                    create_child_task_action = \
                        create_sub_menu.addAction(
                            u'\uf0ae Create Child Task...'
                        )

                    duplicate_task_hierarchy_action = \
                        create_sub_menu.addAction(
                            u'\uf0c5 Duplicate Task Hierarchy...'
                        )
                    delete_task_action = \
                        menu.addAction(u'\uf1f8 Delete Task...')

                    menu.addSeparator()

                # create the status_menu
                status_menu = update_sub_menu.addMenu('Status')

                fix_task_status_action = \
                    status_menu.addAction(u'\uf0e8 Fix Task Status')

                assert isinstance(status_menu, QtWidgets.QMenu)
                status_menu.addSeparator()

                # get all task statuses
                from anima import defaults

                menu_style_sheet = ''
                defaults_status_colors = defaults.status_colors
                for status_code in defaults.status_colors:
                    change_status_menu_action = \
                        status_menu.addAction(status_code)

                    change_status_menu_action.setObjectName(
                        'status_%s' % status_code
                    )

                    change_status_menu_actions.append(
                        change_status_menu_action
                    )

                    menu_style_sheet = "%s %s" % (
                        menu_style_sheet,
                        "QMenu#status_%s { background: %s %s %s}" %
                        (
                            status_code,
                            defaults_status_colors[status_code][0],
                            defaults_status_colors[status_code][1],
                            defaults_status_colors[status_code][2],
                        )
                    )

                # change the BG Color of the status
                status_menu.setStyleSheet(menu_style_sheet)

        try:
            # PySide and PySide2
            accepted = QtWidgets.QDialog.DialogCode.Accepted
        except AttributeError:
            # PyQt4
            accepted = QtWidgets.QDialog.Accepted

        selected_item = menu.exec_(global_position)
        if selected_item:
            if selected_item is reload_action:
                if isinstance(entity, Project):
                    self.fill()
                    self.find_and_select_entity_item(item.task)
                else:
                    item.reload()

            if create_project_action \
               and selected_item is create_project_action:
                from anima.ui import project_dialog
                project_main_dialog = project_dialog.MainDialog(
                    parent=self,
                    project=None
                )
                project_main_dialog.exec_()
                result = project_main_dialog.result()

                # refresh the task list
                if result == accepted:
                    self.fill()

                project_main_dialog.deleteLater()

            if entity:
                from anima import defaults
                url = 'http://%s/%ss/%s/view' % (
                    defaults.stalker_server_internal_address,
                    entity.entity_type.lower(),
                    entity.id
                )

                if selected_item is open_in_web_browser_action:
                    import webbrowser
                    webbrowser.open(url)
                elif selected_item is open_in_file_browser_action:
                    from anima import utils
                    try:
                        utils.open_browser_in_location(entity.absolute_path)
                    except IOError as e:
                        QtWidgets.QMessageBox.critical(
                            self,
                            "Error",
                            "%s" % e,
                            QtWidgets.QMessageBox.Ok
                        )
                elif selected_item is copy_url_action:
                    clipboard = QtWidgets.QApplication.clipboard()
                    clipboard.setText(url)

                    # and warn the user about a new version is created and the
                    # clipboard is set to the new version full path
                    QtWidgets.QMessageBox.warning(
                        self,
                        "URL Copied To Clipboard",
                        "URL:<br><br>%s<br><br>is copied to clipboard!" %
                        url,
                        QtWidgets.QMessageBox.Ok
                    )
                elif selected_item is copy_id_to_clipboard:
                    clipboard = QtWidgets.QApplication.clipboard()
                    clipboard.setText('%s' % entity.id)

                    # and warn the user about a new version is created and the
                    # clipboard is set to the new version full path
                    QtWidgets.QMessageBox.warning(
                        self,
                        "ID Copied To Clipboard",
                        "ID %s is copied to clipboard!" % entity.id,
                        QtWidgets.QMessageBox.Ok
                    )

                elif selected_item is create_time_log_action:
                    from anima.ui import time_log_dialog
                    time_log_dialog_main_dialog = time_log_dialog.MainDialog(
                        parent=self,
                        task=entity,
                    )
                    time_log_dialog_main_dialog.exec_()
                    result = time_log_dialog_main_dialog.result()
                    time_log_dialog_main_dialog.deleteLater()

                    if result == accepted:
                        # refresh the task list
                        if item.parent:
                            item.parent.reload()
                        else:
                            self.fill()

                        # reselect the same task
                        self.find_and_select_entity_item(entity)

                elif selected_item is update_task_action:
                    from anima.ui import task_dialog
                    task_main_dialog = task_dialog.MainDialog(
                        parent=self,
                        task=entity
                    )
                    task_main_dialog.exec_()
                    result = task_main_dialog.result()
                    task_main_dialog.deleteLater()

                    # refresh the task list
                    if result == accepted:
                        # just reload the same item
                        if item.parent:
                            item.parent.reload()
                        else:
                            # reload the entire
                            self.fill()
                        self.find_and_select_entity_item(entity)

                elif selected_item is upload_thumbnail_action:
                    from anima.ui import utils as ui_utils
                    thumbnail_full_path = ui_utils.choose_thumbnail(self)

                    # if the thumbnail_full_path is empty do not do anything
                    if thumbnail_full_path == "":
                        return

                    # get the current task
                    ui_utils.upload_thumbnail(entity, thumbnail_full_path)

                elif selected_item is create_child_task_action:
                    from anima.ui import task_dialog
                    task_main_dialog = task_dialog.MainDialog(
                        parent=self,
                        parent_task=entity
                    )
                    task_main_dialog.exec_()
                    result = task_main_dialog.result()
                    task = task_main_dialog.task
                    task_main_dialog.deleteLater()

                    if result == accepted and task:
                        # reload the parent item
                        if item.parent:
                            item.parent.reload()
                        else:
                            self.fill()
                        self.find_and_select_entity_item(task)

                elif selected_item is duplicate_task_hierarchy_action:
                    duplicate_task_hierarchy_dialog = \
                        DuplicateTaskHierarchyDialog(
                            parent=self, duplicated_task_name=item.task.name
                        )
                    duplicate_task_hierarchy_dialog.exec_()

                    result = duplicate_task_hierarchy_dialog.result()
                    if result == accepted:
                        new_task_name = \
                            duplicate_task_hierarchy_dialog.line_edit.text()

                        keep_resources = \
                            duplicate_task_hierarchy_dialog\
                                .check_box.checkState()

                        from anima import utils
                        from stalker import Task
                        task = Task.query.get(item.task.id)
                        new_task = utils.duplicate_task_hierarchy(
                            task,
                            None,
                            new_task_name,
                            description='Duplicated from Task(%s)' % task.id,
                            user=logged_in_user,
                            keep_resources=keep_resources
                        )
                        if new_task:
                            from stalker.db.session import DBSession
                            DBSession.commit()
                            item.parent.reload()
                            self.find_and_select_entity_item(new_task)

                elif selected_item is delete_task_action:
                    answer = QtWidgets.QMessageBox.question(
                        self,
                        'Delete Task?',
                        "Delete the task and children?<br><br>(NO UNDO!!!!)",
                        QtWidgets.QMessageBox.Yes,
                        QtWidgets.QMessageBox.No
                    )
                    if answer == QtWidgets.QMessageBox.Yes:
                        from stalker.db.session import DBSession
                        from stalker import Task
                        task = Task.query.get(item.task.id)
                        DBSession.delete(task)
                        DBSession.commit()
                        # reload the parent
                        if item.parent:
                            item.parent.reload()
                        else:
                            self.fill()
                        self.find_and_select_entity_item(item.parent.task)

                elif selected_item is export_to_json_action:
                    # show a file browser
                    dialog = QtWidgets.QFileDialog(self, "Choose file")
                    dialog.setNameFilter("JSON Files (*.json)")
                    dialog.setFileMode(QtWidgets.QFileDialog.AnyFile)
                    if dialog.exec_():
                        file_path = dialog.selectedFiles()[0]
                        if file_path:
                            import os
                            import json
                            from anima.utils import task_hierarchy_io

                            # check file extension
                            parts = os.path.splitext(file_path)

                            if not parts[1]:
                                file_path = '%s%s' % (parts[0], '.json')

                            data = json.dumps(
                                entity,
                                cls=task_hierarchy_io.StalkerEntityEncoder,
                                check_circular=False,
                                indent=4
                            )
                            try:
                                with open(file_path, 'w') as f:
                                    f.write(data)
                            except Exception as e:
                                pass
                            finally:
                                QtWidgets.QMessageBox.information(
                                    self,
                                    'Task data Export to JSON!',
                                    'Task data Export to JSON!',
                                )

                elif selected_item is import_from_json_action:
                    # show a file browser
                    dialog = QtWidgets.QFileDialog(self, "Choose file")
                    dialog.setNameFilter("JSON Files (*.json)")
                    dialog.setFileMode(QtWidgets.QFileDialog.ExistingFile)
                    if dialog.exec_():
                        file_path = dialog.selectedFiles()[0]
                        if file_path:
                            import json
                            with open(file_path) as f:
                                data = json.load(f)
                            from anima.utils import task_hierarchy_io
                            if isinstance(entity, Task):
                                project = entity.project
                            elif isinstance(entity, Project):
                                project = entity

                            parent = None
                            if isinstance(entity, Task):
                                parent = entity

                            decoder = \
                                task_hierarchy_io.StalkerEntityDecoder(
                                    project=project
                                )
                            loaded_entity = decoder.loads(data, parent=parent)

                            try:
                                from stalker.db.session import DBSession
                                DBSession.add(loaded_entity)
                                DBSession.commit()
                            except Exception as e:
                                QtWidgets.QMessageBox.critical(
                                    self,
                                    "Error!",
                                    "%s" % e,
                                    QtWidgets.QMessageBox.Ok
                                )
                            else:
                                item.reload()
                                QtWidgets.QMessageBox.information(
                                    self,
                                    'New Tasks are created!',
                                    'New Tasks are created',
                                )

                elif selected_item is create_project_structure_action:
                    answer = QtWidgets.QMessageBox.question(
                        self,
                        'Create Project Folder Structure?',
                        "This will create project folders, OK?",
                        QtWidgets.QMessageBox.Yes,
                        QtWidgets.QMessageBox.No
                    )
                    if answer == QtWidgets.QMessageBox.Yes:
                        from anima import utils
                        try:
                            utils.create_project_structure(entity)
                        except Exception as e:
                            pass
                        finally:
                            QtWidgets.QMessageBox.information(
                                self,
                                'Project Folder Structure is created!',
                                'Project Folder Structure is created!',
                            )
                    else:
                        return

                elif selected_item is create_task_structure_action:
                    answer = QtWidgets.QMessageBox.question(
                        self,
                        'Create Folder Structure?',
                        "This will create task folders, OK?",
                        QtWidgets.QMessageBox.Yes,
                        QtWidgets.QMessageBox.No
                    )
                    if answer == QtWidgets.QMessageBox.Yes:
                        from anima import utils
                        try:
                            utils.create_task_structure(entity)
                        except Exception as e:
                            pass
                        finally:
                            QtWidgets.QMessageBox.information(
                                self,
                                'Folder Structure is created!',
                                'Folder Structure is created!',
                            )
                    else:
                        return

                elif selected_item is fix_task_status_action:
                    from stalker import Task
                    if isinstance(entity, Task):
                        from anima import utils
                        utils.fix_task_statuses(entity)

                        from stalker.db.session import DBSession
                        DBSession.add(entity)
                        DBSession.commit()

                        if item.parent:
                            item.parent.reload()

                elif selected_item is update_project_action:
                    from anima.ui import project_dialog
                    project_main_dialog = project_dialog.MainDialog(
                        parent=self,
                        project=entity
                    )
                    project_main_dialog.exec_()
                    result = project_main_dialog.result()

                    # refresh the task list
                    if result == accepted:
                        self.fill()

                        # reselect the same task
                        self.find_and_select_entity_item(entity)

                    project_main_dialog.deleteLater()

                elif selected_item is assign_users_action:
                    from anima.ui import project_users_dialog
                    project_users_main_dialog = \
                        project_users_dialog.MainDialog(
                            parent=self,
                            project=entity
                        )
                    project_users_main_dialog.exec_()
                    result = project_users_main_dialog.result()

                    project_users_main_dialog.deleteLater()

                elif selected_item in change_status_menu_actions:
                    # get the status code
                    status_code = selected_item.text()

                    from sqlalchemy import func
                    status = \
                        Status.query.filter(
                            func.lower(Status.code) == func.lower(status_code)
                        ).first()

                    # change the status of the entity
                    # if it is a leaf task
                    # if it doesn't have any dependent_of
                    # assert isinstance(entity, Task)
                    if isinstance(entity, Task):
                        if entity.is_leaf and not entity.dependent_of:
                            # then we can update it
                            entity.status = status

                            # # fix other task statuses
                            # from anima import utils
                            # utils.fix_task_statuses(entity)

                            # refresh the tree
                            from stalker.db.session import DBSession
                            DBSession.add(entity)
                            DBSession.commit()

                            if item.parent:
                                item.parent.reload()
                                self.find_and_select_entity_item(entity)
                else:
                    try:
                        # go to the dependencies
                        dep_task = selected_item.task
                        self.find_and_select_entity_item(
                            dep_task,
                            self
                        )
                    except AttributeError:
                        pass