1 /****************************************************************************
2 **
3 ** Copyright (C) 2016 The Qt Company Ltd.
4 ** Contact: https://www.qt.io/licensing/
5 **
6 ** This file is part of the Qt Designer of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:GPL-EXCEPT$
9 ** Commercial License Usage
10 ** Licensees holding valid commercial Qt licenses may use this file in
11 ** accordance with the commercial license agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and The Qt Company. For licensing terms
14 ** and conditions see https://www.qt.io/terms-conditions. For further
15 ** information use the contact form at https://www.qt.io/contact-us.
16 **
17 ** GNU General Public License Usage
18 ** Alternatively, this file may be used under the terms of the GNU
19 ** General Public License version 3 as published by the Free Software
20 ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
21 ** included in the packaging of this file. Please review the following
22 ** information to ensure the GNU General Public License requirements will
23 ** be met: https://www.gnu.org/licenses/gpl-3.0.html.
24 **
25 ** $QT_END_LICENSE$
26 **
27 ****************************************************************************/
28 
29 #include "qdesigneraxwidget.h"
30 
31 #include <QtCore/qmetaobject.h>
32 #include <QtCore/qdebug.h>
33 #include <QtGui/qicon.h>
34 #include <QtGui/qpainter.h>
35 #include <QtGui/qevent.h>
36 
37 #include <ActiveQt/QAxWidget>
38 
39 #include <qt_windows.h>
40 #include <olectl.h>
41 #include <qaxtypes.h>
42 
43 enum { debugAxWidget = 0 };
44 
45 QT_BEGIN_NAMESPACE
46 
47 /* XPM */
48 const char *widgetIconXPM[]={
49 "22 22 6 1",
50 "a c #000000",
51 "# c #808080",
52 "+ c #aaa5a0",
53 "b c #dddddd",
54 "* c #d4d0c8",
55 ". c none",
56 ".........#aa#...#aa#..",
57 ".........abba...abba..",
58 ".........abba...abba..",
59 ".........#aa#...#aa#..",
60 "..........aa.....aa...",
61 "..........aa.....aa...",
62 "..........aa.....aa...",
63 ".......aaaaaaaaaaaaaaa",
64 ".......a*************a",
65 ".......a************#a",
66 ".......a***********+#a",
67 ".......a***********+#a",
68 ".......a***********+#a",
69 "#aa#...a***********+#a",
70 "abbaaaaa***********+#a",
71 "abbaaaaa***********+#a",
72 "#aa#...a***********+#a",
73 ".......a***********+#a",
74 ".......a***********+#a",
75 ".......a**++++++++++#a",
76 ".......a*############a",
77 ".......aaaaaaaaaaaaaaa"};
78 
QDesignerAxWidget(QWidget * parent)79 QDesignerAxWidget::QDesignerAxWidget(QWidget *parent) :
80     QWidget(parent),
81     m_axImage(widgetIcon())
82 {
83 }
84 
~QDesignerAxWidget()85 QDesignerAxWidget::~QDesignerAxWidget()
86 {
87     delete m_axobject;
88 }
89 
widgetIcon()90 QPixmap QDesignerAxWidget::widgetIcon()
91 {
92    return QPixmap(widgetIconXPM);
93 }
94 
control() const95 QString QDesignerAxWidget::control() const
96 {
97     if (m_axobject)
98         return m_axobject->control();
99     return QString();
100 }
101 
setControl(const QString & clsid)102 void QDesignerAxWidget::setControl(const QString &clsid)
103 {
104     if (clsid == control())
105         return;
106      if (clsid.isEmpty()) {
107          resetControl();
108      } else {
109          loadControl(clsid);
110      }
111 }
resetControl()112 void QDesignerAxWidget::resetControl()
113 {
114     if (!m_axobject)
115         return;
116     delete m_axobject;
117     m_axobject = nullptr;
118     update();
119 }
120 
loadControl(const QString & clsid)121 bool QDesignerAxWidget::loadControl(const QString &clsid)
122 {
123     if (clsid.isEmpty())
124         return false;
125     if (m_axobject)
126         resetControl();
127     m_axobject = new QAxWidget();
128 
129     if (!m_axobject->setControl(clsid)) {
130         delete m_axobject;
131         m_axobject = nullptr;
132         return false;
133     }
134     update();
135     return true;
136 }
137 
sizeHint() const138 QSize QDesignerAxWidget::sizeHint() const
139 {
140     if (m_axobject)
141         return m_axobject->sizeHint();
142     return m_defaultSize;
143 }
144 
minimumSizeHint() const145 QSize QDesignerAxWidget::minimumSizeHint() const
146 {
147     if (m_axobject)
148         return m_axobject->minimumSizeHint();
149     return QWidget::minimumSizeHint();
150 }
151 
paintEvent(QPaintEvent *)152 void QDesignerAxWidget::paintEvent(QPaintEvent * /*event */)
153 {
154     QPainter p(this);
155     const QRect r = contentsRect();
156     const int contentsWidth = r.width();
157     const int contentsHeight= r.height();
158     if (m_axobject) { // QAxWidget has no concept of sizeHint()
159         if (m_drawFlags & DrawControl) {
160             m_axobject->resize(size());
161             m_axobject->render(&p, pos());
162         }
163         if (m_drawFlags & DrawIndicator) {
164             static const QString loaded = tr("Control loaded");
165             QColor patternColor(Qt::green);
166             if (m_drawFlags & DrawControl)
167                 patternColor.setAlpha(80);
168             p.setBrush(QBrush(patternColor, Qt::BDiagPattern));
169             p.setPen(Qt::black);
170             if (r.height() > 5)
171                 p.drawText(5,contentsHeight - 5, loaded);
172         }
173     }
174     if (m_drawFlags & DrawFrame) {
175         p.drawRect(r.adjusted(0, 0, -1, -1));
176     }
177     if (m_drawFlags & DrawIndicator) {
178         if (contentsWidth > m_axImage.width() && contentsHeight > m_axImage.height())
179             p.drawPixmap((contentsWidth - m_axImage.width()) / 2,
180                          (contentsHeight-m_axImage.height()) / 2, m_axImage);
181     }
182 }
183 
184 // --------- QDesignerAxPluginWidget
QDesignerAxPluginWidget(QWidget * parent)185 QDesignerAxPluginWidget::QDesignerAxPluginWidget(QWidget *parent) :
186         QDesignerAxWidget(parent)
187 {
188 }
189 
190 QDesignerAxPluginWidget::~QDesignerAxPluginWidget() = default;
191 
metaObject() const192 const QMetaObject *QDesignerAxPluginWidget::metaObject() const
193 {
194     if (const QAxWidget *aw = axobject())
195         return aw->metaObject();
196 
197     return QDesignerAxWidget::metaObject();
198 }
199 
200 #ifndef QT_NO_EXCEPTIONS
201 
msgComException(const QObject * o,const QMetaObject::Call call,int index)202 static QString msgComException(const QObject *o, const QMetaObject::Call call, int index)
203 {
204     return QDesignerAxWidget::tr("A COM exception occurred when executing a meta call of type %1, index %2 of \"%3\".").
205             arg(call).arg(index).arg(o->objectName());
206 }
207 
208 #endif // QT_NO_EXCEPTIONS
209 
qt_metacall(QMetaObject::Call call,int signal,void ** argv)210 int QDesignerAxPluginWidget::qt_metacall(QMetaObject::Call call, int signal, void **argv)
211 {
212     QAxWidget *aw = axobject();
213     if (!aw)
214         return QDesignerAxWidget::qt_metacall(call,signal,argv);
215 
216 
217     const QMetaObject *mo = metaObject();
218     // Have base class handle inherited stuff (geometry, enabled...)
219     const bool inherited = call == QMetaObject::InvokeMetaMethod ?
220                            (signal < mo->methodOffset()) : (signal < mo->propertyOffset());
221     if (inherited)
222         return QDesignerAxWidget::qt_metacall(call, signal, argv);
223 
224     int rc = -1;
225 #ifndef QT_NO_EXCEPTIONS
226     try {
227 #endif
228         if (debugAxWidget)
229                if (call != QMetaObject::InvokeMetaMethod)
230                    qDebug() << objectName() << call << signal << mo->property(signal).name();
231         switch (call) {
232         case QMetaObject::QueryPropertyStored: // Pretend all changed properties are stored for them to be saved
233             if (m_propValues.contains(signal))
234                 if (argv[0])
235                     *reinterpret_cast< bool*>(argv[0]) = true;
236             break;
237         case QMetaObject::ResetProperty:
238             rc = aw->qt_metacall(call, signal, argv);
239             update();
240             m_propValues.remove(signal);
241             break;
242         case QMetaObject::WriteProperty:
243             rc = aw->qt_metacall(call, signal, argv);
244             update();
245             m_propValues.insert(signal, true);
246             break;
247         default:
248             rc = aw->qt_metacall(call, signal, argv);
249             break;
250         }
251 #ifndef QT_NO_EXCEPTIONS
252     } catch(...) {
253         qWarning(msgComException(this, call, signal).toUtf8());
254      }
255 #endif
256     return rc;
257 }
258 
259 QT_END_NAMESPACE
260