Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. QML and Qt Quick
  4. What is the good way to work with pointers in Javascript/Qml?
QtWS25 Last Chance

What is the good way to work with pointers in Javascript/Qml?

Scheduled Pinned Locked Moved Unsolved QML and Qt Quick
pointersjavascript qmlinstanceobjectcomponent
2 Posts 2 Posters 1.0k Views
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • jeanmilostJ Offline
    jeanmilostJ Offline
    jeanmilost
    wrote on last edited by jeanmilost
    #1

    I'm originally a c/c++ developer, and in this language it's possible to keep a pointer to an object, which may be e.g. used to call a function on this object from another one, or to compare if 2 pointers represent the same object instance.

    But the qml language is built above Javascript, and in this language the things are a little more complicated, and the notion of pointers is not exactly the same as in c/c++, for example it's not safe to compare object instances, because they may be different even if they represent the same object.

    However I'm working on a project where I need to retrieve instances of qml components and work with them, for example I need to retrieve the instance of the components hovered by the mouse, and to compare if one of these components matches with another one.

    For example, consider the following code:

    function getItemsAbovePoint(item, point, result)
    {
        // iterate through children
        for (let i = 0; i < item.children.length; ++i)
            getItemsAbovePoint(item.children[i], point, result);
    
        // item contains point?
        if (item.contains(item.mapFromGlobal(point.x, point.y)))
            result.push(item);
    }
    
    ...
    
    MouseArea
    {
        ...
    
        /// Called when the mouse button is released after been pressed (above or outside the control)
        onReleased: function(mouseEvent)
        {
            // not adding a link?
            if (!m_AddingLinkItem)
                return;
    
            // notify the page that the link is no longer dragging
            if (m_Box && m_PageContent)
                m_PageContent.m_DraggingMsg = false;
    
            // no document?
            if (!m_Document)
                return;
    
            let doRemoveMsg = false;
            let targetConn  = null;
    
            try
            {
                let result = [];
    
                // get all controls located above the mouse onto the document
                JSHelper.getItemsAbovePoint(pageContent, this.mapToGlobal(mouseEvent.x, mouseEvent.y), result);
    
                // search for target connector
                for (let i = 0; i < result.length; ++i)
                    if (result[i].objectName === m_Box.leftConnector.objectName  ||
                        result[i].objectName === m_Box.topConnector.objectName   ||
                        result[i].objectName === m_Box.rightConnector.objectName ||
                        result[i].objectName === m_Box.bottomConnector.objectName)
                    {
                        // found it? May break the loop if yes, because no connector can overlap another
                        targetConn = result[i];
                        break;
                    }
    
                // found a valid target connector?
                if (targetConn && targetConn.visible && targetConn.m_Box !== m_Box)
                {
                    console.log("Connector - link added successfully - name - " + m_AddingLinkItem.objectName);
    
                    // yes, attach the new link to it
                    m_AddingLinkItem.m_To = targetConn;
                }
                else
                {
                    console.log("Connector - link adding - CANCELED");
    
                    // no, remove the currently adding link
                    doRemoveMsg = true;
                }
            }
            catch (exception)
            {
                let startBoxName   =  m_Box                           ? m_Box.objectName            : "<unknown>";
                let endBoxName     = (targetConn && targetConn.m_Box) ? targetConn.m_Box.objectName : "<unknown>";
                let targetConnName =  targetConn                      ? targetConn.objectName       : "<unknown>";
    
                // log error
                console.error("Connector - add link - FAILED - start box name - " + startBoxName           +
                              " - end box name - "                                + endBoxName             +
                              " - start connector - "                             + ctConnector.objectName +
                              " - end connector - "                               + targetConnName         +
                              " - error - "                                       + exception);
    
                // remove the incompletely added link
                doRemoveMsg = true;
            }
    
            // do remove the link?
            if (doRemoveMsg)
            {
                m_AddingLinkItem.unbindMsgFromBox(m_Box)
                m_AddingLinkItem.destroy();
    
                // emit signal that link adding was canceled
                m_Page.linkCanceled();
            }
            else
                // emit signal that link was added
                m_Page.linkAdded(m_AddingLinkItem);
    
            // since now link is no longer adding
            m_AddingLinkItem = null;
        }
    }
    

    The above code is a part of the below visual action on my interface:
    Interface.gif

    As you can see, I try to get a component of type "connector" when the mouse button is released, which may be located below the mouse cursor, and which belongs to a parent component of type "box". The purpose of this code is to link a "box" component with another one. If succeeded, the two "boxes" components will be visually linked on the interface with a line, and this line should react to the "box" events, e.g. if a "box" is moved, the line should follow the "box", as it can be seen on the above gif.

    The code works globally well in normal circumstances, however there are several issues, among others:

    1. Comparisons like targetConn.m_Box !== m_Box may fail, because in Javascript, pointers may represent the same object instance but be different. I noticed a such issue if e.g. I try to create dynamically the parent "page" component, which contains my "boxes". In this case the above comparison always succeed even if the instances are the same.
    2. In the same idea, the getItemsAbovePoint() function may retrieve a targetConn target connector which is not the one I expected, as if it was a kind of copy of the connector instance, and in this case the line position isn't updated when the "box" is moved, because attached to the incorrect connector instance

    So as using pointers seems unsafe in Javascript/Qml, my question is: What should I use instead, and how can I safely retrieve the instance of a component and use it? Or is my concept completely wrong, and in this case, what is the correct way to perform the tasks I need to complete?

    I would be grateful if someone may orient me...

    1 Reply Last reply
    0
    • C Offline
      C Offline
      Colton
      wrote on last edited by
      #2

      Javascript abstracts the concept of pointers. Data is only ever passed around by reference. It is usually safer, since memory management is handled automatically and you can be sure an object equals another object if they are compared.

      If you need to compare objects to see if they are identical, you may have better luck creating a "compare" method that directly compares primitive attributes (strings can be compared directly, for instance).

      Hope this helps, sorry I can't provide a more specific implementation suggestion. Too many details to focus on at once.

      1 Reply Last reply
      0

      • Login

      • Login or register to search.
      • First post
        Last post
      0
      • Categories
      • Recent
      • Tags
      • Popular
      • Users
      • Groups
      • Search
      • Get Qt Extensions
      • Unsolved