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))
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()
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
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