Unable to assign QString to QQuickItem* with Qt.resolvedUrl - qml

I have the following code:
Tabs {
Tab {
id: financialDetailsTab
title: i18n.tr("Financial Details")
page: Qt.resolvedUrl("FinancialDetails.qml")
}
Tab {
id: monthlyBudgetTab
title: i18n.tr("Monthly Budget")
page: Qt.resolvedUrl("MonthlyBudget.qml")
}
Tab {
id: annualBudgetTab
title: i18n.tr("Annual Budget")
page: Qt.resolvedUrl("AnnualBudget.qml")
}
Tab {
id: savingsGoalsTab
title: i18n.tr("Savings Goals")
page: Qt.resolvedUrl("SavingsGoals.qml")
}
}
which is generating the following errors:
Unable to assign QString to QQuickItem*
Unable to assign QString to QQuickItem*
Unable to assign QString to QQuickItem*
Unable to assign QString to QQuickItem*
on the lines where Qt::resolvedUrl is being used. The Tabs component is a part of the Ubuntu SDK, and not Qt Quick, and the only example of it's use doesn't provide much insight into the problem.
I've added the exact same lines as properties of the MainView, outside of the Tabs component, and the problem has not been evident there, leading me to believe the issue lies with the Ubuntu component. While the problem may be with the Ubuntu component, some help in understanding what the error message actually means would be helpful.

The error you are getting means that the 'page' property from Tab { } item can't accept a string (or url) content, it wants an Item or derived component.
So I'm pretty sure your AnnualBudget or SavingsGoals files can be instanciated as components, since they are in the same folder (so no import needed) and the file name first letter is uppercase so QML engine automatically allows you to do this :
Tabs {
Tab {
id: financialDetailsTab
title: i18n.tr("Financial Details")
page: financePage;
}
}
FinancialDetails {
id: financePage;
}
So 'financePage' is an ID, so for the QML engine it's a QQuickItem pointer and it will accept it.
Just do the same for each tab/page pair.

Related

ckeditor5 - custom container element - recursion error on paste

