QAbstractTableModel and QComboBox together - python

I have a subclass of a QAbstractTableModel and I want to use QComboBox to display a dropbox for this table.
But by default it shows just the first column of my table, which is not what I want. I've tried setModelColumn to shows the column 1 instead of 0 but it did not work.
After having a look around in the internet, I've found 2 solutions:
Create another QAbstractListModel from the same data in the QAbstractTableModel
Use a QSortFilterProxyModel to hide other columns
Which is the best?
Thanks

Using setModelColumn should work. I would try to fix that. Perhaps you set the modelColumn at the wrong time, docs have this to say about it:
If set prior to populating the combo box, the pop-up view will not be affected and will show the first column (using this property's default value).
If this really doesn't work, and I'm quite sure it should, then use a QSortFilterProxyModel. This will be a lot less work and should be almost trivial.

Related

Filter options provided by QSqlRelationalDelegate/QSqlRelation acourding to some WHERE close

I have a QTableView populated by QSqlRelationalTableModel.
There is a column that references another table, so when I edit/create a row, this column's editor is QCombobox which gets its data from the related table. The problem is that I want to filter the data with some predefined WHERE close on the related table.
Example:
Tables:
Person:
id, name, job_id;
Job:
id, title, salary
What I want is something like
model.setRelation(3,QSqlRelation("Job", "id", "title", "WHERE salary > 50000"))
So that the QCombobox will have only Job titles with salaries > 5000.
I cannot use QSqlQueryModel as suggested in SO question - I still need users to be able to add new data or edit existing data.
It seems that someone managed to achieve this 10 years ago by tweaking the QT source code, but my C++ is bad so I could not figure it out quite well.
Possible solutions:
The first thing that comes to mind is to implement my own QSqlRelationalDelagate and populate QCombobox in the createEditor and set appropriate values in setModelData. I will try to do it myself and report the results back here. But it seems not very clean to me.
The best way would be to Extend the functionality of the QSqlRelation or QSqlRelationalTableModel but the documentation on it seems to be not very clear. So the real question is for experienced QT/PyQT developers: How do I solve the problem this way?
Update
So filtering out the contents of the QCombobox in the createEditor of the delegate works, but it requires a database query every time the editor is created which seems a bit off. And also it was quite a mess to handle new indexes after filtering. But I still wonder about the second way of approaching the problem.

pyqt4: Making Qtableview reflect the changes after calling QStandardItem.setData

I'm trying to build a gui using pyqt4 and am having trouble updating fields on a Qtableview
Here's my code:
table=QTableView(myqMainWindow)
model=QStandardItemModel(0,1,table)
item1= QStandardItem("123")
model.setItem(0,0,item1)
table.setModel(model)
item1.setData("321")
Now the problem I'm facing is that the table still shows "123" at the first column. What is it that I'm missing to get the table reflect the change?
Take a closer look at setData documentation.
setData take two arguments : data and role. Unless you want to define a custom role you must specify one. In your case, you should use DisplayRole
item1.setData("321", QtCore.Qt.DisplayRole)
Alternatively, you could use setText.
item1.setText("321")

Using custom role in QTreeView instead of DisplayRole

A simple question, (hopefully with a simple answer).
QTreeView will pass Qt.DisplayRole to the model's data function when fetching rows for display, by default.
But say I wanted to pass 'MyAwesomeTreeDisplayRole' instead of Qt.DisplayRole, what would I need to do?
I can't seem to find anything about where the view decides to use displayrole or how to override it.
Just before you ask why I want to do such awful things..
Basically, my QAbstractItemModel is intended to be usable both for a treeview (1 column) and a tableview (multiple columns, based on parent).
Using the same DisplayRole for both types of views doesn't really work, since then I'm forced to return the same data for both. This results in me only seeing the first column in the treeview when I want to return a concatenation of a couple of columns.
I think the simplest way would be to just use custom roles (TreeDisplayRole and TableDisplayRole).
Thanks in advance.
I don't know, how to do it in python, but you have to create your own delegate to render items data. Delegate is actually the object, that requests any data from indices and renders it
Note, that in common case QTreeView is able to show multiple columns, you should only have columnCount set incorrectly for top-level index
I've used QTreeView to view a simple table with many columns - it works well - you can adjust the column count by sending it the columnCountChanged signal. So I'm not sure you need to do what you are asking.
But I've used ItemDelegates too: use my_treeview.setItemDelegate() to point the treeview to your item delegate. If this subclasses QStyledItemDelegate then it doesn't need to do much work - it can mostly just pass it all through to super.
The user roles then are just agreed between your custom ItemDelegate and your ItemModel and can be anything you like as long as they are >= than QtCore.Qt.UserRole.
(Edit: Sorry, I put this in as a new answer but it's really just an elaboration on what Lol4t0 said - apart from the columnCountChanged thing)

Looking for a wxpython widget that would let user's fill in data like they would in a table

I want to have a table like display on one of panels where the user can fill in data into pre-made columns. I'm not sure what widget will give me this functionality. I want users to be able to edit elements they have already added, and to easily add another element. Any suggestions?
Look at Grid or ListCtrl to create the columns. I think Grid is a better choice for editing as you can add TextCtrls or the like to the columns.
Try out CSheet, it is much better and customizable than the standard wxGrid and has similar interface.
Try ListCtrl with TextEditMixin - it's pretty neat and offers keyboard navigation to move between cells.

PyGTK - polling GTK table for locations of widgets

I'm working on a Python application involving the use of a GTK table. The application requires that widgets of various sizes be added to a table dynamically. Because of this, I need to be able to ask the table what cells are in use (more accurately, NOT in use) so that I know where I can place a new widget without overlapping.
Based on the information in the reference manual (http://www.pygtk.org/docs/pygtk/) I have been unable to find a way to get that information directly from the table. The only other option I can think of is to create a map object that holds used cell information, and have it updated upon changes to the table.
Since I'm sure someone has dealt with this before me, and I would hope GTK would provide a better way, it seemed wise to ask around before trying to implement the map.
Help would be greatly appreciated.
This function should give you a set of the free cells in the table:
def free_cells(table):
free_cells = set([(x,y) for x in range(table.props.n_columns) for y in range(table.props.n_rows)])
def func(child):
(l,r,t,b) = table.child_get(child, 'left-attach','right-attach','top-attach','bottom-attach')
used_cells = set([(x,y) for x in range(l,r) for y in range(t,b)])
free_cells.difference_update(used_cells)
table.foreach(func)
return free_cells
It starts with a set of all the table cells, then iterates over the children of the table, removing the cells occupied by each child.
I'm the original poster, was logged into wrong account when posting question.
Anyway, this appears to be exactly what I'm looking for! Thanks Geoff!

Categories

Resources