Results 1 to 7 of 7

Thread: Help converting standard class to use d-pointers

  1. #1
    Join Date
    Aug 2007
    Posts
    244
    Thanks
    42
    Thanked 8 Times in 8 Posts
    Qt products
    Qt4
    Platforms
    Unix/X11

    Default Help converting standard class to use d-pointers

    Hi, today I read a blog post about d-pointers and private class:

    http://zchydem.enume.net/2010/01/19/...nd-d-pointers/

    I decided to experiment with it. I started creating a standard class, MyWidget:

    mywidget.h
    Qt Code:
    1. #ifndef MYWIDGET_H
    2. #define MYWIDGET_H
    3.  
    4. #include <QWidget>
    5.  
    6. namespace Ui {
    7. class MyWidget;
    8. }
    9.  
    10. class MyWidget : public QWidget
    11. {
    12. Q_OBJECT
    13.  
    14. public:
    15. explicit MyWidget(const QString &first,
    16. const QString &second,
    17. QWidget *parent = 0);
    18. ~MyWidget();
    19.  
    20. QString first() const;
    21. void setFirst(const QString);
    22.  
    23. QString second() const;
    24. void setSecond(const QString);
    25.  
    26. private:
    27. Ui::MyWidget *ui;
    28.  
    29. QString _first;
    30. QString _second;
    31. };
    32.  
    33. #endif // MYWIDGET_H
    To copy to clipboard, switch view to plain text mode 

    mywidget.cpp
    Qt Code:
    1. #include "mywidget.h"
    2. #include "ui_mywidget.h"
    3.  
    4. MyWidget::MyWidget(const QString &first, const QString &second, QWidget *parent) :
    5. QWidget(parent),
    6. ui(new Ui::MyWidget),
    7. _first(first),
    8. _second(second)
    9. {
    10. ui->setupUi(this);
    11. }
    12.  
    13. MyWidget::~MyWidget()
    14. {
    15. delete ui;
    16. }
    17.  
    18. QString MyWidget::first() const
    19. {
    20. return _first;
    21. }
    22.  
    23. void MyWidget::setFirst(const QString text)
    24. {
    25. _first = text;
    26. }
    27.  
    28. QString MyWidget::second() const
    29. {
    30. return _second;
    31. }
    32.  
    33. void MyWidget::setSecond(const QString text)
    34. {
    35. _second = text;
    36. }
    To copy to clipboard, switch view to plain text mode 

    then I tryed to implement private class/d-pointers; here it is the final work:

    mywidget_p.h
    Qt Code:
    1. #ifndef MYWIDGET_P_H
    2. #define MYWIDGET_P_H
    3.  
    4. #include <QWidget>
    5.  
    6. #include "mywidget.h"
    7.  
    8. class MyWidgetPrivate : public MyWidget
    9. {
    10. Q_DECLARE_PUBLIC(MyWidget)
    11.  
    12. public:
    13. MyWidgetPrivate() {}
    14.  
    15. QString first;
    16. QString second;
    17. };
    18.  
    19. #endif // MYWIDGET_P_H
    To copy to clipboard, switch view to plain text mode 

    mywidget.h
    Qt Code:
    1. #ifndef MYWIDGET_H
    2. #define MYWIDGET_H
    3.  
    4. #include <QWidget>
    5.  
    6. namespace Ui {
    7. class MyWidget;
    8. }
    9.  
    10. class MyWidgetPrivate;
    11.  
    12. class MyWidget : public QWidget
    13. {
    14. Q_OBJECT
    15. Q_PROPERTY(QString first READ first WRITE setFirst)
    16. Q_PROPERTY(QString second READ second WRITE setSecond)
    17.  
    18. public:
    19. explicit MyWidget(const QString &first,
    20. const QString &second,
    21. QWidget *parent = 0);
    22. ~MyWidget();
    23.  
    24. QString first() const;
    25. void setFirst(const QString);
    26. QString second() const;
    27. void setSecond(const QString);
    28.  
    29. protected:
    30. MyWidgetPrivate * const d;
    31.  
    32. private:
    33. Ui::MyWidget *ui;
    34. Q_DECLARE_PRIVATE(MyWidget)
    35. };
    36.  
    37. #endif // MYWIDGET_H
    To copy to clipboard, switch view to plain text mode 

    mywidget.cpp
    Qt Code:
    1. #include "mywidget_p.h"
    2. #include "ui_mywidget.h"
    3.  
    4. MyWidget::MyWidget(const QString &first, const QString &second, QWidget *parent) :
    5. QWidget(parent),
    6. ui(new Ui::MyWidget),
    7. first(first),
    8. second(second)
    9. {
    10. ui->setupUi(this);
    11. }
    12.  
    13. MyWidget::~MyWidget()
    14. {
    15. delete ui;
    16. }
    17.  
    18. QString MyWidget::first() const
    19. {
    20. return d->first;
    21. }
    22.  
    23. void MyWidget::setFirst(const QString text)
    24. {
    25. Q_D(MyWidget);
    26. d->first = text;
    27. }
    28.  
    29. QString MyWidget::second() const
    30. {
    31. return d->second;
    32. }
    33.  
    34. void MyWidget::setSecond(const QString text)
    35. {
    36. Q_D(MyWidget);
    37. d->second = text;
    38. }
    To copy to clipboard, switch view to plain text mode 

    compiling, I got

    Qt Code:
    1. In file included from mywidget.cpp:1:0:
    2. mywidget_p.h: In member function ‘MyWidget* MyWidgetPrivate::q_func()’:
    3. mywidget_p.h:10:5: error: ‘q_ptr’ was not declared in this scope
    4. mywidget_p.h: In member function ‘const MyWidget* MyWidgetPrivate::q_func() const’:
    5. mywidget_p.h:10:5: error: ‘q_ptr’ was not declared in this scope
    6. mywidget_p.h: In constructor ‘MyWidgetPrivate::MyWidgetPrivate()’:
    7. mywidget_p.h:13:23: error: no matching function for call to ‘MyWidget::MyWidget()’
    8. mywidget_p.h:13:23: note: candidates are:
    9. In file included from mywidget_p.h:6:0,
    10. from mywidget.cpp:1:
    11. mywidget.h:19:14: note: MyWidget::MyWidget(const QString&, const QString&, QWidget*)
    12. mywidget.h:19:14: note: candidate expects 3 arguments, 0 provided
    13. mywidget.h:12:7: note: MyWidget::MyWidget(const MyWidget&)
    14. mywidget.h:12:7: note: candidate expects 1 argument, 0 provided
    15. mywidget.cpp: In constructor ‘MyWidget::MyWidget(const QString&, const QString&, QWidget*)’:
    16. mywidget.cpp:7:5: error: class ‘MyWidget’ does not have any field named ‘first’
    17. mywidget.cpp:8:5: error: class ‘MyWidget’ does not have any field named ‘second’
    18. mywidget.cpp:4:1: error: uninitialized member ‘MyWidget::d’ with ‘const’ type ‘MyWidgetPrivate* const’ [-fpermissive]
    19. make: *** [mywidget.o] Errore 1
    To copy to clipboard, switch view to plain text mode 

    Where am I wrong?

    Thanks.
    Giuseppe CalÃ

  2. #2
    Join Date
    Jan 2006
    Location
    Graz, Austria
    Posts
    8,416
    Thanks
    37
    Thanked 1,544 Times in 1,494 Posts
    Qt products
    Qt3 Qt4 Qt5
    Platforms
    Unix/X11 Windows

    Default Re: Help converting standard class to use d-pointers

    The private does not inherit the main class, it is a totally independent one.

    You will see this better if you don't use the Qt macros while you are still experimenting with the idea, i.e. write code manually.

    Qt Code:
    1. class MyWidget : public QWidget
    2. {
    3. Q_OBJECT
    4. Q_PROPERTY(QString first READ first WRITE setFirst)
    5. Q_PROPERTY(QString second READ second WRITE setSecond)
    6.  
    7. public:
    8. explicit MyWidget(const QString &first,
    9. const QString &second,
    10. QWidget *parent = 0);
    11. ~MyWidget();
    12.  
    13. QString first() const;
    14. void setFirst(const QString);
    15. QString second() const;
    16. void setSecond(const QString);
    17.  
    18. private:
    19. class MyWidgetPrivate;
    20. MyWidgetPrivate * const d;
    21. };
    To copy to clipboard, switch view to plain text mode 
    The only member left is the d pointter.

    All members go into the private
    Qt Code:
    1. class MyWidgetPrivate
    2. {
    3. MyWidget * const q; // not stricly necessary, just in case you put methods into MyWidgetPrivate that need access to MyWidget
    4.  
    5. public:
    6. explicit MyWidgetPrivate( MyWidget *parent ) : q( parent ), ui( new Ui::MyWidget )
    7. {
    8. ui->setupUi( parent );
    9. }
    10.  
    11. Ui::MyWidget *ui;
    12.  
    13. QString _first;
    14. QString _second;
    15. };
    To copy to clipboard, switch view to plain text mode 

    Qt Code:
    1. MyWidget::MyWidget(const QString &first, const QString &second, QWidget *parent) :
    2. QWidget(parent),
    3. d( new MyWidgetPrivate( this ) )
    4. {
    5. }
    6.  
    7. MyWidget::~MyWidget()
    8. {
    9. delete d;
    10. }
    To copy to clipboard, switch view to plain text mode 

    Cheers,
    _

  3. #3
    Join Date
    Aug 2007
    Posts
    244
    Thanks
    42
    Thanked 8 Times in 8 Posts
    Qt products
    Qt4
    Platforms
    Unix/X11

    Default Re: Help converting standard class to use d-pointers

    First of all, thanks for your help. I tryed editing the code following your guide lines.

    This is new mywidget_p.h

    Qt Code:
    1. #ifndef MYWIDGET_P_H
    2. #define MYWIDGET_P_H
    3.  
    4. #include <QWidget>
    5.  
    6. #include "mywidget.h"
    7.  
    8. class MyWidgetPrivate
    9. {
    10. MyWidget * const q; // not stricly necessary, just in case you put methods into MyWidgetPrivate that need access to MyWidget
    11.  
    12. public:
    13. explicit MyWidgetPrivate( MyWidget *parent ) : q( parent ), ui( new Ui::MyWidget )
    14. {
    15. ui->setupUi( parent );
    16. }
    17.  
    18. Ui::MyWidget *ui;
    19.  
    20. QString first;
    21. QString second;
    22. };
    23.  
    24. #endif // MYWIDGET_P_H
    To copy to clipboard, switch view to plain text mode 

    and this is mywidget.h
    Qt Code:
    1. #ifndef MYWIDGET_H
    2. #define MYWIDGET_H
    3.  
    4. #include <QWidget>
    5.  
    6. namespace Ui {
    7. class MyWidget;
    8. }
    9.  
    10. class MyWidgetPrivate;
    11.  
    12. class MyWidget : public QWidget
    13. {
    14. Q_OBJECT
    15. Q_PROPERTY(QString first READ first WRITE setFirst)
    16. Q_PROPERTY(QString second READ second WRITE setSecond)
    17.  
    18. public:
    19. explicit MyWidget(const QString &first,
    20. const QString &second,
    21. QWidget *parent = 0);
    22. ~MyWidget();
    23.  
    24. QString first() const;
    25. void setFirst(const QString);
    26. QString second() const;
    27. void setSecond(const QString);
    28.  
    29. private:
    30. MyWidgetPrivate * const d;
    31. };
    32.  
    33. #endif // MYWIDGET_H
    To copy to clipboard, switch view to plain text mode 

    Unfortunately the compiler fails

    Qt Code:
    1. In file included from ../mywidget.cpp:1:0:
    2. ../mywidget_p.h: In constructor 'MyWidgetPrivate::MyWidgetPrivate(MyWidget*)':
    3. ../mywidget_p.h:13:77: error: invalid use of incomplete type 'class Ui::MyWidget'
    4. In file included from ../mywidget_p.h:6:0,
    5. from ../mywidget.cpp:1:
    6. ../mywidget.h:7:7: error: forward declaration of 'class Ui::MyWidget'
    7. In file included from ../mywidget.cpp:1:0:
    8. ../mywidget_p.h:15:15: error: invalid use of incomplete type 'class Ui::MyWidget'
    9. In file included from ../mywidget_p.h:6:0,
    10. from ../mywidget.cpp:1:
    11. ../mywidget.h:7:7: error: forward declaration of 'class Ui::MyWidget'
    12. ../mywidget.cpp: At global scope:
    13. ../mywidget.cpp:4:1: warning: unused parameter 'first' [-Wunused-parameter]
    14. ../mywidget.cpp:4:1: warning: unused parameter 'second' [-Wunused-parameter]
    15. In file included from /usr/include/QtGui/QWidget:1:0,
    16. from ../mywidget_p.h:4,
    17. from ../mywidget.cpp:1:
    18. /usr/include/QtGui/qwidget.h: In member function 'QString MyWidget::first() const':
    19. /usr/include/QtGui/qwidget.h:150:5: error: 'const QWidgetPrivate* QWidget::d_func() const' is private
    20. ../mywidget.cpp:17:5: error: within this context
    21. ../mywidget.cpp:17:5: error: cannot convert 'const QWidgetPrivate*' to 'const MyWidgetPrivate* const' in initialization
    22. In file included from /usr/include/QtGui/QWidget:1:0,
    23. from ../mywidget_p.h:4,
    24. from ../mywidget.cpp:1:
    25. /usr/include/QtGui/qwidget.h: In member function 'void MyWidget::setFirst(QString)':
    26. /usr/include/QtGui/qwidget.h:150:5: error: 'QWidgetPrivate* QWidget::d_func()' is private
    27. ../mywidget.cpp:23:5: error: within this context
    28. ../mywidget.cpp:23:5: error: cannot convert 'QWidgetPrivate*' to 'MyWidgetPrivate* const' in initialization
    29. In file included from /usr/include/QtGui/QWidget:1:0,
    30. from ../mywidget_p.h:4,
    31. from ../mywidget.cpp:1:
    32. /usr/include/QtGui/qwidget.h: In member function 'QString MyWidget::second() const':
    33. /usr/include/QtGui/qwidget.h:150:5: error: 'const QWidgetPrivate* QWidget::d_func() const' is private
    34. ../mywidget.cpp:29:5: error: within this context
    35. ../mywidget.cpp:29:5: error: cannot convert 'const QWidgetPrivate*' to 'const MyWidgetPrivate* const' in initialization
    36. In file included from /usr/include/QtGui/QWidget:1:0,
    37. from ../mywidget_p.h:4,
    38. from ../mywidget.cpp:1:
    39. /usr/include/QtGui/qwidget.h: In member function 'void MyWidget::setSecond(QString)':
    40. /usr/include/QtGui/qwidget.h:150:5: error: 'QWidgetPrivate* QWidget::d_func()' is private
    41. ../mywidget.cpp:35:5: error: within this context
    42. ../mywidget.cpp:35:5: error: cannot convert 'QWidgetPrivate*' to 'MyWidgetPrivate* const' in initialization
    To copy to clipboard, switch view to plain text mode 
    Giuseppe CalÃ

  4. #4
    Join Date
    Jan 2006
    Location
    Graz, Austria
    Posts
    8,416
    Thanks
    37
    Thanked 1,544 Times in 1,494 Posts
    Qt products
    Qt3 Qt4 Qt5
    Platforms
    Unix/X11 Windows

    Default Re: Help converting standard class to use d-pointers

    One error is that you have not included ui_widget.h in mywidget_p.h yet, so the compiler doesn't know about Ui::MyWidget
    Another couple of errors suggest that you have still some Qt macro usages in your widget.cpp, most likely some Q_D you forgot to remove.

    Cheers,
    _

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

    jiveaxe (8th April 2013)

  6. #5
    Join Date
    Aug 2007
    Posts
    244
    Thanks
    42
    Thanked 8 Times in 8 Posts
    Qt products
    Qt4
    Platforms
    Unix/X11

    Default Re: Help converting standard class to use d-pointers

    Thank you anda_skoam, your last tips solved all problems.

    I have one more question: d-pointers should be limited to libraries or is good habit to use them in normal apps, too?

    Regards.

    P.S.
    Here it is final code, if useful to others:

    mywidget_p.h
    Qt Code:
    1. #ifndef MYWIDGET_P_H
    2. #define MYWIDGET_P_H
    3.  
    4. #include "mywidget.h"
    5. #include "ui_mywidget.h"
    6.  
    7. namespace Ui {
    8. class MyWidget;
    9. }
    10.  
    11. class MyWidgetPrivate
    12. {
    13. MyWidget * const q; // not stricly necessary, just in case you put methods into MyWidgetPrivate that need access to MyWidget
    14.  
    15. public:
    16. explicit MyWidgetPrivate( MyWidget *parent ) :
    17. q( parent ), ui( new Ui::MyWidget )
    18. {
    19. ui->setupUi( parent );
    20. }
    21.  
    22. Ui::MyWidget *ui;
    23.  
    24. QString first;
    25. QString second;
    26. };
    27.  
    28. #endif // MYWIDGET_P_H
    To copy to clipboard, switch view to plain text mode 

    mywidget.h
    Qt Code:
    1. #ifndef MYWIDGET_H
    2. #define MYWIDGET_H
    3.  
    4. #include <QWidget>
    5.  
    6. class MyWidgetPrivate;
    7.  
    8. class MyWidget : public QWidget
    9. {
    10. Q_OBJECT
    11. Q_PROPERTY(QString first READ first WRITE setFirst)
    12. Q_PROPERTY(QString second READ second WRITE setSecond)
    13.  
    14. public:
    15. explicit MyWidget(const QString &first,
    16. const QString &second,
    17. QWidget *parent = 0);
    18. ~MyWidget();
    19.  
    20. QString first() const;
    21. void setFirst(const QString);
    22. QString second() const;
    23. void setSecond(const QString);
    24.  
    25. private:
    26. MyWidgetPrivate * const d;
    27. };
    28.  
    29. #endif // MYWIDGET_H
    To copy to clipboard, switch view to plain text mode 

    mywidget.cpp
    Qt Code:
    1. #include "mywidget_p.h"
    2.  
    3. MyWidget::MyWidget(const QString &first, const QString &second, QWidget *parent) :
    4. QWidget(parent),
    5. d( new MyWidgetPrivate( this ) )
    6. {
    7. d->first = first;
    8. d->second = second;
    9. }
    10.  
    11. MyWidget::~MyWidget()
    12. {
    13. delete d;
    14. }
    15.  
    16. QString MyWidget::first() const
    17. {
    18. return d->first;
    19. }
    20.  
    21. void MyWidget::setFirst(const QString text)
    22. {
    23. d->first = text;
    24. }
    25.  
    26. QString MyWidget::second() const
    27. {
    28. return d->second;
    29. }
    30.  
    31. void MyWidget::setSecond(const QString text)
    32. {
    33. d->second = text;
    34. }
    To copy to clipboard, switch view to plain text mode 
    Giuseppe CalÃ

  7. #6
    Join Date
    Jan 2006
    Location
    Graz, Austria
    Posts
    8,416
    Thanks
    37
    Thanked 1,544 Times in 1,494 Posts
    Qt products
    Qt3 Qt4 Qt5
    Platforms
    Unix/X11 Windows

    Default Re: Help converting standard class to use d-pointers

    Quote Originally Posted by jiveaxe View Post
    Thank you anda_skoam, your last tips solved all problems.
    Excellent

    Just in case: I often use this form of d-pointer implementation myself, but one has to understand that it has one disadvantage of the slighty more complex approach taken by Qt's macros: this simple form of a d-pointer makes all members effectively "non-const", e.f. you could write to d->second in MyWidget::second() const without the compiler saying anything.

    This can of course be handy, but if you want to have compiler errors when you try to change members in a const method, then the approach used by Qt's macros can fix that.
    (you don't necessarily have to use the macros themselves of course).

    This alternative approach has a d-pointer member (usually called something else than "d", e.g. "d_ptr") and two accessor functions (often called "d_func()") where one is const and one non-const and the const one returning "const PrivateClass *".
    The main class then does not access d-pointer directly but through the two functions. Due to const-ness of methods, the compiler will chose the const-correct d_func and thus return a const-correct pointer to the private.

    In Qt's case, the Q_D macro hides that d_func access, i.e. it defines a local variable "d" that is initialized with the return of the appropriate d_func().

    But again, the simple approach works as well, it is just important to know about the const "removal"

    Quote Originally Posted by jiveaxe View Post
    I have one more question: d-pointers should be limited to libraries or is good habit to use them in normal apps, too?
    It depends. Not all classes in libraries need it and it can be helpful in application code as well.

    What a d-pointer approach does is that it really enforces the "information hiding" feature of object oriented programming by hiding every internal thing inside the private class.

    Classes in libraries that are public API use this to ensure that their memory layout stays unchanged even if data members have to be added, removed or their types changed.
    The "outward" facing memory layout is always just a single pointer. A library internal class does not strictly need this, so it no code using the library will ever see it anyway.

    In application code it is usually also not required to keep stable binary interfaces since the application is always relinked as one, however, d-pointer based classes can even be useful there.
    One example is classes with lots of members of different complex types, i.e. if the class header would need a lot of includes or those includes in turn dragging in lots of includes.
    A d-pointer approach can serve as dependency shield in this case. All code using the class only has to include that single header, any change to member types wil not trigger rebuilds of code using the class.

    Cheers,
    _

  8. #7
    Join Date
    Aug 2007
    Posts
    244
    Thanks
    42
    Thanked 8 Times in 8 Posts
    Qt products
    Qt4
    Platforms
    Unix/X11

    Default Re: Help converting standard class to use d-pointers

    Thanks for these invaluable explanations. With these new knowledge I was able to edit the code and use Qt macros:

    mywidget_p.h
    Qt Code:
    1. #ifndef MYWIDGET_P_H
    2. #define MYWIDGET_P_H
    3.  
    4. #include "mywidget.h"
    5. #include "ui_mywidget.h"
    6.  
    7. class MyWidgetPrivate
    8. {
    9. public:
    10. explicit MyWidgetPrivate(QWidget *parent) :
    11. ui( new Ui::MyWidget )
    12. {
    13. ui->setupUi( parent );
    14. }
    15. virtual ~MyWidgetPrivate() { delete ui; }
    16.  
    17. QString first;
    18.  
    19. Ui::MyWidget *ui;
    20. };
    21.  
    22. #endif // MYWIDGET_P_H
    To copy to clipboard, switch view to plain text mode 

    mywidget.h
    Qt Code:
    1. #ifndef MYWIDGET_H
    2. #define MYWIDGET_H
    3.  
    4. #include <QWidget>
    5.  
    6. namespace Ui {
    7. class MyWidget;
    8. }
    9.  
    10. class MyWidgetPrivate;
    11.  
    12. class MyWidget : public QWidget
    13. {
    14. Q_OBJECT
    15. Q_PROPERTY(QString first READ first WRITE setFirst)
    16.  
    17. public:
    18. explicit MyWidget(const QString &text, QWidget *parent = 0);
    19. virtual ~MyWidget();
    20.  
    21. void setFirst(QString text);
    22. QString first() const;
    23.  
    24. protected:
    25. MyWidgetPrivate * const d_ptr;
    26. MyWidget(MyWidgetPrivate &dd, QWidget *parent);
    27.  
    28. private:
    29. Q_DECLARE_PRIVATE(MyWidget);
    30. };
    31.  
    32. #endif // MYWIDGET_H
    To copy to clipboard, switch view to plain text mode 

    mywidget.cpp
    Qt Code:
    1. #include "mywidget_p.h"
    2. #include "ui_mywidget.h"
    3.  
    4. MyWidget::MyWidget(const QString &text, QWidget *parent) :
    5. d_ptr(new MyWidgetPrivate(parent))
    6. {
    7. d_ptr->first = text;
    8. }
    9.  
    10. MyWidget::MyWidget(MyWidgetPrivate &dd, QWidget *parent)
    11. : QWidget(parent),
    12. d_ptr(&dd)
    13. {
    14. }
    15.  
    16. MyWidget::~MyWidget()
    17. {
    18. delete d_ptr;
    19. }
    20.  
    21. void MyWidget::setFirst(QString text)
    22. {
    23. Q_D(MyWidget);
    24. d->first = text;
    25. }
    26.  
    27. QString MyWidget::first() const
    28. {
    29. Q_D(const MyWidget);
    30. return d->first;
    31. }
    To copy to clipboard, switch view to plain text mode 
    Giuseppe CalÃ

Similar Threads

  1. Signals Slots and Class Pointers
    By Atomic_Sheep in forum Newbie
    Replies: 18
    Last Post: 7th September 2012, 09:08
  2. Replies: 3
    Last Post: 6th April 2012, 16:44
  3. Replies: 8
    Last Post: 15th July 2010, 21:42
  4. Replies: 5
    Last Post: 20th April 2010, 17:48
  5. Replies: 2
    Last Post: 2nd June 2008, 08:45

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
  •  
Qt is a trademark of The Qt Company.