On one of variables changes value - qt

I have for example:
property var taskType: null
property var taskKind: null
so when I want to run some script each time one of those varibales cahnges, I would do something like:
onTaskTypeChanged: { bla() }
onTaskKindChanged: { bla() }
so as you can see, i need to run the same function when one of those changes... however happens that both of them changes at the same time, so I wish to run the scrip only once... so something like:
if (taskTypeChaned OR taskKindChanged) { bla() }
but that is obvously not correct...
so is there any way for qml to evalute in one of those two variables changes and then run the script?

You can use the Qt.callLater function:
onTaskTypeChanged: Qt.callLater(bla)
onTaskKindChanged: Qt.callLater(bla)

Related

How to write if statement comparing numbers that creates objects conditionally in QML

I'm working with QML and Python3.6 + PySide2 and I'm trying to write script in QML that takes two integers from a connection in python and compares them to decide what image background to use for the window.
There are a few things I'm struggling with. First, I am unsure how to compare my numeric (sunset and sunrise) variables. Second, I don't know how to write an if statement-esque part that produces a background image conditionally. Third, I don't think it's best to do this under Connections, and maybe even in my QML, but I'm not sure how to move my variables somewhere else.
I really appreciate any pointers or help!!
The data I'm drawing from looks like this:
"sunrise":1592565499,"sunset":1592617094
The QML pseudo-ish code:
Connections {
target: weather
function onDataChanged(){
if(!weather.hasError()){
var sunrise = weather.data['dt']['sunrise']
var sunset = weather.data['dt']['sunset']
if (sunrise <= sunset)
Image {
source: "night.png"}
else
Image {
course: "day.png"}
}
You cannot create QML-items from if-statements like that (neither from State's). You can call Qt.createComponent if you like, however, it is rather overkill in this example. You should directly set the source property of your image:
Image {
id: image_tod
}
Connections {
target: weather
function onDataChanged(){
if(!weather.hasError()){
var sunrise = weather.data['dt']['sunrise']
var sunset = weather.data['dt']['sunset']
if (sunrise <= sunset)
image_tod.source = "night.png"
else
image_tod.source = "day.png"
}
}
}
Looking at the code, you might actually be able to bind it directly to the source property (not sure what your model exactly looks like):
Image {
source: {
if(weather.data['dt']['sunrise'] <= weather.data['dt']['sunset'])
return "night.png"
else
return "day.png"
}
}
This works because when compiling the QML, the engine creates a dependency from every referenced variable (weather and data in this case), and re-evaluates the whole binding if any of them signals a change. To make fully use of this, you should also expose hasError as a property rather than a function (and emit whenever it changes).
Follow-up update
Yes, you can make it as wild as you want. I think you mean this:
Image {
source: {
if(weather.data['dt']['sunrise'] <= weather.data['dt']['sunset'])
return "night.png"
else if(weather.data['dt']['sunrise'] > weather.data['dt']['sunset'])
return "day.png"
else
return "" //means no image
}
}

UWP/WinRT with C++/CX: In a chain of asynchronous tasks, how can data be passed between them?

I understand that the return from one lambda is fed into the arguments of the next. However, what about if multiple pieces of data need to be passed, or the return type of one lambda is already set by the program structure?
Here is my working code where both of these are the case for opening up a file picker and then reading its contents as text while remembering what the file it came from was:
create_task(picker->PickSingleFileAsync())
.then([this](StorageFile^ file)
{
if (file == nullptr) cancel_current_task();
m_OpenFilename = file->Name;
return FileIO::ReadTextAsync(file);
})
.then([this](String^ fileContents)
{
//do something with the filename and file contents
});
Note that in order to make this work, I needed to add a class variable to store the filename in between the asynchronous tasks. This strikes me as bad for a number of reasons:
It is ugly having a class variable for the internal use of a single method
It this thread-safe? If someone goes nuts opening file pickers and selecting files, would these asynchronous tasks potentially clobber each other when accessing m_OpenFilename?
This is only a trivial example with one variable, but let's say I also want to keep track of the path of the file, and its file attributes, and a number of other characteristics. Now the class is looking uglier and uglier as the number of class variables increase.
My first approach was to have a variable local in scope to the function, and to pass it into each of the lambda functions by altering their capture lists to be [this, OpenFilename]. However, this would fail because by the time the lambda executed, C++/CX's background memory handlers would have already discarded Openfilename, resulting in an access violation when accessing it.
In my example, how can I pass the metadata of the file along to the results of ReadTextAsync so that I can have access to both the file and its contents at the same time?
The easiest way is to just continue building a chain of nested continuations:
auto picker = ref new FileOpenPicker();
picker->FileTypeFilter->Append(L".txt");
picker->SuggestedStartLocation = PickerLocationId::Desktop;
auto task = create_task(picker->PickSingleFileAsync()).then(
[](StorageFile^ file)
{
auto name = file->Name;
auto task = create_task(file->OpenReadAsync()).then(
[name](IRandomAccessStreamWithContentType^ iras)
{
OutputDebugString(name->Data());
});
});
If you don't want to do that (for whatever reason) another option is to use a shared_ptr to hold the value; in this case I'm going to hold on to the name and the created date in a helper file_info type:
struct file_info
{
Platform::String^ name;
Windows::Foundation::DateTime created;
};
auto picker = ref new FileOpenPicker();
picker->FileTypeFilter->Append(L".txt");
picker->SuggestedStartLocation = PickerLocationId::Desktop;
auto info = std::make_shared<file_info>();
auto task = create_task(picker->PickSingleFileAsync()).then(
[info](StorageFile^ file)
{
info->name = file->Name;
info->created = file->DateCreated;
return create_task(file->OpenReadAsync());
}).then(
[info](IRandomAccessStreamWithContentType^ iras)
{
OutputDebugString(info->name->Data());
OutputDebugString(L"\n");
wchar_t datetime[100];
_i64tow_s(info->created.UniversalTime, datetime, 100, 10);
OutputDebugString(datetime);
});

Select multiple time slots on click

When I click on a empty time slot on fullCalendar, it draws a rectangle on that empty cell. So, If my slotDuration is 30min, the block represents 30 min. I also can drag the cursor over multiple cells and select a custom range. But what I need to do is, when the user click (not drag) on a cell, select and draw the rectangle on 2 cells (representing 1 hour). Is this possible? I cannot change the slotDuration.
If I change the snapDuration to 1 hour, it works, but sadly, I cannot change it also.
What I was looking for is a way to override the event.end but that did not work.
Update 1:
I was able to do this exposing the cellDuration property:
on fullCalendar.js:
t.setCellDuration = function (minutes) {
var duration = moment.duration(minutes, 'minutes');
var view = t.getView();
view.timeGrid.cellDuration = duration;
}
now on the renderEvent handler, I can call
element.fullCalendar("setCellDuration", 60);
It works but if there is an alternative that does not involve change fullCalendar code, it would be nice.
I think you cannot do it just modifying the properties of the calendar, but you could do it modifying the fullCalendar.js file. Yes, I know you specify it on your question, but I think there is not alternative.
Exactly the listenStop function, which resides at line 4527 at version 2.3.3
listenStop check an array call dates
dates[
{FCMoment}, //start
{FCMoment} //end
]
So, before that check, you can modify your end time as you prefer. In addition, you have to render it.
In your code, now listenStop() function should be something like:
listenStop: function(ev) {
if (dates) { // started and ended on a cell?
if (dates[0].isSame(dates[1])) {
dates[1] = dates[0].clone().add(1, 'hours'); //Now we modify the end
_this.renderSelection(dates[0], dates[1]); //And render the modified selection
view.trigger('dayClick', dayEl[0], start, ev);
}
if (isSelectable) {
// the selection will already have been rendered. just report it
view.reportSelection(start, end, ev);
}
}
}

Resetting target values in a composite effect

We need to be able to handle a "playable" (play/pause/seek) effect in which the nature of the effect cannot be determined at compile time.
The problem we are running into is resetting the target(s) state after the effect has completed. If we manually drag the seek slider back to the beginning, everything works fine. However, if we set the playheadTime of the composite effect back to 0, the effected targets retain their original value until the playheadTime gets to the correct position to effect the target.
Here is a simplified (as much as I could) test case with view source enabled:
http://www.openbaseinteractive.com/_tmp/PlayableEffectTest/
The problem is demonstrated if you let it play to the end, and then hit the play button to start it over.
What is the best way to go about manually resetting the target values given that the exact nature of the effect is unknown?
Many thanks for your time!
edit
I forgot to mention we are using Flex 4.5 preview release.
Have you tried:
effect.reverse()
More info
http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/mx/effects/IEffect.html
http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/mx/effects/IEffect.html#reverse()
Well it's a little kludgy, but I was able to accomplish this by calling some internal methods on the effect to capture the start values, then assigned those values to the targets on a reset.
import mx.core.mx_internal;
use namespace mx_internal;
private var _propertyChangesArray:Array;
protected function captureStartValues(effect:Object):void
{
effect.captureStartValues();
_propertyChangesArray = effect.propertyChangesArray;
}
protected function reset(effect:Object):void
{
for each(var change:PropertyChanges in _propertyChangesArray)
{
var target:Object = change.target;
for(var p:String in change.start)
{
if(target.hasOwnProperty(p))
{
var startVal:* = change.start[p];
var endVal:* = target[p];
if(!isNaN(startVal) && startVal != endVal)
{
target[p] = startVal;
}
}
}
}
effect.playheadTime = 0;
}
I don't know if this is the best way to accomplish this, but it seems to be working so far. I am absolutely open to suggestions for a better method.
Cheers!

.toggle(true) throw null in $(document).ready(function())

I am toggling row siblings. I wrote .toggle(true) when document ready. see below picture. I think row sibling are not availble before this function calls.
$(document).ready(function() {
$('tr[#class^=RegText]').hide().children('td');
list_Visible_Ids = [];
var idsString, idsArray;
idsString = $('#myVisibleRows').val();
idsArray = idsString.split(',');
$.each(idsArray, function() {
if (this != "") {
$(this).siblings('.RegText').toggle(true);
list_Visible_Ids[this] = 1;
}
});
How to resolve this? why sliblings are not avaible in when document is ready?
Your posted code doesn't match the debugger code, your code has this, which is (almost!) correct:
$(this).siblings('.RegText').toggle(true);
The debugger has this, which is incorrect:
$(this).siblings(('.RegText').toggle(true));
You need to update whatever you're actually debugging to that code without the extra parenthesis, otherwise you're going to get some pretty funky behavior there.
Also you need a # in there since your debugger shows you're not storing the hash mark in the array, which is perfectly fine. You're currently calling $("row10") (which looks for <row10> elements), but what you need is $("#row10") (which looks for id="row10" elements), so adjust your call like this:
$('#' + this).siblings('.RegText').toggle(true);

Resources