def test_get_thumbnail_path(self):
        import bookmarks.images as images

        a = images.get_thumbnail_path(
            u'server',
            u'job',
            u'root',
            u'server/job/root/folder/file.png')
        self.assertIsInstance(a, unicode)
        b = images.get_thumbnail_path(
            u'server'.upper(),
            u'job'.upper(),
            u'root'.upper(),
            u'server/job/root/folder/file.png'.upper())
        self.assertIsInstance(b, unicode)

        self.assertEqual(a, b)

        a = images.get_thumbnail_path(
            u'server',
            u'job',
            u'root',
            u'server/job/root/folder/file_0001.exr')
        b = images.get_thumbnail_path(
            u'server',
            u'job',
            u'root',
            u'server/job/root/folder/file_0002.exr')
        self.assertNotEqual(a, b)

        a = images.get_thumbnail_path(
            u'server',
            u'job',
            u'root',
            u'server/job/root/folder/file_[1-2].exr')
        b = images.get_thumbnail_path(
            u'server',
            u'job',
            u'root',
            u'server/job/root/folder/file_[1-55].exr')
        self.assertEqual(a, b)

        a = images.get_thumbnail_path(
            u'server',
            u'job',
            u'root',
            u'server/job/root/folder/file_[1000,1001].exr')
        b = images.get_thumbnail_path(
            u'server',
            u'job',
            u'root',
            u'server/job/root/folder/file_[2001,2002].exr'.upper())
        self.assertEqual(a, b)
    def _create_UI(self):
        QtWidgets.QVBoxLayout(self)
        o = common.MARGIN()
        self.layout().setContentsMargins(o, o, o, o)
        self.layout().setSpacing(o)

        row = common_ui.add_row(u'', parent=self)
        self.hide_button = common_ui.ClickableIconButton(
            u'close', (common.REMOVE, common.REMOVE),
            common.MARGIN(),
            description=u'Hide',
            parent=row)

        bookmark = u'{}/{}/{}'.format(self.server, self.job, self.root)
        source = images.get_thumbnail_path(self.server, self.job, self.root,
                                           bookmark)

        pixmap = images.ImageCache.get_pixmap(source, row.height())
        if not pixmap:
            source = images.get_placeholder_path(
                bookmark, fallback=u'thumb_bookmark_gray')
            pixmap = images.ImageCache.get_pixmap(source, row.height())

        if pixmap:
            thumbnail = QtWidgets.QLabel(parent=self)
            thumbnail.setPixmap(pixmap)
            row.layout().addWidget(thumbnail, 0)
            row.layout().addSpacing(o * 0.5)

        text = u'{}  |  {}'.format(self.job.upper(), self.root.upper())
        label = common_ui.PaintedLabel(text, size=common.LARGE_FONT_SIZE())

        row.layout().addWidget(label)
        row.layout().addStretch(1)
        row.layout().addWidget(self.hide_button, 0)

        # *****************************************

        self.templates_widget = managebookmarks.TemplatesWidget(u'asset',
                                                                parent=self)
        self.layout().addWidget(self.templates_widget, 1)

        s = u'Independent of the template, basic <span style="color:rgba({ADD});">mode</span> and \
<span style="color:rgba({ADD});">task</span> are defined in \
<span style="color:rgba({H});">Preferences -> Default Paths</span>. \
Ideally, both the template and the preferences should define the same folders.'.format(
            ADD=common.rgb(common.ADD),
            H=common.rgb(common.TEXT_SELECTED),
        )
        common_ui.add_description(s, label='hint', parent=self)
        self.layout().addStretch(1)
    def add_switch_menu(self, menu_set, widget, label):
        if hasattr(widget.model(), 'sourceModel'):
            model = widget.model().sourceModel()
        else:
            model = widget.model()
        active_index = model.active_index()
        items = model.model_data().items()
        items = sorted(items,
                       key=lambda x: x[1][QtCore.Qt.DisplayRole].lower())

        off_pixmap = images.ImageCache.get_rsc_pixmap(u'folder',
                                                      common.SECONDARY_TEXT,
                                                      common.MARGIN())
        on_pixmap = images.ImageCache.get_rsc_pixmap(u'check', common.ADD,
                                                     common.MARGIN())

        menu_set[label] = {u'disabled': True}
        for idx, item in items:
            if item[common.FlagsRole] & common.MarkedAsArchived:
                continue
            name = item[QtCore.Qt.DisplayRole]
            active = False
            if active_index.isValid():
                n = active_index.data(QtCore.Qt.DisplayRole)
                active = n.lower() == name.lower()

            index = model.index(idx, 0)
            if hasattr(model, 'mapFromSource'):
                index = widget.model().mapFromSource(index)

            thumbnail_path = images.get_thumbnail_path(
                item[common.ParentPathRole][0],
                item[common.ParentPathRole][1],
                item[common.ParentPathRole][2],
                item[QtCore.Qt.StatusTipRole],
            )
            pixmap = images.ImageCache.get_pixmap(thumbnail_path,
                                                  common.MARGIN() * 2)
            pixmap = pixmap if pixmap else off_pixmap
            pixmap = on_pixmap if active else pixmap
            icon = QtGui.QIcon(pixmap)
            menu_set[name.upper()] = {
                u'icon': icon,
                u'action': functools.partial(widget.activate, index)
            }
        return menu_set
    def _create_UI(self):
        QtWidgets.QVBoxLayout(self)
        o = common.MARGIN()
        self.layout().setContentsMargins(o, o, o, o)
        self.layout().setSpacing(0)

        height = common.ROW_HEIGHT() * 0.8
        # ********************************************
        row = common_ui.add_row(None, padding=None, parent=self)
        self.save_button = common_ui.ClickableIconButton(
            u'check', (common.ADD, common.ADD), height)

        bookmark = u'{}/{}/{}'.format(self.server, self.job, self.root)
        source = images.get_thumbnail_path(self.server, self.job, self.root,
                                           bookmark)

        pixmap = images.ImageCache.get_pixmap(source, row.height())
        if not pixmap:
            source = images.get_placeholder_path(
                bookmark, fallback=u'thumb_bookmark_gray')
            pixmap = images.ImageCache.get_pixmap(source, row.height())

        if pixmap:
            thumbnail = QtWidgets.QLabel(parent=self)
            thumbnail.setPixmap(pixmap)
            row.layout().addWidget(thumbnail, 0)
            row.layout().addSpacing(o * 0.5)

        text = u'{}  |  {}'.format(self.job.upper(), self.root.upper())
        label = common_ui.PaintedLabel(text, size=common.LARGE_FONT_SIZE())

        row.layout().addWidget(label)
        row.layout().addStretch(1)
        row.layout().addWidget(self.save_button, 0)

        self.scrollarea = ScrollArea(parent=self)
        self.layout().addSpacing(o * 0.5)
        self.layout().addWidget(self.scrollarea)

        self.save_button.clicked.connect(
            lambda: self.done(QtWidgets.QDialog.Accepted))
