1 /****************************************************************************
2 **
3 ** Copyright (C) 2015 The Qt Company Ltd.
4 ** Contact: http://www.qt.io/licensing/
5 **
6 ** This file is part of the Qt Designer of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:LGPL$
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 http://www.qt.io/terms-conditions. For further
15 ** information use the contact form at http://www.qt.io/contact-us.
16 **
17 ** GNU Lesser General Public License Usage
18 ** Alternatively, this file may be used under the terms of the GNU Lesser
19 ** General Public License version 2.1 or version 3 as published by the Free
20 ** Software Foundation and appearing in the file LICENSE.LGPLv21 and
21 ** LICENSE.LGPLv3 included in the packaging of this file. Please review the
22 ** following information to ensure the GNU Lesser General Public License
23 ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
24 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
25 **
26 ** As a special exception, The Qt Company gives you certain additional
27 ** rights. These rights are described in The Qt Company LGPL Exception
28 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
29 **
30 ** GNU General Public License Usage
31 ** Alternatively, this file may be used under the terms of the GNU
32 ** General Public License version 3.0 as published by the Free Software
33 ** Foundation and appearing in the file LICENSE.GPL included in the
34 ** packaging of this file. Please review the following information to
35 ** ensure the GNU General Public License version 3.0 requirements will be
36 ** met: http://www.gnu.org/copyleft/gpl.html.
37 **
38 ** $QT_END_LICENSE$
39 **
40 ****************************************************************************/
41
42 #include "qaxwidgetpropertysheet.h"
43 #include "qdesigneraxwidget.h"
44
45 #include <QtDesigner/QDesignerMemberSheetExtension>
46 #include <QtDesigner/QDesignerFormWindowInterface>
47 #include <QtDesigner/QDesignerFormEditorInterface>
48 #include <QtDesigner/QDesignerPropertyEditorInterface>
49
50 #include <QtDesigner/QExtensionManager>
51 #include <private/qdesigner_utils_p.h>
52 #include <QtCore/QDebug>
53 #include <QtCore/QTimer>
54
55 static const char *geometryPropertyC = "geometry";
56
57 QT_BEGIN_NAMESPACE
58
59 const char *QAxWidgetPropertySheet::controlPropertyName = "control";
60
designerPropertyToString(const QVariant & value)61 static QString designerPropertyToString(const QVariant &value)
62 {
63 return value.canConvert<qdesigner_internal::PropertySheetStringValue>() ?
64 qvariant_cast<qdesigner_internal::PropertySheetStringValue>(value).value() :
65 value.toString();
66 }
67
QAxWidgetPropertySheet(QDesignerAxWidget * object,QObject * parent)68 QAxWidgetPropertySheet::QAxWidgetPropertySheet(QDesignerAxWidget *object, QObject *parent) :
69 QDesignerPropertySheet(object, parent),
70 m_controlProperty(controlPropertyName),
71 m_propertyGroup(QLatin1String("QAxWidget"))
72 {
73 if (!axWidget()->loaded()) { // For some obscure reason....
74 const int controlIndex = QDesignerPropertySheet::indexOf(m_controlProperty);
75 setPropertyGroup(controlIndex, m_propertyGroup);
76 }
77 }
78
isEnabled(int index) const79 bool QAxWidgetPropertySheet::isEnabled(int index) const
80 {
81 if (propertyName(index) == m_controlProperty)
82 return false;
83 return QDesignerPropertySheet::isEnabled(index);
84 }
85
dynamicPropertiesAllowed() const86 bool QAxWidgetPropertySheet::dynamicPropertiesAllowed() const
87 {
88 return false;
89 }
90
axWidget() const91 QDesignerAxWidget *QAxWidgetPropertySheet::axWidget() const
92 {
93 return static_cast<QDesignerAxWidget*>(object());
94 }
95
96 // Reload as the meta object changes.
reset(int index)97 bool QAxWidgetPropertySheet::reset(int index)
98 {
99 const QString name = propertyName(index);
100 QMap<QString, QVariant>::iterator it = m_currentProperties.changedProperties.find(name);
101 if (it != m_currentProperties.changedProperties.end())
102 m_currentProperties.changedProperties.erase(it);
103 if (name != m_controlProperty)
104 return QDesignerPropertySheet::reset(index);
105 axWidget()->resetControl();
106 QTimer::singleShot(0, this, SLOT(updatePropertySheet()));
107 return true;
108 }
109
property(int index) const110 QVariant QAxWidgetPropertySheet::property(int index) const
111 {
112 // QTBUG-34592, accessing the 'control' property via meta object system
113 // may cause crashes during loading for some controls.
114 return propertyName(index) == m_controlProperty ?
115 QVariant(axWidget()->control()) :
116 QDesignerPropertySheet::property(index);
117 }
118
setProperty(int index,const QVariant & value)119 void QAxWidgetPropertySheet::setProperty(int index, const QVariant &value)
120 {
121
122 // take care of all changed properties
123 const QString name = propertyName(index);
124 m_currentProperties.changedProperties[name] = value;
125 if (name != m_controlProperty) {
126 QDesignerPropertySheet::setProperty(index, value);
127 return;
128 }
129 // Loading forms: Reload
130 if (name == m_controlProperty) {
131 const QString clsid = designerPropertyToString(value);
132 if (clsid.isEmpty() || !axWidget()->loadControl(clsid))
133 reset(index);
134 else
135 QTimer::singleShot(100, this, SLOT(updatePropertySheet()));
136 }
137 }
138
indexOf(const QString & name) const139 int QAxWidgetPropertySheet::indexOf(const QString &name) const
140 {
141 const int index = QDesignerPropertySheet::indexOf(name);
142 if (index != -1)
143 return index;
144 // Loading before recreation of sheet in timer slot: Add a fake property to store the value
145 const QVariant dummValue(0);
146 QAxWidgetPropertySheet *that = const_cast<QAxWidgetPropertySheet *>(this);
147 const int newIndex = that->createFakeProperty(name, dummValue);
148 that->setPropertyGroup(newIndex, m_propertyGroup);
149 return newIndex;
150 }
151
updatePropertySheet()152 void QAxWidgetPropertySheet::updatePropertySheet()
153 {
154 // refresh the property sheet (we are deleting m_currentProperties)
155 struct SavedProperties tmp = m_currentProperties;
156 QDesignerAxWidget *axw = axWidget();
157 QDesignerFormWindowInterface *formWin = QDesignerFormWindowInterface::findFormWindow(axw);
158 Q_ASSERT(formWin != 0);
159 tmp.widget = axw;
160 tmp.clsid = axw->control();
161 // Delete the sheets as they cache the meta object and other information
162 delete this;
163 delete qt_extension<QDesignerMemberSheetExtension *>(formWin->core()->extensionManager(), axw);
164 reloadPropertySheet(tmp, formWin);
165 }
166
reloadPropertySheet(const struct SavedProperties & properties,QDesignerFormWindowInterface * formWin)167 void QAxWidgetPropertySheet::reloadPropertySheet(const struct SavedProperties &properties, QDesignerFormWindowInterface *formWin)
168 {
169 QDesignerFormEditorInterface *core = formWin->core();
170 //Recreation of the property sheet
171 QDesignerPropertySheetExtension *sheet = qt_extension<QDesignerPropertySheetExtension *>(core->extensionManager(), properties.widget);
172
173 bool foundGeometry = false;
174 const QString geometryProperty = QLatin1String(geometryPropertyC);
175 const SavedProperties::NamePropertyMap::const_iterator cend = properties.changedProperties.constEnd();
176 for (SavedProperties::NamePropertyMap::const_iterator i = properties.changedProperties.constBegin(); i != cend; ++i) {
177 const QString name = i.key();
178 const int index = sheet->indexOf(name);
179 if (index == -1)
180 continue;
181 // filter out geometry as this will resize the control
182 // to is default size even if it is attached to an layout
183 // but set the changed flag to work around preview bug...
184 if (name == geometryProperty) {
185 sheet->setChanged(index, true);
186 foundGeometry = true;
187 continue;
188 }
189 if (name == QLatin1String(controlPropertyName)) {
190 sheet->setChanged(index, !designerPropertyToString(i.value()).isEmpty());
191 continue;
192 }
193 sheet->setChanged(index, true);
194 sheet->setProperty(index, i.value());
195 }
196
197 if (!foundGeometry) // Make sure geometry is always changed in Designer
198 sheet->setChanged(sheet->indexOf(geometryProperty), true);
199
200 if (core->propertyEditor()->object() == properties.widget) {
201 formWin->clearSelection(true);
202 formWin->selectWidget(properties.widget);
203 }
204 }
205
206 QT_END_NAMESPACE
207