I am using QListView to show a list of files. When I am using its IconMode and file names are too long, I want it to split text in several lines. PySide documentation tells that setWordWrap function would work in other way:
even if wrapping is enabled, the cell will not be expanded to make room for the text
But that's what I need: break the text and expand item verically.
So, can I use QListView to align files in a way it is often done in a file manager? For example, Thunar:
This is my current code:
import sys
from random import randint
from PySide import QtGui
from PySide import QtCore
app = QtGui.QApplication(sys.argv)
def gen_random_qicon():
pixmap = QtGui.QPixmap(64, 64)
pixmap.fill(
QtGui.QColor(
randint(0,255), randint(0,255), randint(0,255), 255
)
)
icon = QtGui.QIcon()
icon.addPixmap(pixmap)
return(icon)
class Test_model(QtCore.QAbstractListModel):
def __init__(self, parent=None):
super(Test_model, self).__init__(parent)
self.__items = []
def appendItem(self, item):
index = len(self.__items)
self.beginInsertRows(QtCore.QModelIndex(), index, index)
self.__items.append(item)
self.endInsertRows()
def rowCount(self, parent):
return len(self.__items)
def data(self, index, role):
image = self.__items[index.row()]
if role == QtCore.Qt.DisplayRole:
return image['name']
if role == QtCore.Qt.DecorationRole:
return gen_random_qicon()
return None
test_names = ["AB", "UO0E5", "WTRE76", "OSBTTEJ", "M4T2GW4Y55", "LI QM6WJKBC",
"B4MO4 R6JD6"]
test_model = Test_model()
for tn in test_names:
test_model.appendItem({"name": tn})
lv = QtGui.QListView()
lv.setFlow(QtGui.QListView.LeftToRight)
lv.setResizeMode(QtGui.QListView.Adjust)
lv.setViewMode(QtGui.QListView.IconMode)
# Grid
lv.setGridSize(QtCore.QSize(64, 64))
lv.setTextElideMode(QtCore.Qt.ElideNone)
lv.setModel(test_model)
lv.resize(250, 200)
lv.show()
sys.exit(app.exec_())
When I use setGridSize function and set textElideMode as ElideNone, I have this result:
Otherwise, I see complete names, but I won't have the alignment.
Related
I'm trying to design a table widget in pyqt that gets the value in the first column of a row when navigating the table with the arrow keys. I'm able to do that using clicked.connect() on my table class using the pointer, but when using the arrow keys to navigate the table I can't manage to figure out a way to connect my function. I'm just getting my bearings in pyqt and have tried figuring this out from the docs but it doesn't seem any of the signal methods for QAbstractItemModel work. Not sure if I even tried the right thing. I tried adding a KeyPressEvent definition to my QAbstractTableView class but couldn't get that to work - also tried subclassing QTableView to no avail. Off course not sure any of those attempts were down properly. Here is my basic code that makes a table that highlights rows and prints the value in the first column of the selected row when that row is selected via a pointer click, but if you navigate with the arrow keys obviously nothing prints because the method to print the value isn't called.
from PyQt5 import QtCore, QtGui, QtWidgets
from PyQt5.QtCore import Qt, QAbstractTableModel, QVariant
test_data = [[i,j,k] for i in range(2) for j in range(2) for k in range(2)]
class TableStaticModel(QAbstractTableModel):
def __init__(self, header, data):
super(TableStaticModel, self).__init__()
self._data = data
self.header = header
def data(self, index, role=Qt.DisplayRole):
if role==Qt.DisplayRole:
return self._data[index.row()][index.column()]
if role==Qt.TextAlignmentRole:
value = self._data[index.row()][index.column()]
return Qt.AlignCenter
def rowCount(self, index):
return len(self._data)
def columnCount(self,index):
return len(self._data[0])
def headerData(self, col, orientation, role):
if orientation == Qt.Horizontal and role == Qt.DisplayRole:
return QVariant(self.header[col])
return QVariant()
class MainWindow(QtWidgets.QMainWindow):
def __init__(self):
super().__init__()
self.table = QtWidgets.QTableView()
model = TableStaticModel(['A','B','C'],test_data)
self.table.setModel(model)
self.table.clicked.connect(self.get_table_row_value)
self.table.setSelectionBehavior(self.table.SelectRows)
self.table.resizeRowsToContents()
self.table.setColumnWidth(0,83)
self.table.setColumnWidth(1,85)
self.table.setColumnWidth(2,83)
self.setCentralWidget(self.table)
def get_table_row_value(self):
index=self.table.selectionModel().currentIndex()
value=index.sibling(index.row(),0).data()
print(value)
app=QtWidgets.QApplication(sys.argv)
window=MainWindow()
window.show()
app.exec_()
If you only want to select one row then you must set the selectionModel to SingleSelection. On the other hand you must use the selectionChanged signal of the selectionModel:
class MainWindow(QtWidgets.QMainWindow):
def __init__(self):
super().__init__()
self.table = QtWidgets.QTableView(
selectionBehavior=QtWidgets.QTableView.SelectRows,
selectionMode=QtWidgets.QTableView.SingleSelection,
)
model = TableStaticModel(["A", "B", "C"], test_data)
self.table.setModel(model)
self.table.selectionModel().selectionChanged.connect(self.get_table_row_value)
self.table.resizeRowsToContents()
self.table.setColumnWidth(0, 83)
self.table.setColumnWidth(1, 85)
self.table.setColumnWidth(2, 83)
self.setCentralWidget(self.table)
def get_table_row_value(self):
rows = set()
for index in self.table.selectedIndexes():
rows.add(index.row())
for row in rows:
ix = self.table.model().index(row, 0)
print(ix.data())
Consider this example, modified from QStyledItemDelegate paint refresh issues :
import sys
from PyQt5 import QtCore, QtGui, QtWidgets
class MyElement(object):
def __init__(self, numid):
self.numid = numid
self.strid = "Hello world {}".format(numid)
self.param = 'a' if numid%2==0 else 'b'
def __repr__(self):
return "(numid {}, strid '{}', param '{}')".format(self.numid, self.strid, self.param)
elements = [ MyElement(i) for i in range(20) ]
print(elements)
class ElementListModel(QtCore.QAbstractListModel):
def __init__(self, elements = [], parent = None):
super(ElementListModel, self).__init__()
self.__elements = elements
def rowCount(self, parent):
return len(self.__elements)
def data(self, index, role):
thiselement = self.__elements[index.row()]
if role == QtCore.Qt.DisplayRole:
return str( thiselement.strid )
elif role == QtCore.Qt.DecorationRole:
return QtGui.QColor(thiselement.numid*10,thiselement.numid,0)
class ElementThumbDelegate(QtWidgets.QStyledItemDelegate): #(QtGui.QStyledItemDelegate):
def __init__(self, view, parent=None):
super(ElementThumbDelegate, self).__init__(parent)
def paint(self, painter, options, index):
super(ElementThumbDelegate, self).paint(painter, options, index)
#painter.setRenderHint(QtGui.QPainter.Antialiasing)
#painter.setPen(QtGui.QColor(255, 255, 255))
#painter.setBrush(QtGui.QColor(10, 10, 10))
#painter.drawRect(options.rect)
#painter.drawText(options.rect, QtCore.Qt.AlignHCenter | QtCore.Qt.AlignVCenter, str(index.data()))
#def sizeHint(self, options, index):
# return QtCore.QSize(50, 50)
def main():
app = QtWidgets.QApplication(sys.argv)
viewer = QtWidgets.QListView()
viewModel = ElementListModel(elements)
viewer.setModel(viewModel)
#viewer.setViewMode(QtWidgets.QListView.IconMode)
viewer.setItemDelegate(ElementThumbDelegate(viewer))
viewer.show()
sys.exit(app.exec_())
if __name__ == '__main__':
main()
It results with this:
Note that there is a box by default to the left of the item, which you can "color" via DecorationRole in the data method of the ListModel (and apparently, you can also store an icon there, if you return a QIcon instead of QColor, but I've never tried it).
My question is:
How can I draw a border around that icon space/box, depending on some property? In the example above, if MyElement.param == 'a' of a given element in the list, then I would want a light blue (RGB: (38, 76, 100), or #62c2ff) border of width 2 pixels drawn around the "icon space/box" - just like I've manually done in the mockup image in the circled area; otherwise I would not want a border
How could I additionally draw a single letter in the center of that space/box, depending on some property? For instance, if a MyElement.param == 'b' of a given element in the list, then I'd like the letter 'b' written in white in the middle of the "icon space/box" - otherwise, I would not want an extra text written in that space.
The paint() method of ElementThumbDelegate should have otherwise been enough of a pointer on how to do this; but if you uncomment it, you'll see the entire item is changed - not just the left icon box/space.
The class that performs the painting is the delegate who takes the information from the DecorationRole role to create the icon, so the solution is to create the custom icon depending on the item information. That creation can be done in the model or in the delegate, in this case I will use the second option but for this the item must be exposed through a custom role like Qt.UserRole:
import sys
from PyQt5 import QtCore, QtGui, QtWidgets
class MyElement(object):
def __init__(self, numid):
self.numid = numid
self.strid = "Hello world {}".format(numid)
self.param = "a" if numid % 2 == 0 else "b"
def __repr__(self):
return "(numid {}, strid '{}', param '{}')".format(
self.numid, self.strid, self.param
)
elements = [MyElement(i) for i in range(20)]
class ElementListModel(QtCore.QAbstractListModel):
def __init__(self, elements=[], parent=None):
super(ElementListModel, self).__init__()
self.__elements = elements
def rowCount(self, parent=QtCore.QModelIndex()):
return len(self.__elements)
def data(self, index, role):
if not index.isValid() or not (0 <= index.row() < self.rowCount()):
return
thiselement = self.__elements[index.row()]
if role == QtCore.Qt.DisplayRole:
return str(thiselement.strid)
if role == QtCore.Qt.UserRole:
return thiselement
class ElementThumbDelegate(QtWidgets.QStyledItemDelegate):
def initStyleOption(self, option, index):
super().initStyleOption(option, index)
thiselement = index.data(QtCore.Qt.UserRole)
if isinstance(thiselement, MyElement):
if thiselement.param == "a":
option.features |= QtWidgets.QStyleOptionViewItem.HasDecoration
pixmap = QtGui.QPixmap(option.decorationSize)
pixmap.fill(QtGui.QColor("#62c2ff"))
painter = QtGui.QPainter(pixmap)
color = QtGui.QColor(thiselement.numid * 10, thiselement.numid, 0)
painter.fillRect(pixmap.rect().adjusted(2, 2, -2, -2), color)
painter.end()
option.icon = QtGui.QIcon(pixmap)
if thiselement.param == "b":
option.features |= QtWidgets.QStyleOptionViewItem.HasDecoration
pixmap = QtGui.QPixmap(option.decorationSize)
color = QtGui.QColor(thiselement.numid * 10, thiselement.numid, 0)
pixmap.fill(color)
painter = QtGui.QPainter(pixmap)
painter.setPen(QtGui.QColor("white"))
painter.drawText(pixmap.rect(), QtCore.Qt.AlignCenter, "b")
painter.end()
option.icon = QtGui.QIcon(pixmap)
def main():
app = QtWidgets.QApplication(sys.argv)
viewer = QtWidgets.QListView()
viewModel = ElementListModel(elements)
viewer.setModel(viewModel)
viewer.setItemDelegate(ElementThumbDelegate(viewer))
viewer.show()
sys.exit(app.exec_())
if __name__ == "__main__":
main()
I want to have a QListView which displays custom widgets. I guess the best way to do this would be a QItemDelegate. Unfortunately I don't quite understand how to subclass it correctly and how to implement the paint() method, which seems to be the most important one. I couldn't find anything about using a delegate to create another widget.
I already tried to implement something similar without a delegate, but that didn't work out that well, because QListView is not supposed to display widgets.
import sys
from PyQt4 import QtCore
from PyQt4 import QtGui
class Model(QtCore.QAbstractListModel):
def __init__(self, parent=None):
super(QtCore.QAbstractListModel, self).__init__(parent)
self._widgets = []
def headerData(self, section, orientation, role):
""" Returns header for columns """
return "Header"
def rowCount(self, parentIndex=QtCore.QModelIndex()):
""" Returns number of interfaces """
return len(self._widgets)
def data(self, index, role):
""" Returns the data to be displayed """
if role == QtCore.Qt.DisplayRole:
row = index.row()
return self._widgets[row]
def insertRow(self, widget, parentIndex=QtCore.QModelIndex()):
""" Inserts a row into the model """
self.beginInsertRows(parentIndex, 0, 1)
self._widgets.append(widget)
self.endInsertRows()
class Widget(QtGui.QWidget):
def __init__(self, parent=None, name="None"):
super(QtGui.QWidget, self).__init__(parent)
self.layout = QtGui.QHBoxLayout()
self.setLayout(self.layout)
self.checkbox = QtGui.QCheckBox()
self.button = QtGui.QPushButton(self)
self.label = QtGui.QLabel(self)
self.label.setText(name)
self.layout.addWidget(self.checkbox)
self.layout.addWidget(self.button)
self.layout.addWidget(self.label)
class Window(QtGui.QMainWindow):
def __init__(self, parent=None):
super(QtGui.QMainWindow, self).__init__(parent)
self.view = QtGui.QListView(self)
self.model = Model()
self.view.setModel(self.model)
self.setCentralWidget(self.view)
self.model.insertRow(
widget=Widget(self)
)
self.model.insertRow(
widget=Widget(self)
)
self.model.insertRow(
widget=Widget(self)
)
self.model.insertRow(
widget=Widget(self)
)
self.show()
app = QtGui.QApplication(sys.argv)
window = Window()
sys.exit(app.exec_())
So, how would I need to implement a delegate in order to do what I want?
Here's an example of a QTableWidget with a button and text on each row. I defined an add_item method to add a whole row at once: insert a new row, put a button in column 0, put a regular item in column 1.
import sys
from PyQt4 import QtGui,QtCore
class myTable(QtGui.QTableWidget):
def __init__(self,parent=None):
super(myTable,self).__init__(parent)
self.setColumnCount(2)
def add_item(self,name):
#new row
row=self.rowCount()
self.insertRow(row)
#button in column 0
button=QtGui.QPushButton(name)
button.setProperty("name",name)
button.clicked.connect(self.on_click)
self.setCellWidget(row,0,button)
#text in column 1
self.setItem(row,1,QtGui.QTableWidgetItem(name))
def on_click(self):
# find the item with the same name to get the row
text=self.sender().property("name")
item=self.findItems(text,QtCore.Qt.MatchExactly)[0]
print("Button click at row:",item.row())
if __name__=='__main__':
app = QtGui.QApplication(sys.argv)
widget = myTable()
widget.add_item("kitten")
widget.add_item("unicorn")
widget.show()
sys.exit(app.exec_())
Bonus: how to know on which button did the user clicked ? A button doesn't have a row property, but we can create one when we instantiate the buttons, like so:
button.setProperty("row",row)
Problem is, if you sort your table or delete a row, the row numbers will not match any more. So instead we set a "name" property, same as the text of the item in column 1. Then we can use findItems to get the row (see on_click).
I'm trying to implement the QAbstractListModel class in order to display several similar widgets.
The following code shows my problem:
import sys
from PyQt4 import QtCore
from PyQt4 import QtGui
class Model(QtCore.QAbstractListModel):
def __init__(self, parent=None):
super(QtCore.QAbstractListModel, self).__init__(parent)
self._widgets = []
def headerData(self, section, orientation, role):
""" Returns header for columns """
return "bla"
def rowCount(self, parentIndex=QtCore.QModelIndex()):
""" Returns number of interfaces """
return len(self._widgets)
def data(self, index, role):
""" Returns the data to be displayed """
if role == QtCore.Qt.DisplayRole:
row = index.row()
return self._widgets[row]
def insertRow(self, widget, parentIndex=QtCore.QModelIndex()):
""" Inserts a row into the model """
self.beginInsertRows(parentIndex, 0, 1)
self._widgets.append(widget)
self.endInsertRows()
class Widget(QtGui.QWidget):
def __init__(self, parent=None, name="None"):
super(QtGui.QWidget, self).__init__(parent)
self.layout = QtGui.QHBoxLayout()
self.setLayout(self.layout)
self.checkbox = QtGui.QCheckBox()
self.button = QtGui.QPushButton(self)
self.label = QtGui.QLabel(self)
self.label.setText(name)
self.layout.addWidget(self.checkbox)
self.layout.addWidget(self.button)
self.layout.addWidget(self.label)
class Window(QtGui.QMainWindow):
def __init__(self, parent=None):
super(QtGui.QMainWindow, self).__init__(parent)
self.view = QtGui.QListView(self)
self.model = Model()
self.view.setModel(self.model)
self.setCentralWidget(self.view)
self.model.insertRow(
widget=Widget(self)
)
self.model.insertRow(
widget=Widget(self)
)
self.model.insertRow(
widget=Widget(self)
)
self.model.insertRow(
widget=Widget(self)
)
self.show()
app = QtGui.QApplication(sys.argv)
window = Window()
sys.exit(app.exec_())
It works, there are four clickable entries in the list, but in only one of them the widget is actually displayed. Why is that?
I guess this behaviour is either caused by data() or how I'm using beginInsertRows(), but I can't figure out where the error is.
ìnsertRow() function now looks like that
def insertRow(self, widget, parentIndex=QtCore.QModelIndex()):
""" Inserts a row into the model """
self.beginInsertRows(parentIndex, len(self._widgets), len(self._widgets))
self._widgets.append(widget)
self.endInsertRows()
but it still does not work.
Actually, the four widgets are displayed. The issue is, they're all displayed in the top left corner. You can see they overlap if you put names, here "1", "2", "3", "4":
Fixing the row numbers doesn't solve the issue. The widgets will be in the correct rows but will still be displayed on the top left. It is because data is supposed to return text for the display role.
To display simple widgets, I suggest using QListWidget and the setItemWidget method. Otherwise you'll have to use delegates.
self.beginInsertRows(parentIndex, 0, 1)
0 - start
1 - end
You refresh only first row during insert
self.beginInsertRows(parentIndex, len(self._widgets), len(self._widgets))
must be work. Don't remember this method
self.model.reset()
this refresh all list, without specific rows
I am fairly new to PyQt, I'm working on a project that contains a QTableView, with one of its columns displaying system paths. I would like to add a QTreeView so users can click the + or > buttons to expand what is underneath the paths.
Here is my basic implementation:
from PyQt4 import QtGui
from PyQt4 import QtCore
class MainWindow(QtGui.QMainWindow):
def __init__(self, parent=None):
super(MainWindow, self).__init__(parent)
self.resize(600,400)
self.setWindowTitle("My Basic Treeview")
self.treeview = QtGui.QTreeView(self)
self.treeview.model = QtGui.QFileSystemModel()
self.treeview.model.setRootPath('/opt')
self.treeview.setModel(self.treeview.model)
self.treeview.setColumnWidth(0, 200)
self.setCentralWidget(self.treeview)
if __name__ == '__main__':
import sys
app = QtGui.QApplication(sys.argv)
w = MainWindow()
w.show()
sys.exit(app.exec_())
Although, in the above case, I get all folders but I just want the /opt path and its underneath folders.
import operator
from PyQt4.QtCore import *
from PyQt4.QtGui import *
class MyWindow(QWidget):
def __init__(self, data_list, header, *args):
QWidget.__init__(self, *args)
# setGeometry(x_pos, y_pos, width, height)
self.setGeometry(300, 200, 570, 450)
self.setWindowTitle("Click on column title to sort")
table_model = MyTableModel(self, data_list, header)
table_view = QTableView()
table_view.setModel(table_model)
# set font
font = QFont("Courier New", 14)
table_view.setFont(font)
# set column width to fit contents (set font first!)
table_view.resizeColumnsToContents()
# enable sorting
table_view.setSortingEnabled(True)
layout = QVBoxLayout(self)
layout.addWidget(table_view)
self.setLayout(layout)
class MyTableModel(QAbstractTableModel):
def __init__(self, parent, mylist, header, *args):
QAbstractTableModel.__init__(self, parent, *args)
self.mylist = mylist
self.header = header
def rowCount(self, parent):
return len(self.mylist)
def columnCount(self, parent):
return len(self.mylist[0])
def data(self, index, role):
if not index.isValid():
return None
elif role != Qt.DisplayRole:
return None
return self.mylist[index.row()][index.column()]
def headerData(self, col, orientation, role):
if orientation == Qt.Horizontal and role == Qt.DisplayRole:
return self.header[col]
return None
# the solvent data ...
header = ['Name', ' Email', ' Status', ' Path']
# use numbers for numeric data to sort properly
data_list = [
('option_A', 'zyro#email.com', 'Not Copied', '/Opt'),
('option_B', 'zyro#email.com', 'Not Copied', '/Users'),
]
app = QApplication([])
win = MyWindow(data_list, header)
win.show()
app.exec_()
Visual example :
I think your question can be divided in two parts:
how, in a QTreeView, the /opt path and its children can be shown, but without showing its siblings. In other words, how is it possible to show the root directory in a QTreeView ;
how can a QTreeView be added to a QTableView.
1. How to include the root directory in a QTreeView :
The root of a QTreeView is the directory for which the content is shown in the view. It is set when calling the method setRootIndex. According to a post by wysota on Qt Centre:
You can't display the invisibleRootItem because it is a fake item used only to have an equivalent of empty QModelIndex.
A workaround would be to set the root directory to the parent of /opt and filtering out the siblings of /opt with a subclass of a QSortFilterProxyModel. Note that I've also reimplemented the sizeHint method which will be necessary for the resizing of the rows of the QTableView:
from PyQt4 import QtGui, QtCore
import os
class MyQTreeView(QtGui.QTreeView):
def __init__(self, path, parent=None):
super(MyQTreeView, self).__init__(parent)
ppath = os.path.dirname(path) # parent of path
self.setFrameStyle(0)
#---- File System Model ----
sourceModel = QtGui.QFileSystemModel()
sourceModel.setRootPath(ppath)
#---- Filter Proxy Model ----
proxyModel = MyQSortFilterProxyModel(path)
proxyModel.setSourceModel(sourceModel)
#---- Filter Proxy Model ----
self.setModel(proxyModel)
self.setHeaderHidden(True)
self.setRootIndex(proxyModel.mapFromSource(sourceModel.index(ppath)))
#--- Hide All Header Sections Except First ----
header = self.header()
for sec in range(1, header.count()):
header.setSectionHidden(sec, True)
def sizeHint(self):
baseSize = super(MyQTreeView,self).sizeHint()
#---- get model index of "path" ----
qindx = self.rootIndex().child(0, 0)
if self.isExpanded(qindx): # default baseSize height will be used
pass
else: # shrink baseShize height to the height of the row
baseSize.setHeight(self.rowHeight(qindx))
return baseSize
class MyQSortFilterProxyModel(QtGui.QSortFilterProxyModel):
def __init__(self, path, parent=None):
super(MyQSortFilterProxyModel, self).__init__(parent)
self.path = path
def filterAcceptsRow(self, row, parent):
model = self.sourceModel()
path_dta = model.index(self.path).data()
ppath_dta = model.index(os.path.dirname(self.path)).data()
if parent.data() == ppath_dta:
if parent.child(row, 0).data() == path_dta:
return True
else:
return False
else:
return True
2. How to add a *QTreeView* to a *QTableView* :
It is possible to add a QTreeView to a QTableView by using a QItemDelegate. The post by Pavel Strakhov greatly helped me for this, since I had never used QTableView in combination with delegates before answering to this question. I always used QTableWidget instead with the setCellWidget method.
Note that I've setup a signal in the MyDelegate class which call the method resizeRowsToContents in the MyTableView class. This way, the height of the rows resize according the the reimplementation of the sizeHint method of the MyQTreeView class.
class MyTableModel(QtCore.QAbstractTableModel):
def __init__(self, parent, mylist, header, *args):
super(MyTableModel, self).__init__(parent, *args)
self.mylist = mylist
self.header = header
def rowCount(self, parent=QtCore.QModelIndex()):
return len(self.mylist)
def columnCount(self, parent=QtCore.QModelIndex()):
return len(self.mylist[0])
def data(self, index, role):
if not index.isValid():
return None
elif role != QtCore.Qt.DisplayRole:
return None
return self.mylist[index.row()][index.column()]
def headerData(self, col, orientation, role):
if orientation == QtCore.Qt.Horizontal and role == QtCore.Qt.DisplayRole:
return self.header[col]
return None
class MyDelegate(QtGui.QItemDelegate):
treeViewHeightChanged = QtCore.pyqtSignal(QtGui.QWidget)
def createEditor(self, parent, option, index):
editor = MyQTreeView(index.data(), parent)
editor.collapsed.connect(self.sizeChanged)
editor.expanded.connect(self.sizeChanged)
return editor
def sizeChanged(self):
self.treeViewHeightChanged.emit(self.sender())
class MyTableView(QtGui.QTableView):
def __init__(self, data_list, header, *args):
super(MyTableView, self).__init__(*args)
#---- set up model ----
model = MyTableModel(self, data_list, header)
self.setModel(model)
#---- set up delegate in last column ----
delegate = MyDelegate()
self.setItemDelegateForColumn(3, delegate)
for row in range(model.rowCount()):
self.openPersistentEditor(model.index(row, 3))
#---- set up font and resize calls ----
self.setFont(QtGui.QFont("Courier New", 14))
self.resizeColumnsToContents()
delegate.treeViewHeightChanged.connect(self.resizeRowsToContents)
3. Basic application :
Here is a basic application based on the code you provided in your OP:
if __name__ == '__main__':
header = ['Name', ' Email', ' Status', ' Path']
data_list = [('option_A', 'zyro#email.com', 'Not Copied', '/opt'),
('option_B', 'zyro#email.com', 'Not Copied', '/usr')]
app = QtGui.QApplication([])
win = MyTableView(data_list, header)
win.setGeometry(300, 200, 570, 450)
win.show()
app.exec_()
Which results in: