예제 #1
0
def create_flat_button(
    icon=None,
    icon_size=None,
    name='',
    text=200,
    background_color=[54, 51, 51],
    ui_color=68,
    border_color=180,
    push_col=120,
    checkable=True,
    w_max=None,
    w_min=None,
    h_max=None,
    h_min=None,
    policy=None,
    tip=None,
    flat=True,
    hover=True,
    destroy_flag=False,
    context=None,
):

    btn = QPushButton()
    btn.setText(name)
    btn.setCheckable(checkable)
    if icon:
        if isinstance(icon, QIcon):
            btn.setIcon(icon)
        else:
            btn.setIcon(QIcon(icon))
    btn.setFlat(flat)
    if flat:
        change_button_color(button=btn,
                            text_color=text,
                            bg_color=ui_color,
                            hi_color=background_color,
                            mode='button',
                            hover=hover,
                            destroy=destroy_flag,
                            ds_color=border_color)
        btn.toggled.connect(
            lambda: change_button_color(button=btn,
                                        text_color=text,
                                        bg_color=ui_color,
                                        hi_color=background_color,
                                        mode='button',
                                        toggle=True,
                                        hover=hover,
                                        destroy=destroy_flag,
                                        ds_color=border_color))
    else:
        change_button_color(button=btn,
                            text_color=text,
                            bg_color=background_color,
                            hi_color=push_col,
                            mode='button',
                            hover=hover,
                            destroy=destroy_flag,
                            ds_color=border_color)

    if w_max:
        btn.setMaximumWidth(w_max)
    if w_min:
        btn.setMinimumWidth(w_min)
    if h_max:
        btn.setMaximumHeight(h_max)
    if h_min:
        btn.setMinimumHeight(h_min)
    if icon_size:
        btn.setIconSize(QSize(*icon_size))
    if policy:
        btn.setSizePolicy(QSizePolicy.Minimum, QSizePolicy.Expanding)
    if tip:
        btn.setToolTip(tip)
    if context:
        btn.setContextMenuPolicy(Qt.CustomContextMenu)
        btn.customContextMenuRequested.connect(context)

    return btn
예제 #2
0
class WindowStatusBar(statusbar.StatusWidget, object):
    def __init__(self, parent=None):
        super(WindowStatusBar, self).__init__(parent)

        self._info_url = None
        self._tool = None

        self.setFixedHeight(25)
        self._info_btn = QPushButton()
        self._info_btn.setIconSize(QSize(25, 25))
        self._info_btn.setSizePolicy(QSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed))
        self._info_btn.setIcon(resources.icon('info1'))
        self._info_btn.setStyleSheet('QWidget {background-color: rgba(255, 255, 255, 0); border:0px;}')

        self._bug_btn = QPushButton()
        self._bug_btn.setIconSize(QSize(25, 25))
        self._bug_btn.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed)
        self._bug_btn.setIcon(resources.icon('bug'))
        self._bug_btn.setStyleSheet('QWidget {background-color: rgba(255, 255, 255, 0); border:0px;}')

        self.main_layout.insertWidget(0, self._info_btn)
        self.main_layout.insertWidget(1, self._bug_btn)

        self._info_btn.clicked.connect(self._on_open_url)
        self._bug_btn.clicked.connect(self._on_send_bug)

    def set_info_url(self, url):
        """
        Sets the URL used to open tool info documentation web
        :param url: str
        """

        self._info_url = url

    def set_tool(self, tool):
        """

        :param tool:
        :return:
        """

        self._tool = tool

    def has_url(self):
        """
        Returns whether the URL documentation web is set or not
        :return: bool
        """

        if self._info_url:
            return True

        return False

    def has_tool(self):
        """
        Returns whether window has a tool attached or not
        :return: bool
        """

        if self._tool:
            return True

        return False

    def show_info(self):
        """
        Shows the info button of the status bar
        """

        self._info_btn.setVisible(True)

    def hide_info(self):
        """
        Hides the info button of the status bar
        """

        self._info_btn.setVisible(False)

    def show_bug(self):
        self._bug_btn.setVisible(True)

    def hide_bug(self):
        self._bug_btn.setVisible(False)

    def open_info_url(self):
        """
        Opens tool documentation URL in user web browser
        """

        if not self._project:
            return False

        if self._info_url:
            webbrowser.open_new_tab(self._info_url)

    def _on_send_bug(self):

        if not self._project:
            return False

        # tools.ToolsManager().run_tool(self._project, 'bugtracker', extra_args={'tool': self._tool})

    def _on_open_url(self):
        """
        Internal callback function that is called when the user presses the info icon button
        :return:
        """

        self.open_info_url()
