Abstract function qml - qt

i want to create an abstract class with abstract functions in QML in theory some thing like this:
//abstract.qml
QtObject{
abstract function implementLater(var input);
}
Abstract{
//and here i have to implement it
function implementLater(var input){
console.log(input)
}
}
how can i do this in qml or maybe in c++ and register it to qml?
update :
here is what i'm trying to do, in my uvaluemask object i should have a function named mask which will be abstract and i call this for every child which will be different, you can call childs method directly i'm doing this right now and its working, but my component "UValueMask" is missing difinition for mask method,i mean i need to force users of UValueMask to define a mask method .
//UValueMask.qml
QtObject {
property string name:""
}
//singleton Object
UListObject{
property UValueMask timeMask :UValueMask{
id:timemask
name: "time"
function mask(input,splitter){
return innerObj.convertIntToTime(input,splitter)
}
}
property UValueMask dateMask: UValueMask{
id:datemask
name:"date"
function mask(input,splitter){
return innerObj.convertIntToDate(input,splitter)
}
}
}

Related

Haxe: Binding pattern with abstract fields access methods

I'd like to make wrapper to implement simple data binding pattern -- while some data have been modified all registered handlers are got notified. I have started with this (for js target):
class Main {
public static function main() {
var target = new Some();
var binding = new Bindable(target);
binding.one = 5;
// binding.two = 0.12; // intentionally unset field
binding.three = []; // wrong type
binding.four = 'str'; // no such field in wrapped class
trace(binding.one, binding.two, binding.three, binding.four, binding.five);
// outputs: 5, null, [], str, null
trace(target.one, target.two, target.three);
// outputs: 5, null, []
}
}
class Some {
public var one:Int;
public var two:Float;
public var three:Bool;
public function new() {}
}
abstract Bindable<TClass>(TClass) {
public inline function new(source) { this = source; }
#:op(a.b) public function setField<T>(name:String, value:T) {
Reflect.setField(this, name, value);
// TODO notify handlers
return value;
}
#:op(a.b) public function getField<T>(name:String):T {
return cast Reflect.field(this, name);
}
}
So I have some frustrating issues: interface of wrapped object doesn't expose to wrapper, so there's no auto completion or strict type checking, some necessary attributes can be easily omitted or even misspelled.
Is it possible to fix my solution or should I better move to the macros?
I almost suggested here to open an issue regarding this problem. Because some time ago, there was a #:followWithAbstracts meta available for abstracts, which could be (or maybe was?) used to forward fields and call #:op(a.b) at the same time. But that's not really necessary, Haxe is powerful enough already.
abstract Binding<TClass>(TClass) {
public function new(source:TClass) { this = source; }
#:op(a.b) public function setField<T>(name:String, value:T) {
Reflect.setField(this, name, value);
// TODO notify handlers
trace("set: $name -> $value");
return value;
}
#:op(a.b) public function getField<T>(name:String):T {
trace("get: $name");
return cast Reflect.field(this, name);
}
}
#:forward
#:multiType
abstract Bindable<TClass>(TClass) {
public function new(source:TClass);
#:to function to(t:TClass) return new Binding(t);
}
We use here multiType abstract to forward fields, but resolved type is actually regular abstract. In effect, you have completion working and #:op(a.b) called at the same time.
You need #:forward meta on your abstract. However, this will not make auto-completion working unless you remove #:op(A.B) because it shadows forwarded fields.
EDIT: it seems that shadowing happened first time I added #:forward to your abstract, afterwards auto-completion worked just fine.

adobe flex create child object given a parent object

i have the following 2 classes
class A {
var one:int;
}
class B extends A {
var two:int;
}
I now have an object of the class A but need to create and object of class B and set the additional parameters.
Does Flex allow child object creation given a parent object ?
note: there are lot of parameters in A so i don't want to copy individually each one.
Flex does allow multiple constructors, but it would take the form of copying each parameter in the constructor.
public class B extends A {
var two:int;
public function B(instanceA:A) {
this.one = instanceA.one;
//etc
}
}
Another approach could be to use ObjectUtil:
public class B extends A {
var two:int;
public function B(instanceA:A) {
var data = ObjectUtil.getClassInfo(instanceA);
for each (var prop in data.properties) {
this[prop] = instanceA[prop];
}
}
}
n.b. Check the excludes and options arguments of getClassInfo -- if there are properties that would cause problems to be processed in this way, you'll want to make sure to exclude them.

How to assign a dictionary to a QML property?

I have a custom QML object written in C++ where one property is of the type QVariantMap, so it should be compatible with Javascript objects.
However, I have some troubles actually assigning a JS object:
Uploader {
sample: selectSampleButton.fileUrl
parameters: {
x: '3'
y: "String"
}
}
Is this even possible like this? One possiblity I found that works is to assign it in Javascript:
uploader.parameters = {x: "Test"};
You need to wrap it in parentheses, otherwise it is parsed as a binding expression :
Uploader {
sample: selectSampleButton.fileUrl
parameters: ({
x: '3'
y: "String"
})
}
If you have a fixed set of keys you could create a "grouped property", e.g. like font or anchors
The type of a grouped property is just a QObject derived class with respective Q_PROPERTY declaration and an instance of that is used by the main class, in your case the class behin Uploader as a Q_PROPERTY of a pointer to the new type.
Roughly like this
class UploaderParameters : public QObject
{
Q_OBJECT
Q_PROPERTY(int x MEMBER m_x NOTIFY xChanged)
};
class Uploader : public QObject
{
Q_PROPERTY(UploaderParameters* parameters MEMBER m_parameters CONSTANT)
};
in QML
Uploader {
parameters.x: 3
}
or
Uploader {
parameters {
x: 3
}
}

