QML ListModel and custom function property - qml

I want to write tuned version of TableView (TableView.qml in Qt package).
I have ColumnDescriptor.qml with column definition:
Item {
property string title
property var formatDelegate: null
.... (other property definition)
function format(val) {
if (formatDelegate != null)
return formatDelegate(val);
else
return val;
}
}
The above code defines set of properties and fuction format(val), that calls for format value if formatDelefate was set.
In the main table I use list to store predefined columns definition (temporaly) and ListModel to store final columns definition ( the latter is more useful than list in remaining implementation)
list example:
property list<ColumnDescriptor> colDefines: [
ColumnDescriptor {
title: qsTr("col1")
},
ColumnDescriptor {
title: qsTr("col2")
formatDelegate: function(val) { return "!" + val}
}
]
Filling ListModel (id: columnModel):
Component.onCompleted: {
for(var i = 0; i < colDefines.length; ++i)
{
var col = colDefines[i];
...(some calculation)
columnModel.append(col);
}
}
All looks fine, but when I try to call format from model item, Qt sends me the following error
Property 'format' of object QQmlDMListAccessorData(0x8e3bf78) is not a function
Example of calling format:
Repeater {
model: columnModel
Text {
text: model.format([SOME USEFUL DATA])
}
}
On the other hand, if I call format directly from list it works well.
So my question here is how to fill model in a way that the format or other function will work correctly when being called from model?

For QtQuick2 this should work
formatDelegate = [function(val) { return "!" + val}]
formatDelegate[0]("some text")
but you could also use an overriding technique:
Item {
function formatDelegate(val) {
return val;
}
function format(val) {
return formatDelegate(val);
}
}
ColumnDescriptor {
function formatDelegate(val) {
return "!" + val
}
}
This way Item.format() should call "return val" as default and "!"+val for ColumnDescriptor given that ColumnDescriptor is derived from Item.

Try this
Repeater {
model: columnModel
Text {
text: columnModel[index].format([SOME USEFUL DATA])
}
}

Related

Shopify bulk query results parsing