예제 #3
0
class Badge(base.BaseWidget, object):
    """
    Widget that can be located near notification or user avatars to display unread messages count
    We support 3 types of styles:
        1. dof: show a dot
        2. count: show a number
        3. text: show a string
    """
    def __init__(self, widget=None, parent=None):

        self._dot = None
        self._text = None
        self._count = None
        self._widget = widget
        self._overflow_count = 99

        super(Badge, self).__init__(parent=parent)

    # =================================================================================================================
    # PROPERTIES
    # =================================================================================================================

    @property
    def overflow(self):
        """
        Returns current overflow number
        :return: int
        """

        return self._overflow_count

    @overflow.setter
    def overflow(self, value):
        """
        Sets overflow number
        :param value: int
        """

        self._overflow_count = value
        self._update_number()

    @property
    def count(self):
        """
        Returns current badge count number
        :return: int
        """

        return self._count

    @count.setter
    def count(self, value):
        """
        Sets current badge count number
        :param value: int
        """

        self._count = value
        self._update_number()

    @property
    def text(self):
        """
        Returns current badge text
        :return: str
        """

        return self._text

    @text.setter
    def text(self, value):
        """
        Sets current badge text
        :param value: str
        """

        self._text = value
        self._badge_btn.setText(self._text)
        self._badge_btn.setVisible(bool(self._text))
        self._dot = None
        self.style().polish(self)

    def _get_dot(self):
        """
        Returns whether or not current badge style is dot
        :return: bool
        """

        return self._dot

    def _set_dot(self, flag):
        """
        Sets whether or not current badge style is dot
        :param flag: bool
        """

        self._dot = flag
        self._badge_btn.setText('')
        self._badge_btn.setVisible(flag)
        self.style().polish(self)

    dot = Property(bool, _get_dot, _set_dot)

    # =================================================================================================================
    # OVERRIDES
    # =================================================================================================================

    def get_main_layout(self):
        main_layout = layouts.GridLayout(margins=(0, 0, 0, 0))

        return main_layout

    def ui(self):
        super(Badge, self).ui()

        self._badge_btn = QPushButton()
        self._badge_btn.setSizePolicy(QSizePolicy.Minimum, QSizePolicy.Minimum)

        if self._widget is not None:
            self.main_layout.addWidget(self._widget, 0, 0)
        self.main_layout.addWidget(self._badge_btn, 0, 0,
                                   Qt.AlignTop | Qt.AlignRight)

    # =================================================================================================================
    # BASE
    # =================================================================================================================

    @classmethod
    def create_dot(cls, show=False, widget=None, parent=None):
        """
        Creates a new badge with dot style
        :param show: bool
        :param widget: QWidget
        :param parent: QWidget
        :return: Badge
        """

        inst = cls(widget=widget, parent=parent)
        inst.dot = show

        return inst

    @classmethod
    def create_count(cls, count=0, widget=None, parent=None):
        """
        Creates a new badge with count style
        :param count: int
        :param widget: QWidget
        :param parent: QWidget
        :return: Badge
        """

        inst = cls(widget=widget, parent=parent)
        inst.count = count

        return inst

    @classmethod
    def create_text(cls, text='', widget=None, parent=None):
        """
        Creates a new badge with dot style
        :param text: str
        :param widget: QWidget
        :param parent: QWidget
        :return: Badge
        """

        inst = cls(widget=widget, parent=parent)
        inst.text = text

        return inst

    # =================================================================================================================
    # INTERNAL
    # =================================================================================================================

    def _update_number(self):
        """
        Internal function that updates overflow number
        """

        self._badge_btn.setText(
            formatters.overflow_format(self._count, self._overflow_count))
        self._badge_btn.setVisible(self._count > 0)
        self._dot = None
        self.style().polish(self)
