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. Custom widget using and extending Qt's pImpl

Custom widget using and extending Qt's pImpl

Scheduled Pinned Locked Moved Solved General and Desktop
pimpl idiomqt sourcesqwidgetcustom widgetqobjectprivate
6 Posts 3 Posters 831 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.
  • P Offline
    P Offline
    Pl45m4
    wrote on 28 Nov 2023, 17:35 last edited by Pl45m4
    #1

    Currently I'm building a custom widget that should extend a given QWidget class.

    I want to use Qt's pImpl and tried to make use of Q_D, Q_Q, Q_DECLARE_PRIVATE and other macros.

    Since I don't have full access to Qt's private/internal stuff, I can not do it like it's done in the Qt source. There, the WidgetPrivate part inherits from e.g. QPushButtonPrivate, QSpinBoxPrivate or whatever widget the base class is, which my class can't (or better shouldn't, I believe).

    The macros above expand successfully, but there is still something missing, because of no WidgetPrivate/ QObjectPrivate inheritance.
    If I create my own, e.g. QScopedPointer<QMyClassPrivate> const d_ptr pointer, I get warnings that I'm shadowing the original d_ptr due to my QObject inheritance (well, through the widget, which I want to extend).

    Should I suppress and ignore these warnings?
    Are there any (working and good design) templates for this?
    I found this one and built my widget upon this and by looking at the Qt source how it's done there, but it still doesn't feel like a clean solution (warnings etc...).
    The example template also produces warnings, btw.

    Is there a recommended way of doing this?
    Or shouldn't it be done like this at all?

    I feel a bit lost :-P
    Any help appreciated :)


    If debugging is the process of removing software bugs, then programming must be the process of putting them in.

    ~E. W. Dijkstra

    S 1 Reply Last reply 28 Nov 2023, 22:13
    0
    • P Pl45m4
      28 Nov 2023, 17:35

      Currently I'm building a custom widget that should extend a given QWidget class.

      I want to use Qt's pImpl and tried to make use of Q_D, Q_Q, Q_DECLARE_PRIVATE and other macros.

      Since I don't have full access to Qt's private/internal stuff, I can not do it like it's done in the Qt source. There, the WidgetPrivate part inherits from e.g. QPushButtonPrivate, QSpinBoxPrivate or whatever widget the base class is, which my class can't (or better shouldn't, I believe).

      The macros above expand successfully, but there is still something missing, because of no WidgetPrivate/ QObjectPrivate inheritance.
      If I create my own, e.g. QScopedPointer<QMyClassPrivate> const d_ptr pointer, I get warnings that I'm shadowing the original d_ptr due to my QObject inheritance (well, through the widget, which I want to extend).

      Should I suppress and ignore these warnings?
      Are there any (working and good design) templates for this?
      I found this one and built my widget upon this and by looking at the Qt source how it's done there, but it still doesn't feel like a clean solution (warnings etc...).
      The example template also produces warnings, btw.

      Is there a recommended way of doing this?
      Or shouldn't it be done like this at all?

      I feel a bit lost :-P
      Any help appreciated :)

      S Offline
      S Offline
      SGaist
      Lifetime Qt Champion
      wrote on 28 Nov 2023, 22:13 last edited by
      #2

      Hi,

      On which platform are you getting that warning ? I just tested with 6.6.0 on macOS and it went fine without warning.

      Interested in AI ? www.idiap.ch
      Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

      P 1 Reply Last reply 28 Nov 2023, 23:27
      0
      • S SGaist
        28 Nov 2023, 22:13

        Hi,

        On which platform are you getting that warning ? I just tested with 6.6.0 on macOS and it went fine without warning.

        P Offline
        P Offline
        Pl45m4
        wrote on 28 Nov 2023, 23:27 last edited by Pl45m4
        #3

        @SGaist

        5.15 on Windows 10.

        If I remove the d_ptr from my class, it still compiles, the warnings go away but of course I have no pointer to my private widget data class.
        But still can access using Q_D(myClass) and d_func()...
        which will sooner or later crash :o)

        While looking for some in-depth information I came across

        • https://wiki.qt.io/D-Pointer

        One section says:

        Inheriting d-pointers for optimization

        In the above code, creating a single Label results in the memory allocation for LabelPrivate and WidgetPrivate. If we were to employ this strategy for Qt, the situation becomes quite worse for classes like QListWidget - it is 6 levels deep in the class inheritance hierarchy and it would result in upto 6 memory allocations!
        This is solved by having an inheritance hierarchy for our private classes and having the class getting instantiated pass on a the d-pointer all the way up.
        Notice that when inheriting d-pointers, the declaration of the private class has to be in a separate file, for example widget_p.h. It's no longer possible to declare it in the widget.cpp file.

        The example then shows two classes, Label and Widget (not even QWidget), where Label inherits the latter.
        Same with their private classes:

        class LabelPrivate : public WidgetPrivate
        
        Label::Label()
         : Widget(*new LabelPrivate) // initialize the d-pointer with our own Private
        {
        }
        
        Label::Label(LabelPrivate &d) : Widget(d)
        {
        }
        

        I understand the benefits, but this will never work, when you have a QObject-based class, because you can neither pass your own d_ptr "upwards" the tree, since your own private class doesn't inherit from QWidgetPrivate (and further QObjectPrivate), so the argument is not accepted due to wrong type, nor use the existing one, right?!

        That's what I am asking myself the whole time... how to adapt to the QObject-tree to create a fully functional QWidget while having your own implementation, that extends some existing QWidget-class [ * ]?

        You cant? Or am I missing something?!

        [ * ]: And with QWidget I mean QSpinBox, QPushButton etc, not the actual plain QWidget, but this shouldn't make any difference, as they are all QWidgets, just one or two level(s) down the tree :-)


        If debugging is the process of removing software bugs, then programming must be the process of putting them in.

        ~E. W. Dijkstra

        C 1 Reply Last reply 29 Nov 2023, 07:32
        0
        • P Pl45m4
          28 Nov 2023, 23:27

          @SGaist

          5.15 on Windows 10.

          If I remove the d_ptr from my class, it still compiles, the warnings go away but of course I have no pointer to my private widget data class.
          But still can access using Q_D(myClass) and d_func()...
          which will sooner or later crash :o)

          While looking for some in-depth information I came across

          • https://wiki.qt.io/D-Pointer

          One section says:

          Inheriting d-pointers for optimization

          In the above code, creating a single Label results in the memory allocation for LabelPrivate and WidgetPrivate. If we were to employ this strategy for Qt, the situation becomes quite worse for classes like QListWidget - it is 6 levels deep in the class inheritance hierarchy and it would result in upto 6 memory allocations!
          This is solved by having an inheritance hierarchy for our private classes and having the class getting instantiated pass on a the d-pointer all the way up.
          Notice that when inheriting d-pointers, the declaration of the private class has to be in a separate file, for example widget_p.h. It's no longer possible to declare it in the widget.cpp file.

          The example then shows two classes, Label and Widget (not even QWidget), where Label inherits the latter.
          Same with their private classes:

          class LabelPrivate : public WidgetPrivate
          
          Label::Label()
           : Widget(*new LabelPrivate) // initialize the d-pointer with our own Private
          {
          }
          
          Label::Label(LabelPrivate &d) : Widget(d)
          {
          }
          

          I understand the benefits, but this will never work, when you have a QObject-based class, because you can neither pass your own d_ptr "upwards" the tree, since your own private class doesn't inherit from QWidgetPrivate (and further QObjectPrivate), so the argument is not accepted due to wrong type, nor use the existing one, right?!

          That's what I am asking myself the whole time... how to adapt to the QObject-tree to create a fully functional QWidget while having your own implementation, that extends some existing QWidget-class [ * ]?

          You cant? Or am I missing something?!

          [ * ]: And with QWidget I mean QSpinBox, QPushButton etc, not the actual plain QWidget, but this shouldn't make any difference, as they are all QWidgets, just one or two level(s) down the tree :-)

          C Offline
          C Offline
          Christian Ehrlicher
          Lifetime Qt Champion
          wrote on 29 Nov 2023, 07:32 last edited by
          #4

          You can extend a QWidget but must do this without accessing the d pointer of the widget as it is not visible outside of QtWidgets library.

          Qt Online Installer direct download: https://download.qt.io/official_releases/online_installers/
          Visit the Qt Academy at https://academy.qt.io/catalog

          P 1 Reply Last reply 29 Nov 2023, 12:17
          0
          • C Christian Ehrlicher
            29 Nov 2023, 07:32

            You can extend a QWidget but must do this without accessing the d pointer of the widget as it is not visible outside of QtWidgets library.

            P Offline
            P Offline
            Pl45m4
            wrote on 29 Nov 2023, 12:17 last edited by
            #5

            @Christian-Ehrlicher said in Custom widget using and extending Qt's pImpl:

            You can extend a QWidget but must do this without accessing the d pointer of the widget as it is not visible outside of QtWidgets library

            So I should have my own d_ptr for my custom implementation, while keeping the inherited stuff untouched?
            Found out there is Q_DECLARE_PRIVATE_D(myDptr, Class) which declares the d_func() and everything else using the first argument, you pass to that macro.
            Then I have my own d-pointer, named different than d_ptr, which doesn't collide with the inherited, original d_ptr from QObject and there I'm not shadowing it anymore.
            It was just about the naming?!
            Is this the way? :)

            Will try and see how it goes... thx @Christian-Ehrlicher , @SGaist


            If debugging is the process of removing software bugs, then programming must be the process of putting them in.

            ~E. W. Dijkstra

            C 1 Reply Last reply 29 Nov 2023, 12:23
            0
            • P Pl45m4
              29 Nov 2023, 12:17

              @Christian-Ehrlicher said in Custom widget using and extending Qt's pImpl:

              You can extend a QWidget but must do this without accessing the d pointer of the widget as it is not visible outside of QtWidgets library

              So I should have my own d_ptr for my custom implementation, while keeping the inherited stuff untouched?
              Found out there is Q_DECLARE_PRIVATE_D(myDptr, Class) which declares the d_func() and everything else using the first argument, you pass to that macro.
              Then I have my own d-pointer, named different than d_ptr, which doesn't collide with the inherited, original d_ptr from QObject and there I'm not shadowing it anymore.
              It was just about the naming?!
              Is this the way? :)

              Will try and see how it goes... thx @Christian-Ehrlicher , @SGaist

              C Offline
              C Offline
              Christian Ehrlicher
              Lifetime Qt Champion
              wrote on 29 Nov 2023, 12:23 last edited by
              #6

              @Pl45m4 said in Custom widget using and extending Qt's pImpl:

              It was just about the naming?!
              Is this the way? :)

              I would say yes.

              Qt Online Installer direct download: https://download.qt.io/official_releases/online_installers/
              Visit the Qt Academy at https://academy.qt.io/catalog

              1 Reply Last reply
              1
              • P Pl45m4 has marked this topic as solved on 5 Dec 2023, 21:36

              6/6

              29 Nov 2023, 12:23

              • Login

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