PDA

View Full Version : Custom file browser - grouping files



chezifresh
25th June 2009, 02:21
I'm trying to create a custom image file browser. Eventually I want it to have an image preview for the selected image and other things specific to an image browser.

However, I first want to be able to group files together. I want to take a list of files such as these:



foo.0001.png
foo.0002.png
foo.0003.png
foo.0004.png
And display them like this


foo.[0001-0004].png

The builtin QFileDialog will display them as distinct files whereas I want to have an option to display them grouped.

Is it even possible to do this by subclassing QDirModel (http://doc.trolltech.com/latest/qdirmodel.html)? Because, I think that would be the nicest solution but it doesn't seem trivial. Or can this be done using a proxy model?

I can certainly write my own model from scratch (even keep it simple and ignore size and date information) but if its possible to do it with a QDirModel and/or a proxy model that would be great

aamer4yu
25th June 2009, 06:07
Might be you can subclass QDirModel and override the function QDirModel::sort . Hope it might work :)

chezifresh
15th September 2009, 20:27
Update.

Subclassing QDirModel is harder than one might think so I just created a model to mimic a QDirModel... Downsides: read only, and for the time being only presents one column "name". But thats only because its hard to determine size/date/user/etc for a group of files. I just tossed this in to a QListView and it works pretty darn well for a file open/save dialog



class QFileRangeModel(QtGui.QStringListModel):
"""A simple model that emulates a QDirModel to provide file grouping by numeric ranges"""
def __init__(self, directory=None, parent=None):
QtGui.QStringListModel.__init__(self)
if not directory:
directory = os.getcwd()

self._icon_provider = QdFileIconProvider()
self._directory = directory

self._hide_dot = True
self._hide_dotdot = False
self._show_hidden = False

self._name_filters = []

self._file_info = {}

self.setHeaderData(0, Qt.Horizontal, QtCore.QVariant("Name"), Qt.DisplayRole)
self.setDirectory(self._directory)

def setDirectory(self, directory):
"""Sets the current directory being viewed on this model"""
self._directory = directory
self.refresh()

#
# Methods to mimic the QDirModel API
#

def data(self, index, role):
"""Overridden method to allow file icons to be drawn in views"""
# same as Qt.DecorationRole
if role == QtGui.QDirModel.FileIconRole:
return QtCore.QVariant(self.fileIcon(index))
return QtGui.QStringListModel.data(self, index, role)

def flags(self, index):
return Qt.ItemIsSelectable | Qt.ItemIsDragEnabled | Qt.ItemIsDropEnabled | Qt.ItemIsEnabled

def setFilter(self, filters):
"""Interface method from QDirModel to allow filtering out certain results"""
if QtCore.QDir.NoDotAndDotDot & filters:
self._hide_dot = True
self._hide_dotdot = True
return

def setNameFilter(self, nameFilter):
"""Name filter (usually on extention) to filter out files"""
nameFilter = str(nameFilter)
match = re.match(".+\((?P<exts>.+\)", nameFilter)
if match:
return
self._name_filters = [nameFilter]
self.refresh()

def setIconProvider(self, icon_provider):
self._icon_provider = icon_provider

def iconProvider(self):
return self._icon_provider

def fileIcon(self, index):
"""Returns the icon for the given file/directory index"""
if not index.isValid:
return self._icon_provider.icon(QtGui.QFileIconProvider.C omputer)
return self._icon_provider.icon(self._file_info[str(self.fileName(index))])

def fileName(self, index):
"""Returns the basename of the file"""
return self.data(index, Qt.DisplayRole).toPyObject()

def filePath(self, index):
"""Returns the full path to the file"""
name = self.data(index, Qt.DisplayRole)
return os.path.join(self._directory, str(name.toPyObject()))

def isDir(self, index):
"""Checks if the given index is a file/dir"""
return os.path.isdir(self.filePath(index))

def refresh(self):
"""Reloads the model with a fresh call"""
cmd = "foo_ls --groupded"
output = os.popen(cmd).read()

self._file_info = {}

files = []
for line in output:
name = line.strip()
if name == "." and self._hide_dot:
continue
elif name == ".." and self._hide_dotdot:
continue
elif name.startswith(".") and not self._show_hidden:
continue
self._file_info[name] = QtCore.QFileInfo(os.path.join(self._directory, name))
files.append(name)

self.setStringList(self.customSort(files))

def customSort(self, entries, order=Qt.AscendingOrder):
"""Sorts the results in a manner similar to a QDirModel"""
dirs = []
files = []
indexes = {}
for name, info in self._file_info.iteritems():
indexes[entries.index(name)] = name
if info.isDir():
dirs.append(name)
continue
files.append(name)

reverseSort = order == Qt.DescendingOrder
files.sort(reverse=reverseSort)
dirs.sort(reverse=reverseSort)

correctOrder = []
if reverseSort:
correctOrder = files + dirs
else:
correctOrder = dirs+files

return correctOrder

def sort(self, column, order):
"""Overriden method that calls our own customSort"""
stringlist = self.stringList()
correctOrder = self.customSort(list(stringlist), order)
self.setStringList(correctOrder)

majestik666
21st September 2009, 04:05
thanks for posting this !

wil give it a try tonight :)