Exemple #5
0
    def startDrag(self, supported_actions):
        """Creating a custom drag object here for displaying setting hotspots."""
        index = self.selectionModel().currentIndex()
        model = self.model().sourceModel()

        if not index.isValid():
            return
        if not index.data(QtCore.Qt.StatusTipRole):
            return
        if not index.data(common.ParentPathRole):
            return

        self.drag_source_index = index
        drag = QtGui.QDrag(self)
        # Getting the data from the source model
        drag.setMimeData(model.mimeData([
            index,
        ]))

        # Setting our custom cursor icons
        height = index.data(QtCore.Qt.SizeHintRole).height()

        def px(s):
            return images.ImageCache.get_rsc_pixmap(s, None, common.MARGIN())

        # Set drag icon
        drag.setDragCursor(px('CopyAction'), QtCore.Qt.CopyAction)
        drag.setDragCursor(px('MoveAction'), QtCore.Qt.MoveAction)
        # drag.setDragCursor(px('LinkAction'), QtCore.Qt.LinkAction)
        drag.setDragCursor(px('IgnoreAction'), QtCore.Qt.ActionMask)
        drag.setDragCursor(px('IgnoreAction'), QtCore.Qt.IgnoreAction)
        # drag.setDragCursor(px('TargetMoveAction'), QtCore.Qt.TargetMoveAction)

        modifiers = QtWidgets.QApplication.instance().keyboardModifiers()
        no_modifier = modifiers == QtCore.Qt.NoModifier
        alt_modifier = modifiers & QtCore.Qt.AltModifier
        shift_modifier = modifiers & QtCore.Qt.ShiftModifier

        # Set pixmap
        path = index.data(QtCore.Qt.StatusTipRole)
        source = images.get_thumbnail_path(
            index.data(common.ParentPathRole)[0],
            index.data(common.ParentPathRole)[1],
            index.data(common.ParentPathRole)[2], path)
        pixmap = images.ImageCache.get_pixmap(source, height)
        if not pixmap:
            source = images.get_placeholder_path(source)
            pixmap = images.ImageCache.get_pixmap(source, height)

        bookmark = u'/'.join(index.data(common.ParentPathRole)[:3])
        path = path.replace(bookmark, u'')
        path = path.strip(u'/')
        if no_modifier:
            path = common.get_sequence_endpath(path)
        elif alt_modifier and shift_modifier:
            pixmap = images.ImageCache.get_rsc_pixmap(u'folder',
                                                      common.SECONDARY_TEXT,
                                                      height)
            path = QtCore.QFileInfo(path).dir().path()
        elif alt_modifier:
            pixmap = images.ImageCache.get_rsc_pixmap(u'files',
                                                      common.SECONDARY_TEXT,
                                                      height)
            path = common.get_sequence_startpath(path)
        elif shift_modifier:
            path = common.get_sequence_startpath(path) + u', ++'
            pixmap = images.ImageCache.get_rsc_pixmap(u'multiples_files',
                                                      common.SECONDARY_TEXT,
                                                      height)
        else:
            return

        self.update(index)
        if pixmap and not pixmap.isNull():
            pixmap = DragPixmap.pixmap(pixmap, path)
            drag.setPixmap(pixmap)

        try:
            lc = self.parent().parent().listcontrolwidget
            lc.drop_overlay.show()
        except:
            log.error(u'Could not show drag overlay')

        drag.exec_(supported_actions)

        try:
            lc.drop_overlay.hide()
        except:
            log.error('')

        self.drag_source_index = QtCore.QModelIndex()
