def exportThumbnail(self, report_path, thumbpath, name, node, size=None): self.thumbnailer = Thumbnailer() if self.thumbnailer.isThumbnailable(node): pixmap = self.thumbnailer.generate(node, iconSize=256, frames=10, blocking=True) self.thumbnailer.unregister() if pixmap: try: exportPath = os.path.join(report_path, os.path.join(thumbpath, name)) array = QByteArray() qfile = QBuffer(array) qfile.open(QIODevice.ReadWrite) pixmap.save(qfile, 'JPG') qfile.seek(0) with open(exportPath, 'wb') as f: f.write(qfile.read(qfile.size())) qfile.close() return True except Exception as e: qfile.close() return False else: return False
def generateThumbnail(self): self.thumbnailer = Thumbnailer() self.connect(self.thumbnailer, SIGNAL("ThumbnailUpdate"), self.updateThumbnail) pixmap = self.thumbnailer.generate(self.node, iconSize=self.IconSize, frames=self.Frames) if pixmap: self.updateThumbnail(self.node, pixmap)
def __init__(self, parent, request): QNetworkReply.__init__(self, parent) self.qbuffer = None self.connect(self, SIGNAL('abouteToClose()'), self.__close) self.byteArray = QByteArray() self.qbuffer = QBuffer(self.byteArray) self.node = vfs().getnode(str(request.url().path().toUtf8())) self.thumbnailer = Thumbnailer() self.connect(self.thumbnailer, SIGNAL("ThumbnailUpdate"), self.updateThumbnail) self.setRequest(request) self.setOperation(QNetworkAccessManager.GetOperation) mime = "image/jpg" self.setHeader(QNetworkRequest.ContentTypeHeader, QVariant(mime)) self.open() self.setUrl(request.url()) self.connect(parent, SIGNAL("ready"), self.ready) self.ready()
def __init__(self, selection): QAbstractItemModel.__init__(self) self._list = [] self._rows = [] self._current_row = 0 self._row_selected = 0 self._thumb = True self._visible_rows = 0 self._visible_cols = 0 self._recursive = False self._root = None self.selection = selection if self.selection != None: self.connect(self.selection, SIGNAL("selectionChanged"), self.updateSelected) self.setDefaultAttributes() self.connectSignals() self.thumbnailer = Thumbnailer() self.connect(self.thumbnailer, SIGNAL("ThumbnailUpdate"), self.thumbnailUpdate) self.headerorder = {0:0}
def __init__(self, parent): QTreeWidget.__init__(self) self.treeItemMenu = ReportTreeItemMenu(self) self.treeNewItemMenu = ReportTreeNewItemMenu(self) self.header().hide() self.connect(parent, SIGNAL("newCategory"), self.newCategory) self.connect(parent, SIGNAL("newPage"), self.newPage) self.connect(self, SIGNAL("itemClicked(QTreeWidgetItem*, int)"), self.clicked) self.thumbnailer = Thumbnailer() self.reportManager = ReportManager() self.__categoryItems = []
def dumpsJSON(self): thead = [] for head in self.thead: thead.append(head['title']) if NodeListFragment.HeaderAttributes: for attribute in NodeListFragment.HeaderAttributes: thead.append(attribute) buff = '{"title": "' + self.title + '",' + '"widget": "node_list", "thead":' buff += json.dumps(thead) buff += ', "view" : ' + str(self.view) + ', "data" : [' for node in self.nodes: try: rowjson = {} rowjson['widget'] = 'node' for head in self.thead: cb = head['callback'](node) if type(cb) == str: cb = cb.decode('utf-8', 'replace').encode('utf-8') rowjson[head['title']] = cb if self.gui: #Need qt gui for QPixmap or will crash in console #print 'self as GUI !', QApplication.instance() self.thumbnailer = Thumbnailer() if self.thumbnailer.isThumbnailable(node): rowjson[ "thumb"] = "dff-node-thumbnail://" + node.absolute( ).decode('utf-8', 'replace').encode('utf-8') self.thumbnailer.unregister() rowjson['row_details'] = { 'widget': 'node_attribute', 'data': self.attributesToMap(node.attributes()) } buff += json.dumps(rowjson) buff += "," except UnicodeError as e: print "Can't dump node " + str( node.absolute()) + " : " + str(e) buff += "]}" return buff
class NodeListFragment(ReportPageFragment): DefaultHeader = [ { 'title': 'name', 'callback': lambda Node: Node.name() }, { 'title': 'size', 'callback': lambda Node: Node.size() }, { 'title': 'tags', 'callback': lambda Node: getTags(Node) }, ] ListView = 0 GalleryView = 1 DetailedAttributes = None HeaderAttributes = None HeaderAttributesName = None def __init__(self, title, nodes, thead, view): ReportPageFragment.__init__(self, title) self.nodes = nodes self.thead = thead self.view = view self.extract = Extract() self.filepath = None self.thumbpath = None if QApplication.instance(): self.gui = True else: self.gui = False #XXX header don't support '.' in name def addNode(self, node): self.nodes.append(node) def elements(self): return self.nodes def dumpsJSON(self): thead = [] for head in self.thead: thead.append(head['title']) if NodeListFragment.HeaderAttributes: for attribute in NodeListFragment.HeaderAttributes: thead.append(attribute) buff = '{"title": "' + self.title + '",' + '"widget": "node_list", "thead":' buff += json.dumps(thead) buff += ', "view" : ' + str(self.view) + ', "data" : [' for node in self.nodes: try: rowjson = {} rowjson['widget'] = 'node' for head in self.thead: cb = head['callback'](node) if type(cb) == str: cb = cb.decode('utf-8', 'replace').encode('utf-8') rowjson[head['title']] = cb if self.gui: #Need qt gui for QPixmap or will crash in console #print 'self as GUI !', QApplication.instance() self.thumbnailer = Thumbnailer() if self.thumbnailer.isThumbnailable(node): rowjson[ "thumb"] = "dff-node-thumbnail://" + node.absolute( ).decode('utf-8', 'replace').encode('utf-8') self.thumbnailer.unregister() rowjson['row_details'] = { 'widget': 'node_attribute', 'data': self.attributesToMap(node.attributes()) } buff += json.dumps(rowjson) buff += "," except UnicodeError as e: print "Can't dump node " + str( node.absolute()) + " : " + str(e) buff += "]}" return buff def writeSize(self, exportContent): size = 0 if exportContent: for node in self.nodes: size += node.size() return size def writeJSON__(self, fd, page_path, report_path, exportContent=True): self.filepath = page_path + "/" + 'files' self.thumbpath = page_path + "/" + 'thumbs' buff = '{"title": "' + self.title + '",' + '"widget": "node_list", "thead":' fd.write(buff) thead = [] for head in self.thead: thead.append(head['title']) #XXX header don't support '.' in name if NodeListFragment.HeaderAttributesName: for name in NodeListFragment.HeaderAttributesName: thead.append(name) json.dump(thead, fd) bdata = ', "view" : ' + str(self.view) + ', "data" : [' fd.write(bdata) self.notifyWrite(ReportPageFragment.EventWriteElements, len(self.nodes)) for node in self.nodes: self.notifyWrite(ReportPageFragment.EventWriteElementStart, node.absolute()) try: filename = None if exportContent: filename = self.exportNode(node, self.filepath, report_path) self.nodeToJSON(node, filename, fd, report_path, page_path, True) fd.write(',\n') except Exception as e: print "Can't write node " + str( node.absolute()) + " : " + str(e) self.notifyWrite(ReportPageFragment.EventWriteElementFinish, node.absolute()) fd.write("]}") def attributesToMap(self, attributes): attributesMap = {} for key, variantMap in attributes.iteritems(): vmap = self.recurseVariant(variantMap, {}, '') if len(vmap): attributesMap[key] = vmap attributesMap = OrderedDict( sorted(attributesMap.items(), key=lambda t: t[0])) return attributesMap def recurseVariant(self, variant, varMap, keyPath): if isinstance(variant, VMap): for key, vvar in variant.iteritems(): if len(keyPath): self.recurseVariant(vvar, varMap, keyPath + '.' + str(key)) else: self.recurseVariant(vvar, varMap, str(key)) if isinstance(variant, VList): l = [] for i in range(len(variant)): self.recurseVariant(variant[i], varMap, keyPath + ' (' + str(i) + ')') if isinstance(variant, Variant) or isinstance(variant, RCVariant): val = variant.value() if isinstance(val, VMap) or isinstance(val, VList): self.recurseVariant(val, varMap, keyPath) else: if isinstance(val, DateTime): try: val = str(val) except: val = "Invalid" if type(val) == str: val = val.decode('utf-8', 'replace').encode('utf-8') translated = False if NodeListFragment.DetailedAttributes: for ( finalName, attributeName ) in NodeListFragment.DetailedAttributes: #HeaderAttributes depend of this because it's attribute filled in the table will use the result of this function called by attributesMap if there is no detailed attributes there will no translation and the header can't be filled if keyPath == attributeName: varMap[finalName] = val if not translated: varMap[keyPath] = val varMap = OrderedDict(sorted(varMap.items(), key=lambda t: t[0])) return varMap def findInAttributesMap(self, attribute, attributesMap): for module in attributesMap: moduleAttributes = attributesMap.get(module) if moduleAttributes: result = moduleAttributes.get(attribute) if result: return result return "" def nodeToJSON(self, node, filename, fd, report_path, page_path, thumb=False): rowjson = {} rowjson['widget'] = 'node' attrMap = self.attributesToMap(node.attributes()) for head in self.thead: cb = head['callback'](node) if type(cb) == str: cb = cb.decode('utf-8', 'replace').encode('utf-8') rowjson[head['title']] = cb if NodeListFragment.HeaderAttributes: for (name, attribute) in NodeListFragment.HeaderAttributes: result = self.findInAttributesMap(name, attrMap) rowjson[name] = result if filename: rowjson["file"] = self.filepath + "/" + filename if thumb and self.gui: if self.exportThumbnail(report_path, self.thumbpath, filename + '.jpg', node): rowjson["thumb"] = self.thumbpath + "/" + filename + '.jpg' rowjson['row_details'] = {'widget': 'node_attribute', 'data': attrMap} try: json.dump(rowjson, fd) except UnicodeError as e: print 'report.fragment.nodeToJSON failed ' + str(e) print rowjson def exportThumbnail(self, report_path, thumbpath, name, node, size=None): self.thumbnailer = Thumbnailer() if self.thumbnailer.isThumbnailable(node): pixmap = self.thumbnailer.generate(node, iconSize=256, frames=10, blocking=True) self.thumbnailer.unregister() if pixmap: try: exportPath = os.path.join(report_path, os.path.join(thumbpath, name)) array = QByteArray() qfile = QBuffer(array) qfile.open(QIODevice.ReadWrite) pixmap.save(qfile, 'JPG') qfile.seek(0) with open(exportPath, 'wb') as f: f.write(qfile.read(qfile.size())) qfile.close() return True except Exception as e: qfile.close() return False else: return False def exportNode(self, node, path, report_path): abspath = os.path.join(report_path, path) try: local_path = self.extract.extractFile(node, abspath) except Exception as e: pass if local_path: return os.path.basename(local_path) else: return None
class NodeThumbnailRenderReply(QNetworkReply): def __init__(self, parent, request): QNetworkReply.__init__(self, parent) self.qbuffer = None self.connect(self, SIGNAL('abouteToClose()'), self.__close) self.byteArray = QByteArray() self.qbuffer = QBuffer(self.byteArray) self.node = vfs().getnode(str(request.url().path().toUtf8())) self.thumbnailer = Thumbnailer() self.connect(self.thumbnailer, SIGNAL("ThumbnailUpdate"), self.updateThumbnail) self.setRequest(request) self.setOperation(QNetworkAccessManager.GetOperation) mime = "image/jpg" self.setHeader(QNetworkRequest.ContentTypeHeader, QVariant(mime)) self.open() self.setUrl(request.url()) self.connect(parent, SIGNAL("ready"), self.ready) self.ready() def ready(self): if self.node.dataType().find('video') != -1: pixmap = self.thumbnailer.generate(self.node, iconSize=128, frames=10) else: pixmap = self.thumbnailer.generate(self.node, iconSize=256, frames=10) if pixmap: self.updateThumbnail(self.node, pixmap) def updateThumbnail(self, node, pixmap): if pixmap == None: pixmap = QPixmap(":file_broken.png") pixmap.save(self.qbuffer, 'JPG') self.qbuffer.seek(0) QTimer.singleShot(0, self, SIGNAL("readyRead()")) QTimer.singleShot(0, self, SIGNAL("finished()")) def abort(self): self.close() def __del__(self): self.thumbnailer.unregister() def open(self, mode=None): try: self.qbuffer.open(QIODevice.ReadWrite | QIODevice.Unbuffered) self.setOpenMode(QIODevice.ReadWrite | QIODevice.Unbuffered) return True except (AttributeError, IOError): return False def seek(self, pos): if self.qbuffer: return self.qbuffer.seek(pos) return False def __close(self): if self.qbuffer: self.qbuffer.close() self.qbuffer = None return True def readData(self, size): if self.qbuffer: return self.qbuffer.read(size) return "" def pos(self): if self.qbuffer: return self.qbuffer.pos() return 0 def isSequential(self): if self.qbuffer: return self.qbuffer.isSequential() return False def size(self): return self.qbuffer.size() def reset(self): if self.qbuffer: self.qbuffer.seek(0) return True return False def atEnd(self): if self.qbuffer: return self.qbuffer.atEnd() return False
class ThumbnailVideoView(QWidget, Script): IconSize = 256 Frames = 10 def __init__(self): Script.__init__(self, "thumbnailvideo") self.icon = None self.vfs = vfs.vfs() def start(self, args): try: self.preview = args["preview"].value() except IndexError: self.preview = False try: self.node = args["file"].value() except KeyError: pass def g_display(self): QWidget.__init__(self) self.copyMenu = CopyMenu(self) self.copySelectionMenu = CopySelectionMenu(self) self.rubberBand = None self.hlayout = QVBoxLayout() self.setLayout(self.hlayout) self.menuLayout = QHBoxLayout() self.hlayout.addLayout(self.menuLayout) self.frameLayout = QFormLayout() self.menuLayout.addLayout(self.frameLayout) self.frameNumberEdit = QLineEdit(str(self.Frames)) self.frameNumberEdit.setFixedWidth(40) self.frameNumberEdit.setValidator(QIntValidator(0, 256)) self.frameLayout.addRow("Number of frame: ", self.frameNumberEdit) self.connect(self.frameNumberEdit, SIGNAL("textChanged(QString)"), self.setFrameNumber) self.iconLayout = QFormLayout() self.menuLayout.addLayout(self.iconLayout) self.iconSizeEdit = QLineEdit(str(self.IconSize)) self.iconSizeEdit.setFixedWidth(40) self.iconSizeEdit.setValidator(QIntValidator(0, 512)) self.iconLayout.addRow("Size: ", self.iconSizeEdit) self.connect(self.iconSizeEdit, SIGNAL("textChanged(QString)"), self.setIconSize) self.refreshButton = QPushButton("Refresh") self.menuLayout.addWidget(self.refreshButton) self.connect(self.refreshButton, SIGNAL("clicked()"), self.generateThumbnail) self.scrollArea = QScrollArea() self.hlayout.addWidget(self.scrollArea) self.generateThumbnail() def mousePressEvent(self, event): self.dragPosition = event.pos() if not self.rubberBand: self.rubberBand = QRubberBand(QRubberBand.Rectangle, self) self.rubberBand.setGeometry(QRect(self.dragPosition, QSize())) self.rubberBand.show() def mouseMoveEvent(self, event): self.rubberBand.setGeometry( QRect(self.dragPosition, event.pos()).normalized()) def mouseReleaseEvent(self, event): if not self.rubberBand.size().isEmpty(): rect = QRect(self.rubberBand.pos(), self.rubberBand.size()) rect.moveLeft(rect.left() - (self.width() - self.thumbLabel.pixmap().width()) / 2.0) rect.moveTop(rect.top() - (self.height() - self.thumbLabel.pixmap().height()) / 2.0) self.currentSelection = rect self.copySelectionMenu.popup(QCursor.pos()) else: self.copyMenu.popup(QCursor.pos()) self.rubberBand.hide() def copySelectionToClipboard(self): QApplication.clipboard().setPixmap(self.thumbLabel.pixmap().copy( self.currentSelection)) def copyPixmapToClipboard(self): QApplication.clipboard().setPixmap(self.thumbLabel.pixmap()) def setIconSize(self, size): ThumbnailVideoView.IconSize = int(size) def setFrameNumber(self, number): ThumbnailVideoView.Frames = int(number) def generateThumbnail(self): self.thumbnailer = Thumbnailer() self.connect(self.thumbnailer, SIGNAL("ThumbnailUpdate"), self.updateThumbnail) pixmap = self.thumbnailer.generate(self.node, iconSize=self.IconSize, frames=self.Frames) if pixmap: self.updateThumbnail(self.node, pixmap) def updateThumbnail(self, node, pixmap): if pixmap: self.thumbLabel = QLabel() self.thumbLabel.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) self.thumbLabel.setWordWrap(True) self.thumbLabel.setPixmap(pixmap) self.scrollArea.setWidget(self.thumbLabel) else: self.thumbLabel.setText("Can't render, video is corrupted.") self.thumbLabel.setAlignment(Qt.AlignCenter) self.thumbnailer.unregister() def updateWidget(self): pass
class NodeListModel(QAbstractItemModel): def __init__(self, selection): QAbstractItemModel.__init__(self) self._list = [] self._rows = [] self._current_row = 0 self._row_selected = 0 self._thumb = True self._visible_rows = 0 self._visible_cols = 0 self._recursive = False self._root = None self.selection = selection if self.selection != None: self.connect(self.selection, SIGNAL("selectionChanged"), self.updateSelected) self.setDefaultAttributes() self.connectSignals() self.thumbnailer = Thumbnailer() self.connect(self.thumbnailer, SIGNAL("ThumbnailUpdate"), self.thumbnailUpdate) self.headerorder = {0:0} def thumbnailUpdate(self, node, pixmap): currentRow = self.currentRow() visibleRow = self.visibleRows() nodeList = self.list() currentList = nodeList[currentRow:currentRow + visibleRow] index = 0 for cnode in currentList: if node.uid() == cnode.uid(): modelIndex = self.index(index, 0) self.emit(SIGNAL("dataChanged"), modelIndex, modelIndex) index += 1 def _removeNode(self, node): children = node.children() for child in children: self._removeNode(child) for n in self._list: if n.uid() == node.uid(): self._list.remove(n) self._row_selected = 0 for n in self._rows: if n.uid() == node.uid(): self._rows.remove(n) def removeNode(self, node): try: if self._root == None or (self._root.path().find(node.parent().path()) != -1): self._row_selected = 0 self.changeList(node.parent(), self._recursive, None) except Exception as e : pass self._removeNode(node) def vfsNotification(self, node, eventType = None): if eventType == 0xde1: pass #called by noedelistwidget else: if node.parent().uid() == self._root.uid(): self.changeList(self._root, self._recursive, self._list[self._row_selected]) def updateSelected(self, count): self.emit(SIGNAL("layoutChanged()")) def connectSignals(self): self.connect(self, SIGNAL("appendList"), self.appendList) def setData(self, index, value, role): """ \reimp Set the data which value is `value` at index `index` with role `role`. \return `True` if no error occured, `False` otherwise. """ if not index.isValid(): return QVariant() column = index.column() if role == Qt.CheckStateRole: if column == HNAME: node = self.VFS.getNodeById(index.internalId()) if node == None: pass if value == Qt.Unchecked: if (node.uid(), 1) in self.checkedNodes: self.checkedNodes.remove((node.uid(), 1)) else: self.checkedNodes.add((node.uid() , 1)) QAbstractItemModel.setData(self, index, value, role) return True def changeList(self, root, recursive=False, selected=None): """ Change the current list based on root children. If recursive is True, the list will be based on the recursion If selected is provided it will automatically be the current row """ if root != None: self._root = root self._recursive = recursive self._list = [] self.row_selected = 0 self._current_row = 0 if recursive: self._fillRecursiveList(root.children()) else: self._list = root.children() self.sort(self.headerorder.keys()[0], self.headerorder[self.headerorder.keys()[0]]) idx = 0 if not recursive and selected != None: for i in xrange(0, len(self._list)): if selected.uid() == self._list[i].uid(): idx = i break self.emit(SIGNAL("maximum"), len(self._list)) if idx > self._current_row + self._visible_rows: self._current_row = idx self.select(0) else: self.select(idx) self.emit(SIGNAL("changeList")) def currentRoot(self): return self._root def recursive(self): return self._recursive def updateList(self, nodes, recursive=False, selected=None): """ Update list from an existing one. Useful when switching from filtered view """ if len(nodes): self._recursive = recursive self._list = nodes if not recursive and selected != None: for i in xrange(0, len(self._list)): if selected.uid() == self._list[i].uid(): self._current_row = i self.row_selected = i break self.emit(SIGNAL("maximum"), len(self._list)) self.select(0) self.emit(SIGNAL("changeList")) def _fillRecursiveList(self, nodes): for node in nodes: self._list.append(node) if node.hasChildren(): self._fillRecursiveList(node.children()) def appendList(self, node): """ Append a new node to the existing model's list and emit an appended signal with the new size. """ if node != None: try: self._list.append(node) self.emit(SIGNAL("nodeAppended")) self.emit(SIGNAL("maximum"), len(self._list)) self.refresh(self._current_row) except: print "Error while appending node" return def defaultAttributes(self): return self._default_attributes def clearList(self): self.emit(SIGNAL("clearList")) self._recursive = False self._list = [] self._current_row = 0 self.refresh(self._current_row) def columnCount(self, index): attrs = self.availableAttributes() return len(attrs) def data(self, index, role): attributes = self.availableAttributes() if not index.isValid(): return QVariant() if index.row() > len(self._list) or index.row() < 0: return QVariant() try: node = self._rows[index.row()] except: return QVariant() if role == Qt.DisplayRole : attrpath = str(unicode(attributes[index.column()]).encode('utf-8')) if attrpath == "name": return QVariant(QString.fromUtf8(node.name())) elif attrpath == "size": return QVariant(node.size()) elif attrpath == "extension": return QVariant(QString.fromUtf8(node.extension())) elif attrpath == "path": if isinstance(node, VLink): return QVariant(QString.fromUtf8(node.linkPath())) else: return QVariant(QString.fromUtf8(node.path())) elif attrpath == "absolute": if isinstance(node, VLink): return QVariant(QString.fromUtf8(node.linkAbsolute())) else: return QVariant(QString.fromUtf8(node.absolute())) elif attrpath == "module": if node.fsobj(): return QVariant(QString.fromUtf8(node.fsobj().name)) return QVariant() elif attrpath == "has children": if isinstance(node, VLink): return QVariant(node.linkHasChildren()) else: return QVariant(node.hasChildren()) elif attrpath == "child count": if isinstance(node, VLink): return QVariant(node.linkChildCount()) else: return QVariant(node.childCount()) elif attrpath == "is deleted": return QVariant(node.isDeleted()) elif attrpath == "tags": #Special case tag use a delegate to draw boxes return QVariant() else: try : val = node.attributesByName(attrpath, ABSOLUTE_ATTR_NAME) except Exception as e: print "NodeListModel data can't get attribute " + attrpath + " by name " + str(e) return QVariant() if len(val) == 1: if val[0].type() == typeId.DateTime: dateTime = val[0].value() if dateTime: try: return QVariant(str(dateTime)) except: return QVariant() elif val[0].type() == typeId.String: return QVariant(QString.fromUtf8(val[0].value())) else: return QVariant(val[0].value()) else: return QVariant() if role == Qt.ToolTipRole : return QVariant(QString.fromUtf8(node.name())) # Display icons if (role == Qt.DecorationRole) and (attributes[index.column()] == "name"): pixmap = None if self._thumb: if self.thumbnailer.isThumbnailable(node): pixmap = self.thumbnailer.generate(node) if pixmap is None: pixmap = QPixmap(":file_temporary.png") if not pixmap: pixmap = self.getIconPixmap(node) if not pixmap: pixmap = QPixmap(node.icon()) if isinstance(node, VLink): pixmap = pixmap.scaled(QSize(128, 128), Qt.KeepAspectRatio) painter = QPainter(pixmap) linkPixmap = QPixmap(":vlink") painter.drawPixmap(0, 0, linkPixmap) painter.end() elif node.hasChildren(): try: pfsobj = node.children()[0].fsobj().this except AttributeError: pfsobj = None try: nfsobj = node.fsobj().this except AttributeError: nfsobj = None if pfsobj != nfsobj: pixmap = pixmap.scaled(QSize(128, 128), Qt.KeepAspectRatio) painter = QPainter(pixmap) rootPixmap = QPixmap(":root") painter.drawPixmap(0, 0, rootPixmap) painter.end() return QVariant(QIcon(pixmap)) if role == Qt.BackgroundRole: if index.row() == self.activeSelection(): palette = QPalette().color(QPalette.Highlight) return QVariant(QColor(palette)) if role == Qt.ForegroundRole: if index.row() == self.activeSelection(): palette = QPalette().color(QPalette.HighlightedText) return QVariant(QColor(palette)) if node.isDeleted(): return QVariant(QColor(Qt.red)) if (role == Qt.CheckStateRole) and (attributes[index.column()] == "name"): if node.uid() in self.selection.get(): return Qt.Checked else: return Qt.Unchecked return QVariant() def setThumb(self, state): self._thumb = state def getIconPixmap(self, node): ext = self.getExtension(node) if ext != None: if ext in IMAGES: return QPixmap(":image.png") elif ext in AUDIO: return QPixmap(":sound.png") elif ext == "pdf": return QPixmap(":pdf.png") elif ext in DOCUMENT: return QPixmap(":document.png") elif ext in VIDEO: return QPixmap(":video.png") elif ext in ARCHIVES: return QPixmap(":zip") elif ext in SPREADSHEET: return QPixmap(":spreadsheet.png") else: return None def getExtension(self, node): name = node.name() sext = name.split(".") if len(sext) > 1: return sext[len(sext) - 1] else: return None def getNode(self, row): try: node = self._list[row] if node: return node else: return None except IndexError: return None def index(self, row, column, parent = QModelIndex()): if not self.hasIndex(row, column, parent): return QModelIndex() if not parent.isValid(): index = self.createIndex(row, column, self._rows[row]) return index return QModelIndex() def parent(self, index): return QModelIndex() def refresh(self, start): llist = len(self._list) if start < 0: rstart = 0 elif (start >= llist): # End of list rstart = llist - (self._visible_rows) if rstart < 0: rstart = 0 # elif ((llist - start) <= self._visible_rows + 1): # rstart = self._current_row # if rstart < 0: # rstart = 0 else: rstart = start # End of List range if (rstart + self._visible_rows) > len(self._list): end = len(self._list) else: end = rstart + self._visible_rows + 1 self.resetDisplay() try: tmplist = self._list[rstart:end] except IndexError: return try: for nodeId in range(0, len(tmplist)): if tmplist[nodeId] != None: self._rows.append(tmplist[nodeId]) self.emit(SIGNAL("layoutAboutToBeChanged()")) self.emit(SIGNAL("layoutChanged()")) if self._current_row >= 0: self._current_row = rstart else: self._current_row = 0 self.emit(SIGNAL("current"), self._current_row) except IndexError: print "Error while refreshing model" pass def resetDisplay(self): if len(self._rows) > 0: self._rows = [] self.emit(SIGNAL("layoutAboutToBeChanged()")) self.emit(SIGNAL("layoutChanged()")) def rowCount(self, parent = None): return len(self._rows) def currentRow(self): return self._current_row def size(self): return len(self._list) def setVisibleRows(self, rows): self._visible_rows = rows + 1 self.emit(SIGNAL("maximum"), len(self._list)) if self._visible_rows > self.size(): self.emit(SIGNAL("hideScroll")) self.refresh(self._current_row) def visibleRows(self): return self._visible_rows def seek(self, position, where = 0): if where == 0: self.refresh(position) elif where == 1: pos = self._current_row + position self.refresh(pos) else: self.refresh(self._current_row) def select(self, row): """ Set absolute selected row id in model's list """ absrow = self._current_row + row try: node = self._list[absrow] self._row_selected = absrow self.refresh(self._current_row) self.emit(SIGNAL("nodeListClicked"), Qt.NoButton) return True except: return False def activeSelection(self): """ Return relative selected row id """ return self._row_selected - self._current_row def currentNode(self): try: node = self._list[self._row_selected] return node except: return None def nodeSelected(self): nodes = [] nodes.append(self._list[self._row_selected]) return nodes def setDefaultAttributes(self): self._default_attributes = ["name", "size","tags", "path", "extension", "absolute", "module", "has children", "child count", "is deleted"] self.setSelectedAttributes(["name", "size", "tags", "path"]) def setSelectedAttributes(self, attributes): self._selected_attributes = attributes self.refresh(self._current_row) def selectedAttributes(self): return self._selected_attributes def availableAttributes(self): attrs = self.selectedAttributes()[:] return attrs def setHeaderData(self, section, orientation, value, role): self.emit(SIGNAL("layoutAboutToBeChanged()")) QAbstractItemModel.setHeaderData(self, section, orientation, value, role) self.emit(SIGNAL("layoutChanged()")) def headerData(self, section, orientation, role=Qt.DisplayRole): if role != Qt.DisplayRole: return QVariant() if orientation == Qt.Horizontal: attrs = self.availableAttributes() return QVariant(attrs[section]) def sort(self, column, order): """ Sort model's list and check. """ self.headerorder.clear() self.headerorder[column] = order QApplication.setOverrideCursor(QCursor(Qt.WaitCursor)) if order == Qt.DescendingOrder: Reverse = True else: Reverse = False attrs = self.availableAttributes() try: attrpath = str(unicode(attrs[column]).encode('utf-8')) except IndexError: QApplication.restoreOverrideCursor() self.headerorder.clear() self.headerorder = {0:0} self.refresh(0) self.select(0) return if isinstance(self._list, VecNode): tmplist = [] for i in range(0, len(self._list)): tmplist.append(self._list[i]) self._list = tmplist if attrpath in self._default_attributes: if attrpath == "name": self._list = sorted(self._list, cmp=locale.strcoll, key=lambda Node: Node.name(), reverse=Reverse) elif attrpath == "size": self._list = sorted(self._list, key=lambda Node: Node.size(), reverse=Reverse) elif attrpath == "extension": self._list = sorted(self._list, cmp=locale.strcoll, key=lambda Node: Node.extension(), reverse=Reverse) elif attrpath == "path": self._list = sorted(self._list, cmp=locale.strcoll, key=lambda Node: Node.path(), reverse=Reverse) elif attrpath == "absolute": self._list = sorted(self._list, cmp=locale.strcoll, key=lambda Node: Node.absolute(), reverse=Reverse) elif attrpath == "module": self._list = sorted(self._list, cmp=self.cmp_fsobj, key=lambda Node: Node.fsobj(), reverse=Reverse) elif attrpath == "has children": self._list = sorted(self._list, key=lambda Node: Node.hasChildren(), reverse=Reverse) elif attrpath == "child count": self._list = sorted(self._list, key=lambda Node: Node.childCount(), reverse=Reverse) elif attrpath == "is deleted": self._list = sorted(self._list, key=lambda Node: Node.isDeleted(), reverse=Reverse) elif attrpath == "tags": self._list = sorted(self._list, key=lambda Node: len(Node.tags()), reverse=Reverse) else: self._list = sorted(self._list, cmp=self.cmp_none, key=lambda Node: self.attributesByName(Node, attrpath, ABSOLUTE_ATTR_NAME), reverse=Reverse) QApplication.restoreOverrideCursor() self.refresh(0) self.select(0) return def cmp_fsobj(self, x, y): try: return cmp(x.name, y.name) except AttributeError: if x == y == None: return 0 elif x == None: return -1 elif y is None: return 1 def cmp_none(self,x, y): try: return cmp(x, y) except TypeError: if x == None and y == None: return 0 elif x == None: return -1 elif y is None: return 1 except ValueError: if x is None and y is None: return 0 elif x is None: return -1 elif y is None: return 1 def attributesByName(self, node, attrpath, ABSOLUTE_ATTR_NAME): val = node.attributesByName(attrpath, ABSOLUTE_ATTR_NAME) if len(val) == 1: if val[0].type() == typeId.DateTime: return DateTime(val[0].value()) #must copy because or set variant this own to false because rc_variant store DateTime* that is deleted at function return else: val = val[0].value() return val def list(self): return self._list def allListChecked(self): checked = self.selection.get() for node in self._list: if not node.uid() in checked: return False return True def selectAll(self): for node in self._list: self.selection.add(node) def unselectAll(self): for node in self._list: self.selection.rm(node)