Home | All Classes | Main Classes | Annotated | Grouped Classes | Functions |

# Qt Widget Hierarchy (in-process)

The ActiveX control in this example is a QWidget subclass with child widgets that are accessible as sub types.

        class QParentWidget : public QWidget
        {
            Q_OBJECT
        public:
            QParentWidget( QWidget *parent = 0, const char *name = 0, WFlags f = 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.

        QParentWidget::QParentWidget( QWidget *parent, const char *name, WFlags f )
        : QWidget( parent, name, f )
        {
            vbox = new QVBoxLayout( this );
            vbox->setAutoAdd( TRUE );
        }

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 );
            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 (QSubWidget*)child( name, "QSubWidget" );
        }

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 )
        public:
            QSubWidget( QWidget *parent = 0, const char *name = 0, WFlags f = 0 );

            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.

        QSubWidget::QSubWidget( QWidget *parent, const char *name, WFlags f )
        : QWidget( parent, name, f )
        {
        }

        void QSubWidget::setLabel( const QString &text )
        {
            lbl = text;
            setName( 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( colorGroup().text() );
            painter.drawText( rect(), AlignCenter, lbl );
        }

The implementation of the QSubWidget class is self-explanatory.

        class ActiveQtFactory : public QAxFactory
        {
        public:
            ActiveQtFactory( const QUuid &lib, const QUuid &app )
                : QAxFactory( lib, app )
            {}
            QStringList featureList() const
            {
                QStringList list;
                list << "QParentWidget";
                list << "QSubWidget";
                return list;
            }

The `ActiveQtFactory` class implements a QAxFactory. It returns the class names of all supported types, `QParentWidget` and `QSubWidget`, from the `featureList()` reimplementation.

            QWidget *create( const QString &key, QWidget *parent, const char *name )
            {
                if ( key == "QParentWidget" )
                    return new QParentWidget( parent, name );

                return 0;
            }

The factory can however only create objects of the `QParentWidget` type directly - objects of subtypes can only be created through the interface of `QParentWidget` objects.

            QUuid classID( const QString &key ) const
            {
                if ( key == "QParentWidget" )
                    return QUuid( "{d574a747-8016-46db-a07c-b2b4854ee75c}" );
                if ( key == "QSubWidget" )
                    return QUuid( "{850652f4-8f71-4f69-b745-bce241ccdc30}" );

                return QUuid();
            }
            QUuid interfaceID( const QString &key ) const
            {
                if ( key == "QParentWidget" )
                    return QUuid( "{4a30719d-d9c2-4659-9d16-67378209f822}" );
                if ( key == "QSubWidget" )
                    return QUuid( "{2d76cc2f-3488-417a-83d6-debff88b3c3f}" );

                return QUuid();
            }
            QUuid eventsID( const QString &key ) const
            {
                if ( key == "QParentWidget" )
                    return QUuid( "{aac9f855-c3dc-4cae-b747-c77f4d509f4c}" );
                if ( key == "QSubWidget" )
                    return QUuid( "{25fac47e-c723-4696-8c74-6185903bdf65}" );

                return QUuid();
            }

COM however requires the IDs for the interfaces of the sub types as well to be able to marshal calls correctly.

            QString exposeToSuperClass( const QString &key ) const
            {
                if ( key == "QSubWidget" )
                    return key;
                return QAxFactory::exposeToSuperClass(key);
            }
        };

Objects of the `QSubWidget` type should not expose the full functionality of e.g. QWidget. Only those properties and slots explicitly declared in the type are accessible.

        QAXFACTORY_EXPORT( ActiveQtFactory, "{9e626211-be62-4d18-9483-9419358fbb03}", "{75c276de-1df5-451f-a004-e4fa1a587df1}" )

The factory is then exported using the QAXFACTORY_EXPORT macro.

To build the example you must first build the QAxServer library. Then run qmake and your make tool in `examples/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!<br>
        <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 = "<enter object name>">
        <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>

See also The QAxServer Examples.