Hierarchy Example (ActiveQt) | Active Qt 5.6

Qt 5.6 | Active Qt | Hierarchy Example (ActiveQt)

Qt 5.6.2 Reference Documentation

# Hierarchy Example (ActiveQt)

      class QParentWidget : public QWidget
      {
          Q_OBJECT
          Q_CLASSINFO("ClassID", "{d574a747-8016-46db-a07c-b2b4854ee75c}");
          Q_CLASSINFO("InterfaceID", "{4a30719d-d9c2-4659-9d16-67378209f822}");
          Q_CLASSINFO("EventsID", "{4a30719d-d9c2-4659-9d16-67378209f823}");
      public:
          QParentWidget(QWidget *parent = 0);

          QSize sizeHint() const;

      public slots:
          void createSubWidget( const QString &name );

          QSubWidget *subWidget( const QString &name );

      private:
          QVBoxLayout *vbox;
      };

The `QParentWidget` class provides slots to create a widget with a name, and to return a pointer to a named widget. The class declaration uses `Q_CLASSINFO()` to provide the COM identifiers for this class.

      QParentWidget::QParentWidget(QWidget *parent)
      : QWidget(parent)
      {
          vbox = new QVBoxLayout(this);
      }

The constructor of `QParentWidget` creates a vertical box layout. New child widgets are automatically added to the layout.

      void QParentWidget::createSubWidget(const QString &name)
      {
          QSubWidget *sw = new QSubWidget(this, name);
          vbox->addWidget(sw);
          sw->setLabel(name);
          sw->show();
      }

The `createSubWidget` slot creates a new `QSubWidget` with the name provided in the parameter, and sets the label to that name. The widget is also shown explicitly.

      QSubWidget *QParentWidget::subWidget(const QString &name)
      {
          return findChild<QSubWidget*>(name);
      }

The `subWidget` slot uses the `QObject::child()` function and returns the first child of type `QSubWidget` that has the requested name.

      class QSubWidget : public QWidget
      {
          Q_OBJECT
          Q_PROPERTY( QString label READ label WRITE setLabel )

          Q_CLASSINFO("ClassID", "{850652f4-8f71-4f69-b745-bce241ccdc30}");
          Q_CLASSINFO("InterfaceID", "{2d76cc2f-3488-417a-83d6-debff88b3c3f}");
          Q_CLASSINFO("ToSuperClass", "QSubWidget");

      public:
          QSubWidget(QWidget *parent = 0, const QString &name = QString());

          void setLabel( const QString &text );
          QString label() const;

          QSize sizeHint() const;

      protected:
          void paintEvent( QPaintEvent *e );

      private:
          QString lbl;
      };

The `QSubWidget` class has a single string-property `label`, and implements the paintEvent to draw the label. The class uses again `Q_CLASSINFO` to provide the COM identifiers, and also sets the ToSuperClass attribute to QSubWidget, to ensure that only no slots of any superclasses (i.e. QWidget) are exposed.

      QSubWidget::QSubWidget(QWidget *parent, const QString &name)
      : QWidget(parent)
      {
          setObjectName(name);
      }

      void QSubWidget::setLabel(const QString &text)
      {
          lbl = text;
          setObjectName(text);
          update();
      }

      QString QSubWidget::label() const
      {
          return lbl;
      }

      QSize QSubWidget::sizeHint() const
      {
          QFontMetrics fm(font());
          return QSize(fm.width(lbl), fm.height());
      }

      void QSubWidget::paintEvent(QPaintEvent *)
      {
          QPainter painter(this);
          painter.setPen(palette().text().color());
          painter.drawText(rect(), Qt::AlignCenter, lbl);
      }

The implementation of the `QSubWidget` class is self-explanatory.

      #include "objects.h"
      #include <QAxFactory>

      QAXFACTORY_BEGIN("{9e626211-be62-4d18-9483-9419358fbb03}", "{75c276de-1df5-451f-a004-e4fa1a587df1}")
          QAXCLASS(QParentWidget)
          QAXTYPE(QSubWidget)
      QAXFACTORY_END()

The classes are then exported using a QAxFactory. `QParentWidget` is exported as a full class (which can be created ), while `QSubWidget` is only exported as a type, which can only be created indirectly through APIs of `QParentWidget`.

To build the example you must first build the QAxServer library. Then run qmake and your make tool in `activeqt/hierarchy`.

The demonstration requires your WebBrowser to support ActiveX controls, and scripting to be enabled.

      <script language="javascript">
      function createSubWidget( form )
      {
          ParentWidget.createSubWidget( form.nameEdit.value );
      }

      function renameSubWidget( form )
      {
          var SubWidget = ParentWidget.subWidget( form.nameEdit.value );
          if ( !SubWidget ) {
              alert( "No such widget " + form.nameEdit.value + "!" );
              return;
          }
          SubWidget.label = form.labelEdit.value;
          form.nameEdit.value = SubWidget.label;
      }

      function setFont( form )
      {
          ParentWidget.font = form.fontEdit.value;
      }
      </script>

      <p>
      This widget can have many children!
      </p>
      <object ID="ParentWidget" CLASSID="CLSID:d574a747-8016-46db-a07c-b2b4854ee75c"
      CODEBASE="http://www.qt-project.org/demos/hierarchy.cab">
      [Object not available! Did you forget to build and register the server?]
      </object><br />
      <form>
      <input type="edit" ID="nameEdit" value="&lt;enter object name&gt;" />
      <input type="button" value="Create" onClick="createSubWidget(this.form)" />
      <input type="edit" ID="labelEdit" />
      <input type="button" value="Rename" onClick="renameSubWidget(this.form)" />
      <br />
      <input type="edit" ID="fontEdit" value="MS Sans Serif" />
      <input type="button" value = "Set Font" onClick="setFont(this.form)" />
      </form>

Files:

- activeqt/hierarchy/objects.cpp
- activeqt/hierarchy/objects.h
- activeqt/hierarchy/main.cpp
- activeqt/hierarchy/hierarchy.pro