Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. General and Desktop
  4. Expand Activeqt comapp example to separate classes from main.cpp
Forum Updated to NodeBB v4.3 + New Features

Expand Activeqt comapp example to separate classes from main.cpp

Scheduled Pinned Locked Moved Unsolved General and Desktop
forum
11 Posts 3 Posters 144 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.
  • A Offline
    A Offline
    AliQT
    wrote last edited by
    #1

    Hi
    I am trying to use the ActiveQT comapp example in the QT installation examples folder as the basis for finding out how to add ActiveX visibility to an existing QT application, ie turn it into an out of process com server. I am a novice when it comes to QT and c++ but can understand it and make simple alterations to existing code. The initial problem I am having is separating the three classes in the example main.cpp file (ie Application, Document and DocumentList,) into separate .cpp and .h files. I think this is necessary before trying to expand to the multiple classes I will need going forward, as it is impractical to put them all into one .cpp file without headers. The issues I ge largely seem to do with circular dependancies between the classes, as eg the DocumentList has a parent of the Application class. I know there many articles giving advice on how to get around such circular references to be found on the web, but I have tried so many times to use them, without success, that I am desperate. It would be so helpful if someone with both QT and c++ experience could seperate the classes to eg Application.cpp/.h DocumentList.cpp/.h Document.cpp/.h with the example still compiling/ working. Is there anyone who would do this for me? Payment would be available if required.
    Thanks

    JonBJ 1 Reply Last reply
    0
    • A AliQT

      Hi
      I am trying to use the ActiveQT comapp example in the QT installation examples folder as the basis for finding out how to add ActiveX visibility to an existing QT application, ie turn it into an out of process com server. I am a novice when it comes to QT and c++ but can understand it and make simple alterations to existing code. The initial problem I am having is separating the three classes in the example main.cpp file (ie Application, Document and DocumentList,) into separate .cpp and .h files. I think this is necessary before trying to expand to the multiple classes I will need going forward, as it is impractical to put them all into one .cpp file without headers. The issues I ge largely seem to do with circular dependancies between the classes, as eg the DocumentList has a parent of the Application class. I know there many articles giving advice on how to get around such circular references to be found on the web, but I have tried so many times to use them, without success, that I am desperate. It would be so helpful if someone with both QT and c++ experience could seperate the classes to eg Application.cpp/.h DocumentList.cpp/.h Document.cpp/.h with the example still compiling/ working. Is there anyone who would do this for me? Payment would be available if required.
      Thanks

      JonBJ Online
      JonBJ Online
      JonB
      wrote last edited by JonB
      #2

      @AliQT said in Expand Activeqt comapp example to separate classes from main.cpp:

      The issues I ge largely seem to do with circular dependancies between the classes, as eg the DocumentList has a parent of the Application class.

      The classes use pointers to each other. They do not need to see the definition of the other classes, only that they exist. For example if DocumentList is in a separate file from Application it does not need to #include "application.h", you only need to write

      class Application;
      

      above the class DocumentList definition and that allows it to have e.g. explicit DocumentList(Application *application);.

      Note how the main.cpp itself already has

      class Application;
      class DocumentList;
      

      near the top.

      I don't see any circular dependencies there, the classes should be splittable into separate files so long as they only reference each other via pointers. You only need the other class definition if you dereference the pointer, which I don't see going on.

      1 Reply Last reply
      1
      • A Offline
        A Offline
        AliQT
        wrote last edited by
        #3

        Hi Jon, thanks for the swift reply.
        I've split the classes as I think you're suggesting, but am getting issues shown in the below screenprint, ie eg 'use of undefined type ''DocumentList' in application.cpp. I've added the code for the claases and remnant of main.cpp below.

        issues.png

        1 Reply Last reply
        0
        • A Offline
          A Offline
          AliQT
          wrote last edited by
          #4

          The forum doesen't seem to allow posting of code. Do you know how I can get the code to the forum or yourself?

          codeisspam.png

          1 Reply Last reply
          0
          • JonBJ Online
            JonBJ Online
            JonB
            wrote last edited by JonB
            #5

            @AliQT
            I'm afraid the Akismet post checker thing seems to ban a lot of legitimate stuff, especially with large code blocks. Really someone ought try to do something about this, you are not the first person to fall foul. I think I can see you have tried to enclose your code inside a pair of ``` lines, which is just the right thing to do but it still rejects it anyway.

            It's hard to see from the two screenshots just what you have and what is wrong. A whole bunch of consequential errors in the first shot, probably depends on what the cause of the first error is. For the second shot, on the one hand I cannot spot what is wrong with the QTimer::singleShot() call.

            I will have a go now at copying that sample and dividing it into Application/DocumentList/Document module files for you. Will let you know when done and we will find some way of getting it to you.

            1 Reply Last reply
            0
            • JonBJ Online
              JonBJ Online
              JonB
              wrote last edited by JonB
              #6

              @AliQT
              OK, I have done a version which compiles, splitting all 3 classes into their own source files.

              It's a .zip file containing just the sources. I have uploaded to a free site where I understand the link remains available for a week. It is https://limewire.com/d/sFtIk#JbakOrsCmy . I created/uploaded it via https://file.io . So far as I understand this a common site and is all safe & legit, but obviously access at your own risk.

              There are indeed issues which affect the normally-more-straightforward processes of splitting C++ classes into separate files. These were due to Qt features including Q_PROPERTY and QScopedPointer (e.g. there is an issue per https://forum.qt.io/topic/116515/does-a-qsharedpointer-have-to-include-headers-rather-than-a-forward-declaration). I commented these where the problems arose and put in my replacement. I believe the functionality is the same. I agree there are tricky issues here. If what I have done is indeed required then I agree it would not be easy for a beginner.

              I do not do Qt under Windows so I cannot actually compile, let alone test, the stuff to do with QAxObject (you do realise that is Windows only, right?). I have commented out all the lines which which can only compile under Windows, you can put them back in.

              You will have to test with COM/ActiveX --- like the VB example they give on the example page --- to verify whether the couple of changes I was forced to make lead to any problems.

              I may return to this to understand whether I could have made it work without having to make the changes I did.

              1 Reply Last reply
              1
              • A Offline
                A Offline
                AliQT
                wrote last edited by
                #7

                Great, thanks a lot. I've got it from the sharing site. I won't be able to look till this evening, but I'm looking forward to it!

                1 Reply Last reply
                0
                • A Offline
                  A Offline
                  AliQT
                  wrote last edited by
                  #8

                  Thanks Jon, Your code compiled for me ok. However when I uncommented the "QT += axserver" in comapp.pro, and QAXFACTORY macro in main.cpp, I got back to "undefined type" errors. I made no other changes. Yes, I know it's for windows only BTW. If you're in the UK I can send you a machine with QT on windows (:-). issues_QAXFACTORYuncomment.png

                  JonBJ 1 Reply Last reply
                  0
                  • hskoglundH Offline
                    hskoglundH Offline
                    hskoglund
                    wrote last edited by
                    #9

                    Hi, since you've re-enabled the QAXFACTORY macro, you need to also #include the classes mentioned in it, easiest to put them just below #include "qapplication.h", say like this:

                    ...
                    #include "application.h"
                    #include "document.h"
                    #include "documentlist.h"
                    
                    QAXFACTORY_BEGIN("{edd3e836-f537-4c6f-be7d-6014c155cc7a}", "{b7da3de8-83bb-4bbe-9ab7-99a05819e201}")
                        QAXCLASS(Application)
                    ...
                    
                    1 Reply Last reply
                    1
                    • A AliQT

                      Thanks Jon, Your code compiled for me ok. However when I uncommented the "QT += axserver" in comapp.pro, and QAXFACTORY macro in main.cpp, I got back to "undefined type" errors. I made no other changes. Yes, I know it's for windows only BTW. If you're in the UK I can send you a machine with QT on windows (:-). issues_QAXFACTORYuncomment.png

                      JonBJ Online
                      JonBJ Online
                      JonB
                      wrote last edited by JonB
                      #10

                      @AliQT
                      I did not pay much attention to main.cpp, other than commenting out the QAx... stuff I needed to make it compilable under Linux. Once you uncomment the QAXCLASS/QAXTYPE lines then, as @hskoglund has written, you need to replace main.cpp's solo #include "application.h" line to be the same as in the other 3 .cpp files, viz.:

                      #include "application.h"
                      #include "documentlist.h"
                      #include "document.h"
                      

                      Having done that now, for me to test I have added in

                      constexpr int s1 = sizeof(Application);
                      constexpr int s2 = sizeof(Document);
                      constexpr int s3 = sizeof(DocumentList);
                      

                      (you won't need this) immediately below where the QAXFACTORY_BEGIN 5 lines are commented out in my version and it compiles for me. I believe that will mean it shows there is enough definition with all 3 of those headers included for the uncommented QAXFACTORY_BEGIN section to go through for you.

                      In the two changes I said I had to make to get the code to go through, I believe my replacement of the QScopedPointer in QScopedPointer <DocumentList> m_docs in application.h to DocumentList *m_docs will work just the same and has no consequential side effects.

                      However, I am not so happy about my need to comment out the 3 occurrences of Q_PROPERTY(DocumentList* documents READ documents) or Q_PROPERTY(Application *application READ application) in the 3 header files. This is needed because of compiler error

                      static_assert(sizeof(T), "Type argument of Q_PROPERTY or Q_DECLARE_METATYPE(T*) must be fully defined");
                      

                      which comes from

                      /usr/include/x86_64-linux-gnu/qt6/QtCore/qmetatype.h: In instantiation of ‘struct QtPrivate::IsPointerToTypeDerivedFromQObject<Application*>’:
                      

                      during moc processing, meaning that given Q_PROPERTY(Type* property) it requires the full definition of Type to be known at the time it is encountered, for whatever magic Q_PROPERTY causes in moc, even when the property is just a pointer. While the code compiles fine with these lines commented out, I believe the VB example at the bottom of https://doc.qt.io/qt-6/activeqt-activeqt-comapp-example.html, and other similar code you might write, will have a problem. It includes e.g.

                      DocumentsCount.Caption = Application.documents.Count
                      

                      I believe this means that Application.documents must be available as a COM object. Which it would be with the original Q_PROPERTY(DocumentList* documents READ documents) in the Application class but not now that I have had to comment that out. As per the docs

                      Use the Q_PROPERTY() macro to declare properties for the ActiveX control.

                      I am having another think about those now.

                      1 Reply Last reply
                      0
                      • JonBJ Online
                        JonBJ Online
                        JonB
                        wrote last edited by JonB
                        #11

                        @AliQT
                        OK, I have had another go and "fixed" the Q_PROPERTY problems, as well as the QScopedPointer one. The magic was discovering there is a Q_MOC_INCLUDE() macro, at least from Qt 6.0.

                        Briefly, in case you are not aware when you compile sources for Qt which include Q_OBJECT, Q_PROPERTY, signals and other stuff in classes in .h files what actually happens is that first moc is run on on the .h file to produce the file transformed with various stuff into moc_yourfilename.cpp in the build directory and that file is also compiled and linked into your target.

                        While the "standard" way to compile mutually-referencing classes in separate files, so they cannot include the full definitions of each other, is via a "forward declaration" like so:

                        class B;
                        class A
                        {
                            B *b;
                        }
                        

                        this is not enough at the stage moc runs for what it needs to do. The secret is to have just this visible when compiling your own .cpp/.h files while having the full definition visible just at the time the generated moc_yourfilename.cpp is compiled.

                        In each .h file you have such as application.h which has forward declarations like:

                        class DocumentList;
                        class Document;
                        

                        we must add in corresponding

                        Q_MOC_INCLUDE("documentlist.h")
                        Q_MOC_INCLUDE("document.h")
                        

                        for the header files for these classes. This macro only includes the .h files in the moc-generated moc_....cpp file, when it is OK to do so there.

                        It turns out this change also allows me to revert to using the QScopedPointer <DocumentList> m_docs; in application.h per the original code, FWIW.

                        Note that the docs say of Q_MOC_INCLUDE() "This macro was introduced in Qt 6.0." You do not say what Qt version you are using, though your use of .pro file for qmake might indicate you are only on Qt 5.x. For all purposes if that is so you would be advised to move to Qt6.x before proceeding. If you really don't want to do that you might find defining

                        #ifndef QT_ANNOTATE_CLASS
                        # define QT_ANNOTATE_CLASS(type, ...)
                        #endif
                        #define Q_MOC_INCLUDE(...) QT_ANNOTATE_CLASS(qt_moc_include, __VA_ARGS__)
                        

                        in your files works, but I really don't know.

                        I am now uploading the files with the changes again for you to fetch at https://limewire.com/d/bfOQL#jdP77N1uck. I hope/believe this will go through for you, when you uncomment the QAx... stuff too, and that, say, the VB sample client at the end of https://doc.qt.io/qt-6/activeqt-activeqt-comapp-example.html fully works, since now Application.documents should be available as a property from VB.

                        Let me know --- I'm sure you will :)

                        P.S.

                        BTW. If you're in the UK I can send you a machine with QT on windows (:-).

                        About the last thing I want is Qt on a Windows machine... ;-)

                        1 Reply Last reply
                        1

                        • Login

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