I am working on a shopify integration, and I am trying to perform some bulk queries which return data in jsonl format.
I read carefully the documentation, and I understood which is the principle behind this format, but there is one thing I don't understand: the following is a portion of my jsonl file representing the first item in the result
{"id":"gid:\/\/shopify\/Product\/6755349070004","options":[{"id":"gid:\/\/shopify\/ProductOption\/8677003133108","name":"Città","position":1}],"title":"Product title","productType":"Concerto Live"}
{"id":"gid:\/\/shopify\/ProductVariant\/40163436363956","price":"100.00","title":"MIlano","__parentId":"gid:\/\/shopify\/Product\/6755349070004"}
{"id":"gid:\/\/shopify\/ProductVariant\/40163436396724","price":"100.00","title":"Roma","__parentId":"gid:\/\/shopify\/Product\/6755349070004"}
{"id":"gid:\/\/shopify\/ProductVariant\/40163436429492","price":"100.00","title":"Firenze","__parentId":"gid:\/\/shopify\/Product\/6755349070004"}
{"id":"gid:\/\/shopify\/Collection\/272323707060","description":"Product variant description","title":"CONCERTI","__parentId":"gid:\/\/shopify\/Product\/6755349070004"}
{"id":"gid:\/\/shopify\/Collection\/272323739828","description":"Product variant description","title":"LIVE","__parentId":"gid:\/\/shopify\/Product\/6755349070004"}
{"id":"gid:\/\/shopify\/Collection\/273036607668","description":"Product variant description","title":"Product variant description","__parentId":"gid:\/\/shopify\/Product\/6755349070004"}
and it's obtained by the following query
mutation {
bulkOperationRunQuery(
query: """
{
items: products{
pageInfo {
hasNextPage
}
edges {
cursor
node {
id
variants(first: 10) {
edges {
node {
id
price
title
}
}
}
options(first: 5) {
id
name
position
}
title
collections(first: 8) {
edges {
node {
id
metafields(first: 5) {
edges {
node {
id
key
namespace
value
}
}
}
description
title
}
}
}
productType
images(first: 2) {
edges {
node {
src
}
}
}
}
}
}
}
"""
) {
bulkOperation {
id
status
}
userErrors {
field
message
}
}
}
So The first line it the "main" product object, the lines 2,3 and 4 are the variants, then we have the collections and then the image: the problem is that, besides the parent's id, there is no way to know which parent's property a child line refers to. If I want to build back a json from this, how can I know for example that the second line is an item of the array in products.variants?
You can use either:
the id format (gid://shopify/Product/6755349070004 is a product)
the __typename property that exists on all GraphQL objects

Default values in list query parameter

I am trying to display default values in Swashbuckle. Is there a way to define default values in a query list parameter in a .NET Core API.
Something like:
[HttpGet("test")]
public ActionResult<string> TestFunc([FromQuery, BindRequired] List<string> testList = ["value1", "value2"]) {
//Do some stuff
return Ok(results);
}
As far as I know, we couldn't set the default parameter value must be compile-time constant which means we couldn't set a default value for a list or array of string.
That means there is no way to set the defualt value inside the web api paramter.
If you want to show the default value inside the swagger. You could create a class which inherit from IOperationFilter.
Then you could check the paramter name, if the name is equals the testList ,you could set the custom description.
More details, you could refer to below codes example:
Custom class:
public class ParameterClass : IOperationFilter
{
public void Apply(OpenApiOperation operation, OperationFilterContext context)
{
if (operation.Parameters == null)
{
return;
}
foreach (var parameter in operation.Parameters) {
if (parameter.Name == "testList")
{
parameter.Description = #"Default value: ['value1', 'value2']";
}
}
}
}
Register the swaggergen with filter :
services.AddSwaggerGen(c =>
{
c.OperationFilter<ParameterClass>();
});
Result:
Update:
If you want to set the parameter like query string, you could modify the apply method as below:
public void Apply(OpenApiOperation operation, OperationFilterContext context)
{
if (operation.Parameters == null)
{
return;
}
foreach (var parameter in operation.Parameters) {
if (parameter.Name == "testList")
{
parameter.In = 0;
parameter.Description = #"['value1', 'value2']";
parameter.Schema = new OpenApiSchema() { Type = "string" ,Items = null };
}
}
}
Result:

Parent-driven determination that can end in class change

I'm trying to make a use from Steam API data as I like to learn on live examples, and looking at the way various statistics are returned I began to think that OOP approach would suit me best in this case.
What I'm trying to achieve is to loop through all the results, and programatically populate an array with objects of type that corresponds to the actual type of the statistic. I've tried to build myself a basic class, called Statistic, and after instantiating an object determine wheter or not it's class should change (i.e. whether or not to cast an object of type that Statistic is parent to and if so, of what type). How to do that in PHP? My solution gives me no luck, all of the objects are of type Statistic with it's 'type' property being the object I want to store alone in the array. Code:
$data = file_get_contents($url);
$data = json_decode($data);
$data = $data->playerstats;
$data = $data->stats;
$array;
for($i=0;$i<165;$i++)
{
$array[$i] = new Statistic($data[$i]);
echo "<br/>";
}
var_dump($array[10]);
And the classes' code:
<?php
class Statistic
{
public function getProperties()
{
$array["name"] = $this->name;
$array["value"] = $this->value;
$array["type"] = $this->type;
$array["className"] = __CLASS__;
return json_encode($array);
}
public function setType($x)
{
$y = explode("_",$x->name);
if($y[0]=="total")
{
if(!isset($y[2]))
{
$this->type = "General";
}
else
{
if($y[1]=="wins")
{
$this->type = new Map($x);
$this->__deconstruct();
}
if($y[1]=="kills")
{
$this->type = new Weapon($x);
$this->__deconstruct();
}
else $this->type="Other";
}
}
else $this->type = "Other";
}
function __construct($obj)
{
$this->name = $obj->name;
$this->value = $obj->value;
$this->setType($obj);
}
function __deconstruct()
{
echo "deconstructing <br/>";
return $this->type;
}
}
class Weapon extends Statistic
{
public function setType($x)
{
$y = explode("_",$x);
if($y[1]=="kills")
{
$this->type = "kills";
}
else if($y[1]=="shots")
{
$this->type = "shots";
}
else if($y[1]=="hits")
{
$this->type = "hits";
}
}
function __construct($x)
{
$name = explode("_",$x->name);
$this->name = $name[2];
$this->value = $x->value;
$this->setType($x->name);
}
function __deconstruct()
{
}
}
class Map extends Statistic
{
public function setType($x)
{
if($x[1]=="wins")
{
$this->type = "wins";
}
if($x[1]=="rounds")
{
$this->type = "rounds";
}
}
public function setName($name)
{
if(isset($name[3]))
{
if(isset($name[4]))
{
return $name[3] + " " + $name[4];
}
else return $name[3];
}
else return $name[2];
}
function __construct($x)
{
$name = explode("_",$x->name);
$this->name = $this->setName($name);
$this->value = $x->value;
$this->setType($name);
}
function __deconstruct()
{
}
}
Gives the result:
object(Statistic)#223 (3) {
["name"]=> string(18) "total_kills_deagle"
["value"]=> int(33)
["type"]=> object(Weapon)#222 (3) {
["name"]=> string(6) "deagle"
["value"]=> int(33)
["type"]=> string(5) "kills" }
}
Should that determination be driven from the loop itself, the whole advantage of having a set of functions that does everything for me and returns a ready-to-serve data is gone, since I would really have to cast different objects that aren't connected to each other, which is not the case here. How can I achieve returning objects of different type than the object itself is?
For answer your question How can I achieve returning objects of different type than the object itself is?
"Casting to change the object's type is not possible in PHP (without using a nasty extension)"
For more info: Cast the current object ($this) to a descendent class
So you can't change the class type of an instance with type of a derived class. In other world can't change instance of Static with instance of Weapon.

