Solved Trying to customize the 4th column (Data Modified) of QFileSystemModel as my own data.
-
Using Qt5 - Trying to use the 4th column (Data Modified) of QFileSystemModel as my own content (since I don't need the Date Modified field, I am so close... So far I can update the header and set the data correctly to my custom text, but as soon as I try and type in the column it won't save it, it just reverts to the text I have set using data. My functions looks like this:
class MyFileSystemModel(QtWidgets.QFileSystemModel): def __init__(self, parent = None): super(MyFileSystemModel, self).__init__(parent) self.role_dictionary = { 1: QtCore.Qt.UserRole, # Project 2: QtCore.Qt.UserRole + 1} # Path ..... def data(self, index, role=QtCore.Qt.DisplayRole): if not index.isValid(): return self.nullVariant() if index.column() == 3: # Department, overriding Data Modified file_path = self.data(index, self.role_dictionary[2]) if os.path.isdir(file_path): return " " # if you don't return empty, you will get the default file time stamp else: a, b = file_path.rsplit('.', 1) # Account for files that have more then one dot in it. department = self.file_extension_lookup('.' + b) return department return super(MyFileSystemModel, self).data(index, role) def setData(self, index, value, role=QtCore.Qt.EditRole): if not index.isValid(): return False if role == QtCore.Qt.EditRole: if index.column() == 3: print(value) self.dataChanged.emit(index, index) return True return True def flags(self, index): if not index.isValid(): return None if index.column() == 3: # Department return QtCore.Qt.ItemIsEnabled | QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsEditable else: return QtCore.Qt.ItemIsEnabled | QtCore.Qt.ItemIsSelectable
I have tried EVERYTHING, originally I was just creating a QSortFilterProxyModel, with all the setData and override functions on this, and using sourceModel to set and access the data, but I have since split it out like I shown above into a QFileSystemModel and a QSortFilterProxyModel (incase I was using QSortFilterProxyModel wrong), but I still cannot get it to take the data when I type it the 4th column, it just goes back to showing the data I have set in data for the 4th column. Do I need to send the 'value' somewhere in setData? I do not have parent or index implemented, I don't think that's the issue. I tried creating a 5th column of QSortFilterProxyModel, but I could only get the header to change and data would not write anything text there at all... I tried using user roles but to be honest I don't really understand User Roles, but that's not really my question, and I don't believe they are really needed here. This feels like it should be straightforward.
I have read Advanced Qt Programming by Mark Summerfield, and have looked on the internet for days :S
I would really appreciate some help, this is sort of niche topic,
Thankyou, -
@K_17_M
In yourdata()
case you do yourif index.column() == 3: return ...
without looking at therole
parameter. That's not right.In your
setData()
case forif index.column() == 3:
I see you emitting adataChanged()
but I don't see you actually storing the value passed in anywhere.Quite why you are "overriding" the existing Date Modified column for some other purpose I don't know, I would have thought you might add a new column.
-
@K_17_M
In yourdata()
case you do yourif index.column() == 3: return ...
without looking at therole
parameter. That's not right.In your
setData()
case forif index.column() == 3:
I see you emitting adataChanged()
but I don't see you actually storing the value passed in anywhere.Quite why you are "overriding" the existing Date Modified column for some other purpose I don't know, I would have thought you might add a new column.
-
Oh shoot, copy and paste error, I do have this in my data, I am sorry.
def data(self, index, role=QtCore.Qt.DisplayRole): if not index.isValid(): return self.nullVariant() if role == QtCore.Qt.DisplayRole or role == QtCore.Qt.EditRole: if index.column() == 3: # Department, overriding Data Modified file_path = self.data(index, self.role_dictionary[2]) if os.path.isdir(file_path): return " " # if you don't return empty, you will get the default file time stamp else: a, b = file_path.rsplit('.', 1) # Account for files that have more then one dot in it. department = self.file_extension_lookup('.' + b) return department return super(MyFileSystemModel, self).data(index, role)
Thanks for responding, so originally I was only creating a custom QSortFilterProxyModel (with all the overrides there)and using the out of the box QFileSystemModel, so when I tried to create a 5th column it didn't work, and since I was so far down the coding rabbit hold I was trying to shoe horn in the only columns I could get working with my own data. After a big research session last night I realized I need to create a custom QFileSystemModel and a QSortFilterProxyModel and move over all my custom functions to the QFileSystemModel (minus filterAcceptsRow). This since has allowed me to add a 5th column and display my data in 'data' there, but the setData still doesn't work.
I think you are onto something with your point on "I don't see you actually storing the value passed in anywhere.", Do I have to store the value in my own data set? Like maybe a dictionary? and just the act of saving and then reading from there allows it to be editable? I went down this road with the checkbox in column 0, I just thought it was different for some reason...
-
@K_17_M said in Trying to customize the 4th column (Data Modified) of QFileSystemModel as my own data.:
I think you are onto something with your point on "I don't see you actually storing the value passed in anywhere.", Do I have to store the value in my own data set?
Yes :)
In your
data()
method you get yourindex.column() == 3
value ultimately from yourfile_path = self.data(index, self.role_dictionary[2])
. (Probably not right, you're trying to store it in a role here, I would add my own datastore. But in any case...).However, in your
setData()
case you do nothing with the passed invalue
(other than print it). You have store that value somewhere, in such a way that when you are asked to return it in thedata()
case you return that value. Else, as you said, you'll "revert" after editing. You need to pair this with your currentfile_path = self.data(index, self.role_dictionary[2])
, or whatever you have there indata()
. -
Thanks so much, you made me look at the issue differently and I FINALLY have it working, it's a miracle! I think I thought because originally I was using the Date Modified 4th column in the QFileSystemModel, I thought it would just store my data since it stores the date modified data, but that is not the case, so once I created the 5th column and hid the 4th column it was obvious no one was storing my data, I don't know why it took me so long to come to this realization, I did it for the checkbox in column 0 last week! The role_dictionary[2] was just one of the millions trys and because it was returning the path correctly I just left it, I removed it and am using ```
folder_path = self.filePath(index)AGAIN I really appreciate your time on this Monday morning!