Exemple #6
0
    def add_thumbnail_menu(self, menu_set):
        """Menu item resposible for general thumbnail operations."""
        if not self.index.isValid():
            return menu_set

        capture_thumbnail_pixmap = images.ImageCache.get_rsc_pixmap(
            u'capture_thumbnail', common.SECONDARY_TEXT, common.MARGIN())
        pick_thumbnail_pixmap = images.ImageCache.get_rsc_pixmap(
            u'pick_thumbnail', common.SECONDARY_TEXT, common.MARGIN())
        pick_thumbnail_pixmap = images.ImageCache.get_rsc_pixmap(
            u'pick_thumbnail', common.SECONDARY_TEXT, common.MARGIN())
        remove_thumbnail_pixmap = images.ImageCache.get_rsc_pixmap(
            u'remove', common.REMOVE, common.MARGIN())
        show_thumbnail = images.ImageCache.get_rsc_pixmap(
            u'active', common.SECONDARY_TEXT, common.MARGIN())

        menu_set[u'header'] = {
            u'text': 'Thumbnails',
            u'disabled': True,
        }
        menu_set[u'separator'] = {}

        thumbnail_path = images.get_thumbnail_path(
            self.index.data(common.ParentPathRole)[0],
            self.index.data(common.ParentPathRole)[1],
            self.index.data(common.ParentPathRole)[2],
            self.index.data(QtCore.Qt.StatusTipRole),
        )
        exists = QtCore.QFileInfo(thumbnail_path).exists()
        menu_set[u'Show'] = {
            u'icon': show_thumbnail,
            u'action': self.parent().key_space
        }
        menu_set[u'separator'] = {}

        source_index = self.index.model().mapToSource(self.index)
        menu_set[u'capture'] = {
            u'text': 'Capture screen',
            u'icon': capture_thumbnail_pixmap,
            u'action': functools.partial(images.capture, source_index)}

        menu_set[u'file'] = {
            u'text': u'Select file...',
            u'icon': pick_thumbnail_pixmap,
            u'action': functools.partial(
                images.pick, source_index)
        }

        menu_set[u'library'] = {
            u'text': u'Select from library...',
            u'icon': pick_thumbnail_pixmap,
            u'action': functools.partial(
                images.pick_from_library, source_index)
        }

        menu_set[u'separator.'] = {}

        if exists:
            menu_set[u'remove'] = {
                u'text': u'Remove',
                u'action': functools.partial(
                    images.remove, source_index),
                u'icon': remove_thumbnail_pixmap
            }
        menu_set[u'separator_'] = {}
        menu_set[u'reveal'] = {
            u'text': u'Show cached image...',
            u'action': functools.partial(
                common.reveal,
                thumbnail_path,
            )
        }
        return menu_set