Changed event for JavaScript Binding in Qml?

I have a property which is defined by a JavaScript expression (currentContainer):
Item {
id: theContainer
property alias currentIndex: theListView.currentIndex
signal onCurrentIndexChanged()
property MyCustomCppContainer currentContainer: {
if(theListView.currentIndex >= 0)
theModel.getCustomContainer(theListView.currentIndex)
else
null
}
signal onCurrentContainerChanged() // nobody calls this signal (yet)
MyCustomCppModel {
id: theModel
}
ListView {
id: theListView
anchors.fill: parent
model: theModel
currentIndex: -1
onCurrentIndexChanged: theContainer.onCurrentIndexChanged()
/* Other properties stripped for example */
}
}
Sadly I always get the last selected container, not the currently selected one:
ContainerItem {
onCurrentIndexChanged: {
//On first change, currentContainer is null
//though the first one was selected
//After selecting the second entry
//I get the result I expected last time
console.log(currentContainer.name);
}
}
I think a solution would be to have another signal for currentContainer: onCurrentContainerChanged().
But who calls this special signal?
I could solve this using a C++ helper class:
class PropertyChangedHelper : public QObject
{
Q_OBJECT
Q_PROPERTY(QVariant theProperty WRITE setTheProperty NOTIFY thePropertyChanged)
public:
PropertyChangedHelper(QObject* parent = nullptr) : QObject(parent) {}
virtual ~PropertyChangedHelper() {}
void setTheProperty(QVariant) {
Q_EMIT thePropertyChanged();
}
Q_SIGNALS:
void thePropertyChanged();
private:
Q_DISABLE_COPY(PropertyChangedHelper)
};
Usage is quite simple:
PropertyChangedHelper {
theProperty: containerItem.currentContainer
onThePropertyChanged: {
console.log(containerItem.currentContainer.name);
}
}
I am not sure if this violates any Qml/QtQuick philosophies, but it works.

what is the correct way to extract two sets of data from a method class

