Results 1 to 10 of 10

Thread: How to create a "node" using QObject

  1. #1
    Join Date
    May 2017
    Posts
    10
    Thanks
    2
    Qt products
    Qt3 Qt4 Qt5 Qt/Embedded Qt Jambi PyQt3 PyQt4
    Platforms
    Windows

    Question How to create a "node" using QObject

    I have been tasked with modifying the GUI of a software, specifically I need to add a third node under "PORT-1" and "PORT-2" called "CONNECTIONS" . Now I haven't worked in Qt before and really would like some guidance.
    Image: https://i.stack.imgur.com/QG0LE.jpg

    From the start I was told that every node would have its own class and header, in which bespoke functionality could be added. I just need to show an empty "CONNECTIONS" node for the time being.

    I went ahead and created the following header and class file:

    Header: FCConnections.h
    Qt Code:
    1. #ifndef FCCONNECTIONS_H
    2. #define FCCONNECTIONS_H
    3. #include <QObject>
    4. #include "FCInterface.h"
    5.  
    6. class CFCConnections: public CResourceItem
    7. {
    8.  
    9. Q_OBJECT
    10. Q_PROPERTY(QString Name READ fnGetName)
    11. public:
    12. CFCConnections(QObject*);
    13. ~CFCConnections();
    14.  
    15.  
    16. public:
    17. CFCInterface* pParent;
    18. int fnGetName();
    19. };
    20. Q_DECLARE_METATYPE(CFCConnections*);
    21.  
    22. #endif
    To copy to clipboard, switch view to plain text mode 

    Class: FCConnections.cpp

    Qt Code:
    1. #include "FCConnections.h"
    2. #include "FCInterface.h"
    3. #include "other headers"
    4.  
    5.  
    6. CFCConnections::CFCConnections(QObject* parent) : CResourceItem(parent)
    7. {
    8. pParent = (CFCInterface*) parent;
    9.  
    10. }
    11. CFCConnections::~CFCConnections()
    12. {
    13.  
    14. }
    15.  
    16. int CFCConnections:: fnGetName()
    17. {
    18.  
    19. return 3;
    20. }
    To copy to clipboard, switch view to plain text mode 

    The function ***fnGetName*** is just to demonstrate how I would get **READ** to work in **Q_PROPERTY**.

    The main "**FCASM**" node is controlled by a class called "**FCInterface**". Now how would I go about making the "**CONNECTIONS**" node? Do I make a function in **FCInterface** or **FCConnections**? What function can I use?

    The code block for the constructor of FCinterface is :
    Qt Code:
    1. CFCInterface::CFCInterface(QObject* parent): CInterface(parent), CFCAbstract()
    2. {
    3. fnSetProperty("objectName",QString("%1").arg("FCASM"));
    4. fnSetInterfaceType( "FCASM" );
    5. fnSetResourceBaseType(m_enDatabase);
    6. fnSetResourceItemType(m_enInterface);
    7. fnLoadDependentInfo();
    8.  
    9. }
    To copy to clipboard, switch view to plain text mode 

    I realise this is a broad question but any suggestion would be welcome.
    Attached Images Attached Images

  2. #2
    Join Date
    Jan 2008
    Location
    Alameda, CA, USA
    Posts
    5,230
    Thanks
    302
    Thanked 864 Times in 851 Posts
    Qt products
    Qt5
    Platforms
    Windows

    Default Re: How to create a "node" using QObject

    The function ***fnGetName*** is just to demonstrate how I would get **READ** to work in **Q_PROPERTY**.
    Except that the property is a QString, not an int, so this won't actually work. There is no built-in C++ conversion from int to QString.

    specifically I need to add a third node under "PORT-1" and "PORT-2" called "CONNECTIONS" .
    "Under" meaning what, exactly? As a child node of either PORT-1 or PORT-2, or as a sibling of PORT-1 and PORT-2 (i.e. a child of "FCASM")?

    Please be careful that you are not confusing the map for the terrain, in other words, do not confuse the GUI picture of what is displayed on screen (the tree view = "map", a picture of the data) with the underlying data structure that is used to build that view (the "terrain"). These are different things. You can model your data as a hierarchical set of QObject-based classes. You could do exactly the same thing using XML, read into a DOM document. Or in plain old C++.

    So it looks like there are rules for what can be added at each level of your tree. An "FCASM" node can have only "ports" as children, for example. I hope that your tree structure has been defined such that every node inherits from the same C++ base class (CResource, maybe? or CFCAbstract?)

    If "connections" are supposed to be children of "ports", then I would add a virtual function to this base class:

    Qt Code:
    1. virtual bool CFCAbstract::addChild( CFCAbstract * pChild );
    To copy to clipboard, switch view to plain text mode 

    In each derived class, you can perform a dynamic cast (for example) to ensure that "pChild" is a pointer to one of the types you allow as a child of that node at that level of the tree. If it is, you add it and return true, otherwise you do nothing and return false.

    So if "connections" are supposed to be children of "ports", then this code:

    Qt Code:
    1. bool CFCPort::addChild( CFCAbstract * pChild )
    2. {
    3. CFCConnection * pConn = dynamic_cast< CFCConnection * >( pChild );
    4. if ( pConn != nullptr )
    5. {
    6. // add connection child
    7. return true;
    8. }
    9. return false;
    10. }
    To copy to clipboard, switch view to plain text mode 

    If all of your classes are QObject-based, then you could use qobject_cast< CFCConnection * > instead of dynamic_cast<>.
    <=== The Great Pumpkin says ===>
    Please use CODE tags when posting source code so it is more readable. Click "Go Advanced" and then the "#" icon to insert the tags. Paste your code between them.

  3. #3
    Join Date
    May 2017
    Posts
    10
    Thanks
    2
    Qt products
    Qt3 Qt4 Qt5 Qt/Embedded Qt Jambi PyQt3 PyQt4
    Platforms
    Windows

    Default Re: How to create a "node" using QObject

    @d_stranz
    Thank you for the reply!!
    "Connections" is a sibling of "PORT-1" and "PORT-2". So, if I understood the code you wrote correctly,the following should work:
    Qt Code:
    1. bool CFCInterface::addChild( CFCAbstract * pChild )
    2. {
    3. CFCConnection * pConn = qobject_cast< CFCConnection * >( pChild );
    4. if ( pConn != nullptr )
    5. {
    6. // add connection child
    7. return true;
    8. }
    9. return false;
    10. }
    To copy to clipboard, switch view to plain text mode 

    Could you explain what you meant by the "Add connection child" comment?

  4. #4
    Join Date
    Jan 2008
    Location
    Alameda, CA, USA
    Posts
    5,230
    Thanks
    302
    Thanked 864 Times in 851 Posts
    Qt products
    Qt5
    Platforms
    Windows

    Default Re: How to create a "node" using QObject

    Could you explain what you meant by the "Add connection child" comment?
    It means "write the code here that you need to insert the child node into whatever data structure you are using to hold the information in the tree you are building".

    If your CFCAbstract hierarchy is all QObject-based (i.e. CFCAbstract inherits from QObject) then this could be as simple as:

    Qt Code:
    1. bool CFCInterface::addChild( CFCAbstract * pChild )
    2. {
    3. CFCConnection * pConn = qobject_cast< CFCConnection * >( pChild );
    4. if ( pConn != nullptr )
    5. {
    6. pConn->setParent( this );
    7. return true;
    8. }
    9. return false;
    10. }
    To copy to clipboard, switch view to plain text mode 

    But if I were doing this, I would implement a customized tree model that stored this structure independently of the view, then wrap it into a QAbstractItemModel for display in a QTreeView. See the Qt Simple Tree Model example.

    To translate that example to yours, "TreeItem" is replaced everywhere by "CFCAbstract", and all of the specific types derive from the CFCAbstract base class (which itself no longer derives from QObject; it's just an ordinary C++ class). The appendChild() method is what I called "addChild()" above, and would have to be made a virtual method and reimplemented in each class derived from CFCAbstract in order to implement your rules for what can be added where.
    Last edited by d_stranz; 12th May 2017 at 05:59.
    <=== The Great Pumpkin says ===>
    Please use CODE tags when posting source code so it is more readable. Click "Go Advanced" and then the "#" icon to insert the tags. Paste your code between them.

  5. The following user says thank you to d_stranz for this useful post:

    cryomicl (12th May 2017)

  6. #5
    Join Date
    May 2017
    Posts
    10
    Thanks
    2
    Qt products
    Qt3 Qt4 Qt5 Qt/Embedded Qt Jambi PyQt3 PyQt4
    Platforms
    Windows

    Default Re: How to create a "node" using QObject

    @d_stranz
    Thank you so very much!! As you can see, my knowledge in Qt is fairly limited. But with the help of supportive experts like you, people like me will surely learn!

  7. #6
    Join Date
    May 2017
    Posts
    10
    Thanks
    2
    Qt products
    Qt3 Qt4 Qt5 Qt/Embedded Qt Jambi PyQt3 PyQt4
    Platforms
    Windows

    Default Re: How to create a "node" using QObject

    @d_stranz
    I tried implementing the code, but there was no change in the GUI. By using breakpoints I found that the qobjectcast was returning a null pointer (pConn ==nullptr). Could you take a stab at why this could possibly be happening?

  8. #7
    Join Date
    Jan 2008
    Location
    Alameda, CA, USA
    Posts
    5,230
    Thanks
    302
    Thanked 864 Times in 851 Posts
    Qt products
    Qt5
    Platforms
    Windows

    Default Re: How to create a "node" using QObject

    Is the CFCConnection class derived from QObject somewhere in its inheritance hierarchy? Is the Q_OBJECT macro present in the class definition in the header file? Is MOC being run on the header file?
    <=== The Great Pumpkin says ===>
    Please use CODE tags when posting source code so it is more readable. Click "Go Advanced" and then the "#" icon to insert the tags. Paste your code between them.

  9. #8
    Join Date
    May 2017
    Posts
    10
    Thanks
    2
    Qt products
    Qt3 Qt4 Qt5 Qt/Embedded Qt Jambi PyQt3 PyQt4
    Platforms
    Windows

    Default Re: How to create a "node" using QObject

    Quote Originally Posted by d_stranz View Post
    Is the CFCConnection class derived from QObject somewhere in its inheritance hierarchy? Is the Q_OBJECT macro present in the class definition in the header file? Is MOC being run on the header file?
    Yes, yes and yes.

    The code to demonstrate the first two points:
    Qt Code:
    1. #include <QObject> //Included QObject
    2. #include "ResourceItem.h"
    3. #include "MonWindow.h"
    4. #include "FCTab.h"
    5. #include "ResourceItem.h"
    6. #include "FCAbstract.h"
    7. #include "FCInterface.h"
    8.  
    9. class CFCConnections: public CResourceItem
    10. {
    11.  
    12. Q_OBJECT //QObject MACRO
    13.  
    14. public:
    15. CFCConnections(QObject*);
    16. ~CFCConnections();
    17.  
    18. private:
    19. CFCInterface* pParent;
    20.  
    21.  
    22. };
    23.  
    24.  
    25. #endif
    To copy to clipboard, switch view to plain text mode 

    That was the FCConnections.h code. And I know that MOC has run on the header file because I had to manually change its build step to include MOC. This image below shows the inheritance hierarchy. CFCConnections is derived from CResourceItem which has QObject as its base class.
    1.jpg

    POSSIBLE SOLUTION

    I just had to change the line
    Qt Code:
    1. CFCConnections* f_pConn=0;
    To copy to clipboard, switch view to plain text mode 

    to
    Qt Code:
    1. CFCConnections* f_pConn;
    2. f_pConn = new CFCConnections(this);
    To copy to clipboard, switch view to plain text mode 
    Last edited by cryomicl; 16th May 2017 at 08:17.

  10. #9
    Join Date
    Jan 2008
    Location
    Alameda, CA, USA
    Posts
    5,230
    Thanks
    302
    Thanked 864 Times in 851 Posts
    Qt products
    Qt5
    Platforms
    Windows

    Default Re: How to create a "node" using QObject

    I just had to change the line
    So you mean to say you were trying to add a NULL pointer to an instance of CFCConnection to your hierarchy? Of course that won't work. qobject_cast<> won't magically turn a NULL or uninitialized pointer into a real one, it turns a real pointer to some QObject-based class into a pointer to another QObject-based class if the conversion is valid (that is, the type you are trying to cast to inherits from the type that is passed in).
    <=== The Great Pumpkin says ===>
    Please use CODE tags when posting source code so it is more readable. Click "Go Advanced" and then the "#" icon to insert the tags. Paste your code between them.

  11. #10
    Join Date
    May 2017
    Posts
    10
    Thanks
    2
    Qt products
    Qt3 Qt4 Qt5 Qt/Embedded Qt Jambi PyQt3 PyQt4
    Platforms
    Windows

    Default Re: How to create a "node" using QObject

    Quote Originally Posted by d_stranz View Post
    Of course that won't work. qobject_cast<> won't magically turn a NULL or uninitialized pointer into a real one.
    Now I know this from experience, the best way to never forget a lesson.
    Thank you for all your help

Similar Threads

  1. Replies: 2
    Last Post: 24th December 2015, 13:33
  2. Replies: 1
    Last Post: 20th November 2015, 10:02
  3. Replies: 3
    Last Post: 16th March 2015, 07:31
  4. Replies: 2
    Last Post: 27th January 2012, 17:29
  5. Translation QFileDialog standart buttons ("Open"/"Save"/"Cancel")
    By victor.yacovlev in forum Qt Programming
    Replies: 4
    Last Post: 24th January 2008, 19:05

Tags for this Thread

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  
Digia, Qt and their respective logos are trademarks of Digia Plc in Finland and/or other countries worldwide.