예제 #4
0
class Project(base.BaseWidget):
    projectOpened = Signal(object)
    projectRemoved = Signal(str)
    projectImageChanged = Signal(str)

    def __init__(self, project_data, parent=None):

        self._project_data = project_data

        super(Project, self).__init__(parent)

    # ============================================================================================================
    # PROPERTIES
    # ============================================================================================================

    @property
    def name(self):
        return self._project_data.name

    @property
    def path(self):
        return self._project_data.path

    @property
    def full_path(self):
        return self._project_data.full_path

    @property
    def settings(self):
        return self._project_data.settings

    @property
    def project_data(self):
        return self._project_data

    # ============================================================================================================
    # CLASS FUNCTIONS
    # ============================================================================================================

    @classmethod
    def create_project_from_data(cls, project_data_path):
        """
        Creates a new project using a project data JSON file
        :param project_data_path: str, path where project JSON data file is located
        :return: Project
        """

        if project_data_path is None or not path.is_file(project_data_path):
            LOGGER.warning('Project Data Path {} is not valid!'.format(project_data_path))
            return None

        project_data = settings.JSONSettings()
        project_options = settings.JSONSettings()
        project_dir = path.get_dirname(project_data_path)
        project_name = path.get_basename(project_data_path)
        project_data.set_directory(project_dir, project_name)
        project_options.set_directory(project_dir, 'options.json')

        project_name = project_data.get('name')
        project_path = path.get_dirname(path.get_dirname(project_data_path))
        project_image = project_data.get('image')

        LOGGER.debug('New Project found [{}]: {}'.format(project_name, project_path))
        project_data = core_project.ProjectData(
            name=project_name, project_path=project_path, settings=project_data, options=project_options)

        new_project = cls(project_data=project_data)
        if project_image:
            new_project.set_image(project_image)

        return new_project

    # ============================================================================================================
    # OVERRIDES
    # ============================================================================================================

    def ui(self):
        super(Project, self).ui()

        self.setMaximumWidth(qtutils.dpi_scale(160))
        self.setMaximumHeight(qtutils.dpi_scale(200))

        widget_layout = layouts.VerticalLayout(spacing=0, margins=(0, 0, 0, 0))
        main_frame = QFrame()
        main_frame.setFrameStyle(QFrame.StyledPanel | QFrame.Raised)
        main_frame.setLineWidth(1)
        main_frame.setLayout(widget_layout)
        self.main_layout.addWidget(main_frame)

        self.project_btn = QPushButton('', self)
        self.project_btn.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
        self.project_btn.setIconSize(QSize(120, 120))
        project_lbl = label.BaseLabel(self.name, parent=self)
        project_lbl.setObjectName('projectLabel')
        project_lbl.setAlignment(Qt.AlignCenter)
        widget_layout.addWidget(self.project_btn)
        widget_layout.addWidget(project_lbl)

    def setup_signals(self):
        self.project_btn.clicked.connect(self._on_open_project)

    def contextMenuEvent(self, event):
        menu = QMenu(self)
        remove_icon = resources.icon(name='delete')
        remove_action = QAction(remove_icon, 'Remove', menu)
        remove_tooltip = 'Delete selected project'
        remove_action.setStatusTip(remove_tooltip)
        remove_action.setToolTip(remove_tooltip)
        remove_action.triggered.connect(self._on_remove_project)

        folder_icon = resources.icon(name='open_folder', extension='png')
        folder_action = QAction(folder_icon, 'Open in Browser', menu)
        open_project_in_explorer_tooltip = 'Open project folder in explorer'
        folder_action.setStatusTip(open_project_in_explorer_tooltip)
        folder_action.setToolTip(open_project_in_explorer_tooltip)
        folder_action.triggered.connect(self._on_open_in_browser)

        image_icon = resources.icon(name='picture', extension='png')
        set_image_action = QAction(image_icon, 'Set Project Image', menu)
        set_project_image_tooltip = 'Set the image used by the project'
        set_image_action.setToolTip(set_project_image_tooltip)
        set_image_action.setStatusTip(set_project_image_tooltip)
        set_image_action.triggered.connect(self._on_set_project_image)

        for action in [remove_action, None, folder_action, None, set_image_action]:
            if action is None:
                menu.addSeparator()
            else:
                menu.addAction(action)

        menu.exec_(self.mapToGlobal(event.pos()))

    # ============================================================================================================
    # BASE
    # ============================================================================================================

    def open(self):
        """
        Opens project
        """

        self._on_open_project()

    def has_option(self, name, group=None):
        """
        Returns whether the current object has given option or not
        :param name: str, name of the option
        :param group: variant, str || None, group of the option (optional)
        :return: bool
        """

        if not self._project_data:
            return False

        return self._project_data.has_option(name=name, group=group)

    def add_option(self, name, value, group=None, option_type=None):
        """
        Adds a new option to the options file
        :param name: str, name of the option
        :param value: variant, value of the option
        :param group: variant, str || None, group of the option (optional)
        :param option_type: variant, str || None, option type (optional)
        """

        if not self._project_data:
            return

        self._project_data.add_option(name, value, group=group, option_type=option_type)

    def get_option(self, name, group=None, default=None):
        """
        Returns option by name and group
        :param name: str, name of the option we want to retrieve
        :param group: variant, str || None, group of the option (optional)
        :return: variant
        """

        if not self._project_data:
            return

        return self._project_data.get_option(name, group=group, default=default)

    def reload_options(self):
        """
        Reload settings
        """

        if not self._project_data:
            return

        self._project_data.reload_options()

    def clear_options(self):
        """
        Clears all the options
        """

        if not self._project_data:
            return

        self._project_data.clear_options()

    def set_image(self, encoded_image):

        from tpDcc.libs.qt.core import image

        if not encoded_image:
            return

        encoded_image = encoded_image.encode('utf-8')
        project_icon = QIcon(QPixmap.fromImage(image.base64_to_image(encoded_image)))
        if project_icon.isNull():
            project_icon = resources.icon('tpDcc')
        self.project_btn.setIcon(project_icon)

    def remove(self, force=False):
        if not path.is_dir(self.full_path):
            LOGGER.warning('Impossible to remove Project Path: {}'.format(self.full_path))
            return False

        project_name = self.project_data.name
        project_path = self.project_data.path

        if not force:
            result = qtutils.get_permission(
                message='Are you sure you want to delete project: "{}"'.format(self.name),
                title='Deleting Project', cancel=False, parent=self)
            if not result:
                return

        valid_delete = folder.delete_folder(folder_name=project_name, directory=project_path)
        if valid_delete is None:
            return False

        return True

    def load_project_data(self):
        """
        Return dictionary data contained in the project
        :return: dict
        """

        if not self.settings:
            return

        return self.settings.data()

    def get_project_nodes(self):
        """
        Returns path where nodes should be stored
        :return: str
        """

        return [os.path.join(self.full_path, 'nodes'), os.path.join(self.full_path, 'components')]

    def get_options(self):
        """
        Returns all options contained in the project
        :return: str
        """

        return self._project_data.get_options()

    def get_project_image(self):
        """
        Returns the image used by the project
        :return: QPixmap
        """

        return self._project_data.get_project_image()

    # ============================================================================================================
    # CALLBACKS
    # ============================================================================================================

    def _on_open_project(self):
        """
        Internal callback function that is called when a project is opened
        """

        LOGGER.info('Loading project "{}" ...'.format(self.full_path))
        self.projectOpened.emit(self)

    def _on_remove_project(self):
        """
        Internal callback function that is called when a project is removed
        """

        valid_remove = self.remove()
        if valid_remove:
            self.projectRemoved.emit(self.name)

    def _on_open_in_browser(self):
        """
        Internal callback function that is called when a project is browsed
        """

        fileio.open_browser(self.full_path)

    def _on_set_project_image(self):
        """
        Internal callback function that is called when project image is set
        """

        image_file = dcc.select_file_dialog(
            title='Select Project Image File',
            pattern="PNG Files (*.png)")

        if image_file is None or not path.is_file(image_file):
            LOGGER.warning('Selected Image "{}" is not valid!'.format(image_file))
            return

        valid_change = self._project_data.set_project_image(image_file)

        if valid_change:
            project_image = self._project_data.settings.get('image')
            if project_image:
                self.set_image(project_image)
            self.projectImageChanged.emit(image_file)
