tools/designer/src/lib/shared/qdesigner_propertysheet.cpp

Go to the documentation of this file.
00001 /****************************************************************************
00002 **
00003 ** Copyright (C) 1992-2006 Trolltech ASA. All rights reserved.
00004 **
00005 ** This file is part of the Qt Designer of the Qt Toolkit.
00006 **
00007 ** This file may be used under the terms of the GNU General Public
00008 ** License version 2.0 as published by the Free Software Foundation
00009 ** and appearing in the file LICENSE.GPL included in the packaging of
00010 ** this file.  Please review the following information to ensure GNU
00011 ** General Public Licensing requirements will be met:
00012 ** http://www.trolltech.com/products/qt/opensource.html
00013 **
00014 ** If you are unsure which license is appropriate for your use, please
00015 ** review the following information:
00016 ** http://www.trolltech.com/products/qt/licensing.html or contact the
00017 ** sales department at sales@trolltech.com.
00018 **
00019 ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
00020 ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
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 } // qdesigner_internal
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); // use the default for `real' properties
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     // fake properties
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()) { // additional properties
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     // additional properties must be fake
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     // ### TODO: reset for fake properties.
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 

Generated on Thu Mar 15 12:01:29 2007 for Qt 4.2 User's Guide by  doxygen 1.5.1