I'm trying to create a CKEditor5 custom element plugin - mainly for custom format/styles -- nested divs etc. Managed to be able to inject/format the elements, and I can type in them. But if I try to copy and paste text into a custom element I get a too much recursion error.
MyWidget plugin:
export default class MyWidgetPlugin extends Plugin {
init() {
const editor = this.editor;
editor.model.schema.register('my-widget', {
inheritAllFrom: '$root',
isLimit: true,
});
editor.conversion.elementToElement({ model: 'my-widget', view: 'my-widget' });
editor.commands.add('myWidget', new MyWidgetCommand(editor));
}
}
MyWidget command:
class MyWidgetCommand extends Command {
execute() {
const editor = this.editor;
const block = first(this.editor.model.document.selection.getSelectedBlocks());
this.editor.model.change(writer => {
const myWidget = writer.createElement('my-widget')
writer.insert ( myWidget, block, 'after');
writer.appendElement( 'paragraph', myWidget );
});
}
}
Inserting a widget injects this into the editor:
<my-widget>
<p></p>
</my-widget>
And I can type fine, but I can't paste. I'm guessing I got the schema wrong... have played around with quite a few different options.. but to no avail.
I didn't check it but I think that the issue is here:
editor.model.schema.register('my-widget', {
inheritAllFrom: '$root',
isLimit: true,
});
This schema rule says that <my-widget> will allow e.g. a <paragraph> inside it. But it doesn't say anything about where <my-widget> may be used. That's because $root is not allowed in any other element (cause it's a root :)).
I think that the following should work fine:
editor.model.schema.register('my-widget', {
inheritAllFrom: '$root',
allowIn: '$root',
isLimit: true,
});
Alternatively, a more generic solution should work too:
editor.model.schema.register('my-widget', {
inheritAllFrom: '$root',
allowWhere: '$block',
isLimit: true,
});
Still, the editor should not crash with an infinite loop, so I reported https://github.com/ckeditor/ckeditor5-engine/issues/1441.

Cumulocity - Custom widget configuration

I'm writing a chart widget in cumulocity platform.
In widget comes with the platform,
I can select data point after I select device:
But the widget I wrote can only select device, there is no data point option for me to select:
I know there is c8yComponentsProvider that has options for me to select if I want device target or not. Is there a way for me to choose what data point I want?
From angular 2 it has to be done in this way.
In my custom widget project I added to the usedValue secion of app.module.ts as follows.
useValue: {
id: 'acme.text.widget', // 3.
label: 'Text widget',
description: 'Can display a text',
component: WidgetDemo, // 4.
configComponent: WidgetConfigDemo,
data: {
ng1: {
options: {
noDeviceTarget: true
}
}
}
}
You can disable the device selector in the options of the c8yComponentsProvider:
options: {
noDeviceTarget: true
}
And then use the following directive in your widget config html:
<c8y-data-point-list datapoints="data.datapoints"></c8y-data-point-list>
You need to set the data points to choose in the data.datapoints object on the widget configuration controller. Therefore you can search for managed objects with the fragment c8y_DataPoint.
In the document is an example how to do that with the c8yInventory service:
var filters = {fragmentType: 'c8y_DataPoint', withParents: true};
$scope.data = {};
c8yInventory.list(filters).then(function (devices) {
$scope.data.datapoints = [];
_.forEach(devices, function(dp) {
$scope.data.datapoints.push(dp);
});
});
Note that the c8y-data-point-list is a nonofficial directive. If you face any problems or you want a specific look, you might be faster by writing your own directive.

WinJS Listview shows undefined when navigating quickly

I have a WinJS application with listviews in which if quickly navigate between pages before the listview is fully loaded, the next page shows the listview with all elements in it bound as "undefined".
So say I have a hub page with a "to do" that is filtered to only show 6 items, and there is a header that navigates to the full "to do" page, when the hub page is displayed but before it is fully loaded I click on the header link to the "to do" page, the app then goes to the "to do" page, but the items show up with all the properties in the tile as "undefined".
I am using IndexedDB as my data store.
My home page code looks like this:
WinJS.UI.Pages.define("/pages/home/home.html", {
ready: function (element, options) {
WinJS.Utilities.query("a").listen("click", function (e) {
e.preventDefault();
WinJS.Navigation.navigate(e.currentTarget.href);
}, false);
viewModel = new HomeViewModel(element);
viewModel.load(); //loads from indexed db
},
//etc...
To Do Page:
WinJS.UI.Pages.define("/pages/ToDo/ToDo.html", {
ready: function (element, options) {
viewModel = new ToDoViewModel(element);
viewModel.load();
},
etc//
I know there isn't much to go off, but any ideas would be appreciated.
Also tips on how to debug something like this would be great.
Update
I narrowed it down to this one line from the Hub Page:
myLib.GetData(todaysDate, function (result) {
that.trendsModel.today = result;
WinJS.Binding.processAll(that.el.querySelector("#dataPanel"), that.trendsModel); //<--Right Here
});
If I remove that, then when I load the second page the data doesn't show as undefined. What is interesting is the data initially shows correctly on the second page and then it changes to "undefined".
Solution
My fix:
myLib.GetData(todaysDate, function (result) {
var element = that.el.querySelector("#dataPanel");
that.trendsModel.today = result;
if(element) {
WinJS.Binding.processAll(element, that.trendsModel);
}
});
At the point when when the callback returns, I am already on the second page. So the selector was not found returning null. If you pass null to processAll it tries to bind the whole page which is why I was able to see the correct data for a second then it changes to undefined...Wow, what a doozy. I guess it makes sense but what a pain to find.
Hope it helps someone in the future :)
Your ToDoViewModel, and HomeViewModel need to be observable. This means they need to mix in from WinJS.Binding.mixin, and for the properties that you pull in asynchronously, they need to call this.notify("propertyName", newVal, oldVal) from the property setter.
Note that you need to have getter/setter properties. e.g.
var bindingBase = WinJS.Class.mix(function() {}, WinJS.Binding.mixin);
WinJS.Namespace.define("YourNamespace", {
ToDoViewModel: WinJS.Class.derive(bindingBase, function constructor() {
}, {
_titleStorage: "",
title: {
get: function() { return this._titleStorage; },
set: function(newValue) {
if(newValue === this._titleStorage) {
return;
}
var old = this._titleStorage;
this._titleStorage = newValue;
this.notify("title", newValue, old);
}
}
}),
});
myLib.GetData(todaysDate, function (result) {
var element = that.el.querySelector("#dataPanel");
that.trendsModel.today = result;
if(element) {
WinJS.Binding.processAll(element, that.trendsModel);
}
});
At the point when when the callback returns, I am already on the second page. So the selector was not found returning null. If you pass null to processAll it tries to bind the whole page which is why I was able to see the correct data for a second then it change to undefined...Wow, what doozy. I guess it makes sense but what a pain to find.

How to access item in a ListDelegates / ListView outside of it?

I am new to Qt / QML coding and I am facing one problem with respect to accessing the elements in a listdelegate in a listview.
For Example if my Qml looks like this
Item
{
id: item_id
property int focus_id: 0
function setFocusImageSource() {}
ListView
{
id: listView_Id
delegate: listViewdelegate
model: listModeldata
}
Component
{
id: listViewdelegate
Rectangle
{
id: rectangle_id
Image
{
id: focus_Image
source: x.x
}
}
}
ListModel
{
id: listModeldata
/*elements*/
}
}
Now the basic functionality of the list view is working fine with my code ( not the above one ) how ever when I do specific operation I need to change the focusing Image . I want to change it using the function "setFocusImageSource()" . I have tried setting the image source directly using focus_Image.source = "xx" .
Is it like the Image inside the Rectangle component is local to the delegate and cannot be accessed from ITEM tag. If so How can I set the image from the function mention above.
Thanks in advance.
Chand.M
A counterpart of QML Component in C++ is a class. As you know you can change members' values only in class' instances - objects. The same is true for Components too: you can not change anything in Component - only in its instances. There are two possibilities to solve you problem:
Bind properties of listViewdelegate to some property outside of it: property of item_id or listView_Id or something else.
Bind properties of listViewdelegate to some property of the element of listModeldata.
Examples:
Image {
id: focus_Image
source: x.x // defualt value
Connections {
target: item_id
onFocus_idChanged: {
if ( /* some logic if needed */ ) {
focus_Image.source = xx;
}
}
}
}
or
Image {
id: focus_Image
source: {
// inidicator is a property of the element of listModeldata
if (indicator) {
return xx;
}
}
}

Dynamically adding html to panel

I am designing an app in sencha touch2. I have a panel object in my JS file. I need to dynamically set the text/html for this component. The store for this component is defined at the application level. Following is the thing I worked out:
Ext.define('class_name',{
....
config : {
pnlObj : null,
...
}
initialize : function() {
this.config.pnlObj = Ext.create('Ext.Panel');
var store = Ext.data.Storemanager.lookup('some_store');
store.on('load',this.loadStore,this);
this.setItems([{
//some items here
{
flex : 2,
// id : 'somepnl',
config : this.config.pnlObj
}
}]);
},
loadStore : function(store, rec) {
var text = rec.get('text');
var panel = this.config.pnlObj;
// var panel = Ext.getCmp('somepanl');
panel.setHtml(text);
}
});
When I inspect the inspect the element using Firebug console, I can find the panel added there. But I am not able to set the html dynamically. no html text is set there. I tried adding it using panel.add() & panel.setItems() method which doesn't work. If I give an id to that panel(somepanel here) and try to access it using Ext.getCmp('smpanel') then in that case it works fine. I have found that using Ext.getCmp() is not a good practice and want to avoid it as it might somewhere break my code in the future.
I guess the way I am instantiating the panel object is creating some issue. Can someone suggest the best way of doing it?
The recommended way to manipulate your components in Sencha Touch 2 is using controller, through refs and control configs. For example, your panel has a config like this: xtype:'myPanel', then in your controller:
refs: {
myPanel: 'myPanel'
}
control:{
myPanel: {
on_an_event: 'set_html_for_my_panel'
}
}
Lastly, define your function:
set_html_for_my_panel: function()
{
this.getMyPanel().setHtml('my_updated_html');
}
P/S: Behind the scene, Sencha Touch 2 uses Ext.ComponentQuery for refs in controllers