I have a QTableView for a custom class inherited from QAbstractTableModel.
Does someone knows a way to set a particular cell of a QTableView (or the model) as non editable according to a value from another cell of the same row of the model?
Im using PySide.
Thanks in advance.
Override the flags method of the model and make sure that the ItemIsEditable is not included in the results.
For instance include this in your model class:
def flags(self, index):
""" Returns the item flags for the given index.
"""
return Qt.ItemIsEnabled | Qt.ItemIsSelectable
Related
I'm attempting to create a custom search box class named "TkinterEntryBox" based on Tkinter "Entry" widget that would clear its content when left mouse button is pressed inside text entry area. Currently I'm trying to bind a function called "clear" that is a part of custom class that would clear an input in a parent window that would contain instance of "TkinterEntryBox" widget.
I read that inheriting from "Entry" class would be a preferred way of resolving my problem, but I would like to use composition instead of inheritance, since I don't want to have "Entry" class "leaking" outside my custom class.
Problem is, that while callback function is called as expected its "event" argument contains bound "Entry" class widget instance and not "TkinterEntryBox" instance. It causes and exception, since "Entry" class does not have an "clear" method.
Is it possible to force Tkinter to bind my custom class instead of "Entry" class, so that "event" argument in callback function would contain my custom class instance under "widget" property, so that I can safely call "clear" method? Moreover, since I'm new to Tkinter and GUI programming could someone, please tell me if such an approach of creation of widgets is a valid one? If not, then I would greatly appreciate some pointers how to improve my code.
Here is a rough idea of what I created so far:
Below is the custom entry class which "clear" method I would like to call through event callback:
class TkinterEntryBox:
def __init__(self, parent_window: BaseWindow, events_to_callbacks_bindings: Dict[str, Callable]):
self._tkinter_entry = Entry(parent_window)
self._bind_callbacks_to_events(events_to_callbacks_bindings)
def clear(self) -> None:
self._tkinter_entry.delete(ENTRY_BOX_POINTER_START_INDEX, ENTRY_BOX_POINTER_TO_END)
def input(self) -> str:
return self._tkinter_entry.get()
def set(self, text: str) -> None:
self._tkinter_entry.insert(ENTRY_BOX_POINTER_START_INDEX, text)
def place(self, placement_orientation: Geometry) -> None:
self._tkinter_entry.pack(side=str(placement_orientation))
def _bind_callbacks_to_events(self, events_to_callbacks_bindings: Dict[str, Callable]) -> None:
for event_name, callback_function in events_to_callbacks_bindings.items():
self._bind_callback_to_event(event_name, callback_function)
def _bind_callback_to_event(self, event_name: str, callback_function: Callable) -> None:
self._tkinter_entry.bind(event_name, callback_function)
Here is how I initialize my custom entry box class:
def _initialize_search_entry_box(self, factory: TkinterWidgetFactory) -> TkinterEntryBox:
events_to_callbacks_bindings = {
EVENT_ON_LEFT_MOUSE_BUTTON_DOWN: self._on_left_mouse_button_down
}
search_entry_box = factory.assemble_entry_box(self, INGREDIENT_SEARCH_BOX_PLACEHOLDER, events_to_callbacks_bindings)
return search_entry_box
And here is an callback function that is called when left mouse button is pressed inside entry box input area:
#staticmethod
def _on_left_mouse_button_down(event) -> None:
event.widget.clear()
The error message I'm getting in above function call is:
AttributeError: 'Entry' object has no attribute 'clear'
You can simply add self._tkinter_entry.clear = self.clear after creating the entry:
class TkinterEntryBox:
def __init__(self, parent_window: BaseWindow, events_to_callbacks_bindings):
self._tkinter_entry = Entry(parent_window)
self._tkinter_entry.clear = self.clear
...
I have a view-based NSOutlineView with a dataSource/delegate model instead of binding to a tree controller (I want control over the insert/update animations).
I'm replacing an item in my model and would like to update that specific row in the outline view without having to call reloadData().
I cannot get this to work. Either the item does not update at all or the item's expanded state doesn't update. There seems to be some caching being done inside of NSOutlineView according to this, but even with these suggestions, I could not get it to work.
What I have:
(1) The outline view represents a folder structure
(2) At first, there is a singe file:
(3) The file is then replaced with a folder item:
// Model update
let oldFileItem = rootItem.children.first!
rootItem.children.remove(at: 0)
rootItem.children.append(Item(title: "Folder", children:[], isExpandable:true))
Expected result:
Actual result (reloadItem):
outlineView.reloadItem(oldFileItem) // I kept a reference
Icon and title reloaded, but note that the expansion triangle is missing.
I can somewhat understand that reloadItem() might not work in this case, because the old item is not part of the data model anymore. Strangely enough, the item's title and icon update, but not the expansion state.
Actual result (reloadData(forRowIndexes:columnIndexes:):
outlineView.reloadData(forRowIndexes: IndexSet(integer:0), columnIndexes: IndexSet(integer:0))
No effect whatsoever. This is the one that I would have expected to work.
Actual result (remove/insert):
outlineView.removeItems(at: IndexSet(integer:0), inParent: rootItem, withAnimation: [])
outlineView.insertItems(at: IndexSet(integer:0), inParent: rootItem, withAnimation: [])
No effect whatsoever.
The docs say about removeItems(): "The method does nothing if parent is not expanded." and isExpanded does indeed return false for the root node, although its children are visible. Is this special behavior for items that are direct children of the root node? What am I missing here?
For reference, my data model:
class Item:NSObject {
var title:String
var children:[Item]
var isExpandable:Bool
init(title:String, children:[Item], isExpandable:Bool) {
self.title = title
self.children = children
self.isExpandable = isExpandable
}
}
For reference:
It turned out to be an issue with how I used the API. NSOutlineView.removeItems/insertItems expect nil for the inParent parameter for the root item. I was handing in the actual root item. Using nil instead of the root item solved the problem.
I want to display some items in my sidebar, with the count of each tag also displayed:
How do I do this efficiently and automatically? The easy option would be to use cocoa bindings, but I'm not sure what the best way to do this: would each button needs it's own NSArrayController with a fetch predicate set for the 'tag'? That could end up with X number of NSArrayControllers (one for each tag) which would be pretty heavy-weight (I would think).
The other option is to create fetch requests manually, then refetch for every change in managed object context. But that seems a bit messy and not-as-automatic.
Is there a simpler solution for this? I've googled around and haven't found anything.
Let's assume that in your NSOutlineView you have a childrenKeyPath of "children" and the children have a boolean isNew attribute. What you want is a nice numberOfNewItems bubble in the cell view for one object class. I'll call that the parent object.
If you just want the number of objects in the childrenKeyPath, heck, that's even easier, but I'll take you through the more complex case of tracking a specific boolean property on the children because it's easy enough to simplify this pattern.
In the table cell view for the parent object add a recessed button with the title bound to objectValue.numberOfNewItems and hidden bound to objectValue.NumberOfNewItems with value transformer NSNegateBoolean. If you just want the number of children, swith those keypaths to objectValue.children.count and you're done. If you want to track a property like isNew, let's continue...
In the parent object class, there is this code:
- (NSNumber*) numberOfNewItems
{
// Collection operator on boolean returns total number of new children
return [self valueForKeyPath:#"children.#sum.isNew"];
}
// This setter does nothing, but with KVO it causes bindings
// to numberOfNewItems to call the above getter
- (void) setNumberOfNewItems:(NSNumber*)number { }
// This ensures that changes to the children set causes KVO calls to the above getter
+ (NSSet*) keyPathsForValuesAffectingNumberOfNewItems
{
return [[NSSet alloc] initWithObjects:#"children", nil];
}
What that does is cause numberOfNewItems to be recalculated any time the table cell's objectValue gets a new child added to or removed from its children to-many relationship.
In the childItem class, there's this in the one place that the childItem is transitioned from isNew to not-New:
// If collapsing an item, mark it as not new
if (!isExpanded.boolValue && self.isNewValue) {
self.isNew = #NO;
[self.parent setNumberOfNewItems:nil]; // Triggers KVO for button binding
}
... and what that does is use the parent's empty setNumberOfNewItems setter to force the button binding to call the getter. So the whole to-many children relationship is enumerated each time an item is marked not-new. I supposed that could be improved, but I haven't played around with that yet.
I took advantage of the fact that an item is marked not-new only one place in my code. If you have several things resetting or setting isNew in the child, you might override setIsNew in the childItem class to call self.parent setNumberOfNewItems:nil instead.
The trick here is that having the parent add itself as a KVO observer for the isNew keypath for all children would be a terrible pain. So I wanted to avoid that. If you simply have the children call the empty setter in the parent, the parent can own the calculation, and there's no KVO outside what the bindings use.
Looks like this:
I want to get xtragrid focused cell entity property. Because of this :
I'm trying to get, focused cell isnull property, for this i need to get focused cell entityproperty
I tried to get object like (EdmScalarPropertyAttribute)gird.focusedrowvalue, but i got null value exception
How can i do this ?
Thanks
Another way to get the RowHandle of the XtraGridView is this:
int rowHandle = gridView1.GetSelectedRows()[0]
hope it helps, and if you are trying to get the value of the cell you can use the following code
object obj = gridView1.GetRowCellValue(gridView1.GetSelectedRows()[0], gridView1.FocusedColumn.FieldName);
I am not getting clear about the concept of getPreferredWidth() and getPreferredHeight() methods. What do they return means on what what basis the values are returned.??
What is difference between getWidth() and getPreferredWidth()???
Thank you..
By default, Field#getPreferredHeight() and Field#getPreferredWidth() return 0. They're there for your custom Fields to override with whatever your custom Field's preferred width/height is.
The value you supply in your overridden methods is then taken into consideration when it comes to laying out your Field. If your preferred values are suitable for the display area and your Field's content, then your preferred values will be used. These values are just suggestions.
Field#getHeight() and Field#getWidth() on the other hand return the actual extent of the Field.
Field#getPreferredWidth() is used to determine width of the specific field when it is created. You need to override this method if you want to create some customization. Display#getWidth() returns the physical screen size of your device or simulator which you can use to create buttons relative to the screen width. Field#getWidth() returns the actual width of your field that you created earlier. I used that code block to create a button which fills whole screen width and with default height.
This is how you override the getPreferredWidth() method for a specific field i.e. ButtonField.
ButtonField myButton = new ButtonField("Click", USE_ALL_WIDTH){
public int getPreferredWidth(){
return Display.getWidth();
}
};