Exemple #7
0
    def process_data(self, ref):
        """Populates the ImageCache with an existing thumbnail or generates a
        new one if `ref` refers to a file understood by OpenImageIO.

        If the return value is not `None`, the model will request a repaint
        event for the row the `ref` corresponds to. See the `@process` decorator
        for details.

        Args:
            ref (weakref.ref): A weakref to a data segment.

        Returns:
            ref or None: `ref` if loaded successfully, else `None`.

        """
        def is_valid():
            return False if not ref() or self.interrupt or ref()[
                common.ThumbnailLoaded] or ref()[
                    common.FlagsRole] & common.MarkedAsArchived else True

        if not is_valid():
            return False
        size = ref()[QtCore.Qt.SizeHintRole].height()

        if not is_valid():
            return False
        _p = ref()[common.ParentPathRole]

        if not is_valid():
            return False
        source = ref()[QtCore.Qt.StatusTipRole]

        # Resolve the thumbnail's path...
        destination = images.get_thumbnail_path(
            _p[0],
            _p[1],
            _p[2],
            source,
        )
        # ...and use it to load the resource
        image = images.ImageCache.get_image(
            destination,
            int(size),
            force=True  # force=True will refresh the cache
        )

        try:
            # If the image successfully loads we can wrap things up here
            if image and not image.isNull():
                images.ImageCache.get_image(destination, int(size), force=True)
                images.ImageCache.make_color(destination)
                return True

            # Otherwise, we will try to generate a thumbnail using OpenImageIO

            # If the items is a sequence, we'll use the first image of the
            # sequence to make the thumbnail.
            if not is_valid():
                return False
            if ref()[common.TypeRole] == common.SequenceItem:
                if not is_valid():
                    return False
                source = ref()[common.EntryRole][0].path.replace(u'\\', u'/')

            buf = images.oiio_get_buf(source)
            if not buf:
                return False

            if QtCore.QFileInfo(source).size() >= pow(1024, 3) * 2:
                return False
            res = images.ImageCache.oiio_make_thumbnail(
                source,
                destination,
                common.THUMBNAIL_IMAGE_SIZE,
            )
            if res:
                images.ImageCache.get_image(destination, int(size), force=True)
                images.ImageCache.make_color(destination)
                return True

            # We should never get here ideally, but if we do we'll mark the item
            # with a bespoke 'failed' thumbnail
            res = images.ImageCache.oiio_make_thumbnail(
                common.rsc_path(__file__, u'failed'), destination,
                common.THUMBNAIL_IMAGE_SIZE)
            if res:
                images.ImageCache.get_image(destination, int(size), force=True)
                images.ImageCache.make_color(destination)
                return True
            return False
        except:
            log.error(u'Failed to generate thumbnail')
        finally:
            if ref():
                ref()[common.ThumbnailLoaded] = True