Qt 4.0: Hierarchy Example (ActiveQt)

|  | Home · All Classes · Main Classes · Grouped Classes · Modules · Functions |

# Hierarchy Example (ActiveQt)

Files:

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

The Hierarchy example is shows how to write an in-process ActiveX control. The control is a QWidget subclass with child widgets that are accessible as sub-types.

        class QParentWidget : public QWidget
        {
            Q_OBJECT
            Q_CLASSINFO("ClassID", "{d574a747-8016-46db-a07c-b2b4854ee75c}");
            Q_CLASSINFO("InterfaceID", "{4a30719d-d9c2-4659-9d16-67378209f822}");
        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 qFindChild<QSubWidget*>(this, 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.h>

        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 `examples/activeqt/multiple`.

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.trolltech.com/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>