Issue rendering the selected cell on a QTableView - pyqt4

I have a custom QTableView and a custom QAbstractTableModel. The view only allows single selections. I'm trying to customize the background color of the selected cell under some conditions with no success. I expected to do it by combining the data method of the model with the selectionChanged method of the view. For instance, let's suppose I want to change the color of the selected cell when it matches a given row. My code for the selectionChanged method is:
def selectionChanged(self, selected, deselected):
#QtGui.QTableView.selectionChanged(self, selected, deselected)
# Get the selected indexes from the QItemSelection object
selection = selected.indexes()
# Let the model track the selected cell
self.tmodel.selected_index = selection[0]
# Desperately try to make it work
self.tmodel.dataChanged.emit(selection[0], selection[0])
self.viewport().update()
My simplified code for the data method is:
def data(self, index, role=QtCore.Qt.DisplayRole):
if not index.isValid():
return None
# Some code here dealing with several roles
if role == QtCore.Qt.DisplayRole:
...
elif role == QtCore.Qt.BackgroundRole:
if ((index == self.selected_index) and (index.row() == 3)):
print '++++ displaying selected'
return QtGui.QColor(QtCore.Qt.yellow)
else:
return QtGui.QColor(QtCore.Qt.green)
else:
return None
The non selected cells have a green background as expected. The strange thing is that when I select a cell in the matching row, the message ++++ displaying selected is printed but the selected cell has the system default background instead of a yellow one. I must be missing something important/obvious here but I've no idea about what it is.
Update
I know I can achieve my goal using a custom delegate and implementing its paint method but I'd like to know why the code above fails.

OK, I think I got it. The think is that the default delegate uses the values returned by data in order to render the table cells. Accordingly to the docs:
By supplying appropriate item data for each role, models can provide
hints to views and delegates about how items should be presented to
the user. Different kinds of views have the freedom to interpret or
ignore this information as required.
So the behavior described in the question is explained as follow: non selected cells are rendered in the standard way by the default delegate which implies the color returned by data method will be used. However, selected cell are rendered in a different way by the default delegate, the value returned by data method is ignored in this case because it uses the background provided by the system style.

Related

How to enable/disable button when QComboxBox and QLineEdit are activated

I cannot get a push-button enabled when both a text box is filled and a combox box item is selected.
I have the following code, which enables the button as soon as I enter text, but have no selected combobox item:
self.combo_box.currentIndexChanged[int].connect(self.showbutton)
self.textbox.textChanged.connect(self.showbutton)
def showbutton(self,index):
self.enableNewButton.setEnabled((index != -1) and bool(self.textbox.text()))
So I then did a print(index) and I do see the proper index being printed when I select a combo box item; but I also see each character printed as well when I enter stuff in the text box.
I have no problems enabling buttons based on multiple text input boxes but this one is not working for me.
The textChanged signal sends the current text, which cannot ever be equal to -1. So rather than using the parameters emitted by the signals, you should directly check both values via the widgets themselves, like so:
class Window(QtWidgets.QWidget):
...
def showbutton(self):
self.enableNewButton.setEnabled(
self.combo_box.currentIndex() >= 0 and bool(self.textbox.text()))

How to prevent no selection in QTableWidget?

I have a QTableWidget with some rows in it. I want selection to be always present. But once I click somewhere on the Table outside the rows I lose my selection. Could someone help me with this problem?
The simplest solution is to ensure that an item exists at the coordinates the user clicks in.
This can be done by ensuring that QTableWidget.indexAt(pos) returns a valid index: if it is, it means that an item exists there, so we can proceed with the base class mousePressEvent, otherwise we just ignore it.
class AlwaysSelectedTable(QtWidgets.QTableWidget):
def mousePressEvent(self, event):
if self.indexAt(event.pos()).isValid():
QtWidgets.QTableWidget.mousePressEvent(self, event)

Getting data from a datasource with Filter by Column Value?

I have a list box where I am trying to get the datafrom the people view in names.nsf.
The first column of the people view is computed and shows Last Name , First Name.
The code below works fine for my list box values but it does not take into consideration the value in the Filter By Column Value. Basiclly the code below acts like the Filter By Column value property does not exist. I know the Filter by Column value property is working because I replaced a repeat control on the page with a computed field and the repeat control is displaying the value excepected but the list box is displaying values from the first document in the view.
Thoughts I had to fix this are:
Use getAllDocumentsByKey to just search the people view but when I do that I lose the column values and I would need to recompute the value, something that I would like to avoid if possible incase the column formula changes.
Use FTSearch but what I really need to do is search that first column only and I am not aware of search operator that searchs a column only. Is there such a thing?
Another thought would be to somehow use the values of a repeat control, as the values for my list box, but I am guessing that this is not possible. I sort of thinking something with a scope varibale but I have not worked that out yet.
A repeat control works. How can I get my code to loop through the doeuments the same way a repeat control does?
And as a side question, is there anyway to tie a pager to a datasource as oppsed to a repeat control.
BTW What I currently do is to build a list box using a few computed fields and a repeat control but what I really want to do is to use a regular xpages list box control.
Here is the code:
var doc:NotesDocument = view1.getFirstDocument();
while (doc != null && count<10)
{
var tmpDoc:NotesDocument = view1.getNextDocument(doc)
ret.push(doc.getColumnValues()[1]);
doc.recycle();
count++;
doc = tmpDoc;
}
Try to use getAllEntriesByKey. This will give You access to column values (through ColumnValue property of view entry).

