Treeview + QFileSystemModel, how can i retrieve multi selection list
-
Hello Guys,
I have alot of queries, this is just tip of the iceberg.
I create a treeview with qfilesystemmodel for folder icons visibility all worked fine.(any better approach please let me know)
What i want, is there by any chance we can get multiselection list(drag select list of items from tree view), because i was successful with single toggle, below is test codeindex = self.qtreeview.currentIndex() for ix in self.qtreeview.selectionModel().selectedIndexes(): text = ix.data(QtCore.Qt.DisplayRole) # or ix.data() print(text) print(self.model.filePath(index))
as you can see above for loop, yes it still considers only single click item
and if possible can you provide an eg. -
@blossomsg Hi,
Did you configure the tree view to support extended or multiple selection ?
tree->setSelectionMode(QAbstractItemView.ExtendedSelection);
see https://doc.qt.io/qt-5/qabstractitemview.html#selectionMode-prop
-
Hey @Gojir4 ,
Yes i did
self.treeview.setSelectionMode(QtWidgets.QAbstractItemView.ExtendedSelection)
so selection works fine, after the selection i want to query all the highlighted selections
and pyside2 should return me object or str or unicode, so through that i can extract exact path of all the highlighted items -
@blossomsg I'm not sure to understand what is the problem here. anyway here is a small example using signal
selectionChanged
fromQItemSelectionModel
.from PySide2.QtWidgets import QTreeView, QAbstractItemView, QApplication from PySide2.QtGui import QStandardItemModel, QStandardItem from PySide2.QtCore import Qt, QObject, QItemSelectionModel import sys a = QApplication(sys.argv) tree = QTreeView() model = QStandardItemModel(tree) tree.setModel(model) tree.setSelectionMode(QAbstractItemView.ExtendedSelection) row = QStandardItem('Row 1') model.appendRow(row) row.appendRow(QStandardItem('Row 1 1')) row.appendRow(QStandardItem('Row 1 2')) row = QStandardItem('Row 2') model.appendRow(row) row.appendRow(QStandardItem('Row 2 1')) row.appendRow(QStandardItem('Row 2 2')) model.appendRow(QStandardItem('Row 3')) model.appendRow(QStandardItem('Row 4')) selectionModel: QItemSelectionModel = tree.selectionModel() def selectionChanged(selected, deselected): print('selected: {}'.format(','.join(str(i.row()) for i in selected.indexes()))) # Displaying Row index print('full selection: {}'.format(','.join(str(i.row()) for i in selectionModel.selectedIndexes()))) # Displaying data print('full selection text: {}'.format(','.join(str(i.data()) for i in selectionModel.selectedIndexes()))) selectionModel.selectionChanged.connect(selectionChanged) tree.show() a.exec_()
-
Hey Thanks for the snippet @Gojir4 ,
the extended selection works fine, but if now i want to print every item that i have selected randomly how can i do that?eg:
D:/
a
b
c
e
fso then if i select a, c, e, f-- how can i return selection values of all four items as strings
any approach? -
@blossomsg Using
i.data()
instead ofi.row()
I have updated my previous post to display data. Note with QFileSystemModel you probably need to use
QFileSystemModel.FilePathRole
role instead of default Qt.DisplayRole. see https://doc.qt.io/qt-5/qfilesystemmodel.html#Roles-enumSo instead of
i.data()
, it will bei.data(QtWidgets.QFileSystemModel.FilePathRole)
def selectionChanged(selected, deselected): ... # Displaying Row index print('full selection: {}'.format(','.join(str(i.row()) for i in selectionModel.selectedIndexes()))) # Displaying data print('full selection text: {}'.format(','.join(str(i.data()) for i in selectionModel.selectedIndexes())))
Outputs:
full selection: 1,2,0,1 full selection text: Row 2,Row 3,Row 2 1,Row 2 2
For converting list of QModelIndex to string list:
stringlist = [str(i.data()) for i in selectionModel.selectedIndexes()] # or simpler stringlist = [] for i in selectionModel.selectedIndexes(): stringlist.append(str(i.data()))
-
-
@blossomsg
selectionModel: QItemSelectionModel = tree.selectionModel()
I haven't used it myself, but I believe in later Python 3 you can (optionally) write
: type-specification
when you create a variable. I use the: type-specification
only for the parameters received by methods. This is not a PySide2 thing.If you don't like it, or your Python doesn't, it should be just:
selectionModel = tree.selectionModel()
It only affects the reading/editing experience anyway, has no effect at runtime.
-
@Gojir4
No need to apologise, it's good style. The last time I first looked at Python at Python 3.something-less-than-7/6/5??, it had the: type
for method parameters, and the-> type
for returns, but not for variables, and it barfed if you tried one. So I wrote all my code using method param types (which personally I highly recommend, but then I like C++ and not Python!), and never could do anything about variables. So that support must have arrived at some more recent Python 3 version? (Or, it's just possible that it was PyCharm which didn't yet understand it, but I thought I saw it only arrived in a recent Python 3?) -
Hi,
Type hinting has been introduced in Python 3.5.
-
@SGaist
Indeed. In 3.5 "type annotations of function parameters, a.k.a. type hints". But the line in @Gojir4 code:selectionModel: QItemSelectionModel = tree.selectionModel()
is variable type-hinting. And I believe that did not come till Python 3.6, see https://stackoverflow.com/questions/39971929/what-are-variable-annotations-in-python-3-6 and https://docs.python.org/3.6/whatsnew/3.6.html#whatsnew36-pep526.
So I must have started out on 3.5.x.
-
@JonB I did start using Python 3.6 and switched quickly to 3.8. Taking inspiration from PySide2 functions declaration it was natural for me to use this type hinting also in the code, without even knowing it was something new :). I agree with your I also use method param types, that's make code more clear and understandable, especially with custom types, and probably also because of ten years of C++ :D.
-
Hello Guys,
Thank you for all your effort especially @Gojir4
your snippet was amazingand the above link helped me resolve the 4 modelindex values to 1 modelindex --- which results 1 path rather than showing all the 4 column paths
from PySide2 import QtCore from PySide2 import QtWidgets from PySide2 import QtGui import sys def selectionChanged(selected, deselected): index = qtreeview_files.currentIndex() print model.filePath(index) qtreeview_files = QtWidgets.QTreeView() model = QtWidgets.QFileSystemModel() model.setRootPath("") qtreeview_files.setModel(model) qtreeview_files.hideColumn(1) qtreeview_files.hideColumn(2) qtreeview_files.hideColumn(3) qtreeview_files.setSelectionMode(QtWidgets.QAbstractItemView.ExtendedSelection) selectionModel = qtreeview_files.selectionModel() win_wid = QtWidgets.QWidget() layout = QtWidgets.QVBoxLayout() layout.addWidget(qtreeview_files) win_wid.setLayout(layout) #win_wid.resize(200, 50) win_wid.show() selectionModel.selectionChanged.connect(selectionChanged)
-
Sorry for late reply got caught up with some personal work
just an updated code.
from PySide2 import QtCore from PySide2 import QtWidgets from PySide2 import QtGui import sys import os def selectionChanged(selected, deselected): index = qtreeview_files.currentIndex() print model.filePath(index) qtreeview_files = QtWidgets.QTreeView() model = QtWidgets.QFileSystemModel() model.setRootPath("") qtreeview_files.setModel(model) qtreeview_files.hideColumn(1) qtreeview_files.hideColumn(2) qtreeview_files.hideColumn(3) qtreeview_files.setSelectionMode(QtWidgets.QAbstractItemView.ExtendedSelection) selectionModel = qtreeview_files.selectionModel() win_wid = QtWidgets.QWidget() layout = QtWidgets.QVBoxLayout() layout.addWidget(qtreeview_files) win_wid.setLayout(layout) #win_wid.resize(200, 50) win_wid.show() ##after you confirm the selection run this to get final selection list list_of_sel_files = [] all = qtreeview_files.selectedIndexes() for x in all: print model.filePath(x) list_of_sel_files.append(model.filePath(x)) ########################################## selectionModel.selectionChanged.connect(selectionChanged)
closing ticket