Qt Reference Documentation

Hierarchy Example (ActiveQt)

Files:

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}");
     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 examples/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://qt.nokia.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>