Dynamic Layouts in Filemaker

First off I am new to FM but I have a good handle on the basics. What I need to do is this - in a contact information type layout I want to be able to alter the layout based on a specific field. Ex. When the record is brought up, the background of the layout will change colors for a client, another for vendor, etc.
I tried to change a label based on a field, with no success. My guess is that the layout is static and only the data fields change.
We use FM Pro.
Thanks,
Mark
FileMaker layouts are static, but there are still some things you can do to alter the layout based on the values of fields:
Calculation Fields
If you want the data shown in an area to change, you can use a Calculation field. A typical example of this would be a status field. To do this you would add a new field to your table and use enter a calculation on that field like:
Case (
IsEmpty(myTable::myField) ; "Please enter a value for myField." ;
myTable::myField = "wrong value" ; "Please enter a correct value for myField." ;
"Everything seems okay."
)
Conditional Formatting
To make things like background color change you can use a conditionally formatted field. I will typically add an empty numeric field (for this example we'll call it emptyField) and set it so that it can't be edited during modification.
If you place emptyField on your layout, below all the other fields and disallow the user to enter the field in either Browse or Find mode, you can then use conditional formatting to change the field's color.
Portal Hiding
You can use this technique when you want some elements of your UI to disappear when they aren't needed. For example, if you want a "submit" button to appear only when all of the records on a field are filled out.
To use this technique I will usually create a Calculated number field, called ReadyForSubmit, on the original table and give it a logical calculation like:
not IsEmpty(field1) and ... and not IsEmpty(fieldN)
(Note that the value of the above function would be 1 or 0)
I will then create a new Support table in my database and add to it a field One with a calculated value set to 1.
I will then make a relationship between myTable::readyForSubmit and Support::One.
On the layout, create a portal with one row. Put your Submit button in that layout. Now, when readyForSubmit calculates to 1 the button will appear. When it calculates to 0 the button will be hidden.
Hidden Tab Browser
Finally, you can use a tab browser where you set the title font size to 1 point, hide the border, and control the browser programmatically. You can use this for having different field arrangements for different types of records. To do this you would first give an Object name to each tab of the tab browser, say Tab1, Tab2, Tab3.
Then you would add a script, goToTab, with the logic for when you want to go to each tab. Say:
If (myTable::myField = "corn")
Go to Object (Tab1)
Else If (myTable::myField = "squash")
Go To Object (Tab2)
End If
You would then use Script Triggers to run goToTab when On Record Load.
With the release of filemaker 13 there may be another way to do this. You could use a slide control, name the panels in the control, and conditionally switch to the correct panel based on the record type.
you would drop the appropriate fields for the record type in each panel.
http://help.filemaker.com/app/answers/detail/a_id/12012/~/using-slide-controls-and-slide-panels-in-filemaker-pro

jqGrid Filtering Records

It seems there have been a few questions here regarding this subject, and they have some great answers, but it seems that my case is a little different. I need to filter the records displayed in a jqGrid, but entirely client-side.
For a number of reasons, the best way for me to populate my grid is with an array that's emitted directly into the JavaScript on the page. The grid itself doesn't interact with the server at all. I have some custom AJAX happening in various grid events, but that's it. (Basically, I'm integrating this with an existing set of available services which can't change significantly.)
What I'm looking to do is filter the grid based on a simple text input and button. My page has the text input, the button, and a table (which becomes the grid on document ready). I'd like to bind to the click event of the button (normal jQuery event binding, nothing special) and use the value from the text input as a display filter on the jqGrid.
By "filter" I mean to display only the records which contain a match (in any field) for the text in the input. Then, to display all records, just empty the input and click the button again. Additionally, the grid is multi-select and the selections need to persist through filtering. I just need to be able to hide the rows which don't match what's in the input.
Is this possible?
To filter local grid you should only fill filters property of the postData parameter of jqGrid and set additionally search:true.
To save selection of the grid you can use reloadGrid with additional parameter [{page:1,current:true}] (see here).
The corresponding code can be the following
$("#search").click(function() {
var searchFiler = $("#filter").val(), grid = $("#list"), f;
if (searchFiler.length === 0) {
grid[0].p.search = false;
$.extend(grid[0].p.postData,{filters:""});
}
f = {groupOp:"OR",rules:[]};
f.rules.push({field:"name",op:"cn",data:searchFiler});
f.rules.push({field:"note",op:"cn",data:searchFiler});
grid[0].p.search = true;
$.extend(grid[0].p.postData,{filters:JSON.stringify(f)});
grid.trigger("reloadGrid",[{page:1,current:true}]);
});
I made the demo for you which filter for two columns 'Client' ('name') and 'Notes' ('note') you can extend the code to search in all columns which you need.
Depend on what you exactly mean with the saving row selection you can need to save the current selection from the selarrrow in a variable and restore the selected rows with respect of setSelection method.

Resources