예제 #5
0
class SaveWidget(BaseSaveWidget, object):
    def __init__(self, item, settings, temp_path=None, parent=None):

        self._script_job = None
        self._sequence_path = None
        self._icon_path = ''

        super(SaveWidget, self).__init__(item=item,
                                         settings=settings,
                                         temp_path=temp_path,
                                         parent=parent)

        self.create_sequence_widget()
        self.update_thumbnail_size()

        try:
            self._on_selection_changed()
            # self.set_script_job_enabled(True)
        except NameError as e:
            LOGGER.error('{} | {}'.format(e, traceback.format_exc()))

    def ui(self):
        super(SaveWidget, self).ui()

        model_panel_layout = layouts.HorizontalLayout()
        model_panel_layout.setContentsMargins(0, 0, 0, 0)
        model_panel_layout.setSpacing(0)
        thumbnail_layout = layouts.VerticalLayout()
        thumbnail_layout.setContentsMargins(0, 0, 0, 0)
        thumbnail_layout.setSpacing(0)
        self._thumbnail_frame = QFrame()
        self._thumbnail_frame.setMinimumSize(QSize(50, 50))
        self._thumbnail_frame.setMaximumSize(QSize(150, 150))
        self._thumbnail_frame.setSizePolicy(QSizePolicy.Expanding,
                                            QSizePolicy.Expanding)
        self._thumbnail_frame.setFrameShape(QFrame.NoFrame)
        self._thumbnail_frame.setFrameShadow(QFrame.Plain)
        self._thumbnail_frame.setLineWidth(0)
        self._thumbnail_frame.setLayout(thumbnail_layout)
        model_panel_layout.addWidget(self._thumbnail_frame)
        self._thumbnail_btn = QPushButton()
        self._thumbnail_btn.setMinimumSize(QSize(0, 0))
        self._thumbnail_btn.setSizePolicy(QSizePolicy.Expanding,
                                          QSizePolicy.Expanding)
        self._thumbnail_btn.setMaximumSize(QSize(150, 150))
        self._thumbnail_btn.setToolTip('Take snapshot')
        self._thumbnail_btn.setStyleSheet(
            'color: rgb(40, 40, 40);border: 0px solid rgb(0, 0, 0, 150);background-color: rgb(254, 255, 230, 200);'
        )
        self._thumbnail_btn.setIcon(resources.icon('thumbnail'))
        self._thumbnail_btn.setToolTip("""
        Click to capture a thumbnail from the current viewport.\n
        CTRL + Click to show the capture window for better framing
        """)
        thumbnail_layout.addWidget(self._thumbnail_btn)

        self._extra_layout.addLayout(model_panel_layout)

    def setup_signals(self):
        super(SaveWidget, self).setup_signals()
        self._thumbnail_btn.clicked.connect(self._on_thumbnail_capture)

    def resizeEvent(self, event):
        """
        Overrides base QWidget resizeEvent function
        :param event: QResizeEvent
        """

        self.update_thumbnail_size()

    def icon_path(self):
        """
        Returns the icon path to be used for the thumbnail
        :return: str
        """

        return self._icon_path

    def set_icon(self, icon):
        """
        Sets the icon for the create widget thumbnail
        :param icon: QIcon
        """

        self._thumbnail_btn.setIcon(icon)
        self._thumbnail_btn.setIconSize(QSize(200, 200))
        self._thumbnail_btn.setText('')

    def sequence_path(self):
        """
        Returns the playblast path
        :return: str
        """

        return self._sequence_path

    def set_sequence_path(self, path):
        """
        Sets the disk location for the image sequence to be saved
        :param path: str
        """

        self._sequence_path = path
        self._thumbnail_btn.set_dirname(os.path.dirname(path))

    def create_sequence_widget(self):
        """
        Creates a sequence widget to replace the static thumbnail widget
        """

        sequence_widget = widgets.LibraryImageSequenceWidget(self)
        sequence_widget.setObjectName('thumbnailButton')
        sequence_widget.setStyleSheet(self._thumbnail_btn.styleSheet())
        sequence_widget.setToolTip(self._thumbnail_btn.toolTip())

        camera_icon = resources.get('icons', 'camera.svg')
        expand_icon = resources.get('icons', 'expand.svg')
        folder_icon = resources.get('icons', 'folder.svg')

        sequence_widget.addAction(camera_icon, 'Capture new image',
                                  'Capture new image',
                                  self._on_thumbnail_capture)
        sequence_widget.addAction(expand_icon, 'Show Capture window',
                                  'Show Capture window',
                                  self._on_show_capture_window)
        sequence_widget.addAction(folder_icon, 'Load image from disk',
                                  'Load image from disk',
                                  self._on_show_browse_image_dialog)

        sequence_widget.setIcon(resources.icon('thumbnail2'))
        self._thumbnail_frame.layout().insertWidget(0, sequence_widget)
        self._thumbnail_btn.hide()
        self._thumbnail_btn = sequence_widget
        self._thumbnail_btn.clicked.connect(self._on_thumbnail_capture)

    def set_sequence(self, source):
        """
        Sets the sequenced path for the thumbnail widget
        :param source: str
        """

        self.set_thumbnail(source, sequence=True)

    def set_thumbnail(self, source, sequence=False):
        """
        Sets the thumbnail
        :param source: str
        :param sequence: bool
        """

        source = os.path.normpath(source)

        # TODO: Find a way to remove temp folder afteer saving the file
        # filename, extension = os.path.splitext(source)
        # with path_utils.temp_dir() as dir_path:
        # dir_path = path_utils.temp_dir()
        # target = os.path.join(dir_path, 'thumbnail{}'.format(extension))
        # shutil.copyfile(source, target)
        # tpQtLib.logger.debug('Source Thumbnail: {}'.format(source))
        # tpQtLib.logger.debug('Target Thumbnail: {}'.format(target))
        # self._icon_path = target
        # self._thumbnail_btn.set_path(target)

        self._icon_path = source
        self._thumbnail_btn.set_path(source)

        if sequence:
            self.set_sequence_path(source)

    def update_thumbnail_size(self):
        """
        Updates the thumbnail button to teh size of the widget
        """

        width = self.width() - 10
        if width > 250:
            width = 250
        size = QSize(width, width)
        self._thumbnail_btn.setIconSize(size)
        self._thumbnail_btn.setMaximumSize(size)
        self._thumbnail_frame.setMaximumSize(size)

    def show_by_frame_dialog(self):
        """
        Show the by frame dialog
        """

        help_text = """
        To help speed up the playblast you can set the "by frame" to another greather than 1.
        For example if the "by frame" is set to 2 it will playblast every second frame
        """

        options = self._options_widget.values()
        by_frame = options.get('byFrame', 1)
        start_frame, end_frame = options.get('frameRange', [None, None])
        duration = 1
        if start_frame is not None and end_frame is not None:
            duration = end_frame - start_frame
        if duration > 100 and by_frame == 1:
            buttons = QDialogButtonBox.Ok | QDialogButtonBox.Cancel
            result = messagebox.MessageBox.question(
                self.library_window(),
                title='Tip',
                text=help_text,
                buttons=buttons,
                enable_dont_show_checkbox=True)
            if result != QDialogButtonBox.Ok:
                raise Exception('Cancelled by user')

    def show_thumbnail_capture_dialog(self):
        """
        Asks the user if they would like to capture a thumbnail
        :return: int
        """

        buttons = QDialogButtonBox.Yes | QDialogButtonBox.Ignore | QDialogButtonBox.Cancel
        parent = self.item().library_window()
        btn = messagebox.MessageBox.question(
            None,
            'Create a thumbnail',
            'Would you like to capture a thumbnail?',
            buttons=buttons)
        if btn == QDialogButtonBox.Yes:
            self.thumbnail_capture()

        return btn

    def thumbnail_capture(self, show=False):
        """
        Captures a playblast and saves it to the temporal thumbnail path
        :param show: bool
        """

        options = self._options_widget.values()
        start_frame, end_frame = options.get('frameRange', [None, None])
        step = options.get('byFrame', 1)

        if not qtutils.is_control_modifier():
            self.show_by_frame_dialog()

        if not self._temp_path or not os.path.isdir(self._temp_path):
            self._temp_path = tempfile.mkdtemp()
        self._temp_path = os.path.join(self._temp_path, 'thumbnail.jpg')

        try:
            snapshot.SnapshotWindow(path=self._temp_path,
                                    on_save=self._on_thumbnail_captured)
            # thumbnail.ThumbnailCaptureDialog.thumbnail_capture(
            #     path=self._temp_path,
            #     show=show,
            #     start_frame=start_frame,
            #     end_frame=end_frame,
            #     step=step,
            #     clear_cache=False,
            #     captured=self._on_thumbnail_captured
            # )
        except Exception as e:
            messagebox.MessageBox.critical(self.library_window(),
                                           'Error while capturing thumbnail',
                                           str(e))
            LOGGER.error(traceback.format_exc())

    def save(self, path, icon_path, objects=None):
        """
        Saves the item with the given objects to the given disk location path
        :param path: list(str)
        :param icon_path: str
        :param objects: str
        """

        item = self.item()
        options = self._options_widget.values()
        sequence_path = self.sequence_path()
        if sequence_path:
            sequence_path = os.path.dirname(sequence_path)

        item.save(path=path,
                  objects=objects,
                  icon_path=icon_path,
                  sequence_path=sequence_path,
                  **options)

        self.close()

    def _on_selection_changed(self):
        """
        Internal callback functino that is called when DCC selection changes
        """

        if self._options_widget:
            self._options_widget.validate()

    def _on_thumbnail_capture(self):
        self.thumbnail_capture(show=False)

    def _on_thumbnail_captured(self, captured_path):
        """
        Internal callback function that is called when thumbnail is captured
        :param captured_path: str
        """

        self.set_sequence(captured_path)

    def _on_show_capture_window(self):
        """
        Internal callback function that shows the capture window for framing
        """

        self.thumbnail_capture(show=True)

    def _on_show_browse_image_dialog(self):
        """
        Internal callback function that shows a file dialog for choosing an image from disk
        """

        file_dialog = QFileDialog(self,
                                  caption='Open Image',
                                  filter='Image Files (*.png *.jpg)')
        file_dialog.fileSelected.connect(self.set_thumbnail)
        file_dialog.exec_()