1 /************************************************************************
2  *
3  * Copyright 2010-2012 Jakob Leben (jakob.leben@gmail.com)
4  *
5  * This file is part of SuperCollider Qt GUI.
6  *
7  * This program is free software: you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation, either version 2 of the License, or
10  * (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
19  *
20  ************************************************************************/
21 
22 #pragma once
23 
24 #include "QcObjectFactory.h"
25 #include "QWidgetProxy.h"
26 
27 #include <QMetaMethod>
28 #include <QLayout>
29 
30 template <class QWIDGET> class QcWidgetFactory : public QcObjectFactory<QWIDGET> {
31 public:
newInstance(PyrObject * scObject,QtCollider::MetaValue arg[10])32     virtual QObjectProxy* newInstance(PyrObject* scObject, QtCollider::MetaValue arg[10]) {
33         // Omit the first two arguments - parent and bounds
34 
35         QWIDGET* w;
36 
37         if (!arg[2].type()) {
38             w = new QWIDGET;
39         } else {
40             QObject* obj = QWIDGET::staticMetaObject.newInstance(
41                 arg[2].toGenericArgument(), arg[3].toGenericArgument(), arg[4].toGenericArgument(),
42                 arg[5].toGenericArgument(), arg[6].toGenericArgument(), arg[7].toGenericArgument(),
43                 arg[8].toGenericArgument(), arg[9].toGenericArgument());
44 
45             w = qobject_cast<QWIDGET*>(obj);
46             if (!w) {
47                 qcNoConstructorMsg(QcObjectFactory<QWIDGET>::metaObject(), 8, &arg[2]);
48                 return 0;
49             }
50         }
51 
52         // NOTE: performance: it is completely equal if parent is passed
53         // in constructor, or set later, but for some reason it is cheaper
54         // if it is set here, before setting other stuff like geometry, etc.
55 
56         QWidget* parent = arg[0].value<QWidget*>();
57 
58         if (parent) {
59             const QMetaObject* mo = parent->metaObject();
60             int mi = mo->indexOfMethod("addChild(QWidget*)");
61             bool ok;
62             if (mi >= 0) {
63                 QMetaMethod mm = mo->method(mi);
64                 ok = mm.invoke(parent, Q_ARG(QWidget*, w));
65                 if (!ok) {
66                     qcErrorMsg("Could not set parent!");
67                     delete w;
68                     return 0;
69                 }
70             } else {
71                 if (parent->layout())
72                     parent->layout()->addWidget(w);
73                 else
74                     w->setParent(parent);
75             }
76         }
77 
78         // set requested geometry
79 
80         QRect r(arg[1].value<QRectF>().toRect());
81         if (r.size().isEmpty())
82             r.setSize(w->sizeHint());
83 
84         w->setGeometry(r);
85 
86         // automatically support drag and drop
87 
88         w->setAcceptDrops(true);
89 
90         // ensure visible:
91 
92         if (parent && parent->isVisible())
93             w->show();
94 
95         // create the proxy:
96 
97         QObjectProxy* prox(proxy(w, scObject));
98 
99         return prox;
100     }
101 
102 protected:
proxy(QWIDGET * w,PyrObject * sc_obj)103     virtual QObjectProxy* proxy(QWIDGET* w, PyrObject* sc_obj) {
104         QWidgetProxy* prox(new QWidgetProxy(w, sc_obj));
105         initialize(prox, w);
106         return prox;
107     }
108 
109     // avoid overload of virtual initialize( QObjectProxy *, QWIDGET * )
110     using QcObjectFactory<QWIDGET>::initialize;
111 
initialize(QWidgetProxy * proxy,QWIDGET * obj)112     virtual void initialize(QWidgetProxy* proxy, QWIDGET* obj) {};
113 };
114 
115 #define QC_DECLARE_QWIDGET_FACTORY(QWIDGET) QC_DECLARE_FACTORY(QWIDGET, QcWidgetFactory<QWIDGET>)
116