I am new to OOP and still a bit confused by the concepts
I created a class` method that will extract two sets of data from a Zend_Session_Namespace. my problem now is that I don't know how to extract these data when its pulled into another method.
It might be best if I show you what I mean:
Public function rememberLastProductSearched()
{
$session = new Zend_Session_Namespace(searchedproducts);
if ($this->getRequest()->getParam('product-searched')) {
$session->ProductSearched = $this->getRequest()->getParam('product-searched');
return " $session->ProductSearched";
} else {
if ($session->ProductSearched) {
return " $session->ProductSearched ";
}
}
if ($this->getRequest()->getParam('search-term')) {
$session->SearchTerm = $this->getRequest()->getParam('search-term');
return " $session->SearchTerm";
} else {
if ($session->SearchTerm) {
return " $session->SearchTerm ";
}
}
This method should obtain two sets of data i.e the
$session->SearchTerm
$session->ProductSearched
my confusion is this; how do I now extract both sets of data in another method call (that is within the same class).i.e
Above is my attempt to extract the information- but it did not work.
Alternatively, should I have placed the information into an array- if so, can somebody please tell me how I could have done this.
It looks like what you're trying to do is use the product-searched and search-terms from params and store them in the session if they're set, otherwise access previously saved values. It would help a bit to see how you're calling this method, but I would probably modify your code slightly to return the session namespace object instead, since that then contains the two values, regardless of whether they came from params or were there already:
public function rememberLastProductSearched()
{
$searchedProducts = new Zend_Session_Namespace('searchedproducts');
if ($this->getRequest()->getParam('product-searched')) {
$searchedProducts->ProductSearched = $this->getRequest()->getParam('product-searched');
}
if ($this->getRequest()->getParam('search-term')) {
$searchedProducts->SearchTerm = $this->getRequest()->getParam('search-term');
}
return $searchedProducts;
}
I'm assuming you have this method in a controller class, so you'd call it like this:
public function searchAction()
{
$searchedProducts = $this->rememberLastProductSearched();
// do something with the values here
}
you'll then have the two values in $searchedProducts->ProductSearched and $searchedProducts->SearchTerm.
The line "return $something;" will stop the code execution and return the value. If you want to return more than one value, you will need to either return an array or use two separate functions to return the values. If you want to return an array, you could do it this way:
public function rememberLastProductSearched() {
$returnArray = array();
$session = new Zend_Session_Namespace(searchedproducts);
if ($this->getRequest()->getParam('product-searched')) {
$session->ProductSearched = $this->getRequest()->getParam('product-searched');
$returnArray['productSearched'] = $session->ProductSearched;
} else {
if ($session->ProductSearched) {
$returnArray['productSearched'] = $session->ProductSearched;
}
}
if ($this->getRequest()->getParam('search-term')) {
$session->SearchTerm = $this->getRequest()->getParam('search-term');
$returnArray['searchTerm'] = $session->SearchTerm;
} else {
if ($session->SearchTerm) {
$returnArray['searchTerm'] = $session->SearchTerm;
}
}
return $returnArray;
}
In your controller or wherever you wanted to check for those values:
$lastSearch = $this->rememberLastProductSearched();
echo $lastSearch['productSearched']; // Product Searched
echo $lastSearch['searchTerm']; // Search terms
But it might be cleaner to use two function
public function getLastProductSearched() {
$session = new Zend_Session_Namespace(searchedproducts);
if ($this->getRequest()->getParam('product-searched')) {
$session->ProductSearched = $this->getRequest()->getParam('product-searched');
$returnValue = $session->ProductSearched;
} else {
if ($session->ProductSearched) {
$returnValue = $session->ProductSearched;
}
}
return $returnValue;
}
public function getLastSearchTerms() {
$session = new Zend_Session_Namespace(searchedproducts);
if ($this->getRequest()->getParam('search-term')) {
$session->SearchTerm= $this->getRequest()->getParam('search-term');
$returnValue = $session->SearchTerm;
} else {
if ($session->SearchTerm) {
$returnValue = $session->SearchTerm;
}
}
return $returnValue;
}
And you could use them like this:
echo $this->getLastProductSearched(); // Product Searched
echo $this->getLastSearchTerms(); // Search terms
It will make your code easier to read and debug later on. A few more notes on your code. You could avoid using nested ifs by using ||.
if ($this->getRequest()->getParam('product-searched') || $session->ProductSearched) {
$returnValue = $this->getRequest()->getParam('product-searched') || $session->ProductSearched;
}
will achieve the same thing as :
if ($this->getRequest()->getParam('product-searched')) {
$session->ProductSearched = $this->getRequest()->getParam('product-searched');
$returnArray['productSearched'] = $session->ProductSearched;
} else {
if ($session->ProductSearched) {
$returnArray['productSearched'] = $session->ProductSearched;
}
}
Hope this helps !