How can I modify a property value in QJsonValue or QJsonObject? - qt

I haven't found any method on those qt object that seems useful for modifying properties. See my code comment for exactly what I want to do.
for (const QJsonValue& value : array) {
// here I want to set the value for the 'id' key to 0
addRecording(new Recording(value.toObject()));
}
I am not picky about the approach
It doesn't matter to me if I modify the QJsonValue or the QJsonObject returned by the toObject method.
I am fine with copying and creating a temporary variable if that would be needed

I figured out a solution to this:
for (const QJsonValue& value : array) {
QJsonObject obj = value.toObject();
auto iterator = obj.find("id");
obj.erase(iterator);
obj.insert("id", 1000);
addRecording(new Recording(obj));
}

Related

Accessing pointer object properties in Vala

I have refactored a bit my code, so i need a pointer that could contain multiple liste types :
owl_list = new Gee.LinkedList<OpenWithAction> ();
a_list = new Gee.LinkedList<OpenAppAction> ();
Gee.List* any_list = null;
So i have a pointer any_list which i can use to access either owl_list or a_list (depending on a switch no present here, but assume there is)
if (!any_list.size)
return null;
But this will fail as valac throws at me error: The name `size' does not exist in the context of `Gee.List*'
if (!any_list.size)
I haven't done any C,C++ since a very long time and I'm no vala expert, since i use more typeless languages, but is there any way this could work ?
EDIT:
I just tried
fieldType = OpenWithAction.get_type();
if (!(any_list as Gee.List<fieldType>).size)
error: The type name `fieldType' could not be found
if (!(any_list as Gee.List<fieldType>).size)
Obviously I'm doing something wrong, what i'm trying to do is : Vala: determine generic type inside List at runtime, i just can"t manage to implement it.
return null;
EDIT 2:
I just solved partially my problem :
As said by #jens-mühlenhoff, yes OpenWithAction and OpenAppAction have a common ancestor and it is GLib.Action
So all i had to do is declare :
Gee.List<Action> any_list = null;
instead of
Gee.List* any_list = null;
now foreach (var action in any_list) is working, but i'm still getting an error with
if (any_list->size == null)
return null;
error: The name `size' does not exist in the context of `Gee.List<Synapse.Action>?'
if (any_list->size == null)
another try is :
if (!any_list.size)
return null;
Operator not supported for `int'
if (!any_list.size)
any_list is a pointer, so you can't use the . operator. Try any_list->size.
Two things i was doing wrong :
1-
Like in C# i should not have used a pointer if not needed. So using :
Gee.List<Action> any_list = null; is just working fine. The explanation is that OpenWithAction and OpenAppAction have a common ancestor class, So declaring a List with that type is just working fine ( on the other hand i don't know in the case they didn't have a common ancestor).
2- int type can't be used as bool type so if (any_list.size == 0) would work whereas if (!any_list.size) would throw an error
Thanks every one for helping :)

How do I create the correct KeyboardEvent objects for a given string of text?

I'd like to simulate some keyboard input by dispatching KeyboardEvent objects manually. Creating such events involves passing a key code.
Alas, I only have a given string
const text: String = "Hello";
I can easily get the char code using String::charCodeAt, but how can I get the key code? For any given character (say: "H") there may be just a single key code, a key code plus some modifier (in this case: Shift + keycode_of_h) or even multiple key codes. Is there maybe a way to get the key code for a given char code (possibly by considering the keyboard mapping of the user)?
This isn't too difficult but it will just take a little bit to set up.
First create a dictionary or Object mapping the UTF-8 values to key values like this:
var keyCodes:Dictionary = new Dictionary();
keyCodes[49] = Keyboard.NUMBER_1; //1
// add the rest of the mappings...
Then because you need to specify SHIFT
var shiftedKeyCodes:Dictionary = new Dictionary();
shiftedKeyCodes[33] = Keyboard.NUMBER_1; //!
// add the rest of the shifted mappings
Then create a utility function like this:
public function charCodeToKeyboardEvent(charCode:int):KeyboardEvent{
var event:KeyboardEvent = new KeyboardEvent(KeyboardEvent.KEY_UP);
event.charCode = charCode;
if(keyCodes[charCode]){
event.keyCode = keyCodes[charCode];
} else if (shiftedKeyCodes[charCode]){
event.keyCode = shiftedKeyCodes[charCode];
event.shiftKey = true;
} else {
return null;
}
return event;
}
Then loop through your string and do this:
for(var i:int = 0; i < myString.length; i++){
dispatchEvent(charCodeToKeyboardEvent(myString.charCodeAt(i)));
}
EDIT: I updated this to use the constants on the Keyboard class so that it will work independent of device or operating system.
It turns out that I didn't need a 100% correct KeyboardEvent in the first place. Instead, there were two things I was missing:
A flash.events.TextEvent needs to be dispatched for plain text (like "Hello") input.
The events need to be dispatched to the embedded edit control which can be accessed using the textDisplay property.

ILGenerator. Whats wrong with this Code

I am trying to build a dynamic Property Accessor. Want something which is like really fast as close to calling the actually Property. Dont want to go the Reflection route as its very slow. So i opted to using DynamicAssembly and inject IL using ILGenerator. Below is the ILGenerator related code which seems to work
Label nulllabel = getIL.DefineLabel();
Label returnlabel = getIL.DefineLabel();
//_type = targetGetMethod.ReturnType;
if (methods.Count > 0)
{
getIL.DeclareLocal(typeof(object));
getIL.DeclareLocal(typeof(bool));
getIL.Emit(OpCodes.Ldarg_1); //Load the first argument
//(target object)
//Cast to the source type
getIL.Emit(OpCodes.Castclass, this.mTargetType);
//Get the property value
foreach (var methodInfo in methods)
{
getIL.EmitCall(OpCodes.Call, methodInfo, null);
if (methodInfo.ReturnType.IsValueType)
{
getIL.Emit(OpCodes.Box, methodInfo.ReturnType);
//Box if necessary
}
}
getIL.Emit(OpCodes.Stloc_0); //Store it
getIL.Emit(OpCodes.Br_S,returnlabel);
getIL.MarkLabel(nulllabel);
getIL.Emit(OpCodes.Ldnull);
getIL.Emit(OpCodes.Stloc_0);
getIL.MarkLabel(returnlabel);
getIL.Emit(OpCodes.Ldloc_0);
}
else
{
getIL.ThrowException(typeof(MissingMethodException));
}
getIL.Emit(OpCodes.Ret);
So above get the first argument which is the object that contains the property. the methods collection contains the nested property if any. for each property i use EmitCall which puts the the value on the stack and then i try to box it. This works like a charm.
The only issue is if you have a property like Order.Instrument.Symbol.Name and assume that Instrument object is null. Then the code will throw an null object exception.
So this what i did, i introduced a null check
foreach (var methodInfo in methods)
{
getIL.EmitCall(OpCodes.Call, methodInfo, null);
getIL.Emit(OpCodes.Stloc_0);
getIL.Emit(OpCodes.Ldloc_0);
getIL.Emit(OpCodes.Ldnull);
getIL.Emit(OpCodes.Ceq);
getIL.Emit(OpCodes.Stloc_1);
getIL.Emit(OpCodes.Ldloc_1);
getIL.Emit(OpCodes.Brtrue_S, nulllabel);
getIL.Emit(OpCodes.Ldloc_0);
if (methodInfo.ReturnType.IsValueType)
{
getIL.Emit(OpCodes.Box, methodInfo.ReturnType);
//Box if necessary
}
}
Now this code breaks saying That the object/memory is corrupted etc. So what exactly is wrong with this code. Am i missing something here.
Thanks in Advance.
Previously, if you had consecutive properties P returning string and then Q returning int, you would get something like this:
...
call P // returns string
call Q // requires a string on the stack, returns an int
box
...
Now you have something like this:
...
call P // returns string
store // stores to object
... // load, compare to null, etc.
load // loads an *object*
call Q // requires a *string* on the stack
store // stores to object *without boxing*
...
So I see two clear problems:
You are calling methods in such a way that the target is only known to be an object, not a specific type which has that method.
You are not boxing value types before storing them to a local of type object.
These can be solved by reworking your logic slightly. There are also a few other minor details you could clean up:
Rather than ceq followed by brtrue, just use beq.
There's no point in doing Stloc_1 followed by Ldloc_1 rather than just using the value on the stack since that local isn't used anywhere else.
Incorporating these changes, here's what I'd do:
Type finalType = null;
foreach (var methodInfo in methods)
{
finalType = methodInfo.ReturnType;
getIL.EmitCall(OpCodes.Call, methodInfo, null);
if (!finalType.IsValueType)
{
getIL.Emit(OpCodes.Dup);
getIL.Emit(OpCodes.Ldnull);
getIL.Emit(OpCodes.Beq_S, nulllabel);
}
}
if (finalType.IsValueType)
{
getIL.Emit(OpCodes.Box, methodInfo.ReturnType);
//Box if necessary
}
getIL.Emit(OpCodes.Br_S, returnLabel);
getIL.MarkLabel(nulllabel);
getIL.Emit(OpCodes.Pop);
getIL.Emit(OpCodes.Ldnull);
getIL.MarkLabel(returnlabel);
Note that we can get rid of both locals since we now just duplicate the top value on the stack before comparing against null.

AS3: Whats determines the order of: for..in

OK I am looping through the properties in an object like so:
private var _propsList:Object = {'Type':'product_type'
,'Kind':'product_type_sub'
,'Stone':'primary_stone'
,'Stone Color':'primary_stone_sub'
,'Metal':'metal_type'
,'Brand':'product_brand'};
for(key in _propsList)
{
val = _propsList[key];
trace(key +" = "+ val);
}
I am expecting the first trace to be Type = property_type since that is the first one defined in the array, however it is coming up random everytime. I guess this is because my keys are strings and not integers, however is there a way to specify the order it loops through them?
Thanks!!
You can't rely on for (v in someObject) ... to return things in a predictable order, no.
Depending on your specific situation, you could just use an array to hold the keys, and just iterate through that:
private var keys:Array = ["Type", "Kind", "Stone", "Stone Color", "Metal", "Brand"];
private function iterate():void
{
for each (var k:String in keys)
{
trace(_propsList[k]);
}
}
Maybe a bit obvious or non-elegant, but it'd get the job done. :)
you could hack it by classing-out your "_propsList" object creating an array inside of the newly created PropsList class that references the properties in order. At that point, you could run a FOR loop on the array and get your properties in order.
OR, you could have a function inside that new class that would return an Array of those properties. like this:
public function getProps():Array {
return [myPropertyOne, myPropertyTwo, myPropertyThree];
}
In general, I think this is a case where you shouldn't depend on a particular behavior from the framework/language you are using. This type of behavior is generally poorly documented and can change from version to version.
If you really need a specific retrieval order, I would create a wrapper class as jevinkones suggested above. Maybe there's even a utility class in the framework somewhere to accomplish this (Dictionary, etc.?)
HTH,
Karthik
I found this link that gives some background:
Subtle Change in for..in Loops for ActionScript 3
This question is actually a dup of this one.
How about using an array representation like this:
var _propsList:Array = [
['Type', 'product_type'],
['Kind', 'product_type_sub'],
['Stone', 'primary_stone'],
['Stone Color', 'primary_stone_sub'],
['Metal', 'metal_type'],
['Brand', 'product_brand']
];
for(var i in _propsList) {
var elem = _propsList[i];
var key = elem[0];
var val = elem[1]
}

Get the type in flex

can someone tell me how I can identify the type of an object in flex? In particular I have an array where I store multiple types in (but all UIComponents) now as I evaluate the array I want to find out whether I have a TextInput Control or a RadioButton. Does someone have an idea?
Thanks in advance
You can either test against a particular class using the "is" operator or you can use flash.utils.getQualifiedClassName() (you pass it your object) - which will return a string of the fully qualified class name.
ITS WORKING :)
Following is the way I solved this issue
switch( true )
{
case item is Customer_SF:
c = item as Customer_SF;
break;
case item is Opportunity:
o = item as Opportunity;
break;
case item is Product:
o = ( item as Product )._opportunity;
break;
default:
return true;
}
Try to use the "className" property.
It should return "TextInput" or "Button" depending the case
for each (var item:* in myArray)
{
if(item.hasProperty('className'))
{
trace("item ["+i+"] is :" + item['className']);
}
}
The operator "is" represents one option.
Then there is the operator instanceof, which might or might not be useful depending on situation.
Also there's the ObjectUtil class with static method getClassInfo. This one returns more than just the object's class name.
Operator "typeof" unfortunately is useless for classes.
And, as Branden Hall already suggested, flash.utils.getQualifiedClassName().
here's some simple pseudo-code which demonstrates how to use the is operator for what you want to do:
for each (var item:* in myArray)
{
if (item is TextInput)
doSomethingWithTextInput(item as TextInput);
else if (item is RadioButton)
doSomethingWithRadioButton(item as RadioButton);
}
The is operator tests for type compatibility, yes. From the docs, is:
... evaluates whether an object is
compatible with a specific data type,
class, or interface. Use the is
operator instead of the instanceof
operator for type comparisons. You can
also use the is operator to check
whether an object implements an
interface.
Other useful operators in this category are typeof (which returns a string representation of a primitive), instanceof (similar to is, but disregards interface compatibility) and as. A great and complete list of ActionScript operators is available here.
Hope it helps!
Your best bet is using the "is" operator and use something like:
for( var i:int = 0; i < componentArr.length; i++ )
{
var comp:UIComponent = componentArr[ i ];
if( comp is DataGrid )
// Handle DataGrid functionality here.
else if (comp is DropDown )
// Handle DropDown here
}
There is one problem with this approach, however. Because "is" will return true for all descendant classes, you must put all of the descendant classes before their ancestors -- List must come before ListBase. This can cause some annoyances.
// This is important to remember:
var mc:MovieClip = new MovieClip();
trace( mc is Sprite ); // true
There is one other option for cases where you want objects to be a member of a specific class (and not a descendant class): you can use the constructor property of the object and use a switch statement.
for( var i:int = 0; i < componentArr.length; i++ )
{
var klass:Class = componentArr[ i ].constructor;
switch( klass )
{
case DataGrid:
// Handle DataGrid
break;
case Text:
// Handle Text
break;
case NumericStepper:
// Handle NumericStepper
break;
default:
// Handle default
break;
}
}

Resources