00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #include "qdesigner_propertysheet_p.h"
00025 #include "qdesigner_utils_p.h"
00026
00027 #include <QtDesigner/QDesignerFormWindowInterface>
00028
00029 #include <QtCore/QVariant>
00030 #include <QtCore/QMetaObject>
00031 #include <QtCore/QMetaProperty>
00032
00033 #include <QtGui/QLayout>
00034 #include <QtGui/QImage>
00035 #include <QtGui/QPixmap>
00036
00037 #include <QtGui/QDockWidget>
00038 #include <QtGui/QDialog>
00039 #include <QtGui/QStackedWidget>
00040 #include <QtGui/QToolBar>
00041 #include <QtGui/QStatusBar>
00042 #include <QtGui/QLabel>
00043 #include <QtGui/QCalendarWidget>
00044 #include <QtGui/QDialogButtonBox>
00045
00046 namespace qdesigner_internal {
00047
00048 static const QMetaObject *introducedBy(const QMetaObject *meta, int index)
00049 {
00050 if (index >= meta->propertyOffset())
00051 return meta;
00052
00053 if (meta->superClass())
00054 return introducedBy(meta->superClass(), index);
00055
00056 return 0;
00057 }
00058
00059 }
00060
00061 using namespace qdesigner_internal;
00062
00063 static bool hasLayoutAttributes(QObject *object)
00064 {
00065 if (qobject_cast<QStackedWidget*>(object) != 0)
00066 return false;
00067 if (qobject_cast<QLabel*>(object) != 0)
00068 return false;
00069 if (qobject_cast<QDockWidget*>(object) != 0)
00070 return false;
00071 if (qobject_cast<QToolBar*>(object) != 0)
00072 return false;
00073 if (qobject_cast<QStatusBar*>(object) != 0)
00074 return false;
00075 if (qobject_cast<QCalendarWidget*>(object) != 0)
00076 return false;
00077 if (qobject_cast<QDialogButtonBox*>(object) != 0)
00078 return false;
00079 return true;
00080 }
00081
00082 QDesignerPropertySheet::QDesignerPropertySheet(QObject *object, QObject *parent)
00083 : QObject(parent),
00084 m_object(object),
00085 meta(object->metaObject())
00086 {
00087 const QMetaObject *baseMeta = meta;
00088
00089 while (baseMeta && QString::fromUtf8(baseMeta->className()).startsWith(QLatin1String("QDesigner"))) {
00090 baseMeta = baseMeta->superClass();
00091 }
00092 Q_ASSERT(baseMeta != 0);
00093
00094 for (int index=0; index<count(); ++index) {
00095 QMetaProperty p = meta->property(index);
00096
00097 if (p.type() == QVariant::KeySequence)
00098 createFakeProperty(QString::fromUtf8(p.name()));
00099 else
00100 setVisible(index, false);
00101
00102 QString pgroup = QString::fromUtf8(baseMeta->className());
00103
00104 if (const QMetaObject *pmeta = qdesigner_internal::introducedBy(baseMeta, index)) {
00105 pgroup = QString::fromUtf8(pmeta->className());
00106 }
00107
00108 setPropertyGroup(index, pgroup);
00109 }
00110
00111 if (object->isWidgetType()) {
00112 createFakeProperty(QLatin1String("focusPolicy"));
00113 createFakeProperty(QLatin1String("cursor"));
00114 createFakeProperty(QLatin1String("toolTip"));
00115 createFakeProperty(QLatin1String("whatsThis"));
00116 createFakeProperty(QLatin1String("acceptDrops"));
00117 createFakeProperty(QLatin1String("dragEnabled"));
00118 createFakeProperty(QLatin1String("windowModality"));
00119
00120 if (hasLayoutAttributes(object)) {
00121 int pindex = -1;
00122
00123 pindex = count();
00124 createFakeProperty(QLatin1String("margin"), 0);
00125 setAttribute(pindex, true);
00126 setPropertyGroup(pindex, tr("Layout"));
00127
00128 pindex = count();
00129 createFakeProperty(QLatin1String("spacing"), 0);
00130 setAttribute(pindex, true);
00131 setPropertyGroup(pindex, tr("Layout"));
00132 }
00133 }
00134
00135 if (qobject_cast<QDialog*>(object)) {
00136 createFakeProperty(QLatin1String("modal"));
00137 }
00138 if (qobject_cast<QDockWidget*>(object)) {
00139 createFakeProperty(QLatin1String("floating"));
00140 }
00141 }
00142
00143 QDesignerPropertySheet::~QDesignerPropertySheet()
00144 {
00145 }
00146
00147 void QDesignerPropertySheet::createFakeProperty(const QString &propertyName, const QVariant &value)
00148 {
00149
00150 int index = meta->indexOfProperty(propertyName.toUtf8());
00151 if (index != -1) {
00152 setVisible(index, false);
00153 QVariant v = value.isValid() ? value : metaProperty(index);
00154 m_fakeProperties.insert(index, v);
00155 } else if (value.isValid()) {
00156 int index = count();
00157 m_addIndex.insert(propertyName, index);
00158 m_addProperties.insert(index, value);
00159 }
00160 }
00161
00162 bool QDesignerPropertySheet::isAdditionalProperty(int index) const
00163 {
00164 return m_addProperties.contains(index);
00165 }
00166
00167 bool QDesignerPropertySheet::isFakeProperty(int index) const
00168 {
00169
00170 return (m_fakeProperties.contains(index) || isAdditionalProperty(index));
00171 }
00172
00173 int QDesignerPropertySheet::count() const
00174 {
00175 return meta->propertyCount() + m_addProperties.count();
00176 }
00177
00178 int QDesignerPropertySheet::indexOf(const QString &name) const
00179 {
00180 int index = meta->indexOfProperty(name.toUtf8());
00181
00182 if (index == -1)
00183 index = m_addIndex.value(name, -1);
00184
00185 return index;
00186 }
00187
00188 QString QDesignerPropertySheet::propertyName(int index) const
00189 {
00190 if (isAdditionalProperty(index))
00191 return m_addIndex.key(index);
00192
00193 return QString::fromUtf8(meta->property(index).name());
00194 }
00195
00196 QString QDesignerPropertySheet::propertyGroup(int index) const
00197 {
00198 QString g = m_info.value(index).group;
00199
00200 if (!g.isEmpty())
00201 return g;
00202
00203 if (propertyName(index).startsWith(QLatin1String("accessible")))
00204 return QString::fromUtf8("Accessibility");
00205
00206 if (isAdditionalProperty(index))
00207 return QString::fromUtf8(meta->className());
00208
00209 return g;
00210 }
00211
00212 void QDesignerPropertySheet::setPropertyGroup(int index, const QString &group)
00213 {
00214 if (!m_info.contains(index))
00215 m_info.insert(index, Info());
00216
00217 m_info[index].group = group;
00218 }
00219
00220 QVariant QDesignerPropertySheet::property(int index) const
00221 {
00222 if (isAdditionalProperty(index)) {
00223 if (isFakeLayoutProperty(index) && m_object->isWidgetType()) {
00224 QWidget *widget = qobject_cast<QWidget*>(m_object);
00225 if (QLayout *l = widget->layout())
00226 return l->property(propertyName(index).toUtf8());
00227 }
00228
00229 return m_addProperties.value(index);
00230 }
00231
00232 if (isFakeProperty(index)) {
00233 return m_fakeProperties.value(index);
00234 }
00235
00236 QMetaProperty p = meta->property(index);
00237 QVariant v = p.read(m_object);
00238
00239 if (p.isFlagType()) {
00240 FlagType e;
00241 e.value = v;
00242 QMetaEnum me = p.enumerator();
00243 for (int i=0; i<me.keyCount(); ++i) {
00244 QString k = QString::fromUtf8(me.scope());
00245 k += QString::fromUtf8("::");
00246 k += QLatin1String(me.key(i));
00247 e.items.insert(k, me.keyToValue(k.toUtf8()));
00248 }
00249
00250 qVariantSetValue(v, e);
00251 } else if (p.isEnumType()) {
00252 EnumType e;
00253 e.value = v;
00254 QMetaEnum me = p.enumerator();
00255 QString scope = QString::fromUtf8(me.scope());
00256 if (!scope.isEmpty())
00257 scope += QString::fromUtf8("::");
00258 for (int i=0; i<me.keyCount(); ++i) {
00259 QString key = scope + QLatin1String(me.key(i));
00260 e.items.insert(key, me.keyToValue(key.toUtf8()));
00261 e.names.append(key);
00262 }
00263
00264 qVariantSetValue(v, e);
00265 }
00266
00267 return v;
00268 }
00269
00270 QVariant QDesignerPropertySheet::metaProperty(int index) const
00271 {
00272 Q_ASSERT(!isFakeProperty(index));
00273
00274 QMetaProperty p = meta->property(index);
00275 QVariant v = p.read(m_object);
00276
00277 if (p.isFlagType()) {
00278 FlagType e;
00279 e.value = v;
00280 QMetaEnum me = p.enumerator();
00281 for (int i=0; i<me.keyCount(); ++i) {
00282 QString key;
00283 key += QLatin1String(me.scope());
00284 key += QLatin1String("::");
00285 key += QLatin1String(me.key(i));
00286
00287 e.items.insert(key, me.keyToValue(key.toUtf8()));
00288 }
00289
00290 qVariantSetValue(v, e);
00291 } else if (p.isEnumType()) {
00292 EnumType e;
00293 e.value = v;
00294 QMetaEnum me = p.enumerator();
00295 QString scope = QString::fromUtf8(me.scope());
00296 if (!scope.isEmpty())
00297 scope += QString::fromUtf8("::");
00298 for (int i=0; i<me.keyCount(); ++i) {
00299 QString key = scope + QLatin1String(me.key(i));
00300 e.items.insert(key, me.keyToValue(key.toUtf8()));
00301 e.names.append(key);
00302 }
00303
00304 qVariantSetValue(v, e);
00305 }
00306
00307 return v;
00308 }
00309
00310 QVariant QDesignerPropertySheet::resolvePropertyValue(const QVariant &value) const
00311 {
00312 QVariant v;
00313 EnumType e;
00314 FlagType f;
00315
00316 if (qVariantCanConvert<FlagType>(value))
00317 v = qvariant_cast<FlagType>(value).value;
00318 else if (qVariantCanConvert<EnumType>(value))
00319 v = qvariant_cast<EnumType>(value).value;
00320 else
00321 v = value;
00322
00323 return v;
00324 }
00325
00326 void QDesignerPropertySheet::setFakeProperty(int index, const QVariant &value)
00327 {
00328 Q_ASSERT(isFakeProperty(index));
00329
00330 QVariant &v = m_fakeProperties[index];
00331
00332 if (qVariantCanConvert<FlagType>(value) || qVariantCanConvert<EnumType>(value)) {
00333 v = value;
00334 } else if (qVariantCanConvert<FlagType>(v)) {
00335 FlagType f = qvariant_cast<FlagType>(v);
00336 f.value = value;
00337 qVariantSetValue(v, f);
00338 Q_ASSERT(f.value.type() == QVariant::Int);
00339 } else if (qVariantCanConvert<EnumType>(v)) {
00340 EnumType e = qvariant_cast<EnumType>(v);
00341 e.value = value;
00342 qVariantSetValue(v, e);
00343 Q_ASSERT(e.value.type() == QVariant::Int);
00344 } else {
00345 v = value;
00346 }
00347 }
00348
00349 void QDesignerPropertySheet::setProperty(int index, const QVariant &value)
00350 {
00351 if (isAdditionalProperty(index)) {
00352 if (isFakeLayoutProperty(index) && m_object->isWidgetType()) {
00353 QWidget *widget = qobject_cast<QWidget*>(m_object);
00354 if (QLayout *l = widget->layout()) {
00355 l->setProperty(propertyName(index).toUtf8(), value);
00356 return;
00357 }
00358 }
00359
00360 m_addProperties[index] = value;
00361 } else if (isFakeProperty(index)) {
00362 setFakeProperty(index, value);
00363 } else {
00364 QMetaProperty p = meta->property(index);
00365 p.write(m_object, resolvePropertyValue(value));
00366 }
00367 }
00368
00369 bool QDesignerPropertySheet::hasReset(int index) const
00370 {
00371 if (isAdditionalProperty(index))
00372 return m_info.value(index).reset;
00373
00374 return true;
00375 }
00376
00377 bool QDesignerPropertySheet::reset(int index)
00378 {
00379 if (isAdditionalProperty(index))
00380 return false;
00381 else if (isFakeProperty(index)) {
00382 QMetaProperty p = meta->property(index);
00383 bool result = p.reset(m_object);
00384 m_fakeProperties[index] = p.read(m_object);
00385 return result;
00386 }
00387
00388
00389
00390 QMetaProperty p = meta->property(index);
00391 return p.reset(m_object);
00392 }
00393
00394 bool QDesignerPropertySheet::isChanged(int index) const
00395 {
00396 return m_info.value(index).changed;
00397 }
00398
00399 void QDesignerPropertySheet::setChanged(int index, bool changed)
00400 {
00401 if (!m_info.contains(index))
00402 m_info.insert(index, Info());
00403
00404 m_info[index].changed = changed;
00405 }
00406
00407 bool QDesignerPropertySheet::isFakeLayoutProperty(int index) const
00408 {
00409 if (!isAdditionalProperty(index))
00410 return false;
00411
00412 QString pname = propertyName(index);
00413
00414 if (pname == QLatin1String("margin")
00415 || pname == QLatin1String("spacing")
00416 || pname == QLatin1String("sizeConstraint"))
00417 return true;
00418
00419 return false;
00420 }
00421
00422 bool QDesignerPropertySheet::isVisible(int index) const
00423 {
00424 if (isAdditionalProperty(index)) {
00425 if (isFakeLayoutProperty(index) && m_object->isWidgetType()) {
00426 QWidget *widget = qobject_cast<QWidget*>(m_object);
00427 return (widget->layout() != 0);
00428 }
00429
00430 return m_info.value(index).visible;
00431 }
00432
00433 if (isFakeProperty(index))
00434 return true;
00435
00436 QMetaProperty p = meta->property(index);
00437 return (p.isWritable() && p.isDesignable(m_object)) || m_info.value(index).visible;
00438 }
00439
00440 void QDesignerPropertySheet::setVisible(int index, bool visible)
00441 {
00442 if (!m_info.contains(index))
00443 m_info.insert(index, Info());
00444
00445 m_info[index].visible = visible;
00446 }
00447
00448 bool QDesignerPropertySheet::isAttribute(int index) const
00449 {
00450 if (isAdditionalProperty(index))
00451 return m_info.value(index).attribute;
00452
00453 if (isFakeProperty(index))
00454 return false;
00455
00456 return m_info.value(index).attribute;
00457 }
00458
00459 void QDesignerPropertySheet::setAttribute(int index, bool attribute)
00460 {
00461 if (!m_info.contains(index))
00462 m_info.insert(index, Info());
00463
00464 m_info[index].attribute = attribute;
00465 }
00466
00467
00468 QDesignerPropertySheetFactory::QDesignerPropertySheetFactory(QExtensionManager *parent)
00469 : QExtensionFactory(parent)
00470 {
00471 }
00472
00473 QObject *QDesignerPropertySheetFactory::createExtension(QObject *object, const QString &iid, QObject *parent) const
00474 {
00475 if (iid == Q_TYPEID(QDesignerPropertySheetExtension))
00476 return new QDesignerPropertySheet(object, parent);
00477
00478 return 0;
00479 }
00480