QML: Make property readonly in derived class

I'm pretty sure the answer is no, but I thought I should ask anyway. Can an inherited property be made readonly/constant in a pure QML derived class?
// Base.qml
Item {
property int foo: 42
}
// Derived.qml
Base {
foo: 99 // Make constant somehow!
}
I'm currently tackling this by detecting a change in foo and printing an error to the console, but that's hardly a mark of good API...
I have a menu item class which can represent menu entries, submenus, separators, etc. I need to specialise it's behaviour, but only for when it is in submenu mode. I can change the inheritance tree so I have a subclass for each menu type, but this seems silly as each subclass will only contain a single readonly property. However if there isn't another way, I will have to.
You can also transform foo as a readonly alias to an internal property _foo that you will use only for assignment in the derived class:
// Base.qml
Item {
id: base
readonly property alias foo: base._foo
property int _foo: 42 // only used for assignment in subclasses
}
To be used in another Component:
Item {
Base {
id: child0
}
Base {
id: child1
_foo: 99
}
Base {
id: child2
_foo: child1.foo
}
Component.onCompleted: {
console.log("child0:", child0.foo,"child1:", child1.foo, "child2:", child2.foo)
child1.foo = 5 // not allowed!
console.log("child0:", child0.foo,"child1:", child1.foo, "child2:", child2.foo)
}
}
Output:
child0: 42 child1: 99 child2: 99
TypeError: Cannot assign to read-only property "foo"
Note: of course it is still possible to modify _foo later. But if you remember to use it only for assignment, then you have the desired behavior with a readonly foo in the derived class.
Why not use inherited getter/setters for a private foo?
something like :
//Base.qml
Item
{
QtObject
{
id : privateFoo
property int foo : 42
}
function getFoo() {return privateFoo.foo;}
function setFoo(newFoo) { privateFoo.foo = newFoo; }
}
//derived.qml
Base
{
function getFoo() {return 99;}
function setFoo(newFoo) { /*do nothing */ }
}
(I haven't tested this code)

Get all descendants types of base class

I have a base class called BaseEvent and several descendants classes:
public class BaseEvent {
// the some properties
// ...
}
[MapInheritance(MapInheritanceType.ParentTable)]
public class Film : BaseEvent {
// the some properties
// ...
}
[MapInheritance(MapInheritanceType.ParentTable)]
public class Concert : BaseEvent {
// the some properties
// ...
}
I have a code which create the BaseEvent instance at runtime:
BaseEvent event = new BaseEvent();
// assign values for a properties
// ...
baseEvent.XPObjectType = Database.XPObjectTypes.SingleOrDefault(
t => t.TypeName == "MyApp.Module.BO.Events.BaseEvent");
Now, this event will be shows in BaseEvent list view.
I want to do the following: when a user click Edit button then show in list view lookup field with all descendants types. And when user saves record change ObjectType to selected value.
How can I do this?
Thanks.
PS. this is asp.net app.
I'm not sure that your approach is correct for what you are trying to achieve. First, I'll answer the question you have asked, and afterwards I'll try to explain how the XAF already provides the functionality you are trying to achieve, namely how to choose which subclass of record to create from the user interface.
In order to create a property which allows the user to choose a Type within the application, you can declare a TypeConverter:
public class EventClassInfoTypeConverter : LocalizedClassInfoTypeConverter
{
public override StandardValuesCollection GetStandardValues(ITypeDescriptorContext context)
{
List<Type> values = new List<Type>();
foreach (ITypeInfo info in XafTypesInfo.Instance.PersistentTypes)
{
if ((info.IsVisible && info.IsPersistent) && (info.Type != null))
{
// select BaseEvent subclasses
if (info.Type.IsSubclassOf(typeof(BaseEvent)))
values.Add(info.Type);
}
}
values.Sort(this);
values.Insert(0, null);
return new TypeConverter.StandardValuesCollection(values);
}
}
And then your base event class would look like:
public class BaseEvent: XPObject
{
public BaseEvent(Session session)
: base(session)
{ }
private Type _EventType;
[TypeConverter(typeof(EventClassInfoTypeConverter))]
public Type EventType
{
get
{
return _EventType;
}
set
{
SetPropertyValue("EventType", ref _EventType, value);
}
}
}
However, I suspect this is not the functionality you require. Modifying the value of the property will NOT change the base type of the record. That is, you will end up with a record of type BaseEvent which has a property Type equal to 'Concert' or 'Film'.
XAF already provides a mechanism for selecting the type of record to create. In your scenario, you will find that the New button is a dropdown with your different subclasses as options:
Therefore you do not need to create a 'type' property within your object. If you need a column to show the type of event in the list view, you can declare a property as follows
[PersistentAlias("XPObjectType.Name")]
public string EventType
{
get
{
return base.ClassInfo.ClassType.Name;
}
}

Resources