Important: Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

A few design questions...



  • Hey, Zap. That worked like a champ...thanks so much. A few comments:

    The reason I was using shaperOutIString() was to gain some control over the format of the output. I did remove it, though, and...my formatting is magically how I want it. I guess I made another fix to this somewhere else.

    I'd like to move the timer out of the widget and into the test loop (or at least copy it). But...I don't think I'll put it in the constructor of the filter, will I? seems like it should be in the testCycle loop.

    Also...it seems as though there's an unnecessary level of indirection here, using the SoC to get to the filter. Since I'm going to be replicating this with other kinds of filters, should I be devising a scheme to allow the widget to directly access any objects with members on display?

    Thanks again.



  • [quote author="mzimmers" date="1305900771"]Hey, Zap. That worked like a champ...thanks so much.
    [/quote]
    No problem. ;-)

    [quote author="mzimmers" date="1305900771"]
    A few comments:

    The reason I was using shaperOutIString() was to gain some control over the format of the output. I did remove it, though, and...my formatting is magically how I want it. I guess I made another fix to this somewhere else.
    [/quote]

    The reason is that the QML engine automatically calls the shaperOutIString() function for you when it is notified that it's value has changed. Set a break point in that function and run it then look at the call stack. You'll see that the calls originate from within the QDeclarative.dll module.

    [quote author="mzimmers" date="1305900771"]
    I'd like to move the timer out of the widget and into the test loop (or at least copy it). But...I don't think I'll put it in the constructor of the filter, will I? seems like it should be in the testCycle loop.
    [/quote]

    That's entirely up to you. Putting it in the Soc class would seem a reasonable place to me but I do not have as much info as you about what you are trying to do.

    [quote author="mzimmers" date="1305900771"]
    Also...it seems as though there's an unnecessary level of indirection here, using the SoC to get to the filter. Since I'm going to be replicating this with other kinds of filters, should I be devising a scheme to allow the widget to directly access any objects with members on display?
    [/quote]

    Well all we're doing is exposing a pointer to the filter object by means of an accessor function on the Soc class. Picture it as a hierarchical system. The Soc class (system on chip?) contains a number of subsystem objects, one of them is DemodShaperFilter in this case, which in turn could provide access to an even lower level of components.

    If you GUI only starts off with a pointer to the Soc object then the two obvious ways of getting at the properties of the sub or sub-sub systems are:

    • provide getter functions that provide pointers to the lower-level (children) objects - this is what we have done here OR
    • provide a set of simple forwarding functions that provide access to the properties directly from the top-level Soc object.

    Option 2 leads to a lot of boring code to write like:

    @
    long Soc::myCoolPropertyOfGrandChild()
    {
    return m_childObject->myCoolPropertyOfChild();
    }
    ...
    long ChildObject::myCoolPropertyOfChild()
    {
    return m_childOfChild->myCoolProperty();
    }
    @

    This quickly leads to lots of code and a huge API to the Soc class with likely naming collisions.

    Sometimes it is useful to hide internal implementation details this way but in your case I think it would be of no real benefit.

    [quote author="mzimmers" date="1305900771"]
    Thanks again.
    [/quote]

    You're welcome.



  • Good points made, Zap.

    Regarding the timer: as you know, my testCycle routine loops about 1000 times. I just wanted to put a small delay in there, so that you can watch the GUI update the figure. Right now, it happens so fast that you only see the final value.

    bq. The reason is that the QML engine automatically calls the shaperOutIString() function for you when it is notified that it’s value has changed. Set a break point in that function and run it then look at the call stack. You’ll see that the calls originate from within the QDeclarative.dll module.

    How does it know to do this? Automatic black magic within QML via the routine naming convention?



  • [quote author="mzimmers" date="1305903192"]Good points made, Zap.
    Regarding the timer: as you know, my testCycle routine loops about 1000 times. I just wanted to put a small delay in there, so that you can watch the GUI update the figure. Right now, it happens so fast that you only see the final value.
    [/quote]

    Do you want your filter loop to run 1024 times per Soc simulation cycle but still be able to see the results? If so then you need to allow some time for the event loop to run each time around the loop (or every n-iterations around the loop).

    This is done by calling qApp->processEvents() somewhere in your loop. This allows control to return to the event loop breifly so that it can process paintEvents (amongst other things). Try inserting a call to qApp->processEvents after yoru call to setShaperIOut() in your loop.

    You'll notice that this will still be too fast to see much. If you want to slow it down then you could refactor your code to use another timer. Be careful of how this would interact with the other timer that kicks off the Soc simulation loop though.

    What are you trying to achieve?

    A simulation that runs as fast as possible with state updated in a GUI now and then. or

    a simulation that is deliberately slow in order to allow humans to see each and every step at a sane rate?

    [quote author="mzimmers" date="1305903192"]
    How does it know to do this? Automatic black magic within QML via the routine naming convention?[/quote]

    No it is not black magic. It is because you emit the notifier signal in this function:

    @
    void DemodShaper::setShaperOutI(long i)
    {
    if (shaperOutI != i) // only emit signal if value has changed
    {
    shaperOutI = i;
    emit shaperOutIChanged();
    }
    }
    @

    and in your ctor you have connected that notifier signal to the notifier signal for the hex formatted string property:

    @
    DemodShaper::DemodShaper(QObject *parent, long rv) :
    QObject(parent),
    cellArrayI(NBR_CELLS, Cell(rv)),
    cellArrayQ(NBR_CELLS, Cell(rv)),
    shaperOutI(0)
    {
    connect (this, SIGNAL(shaperOutIChanged()),
    this, SIGNAL(shaperOutIStringChanged()));
    }
    @

    The QML engine knows what property bindings you have made in your .qml file and so it knows which property notifier signals to connect to in order to be able to spot when an update is needed.

    This all fits together such that when you set the shaperOutI property the QML engine calls the getter function for the hex formatted string property. The chain of events looks like this:

    • call setShaperOutI(long i)
    • signal shaperOutIChanged() is emitted (if value is different)
    • signal shaperOutIStringChanged() is emitted (because of the above signal-signal connection)
    • QML engine notices this and knows that in this eventuality it needs to update the properties in the qml file that are in some way bound to it. In order to update them it has to first fetch the new property value and so it calls the function shaperOutIString().

    So you see. No magic. Just some clever plumbing ;-)



  • Ah, yes...good explanation of the chain of events. I still have trouble keeping all this clear in my head.

    Regarding the delay timer: I'll want to do different things eventually, but right now, I'd be happy if each iteration of the test loop included a brief delay, just so the updated value can be observed for a moment. This isn't how it will run in production, but for now, there's value in having it work this way.



  • OK. I have to run now, but I'll give it some thought and see if I can patch your source code over the weekend to get it to do this.



  • Thanks, Zap. Don't sweat it too much; I may not be explaining it well, but I'm almost sure it's no big deal to do.


Log in to reply