def query(self, queryText, limit=0, page=1): self.queryText = queryText self.limit = limit self.page = page directory = "ASC" if self.orderDir == Qt.AscendingOrder else "DESC" orderBy = [] if self.orderByColumnId is not None: if self.orderByColumnId == self.ID: orderBy.append(("id", directory)) elif self.orderByColumnId == self.TITLE: orderBy.append(("title", directory)) #This is not exactly sorting by pure rating, but by fields and their values... elif self.orderByColumnId == self.RATING: orderBy.append(("items_fields_field_id", "DESC")) orderBy.append(("items_fields_field_value", directory)) def resetRow(row): self.resetSingleRow(row) QtCore.QCoreApplication.processEvents() uow = self._repo.createUnitOfWork() items = [] try: if self._thread is not None and self._thread.isRunning(): self._thread.interrupt = True self._thread.wait(5 * 1000) if queryText is None or queryText.strip() == "": items = uow.executeCommand( cmds.GetUntaggedItems(limit, page, orderBy)) else: queryTree = query_parser.parse(queryText) cmd = cmds.QueryItemsByParseTree(queryTree, limit, page, orderBy) items = uow.executeCommand(cmd) self._thread = ThumbnailBuilderThread(self, self._repo, items, self._lock) self.connect(self._thread, QtCore.SIGNAL("progress"), lambda percents, row: resetRow(row)) self._thread.start() except (errors.YaccError, errors.LexError) as ex: raise errors.MsgException( self.tr("Error in the query. Detail info: {}").format(str(ex))) finally: uow.close() self.setObjs(items)
def query(self, queryText, limit=0, page=1): self.queryText = queryText self.limit = limit self.page = page directory = "ASC" if self.orderDir == Qt.AscendingOrder else "DESC" orderBy = [] if self.orderByColumnId is not None: if self.orderByColumnId == self.ID: orderBy.append(("id", directory)) elif self.orderByColumnId == self.TITLE: orderBy.append(("title", directory)) #This is not exactly sorting by pure rating, but by fields and their values... elif self.orderByColumnId == self.RATING: orderBy.append(("items_fields_field_id", "DESC")) orderBy.append(("items_fields_field_value", directory)) def resetRow(row): self.resetSingleRow(row) QtCore.QCoreApplication.processEvents() uow = self._repo.createUnitOfWork() items = [] try: if self._thread is not None and self._thread.isRunning(): self._thread.interrupt = True self._thread.wait(5*1000) if queryText is None or queryText.strip()=="": items = uow.executeCommand(cmds.GetUntaggedItems(limit, page, orderBy)) else: queryTree = query_parser.parse(queryText) cmd = cmds.QueryItemsByParseTree(queryTree, limit, page, orderBy) items = uow.executeCommand(cmd) self._thread = ThumbnailBuilderThread(self, self._repo, items, self._lock) self.connect(self._thread, QtCore.SIGNAL("progress"), lambda percents, row: resetRow(row)) self._thread.start() except (errors.YaccError, errors.LexError) as ex: raise errors.MsgException(self.tr("Error in the query. Detail info: {}").format(str(ex))) finally: uow.close() self.setObjs(items)
class ItemsTableModel(UnivTableModel): ROW_NUM = "row_num" ID = "id" TITLE = "title" IMAGE_THUMB = "image_thumb" TAGS = "tags" STATE = "state" #State of the item (in the means of its integrity) RATING = "rating" def __init__(self, repo, lock, userLogin): super(ItemsTableModel, self).__init__() self._repo = repo self._lock = lock self.userLogin = userLogin #This is a thread for building image thumbnails in the background self._thread = None self.queryText = "" self.limit = 0 self.page = 1 self.orderByColumnId = None self.orderDir = None self.createColumns() def createColumns(self): def formatRowNum(row, item, role): if role == Qt.DisplayRole: return str(row + 1) if role == QtCore.Qt.TextAlignmentRole: return int(QtCore.Qt.AlignRight | QtCore.Qt.AlignVCenter) if role == Qt.ToolTipRole: return self.tr("Table row number") return None self.registerColumn(UnivTableColumn(ItemsTableModel.ROW_NUM, self.tr("Row"), formatRowNum)) def formatId(row, item, role): if role == Qt.DisplayRole: return str(item.id) if role == QtCore.Qt.TextAlignmentRole: return int(QtCore.Qt.AlignRight | QtCore.Qt.AlignVCenter) return None self.registerColumn(col = UnivTableColumn(ItemsTableModel.ID, self.tr("Id"), formatId)) def formatTitle(row, item, role): if role == Qt.DisplayRole: return "<b>" + item.title + "</b>" + ("<br/><font>" + item.data_ref.url + "</font>" if item.data_ref else "") if role == Qt.ToolTipRole: if item.data_ref is not None: s = str(item.data_ref.type) + ": " + item.data_ref.url if item.data_ref.type == db.DataRef.FILE: s += os.linesep + self.tr("Checksum (hash): {}").format(item.data_ref.hash) s += os.linesep + self.tr("File size: {} bytes").format(item.data_ref.size) s += os.linesep + self.tr("Date hashed: {}").format(item.data_ref.date_hashed) s += os.linesep + self.tr("Created by: {}").format(item.data_ref.user_login) s += os.linesep + self.tr("Date created: {}").format(item.data_ref.date_created) return s return None self.registerColumn(UnivTableColumn("title", self.tr("Title"), formatTitle, helpers.HTMLDelegate(self))) def formatThumbnail(row, item, role): if role != QtCore.Qt.UserRole: return None if item.data_ref is None: return None if item.data_ref.is_image(): pixmap = QtGui.QPixmap() try: self._lock.lockForRead() if len(item.data_ref.thumbnails) > 0: pixmap.loadFromData(item.data_ref.thumbnails[0].data) except Exception: traceback.format_exc() finally: self._lock.unlock() return pixmap self.registerColumn(UnivTableColumn(ItemsTableModel.IMAGE_THUMB, self.tr("Thumbnail"), formatThumbnail, delegate=helpers.ImageThumbDelegate(self))) def formatTags(row, item, role): if role == Qt.DisplayRole: return item.format_tags() if role == Qt.ToolTipRole: return item.format_field_vals() return None self.registerColumn(UnivTableColumn(ItemsTableModel.TAGS, self.tr("Tags"), formatTags, helpers.HTMLDelegate(self))) def __formatErrorSetShort(error_set): if error_set is None: return "" if len(error_set) <= 0: return self.tr("OK") elif len(error_set) > 0: return helpers.to_commalist(error_set, lambda x: __formatErrorShort(x)) def __formatErrorShort(itemErrorCode): if itemErrorCode == db.Item.ERROR_FILE_NOT_FOUND: return self.tr("File not found") elif itemErrorCode == db.Item.ERROR_FILE_HASH_MISMATCH: return self.tr("Hash mismatch") else: assert False, "Unknown error code" def formatState(row, item, role): if role == Qt.DisplayRole: try: self._lock.lockForRead() return __formatErrorSetShort(item.error) finally: self._lock.unlock() return None self.registerColumn(UnivTableColumn(ItemsTableModel.STATE, self.tr("State"), formatState)) def formatRating(row, item, role): if role == Qt.DisplayRole: ratingStr = item.getFieldValue(consts.RATING_FIELD, self.userLogin) try: rating = int(ratingStr) except: rating = 0 return rating return None def setRating(item, row, value, role): if role != Qt.EditRole: return False oldValue = item.getFieldValue(consts.RATING_FIELD, self.userLogin) if oldValue == value: return False item.setFieldValue(consts.RATING_FIELD, value, self.userLogin) uow = self._repo.createUnitOfWork() try: srcAbsPath = os.path.join(self._repo.base_path, item.data_ref.url) if item.data_ref is not None else None dstRelPath = item.data_ref.url if item.data_ref is not None else None cmd = cmds.UpdateExistingItemCommand(item, srcAbsPath, dstRelPath, self.userLogin) uow.executeCommand(cmd) return True except: item.setFieldValue(consts.RATING_FIELD, oldValue, self.userLogin) return False finally: uow.close() self.registerColumn(UnivTableColumn(ItemsTableModel.RATING, self.tr("Rating"), formatObjFun=formatRating, delegate=helpers.RatingDelegate(self), setDataFun=setRating)) def sort(self, columnIndex, order=Qt.AscendingOrder): column = self.column(columnIndex) if column.id not in [self.ID, self.TITLE, self.RATING]: return self.orderByColumnId = column.id self.orderDir = order self.query(self.queryText, self.limit, self.page) def query(self, queryText, limit=0, page=1): self.queryText = queryText self.limit = limit self.page = page directory = "ASC" if self.orderDir == Qt.AscendingOrder else "DESC" orderBy = [] if self.orderByColumnId is not None: if self.orderByColumnId == self.ID: orderBy.append(("id", directory)) elif self.orderByColumnId == self.TITLE: orderBy.append(("title", directory)) #This is not exactly sorting by pure rating, but by fields and their values... elif self.orderByColumnId == self.RATING: orderBy.append(("items_fields_field_id", "DESC")) orderBy.append(("items_fields_field_value", directory)) def resetRow(row): self.resetSingleRow(row) QtCore.QCoreApplication.processEvents() uow = self._repo.createUnitOfWork() items = [] try: if self._thread is not None and self._thread.isRunning(): self._thread.interrupt = True self._thread.wait(5*1000) if queryText is None or queryText.strip()=="": items = uow.executeCommand(cmds.GetUntaggedItems(limit, page, orderBy)) else: queryTree = query_parser.parse(queryText) cmd = cmds.QueryItemsByParseTree(queryTree, limit, page, orderBy) items = uow.executeCommand(cmd) self._thread = ThumbnailBuilderThread(self, self._repo, items, self._lock) self.connect(self._thread, QtCore.SIGNAL("progress"), lambda percents, row: resetRow(row)) self._thread.start() except (errors.YaccError, errors.LexError) as ex: raise errors.MsgException(self.tr("Error in the query. Detail info: {}").format(str(ex))) finally: uow.close() self.setObjs(items) def isOpenItemActionAllowed(self, index): c = self.column(index.column()) if c.id == ItemsTableModel.RATING: return False else: return True
class ItemsTableModel(UnivTableModel): ROW_NUM = "row_num" ID = "id" TITLE = "title" IMAGE_THUMB = "image_thumb" TAGS = "tags" STATE = "state" #State of the item (in the means of its integrity) RATING = "rating" def __init__(self, repo, lock, userLogin): super(ItemsTableModel, self).__init__() self._repo = repo self._lock = lock self.userLogin = userLogin #This is a thread for building image thumbnails in the background self._thread = None self.queryText = "" self.limit = 0 self.page = 1 self.orderByColumnId = None self.orderDir = None self.createColumns() def createColumns(self): def formatRowNum(row, item, role): if role == Qt.DisplayRole: return str(row + 1) if role == QtCore.Qt.TextAlignmentRole: return int(QtCore.Qt.AlignRight | QtCore.Qt.AlignVCenter) if role == Qt.ToolTipRole: return self.tr("Table row number") return None self.registerColumn( UnivTableColumn(ItemsTableModel.ROW_NUM, self.tr("Row"), formatRowNum)) def formatId(row, item, role): if role == Qt.DisplayRole: return str(item.id) if role == QtCore.Qt.TextAlignmentRole: return int(QtCore.Qt.AlignRight | QtCore.Qt.AlignVCenter) return None self.registerColumn( col=UnivTableColumn(ItemsTableModel.ID, self.tr("Id"), formatId)) def formatTitle(row, item, role): if role == Qt.DisplayRole: return "<b>" + item.title + "</b>" + ( "<br/><font>" + item.data_ref.url + "</font>" if item.data_ref else "") if role == Qt.ToolTipRole: if item.data_ref is not None: s = str(item.data_ref.type) + ": " + item.data_ref.url if item.data_ref.type == db.DataRef.FILE: s += os.linesep + self.tr( "Checksum (hash): {}").format(item.data_ref.hash) s += os.linesep + self.tr( "File size: {} bytes").format(item.data_ref.size) s += os.linesep + self.tr("Date hashed: {}").format( item.data_ref.date_hashed) s += os.linesep + self.tr("Created by: {}").format( item.data_ref.user_login) s += os.linesep + self.tr("Date created: {}").format( item.data_ref.date_created) return s return None self.registerColumn( UnivTableColumn("title", self.tr("Title"), formatTitle, helpers.HTMLDelegate(self))) def formatThumbnail(row, item, role): if role != QtCore.Qt.UserRole: return None if item.data_ref is None: return None if item.data_ref.is_image(): pixmap = QtGui.QPixmap() try: self._lock.lockForRead() if len(item.data_ref.thumbnails) > 0: pixmap.loadFromData(item.data_ref.thumbnails[0].data) except Exception: traceback.format_exc() finally: self._lock.unlock() return pixmap self.registerColumn( UnivTableColumn(ItemsTableModel.IMAGE_THUMB, self.tr("Thumbnail"), formatThumbnail, delegate=helpers.ImageThumbDelegate(self))) def formatTags(row, item, role): if role == Qt.DisplayRole: return item.format_tags() if role == Qt.ToolTipRole: return item.format_field_vals() return None self.registerColumn( UnivTableColumn(ItemsTableModel.TAGS, self.tr("Tags"), formatTags, helpers.HTMLDelegate(self))) def __formatErrorSetShort(error_set): if error_set is None: return "" if len(error_set) <= 0: return self.tr("OK") elif len(error_set) > 0: return helpers.to_commalist(error_set, lambda x: __formatErrorShort(x)) def __formatErrorShort(itemErrorCode): if itemErrorCode == db.Item.ERROR_FILE_NOT_FOUND: return self.tr("File not found") elif itemErrorCode == db.Item.ERROR_FILE_HASH_MISMATCH: return self.tr("Hash mismatch") else: assert False, "Unknown error code" def formatState(row, item, role): if role == Qt.DisplayRole: try: self._lock.lockForRead() return __formatErrorSetShort(item.error) finally: self._lock.unlock() return None self.registerColumn( UnivTableColumn(ItemsTableModel.STATE, self.tr("State"), formatState)) def formatRating(row, item, role): if role == Qt.DisplayRole: ratingStr = item.getFieldValue(consts.RATING_FIELD, self.userLogin) try: rating = int(ratingStr) except: rating = 0 return rating return None def setRating(item, row, value, role): if role != Qt.EditRole: return False oldValue = item.getFieldValue(consts.RATING_FIELD, self.userLogin) if oldValue == value: return False item.setFieldValue(consts.RATING_FIELD, value, self.userLogin) uow = self._repo.createUnitOfWork() try: srcAbsPath = os.path.join( self._repo.base_path, item.data_ref.url) if item.data_ref is not None else None dstRelPath = item.data_ref.url if item.data_ref is not None else None cmd = cmds.UpdateExistingItemCommand(item, srcAbsPath, dstRelPath, self.userLogin) uow.executeCommand(cmd) return True except: item.setFieldValue(consts.RATING_FIELD, oldValue, self.userLogin) return False finally: uow.close() self.registerColumn( UnivTableColumn(ItemsTableModel.RATING, self.tr("Rating"), formatObjFun=formatRating, delegate=helpers.RatingDelegate(self), setDataFun=setRating)) def sort(self, columnIndex, order=Qt.AscendingOrder): column = self.column(columnIndex) if column.id not in [self.ID, self.TITLE, self.RATING]: return self.orderByColumnId = column.id self.orderDir = order self.query(self.queryText, self.limit, self.page) def query(self, queryText, limit=0, page=1): self.queryText = queryText self.limit = limit self.page = page directory = "ASC" if self.orderDir == Qt.AscendingOrder else "DESC" orderBy = [] if self.orderByColumnId is not None: if self.orderByColumnId == self.ID: orderBy.append(("id", directory)) elif self.orderByColumnId == self.TITLE: orderBy.append(("title", directory)) #This is not exactly sorting by pure rating, but by fields and their values... elif self.orderByColumnId == self.RATING: orderBy.append(("items_fields_field_id", "DESC")) orderBy.append(("items_fields_field_value", directory)) def resetRow(row): self.resetSingleRow(row) QtCore.QCoreApplication.processEvents() uow = self._repo.createUnitOfWork() items = [] try: if self._thread is not None and self._thread.isRunning(): self._thread.interrupt = True self._thread.wait(5 * 1000) if queryText is None or queryText.strip() == "": items = uow.executeCommand( cmds.GetUntaggedItems(limit, page, orderBy)) else: queryTree = query_parser.parse(queryText) cmd = cmds.QueryItemsByParseTree(queryTree, limit, page, orderBy) items = uow.executeCommand(cmd) self._thread = ThumbnailBuilderThread(self, self._repo, items, self._lock) self.connect(self._thread, QtCore.SIGNAL("progress"), lambda percents, row: resetRow(row)) self._thread.start() except (errors.YaccError, errors.LexError) as ex: raise errors.MsgException( self.tr("Error in the query. Detail info: {}").format(str(ex))) finally: uow.close() self.setObjs(items) def isOpenItemActionAllowed(self, index): c = self.column(index.column()) if c.id == ItemsTableModel.RATING: return False else: return True