I need to create QTreeWidgetItems which have support for formatted texts, such as:
MyCreatedType - INTEGER(1)
(ie: the line above should have a "normal" part : MyCreatedType and a "formatted" part (INTEGER(1) in our case).
Any idea how to accomplish this?
Thanks.
What you need is a delegate. Delegates are explained here:
Star Delegate Example http://qt-project.org/doc/qt-4.8/itemviews-stardelegate.html
QItemDelegate Reference http://qt-project.org/doc/qt-4.8/qitemdelegate.html
The general procedure I follow when creating and using custom delegates:
Create a custom type with the information you want to encapsulate.
For your case, perhaps fields for the variable type name and type value.
Store these custom types in your model, wrapping them in QVariants to satisfy the return types required by QAbstractItemModel
Create a control that matches the UI you want.
In this case it might mean a QText label for "MyCreatedType" followed by a second label in bold for "Integer(1)".
Perhaps the control has methods like "setTypeName" and "setTypeValue"
Create a delegate that paints your specific control when your custom type is found.
You will have to map fields in the custom type to fields in the custom UI control as needed.
Associate your model and delegate with the Tree View you are using.
I hope this general procedure makes sense. I would recommend completing the Star Delegate Example and then reading my procedure, as it will make more sense with some background.
Related
I have a tree model and use QDataWidgetMapper to map the model data to some widgets.
In the model, some of the data are flagged as read-only, so, what I would like to do is to let the mapped widget, say, a QLineEdit, be able to act upon this flag and set itself to readonly when the model data it points to is readonly.
Any help is appreciated!
Qt's QAbstractDataModel interface doesn't expose writability of a piece of data as an attribute: there's nothing you can read to know whether an item can be modified or not. One could think of some non-general hacks, such as attempting to write back the current value of the item to check if it can be changed. They are but hacks, e.g. a model fulfilling the contract mandated by Qt might return true from setData even on a read-only item if the new value equals old value.
If you're using a model that exposes the writability attribute, you'll need to derive from QDataWidgetMapper and implement that functionality yourself.
I would like to set a marker interface to some objects that should have additional fields. If I remove this marker interface again the fields should be removed too.
Now I'm trying to understand plone.behavior. But I'm not sure if a behavior must be enabled for all objects of a type or is it possible to enable it for only a subset of objects of that type?
Take a look at collective.instancebehavior, an add-on aimed to do exactly what you want: to enable behaviors per content type instance.
Unfortunately I don't think there is a solution out of the box.
The simplest thing you can do is working on the form fields by overriding the updateFields method in the form.
This is untested demo code:
def updateFields(self):
if not IMyInterface.providedBy(self.context):
self.fields = (
self.fields.omit('IMyBehaviour.my_field')
)
As a reference have a look to:
https://github.com/plone/plone.app.users/search?utf8=%E2%9C%93&q=def+updateFields
I have this piece of code:
controlDetails = this.form().design(1).addControl(FormControlType::Group, #quickCreateDetails);
controlDetails.dataSource(fbds.id());
controlDetails.dataGroup(#quickCreateDetails);
controlDetails.frameType(10);
controlDetails.autoDataGroup(true);
controlDetails.hideIfEmpty(false);
controlDetails.columns(2);
I want to modify the editability of one certain field on that dataGroup, but I don't know how to do it with code or in the AOT (DS). Seems like Im pretty much limited...
You have next options:
change Form Data Source filed editability
via AOT - https://msdn.microsoft.com/EN-US/library/aa860145.aspx
via code FormDataSource.object: InventTrans_ds.object(fieldNum(InventTrans, Qty)).allowEdit(false)
change child control design property. addControl returns FormBuildGroupControl. Then you have to loop through controlNum(), find correct design control and cast it to one of FormBuildControl nested type with data bounding. There you have allowEdit method.
I've got an object with a list defined inside it which points to a type that can be inherited. From what I understand MVC's default model binder will always instance the base type when reading data back in to this array from a form so by default I will have a list of base types.
So I need to use my own model binder and override CreateModel to instance a specific type (say from a hidden field). However when I do this and use
bindingContext.ValueProvider.GetValue("ModelType")
it always returns null even though through using fiddler I can see that form value Settings[0].ModelType contains my objects type and I need this value in CreateModel to instance the correct type.
Solved it. If your array objects need to be typed based on each item you need to use the following call to get "into" the array item
bindingContext.ValueProvider.GetValue(bindingContext.ModelName + ".ModelType")
I'm not sure if this is the standard way to do it. If anyone has any better suggestions feel free to add them
I have a Dexterity content type based on plone.directives.form.Schema which has a number of form hints for assigning defaults:
#form.default_value(field=ITrial['start_on'])
def default_start_on(data):
return datetime.now()
Some of the defaults are more complex, passing back objects that are themselves instances of Dexterity types. These objects are essential for the main type's setup, which is triggered by various events.
I'm now in the process of testing. Ideally, I'd like to be able to use something like:
item = createContentInContainer(folder, 'ctcc.model.trial', 'item')
That is, I'd like the defaults to be picked up by the item without having to be manually passed into the constructor.
If I was using zope.schema I could use FieldProperty to set up proxies to the schema fields. Is there something equivalent for Dexterity, or perhaps a function for pushing an object through form creation?
Solution: I ended up going with David's option #1, intercepting ObjectCreatedEvent.
#grok.subscribe(ITrial, IObjectCreatedEvent)
def create_trial(trial, event):
if getattr(trial, 'start_on', None) is None:
trial.start_on = default_start_on(None)
It stills feels like I'm replicating part of form behaviour, but at least it's using the same functions that are providing the form defaults.
As you've discovered, the #form.default_value decorator is respected by z3c.form forms, but not when items are created in other ways. You have several options:
Write a handler for the ObjectCreatedEvent for your content type which sets up the necessary default values. This is the simplest approach to implement, but may not work if there are other handlers of this event that need the values in place.
Create your own subclass of Dexterity's generic Item class, and use it instead of Item as the basis for your content type. Then you can customize the __init__ method to set whatever you want. This would require migration of existing content items though, if you already have some.
This is a more complicated option. Replace the factory utility used to construct the content type. createContentInContainer ends up looking for an IFactory utility with a name equal to the factory attribute of the content type's FTI. The default implementation is in plone.dexterity.factory but you could replace it with a different one that does more.