diff options
Diffstat (limited to 'tools/designer/src/components/propertyeditor')
34 files changed, 8825 insertions, 0 deletions
diff --git a/tools/designer/src/components/propertyeditor/brushpropertymanager.cpp b/tools/designer/src/components/propertyeditor/brushpropertymanager.cpp new file mode 100644 index 0000000..2a63ba6 --- /dev/null +++ b/tools/designer/src/components/propertyeditor/brushpropertymanager.cpp @@ -0,0 +1,288 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the Qt Designer of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "brushpropertymanager.h" +#include "qtpropertymanager.h" +#include "qtvariantproperty.h" +#include "qtpropertybrowserutils_p.h" + +#include <QtCore/QCoreApplication> +#include <QtCore/QVariant> +#include <QtCore/QString> + +static const char *brushStyles[] = { +QT_TRANSLATE_NOOP("BrushPropertyManager", "No brush"), +QT_TRANSLATE_NOOP("BrushPropertyManager", "Solid"), +QT_TRANSLATE_NOOP("BrushPropertyManager", "Dense 1"), +QT_TRANSLATE_NOOP("BrushPropertyManager", "Dense 2"), +QT_TRANSLATE_NOOP("BrushPropertyManager", "Dense 3"), +QT_TRANSLATE_NOOP("BrushPropertyManager", "Dense 4"), +QT_TRANSLATE_NOOP("BrushPropertyManager", "Dense 5"), +QT_TRANSLATE_NOOP("BrushPropertyManager", "Dense 6"), +QT_TRANSLATE_NOOP("BrushPropertyManager", "Dense 7"), +QT_TRANSLATE_NOOP("BrushPropertyManager", "Horizontal"), +QT_TRANSLATE_NOOP("BrushPropertyManager", "Vertical"), +QT_TRANSLATE_NOOP("BrushPropertyManager", "Cross"), +QT_TRANSLATE_NOOP("BrushPropertyManager", "Backward diagonal"), +QT_TRANSLATE_NOOP("BrushPropertyManager", "Forward diagonal"), +QT_TRANSLATE_NOOP("BrushPropertyManager", "Crossing diagonal"), +}; + +QT_BEGIN_NAMESPACE + +namespace qdesigner_internal { + +BrushPropertyManager::BrushPropertyManager() +{ +} + +int BrushPropertyManager::brushStyleToIndex(Qt::BrushStyle st) +{ + switch (st) { + case Qt::NoBrush: return 0; + case Qt::SolidPattern: return 1; + case Qt::Dense1Pattern: return 2; + case Qt::Dense2Pattern: return 3; + case Qt::Dense3Pattern: return 4; + case Qt::Dense4Pattern: return 5; + case Qt::Dense5Pattern: return 6; + case Qt::Dense6Pattern: return 7; + case Qt::Dense7Pattern: return 8; + case Qt::HorPattern: return 9; + case Qt::VerPattern: return 10; + case Qt::CrossPattern: return 11; + case Qt::BDiagPattern: return 12; + case Qt::FDiagPattern: return 13; + case Qt::DiagCrossPattern: return 14; + default: break; + } + return 0; +} + +Qt::BrushStyle BrushPropertyManager::brushStyleIndexToStyle(int brushStyleIndex) +{ + switch (brushStyleIndex) { + case 0: return Qt::NoBrush; + case 1: return Qt::SolidPattern; + case 2: return Qt::Dense1Pattern; + case 3: return Qt::Dense2Pattern; + case 4: return Qt::Dense3Pattern; + case 5: return Qt::Dense4Pattern; + case 6: return Qt::Dense5Pattern; + case 7: return Qt::Dense6Pattern; + case 8: return Qt::Dense7Pattern; + case 9: return Qt::HorPattern; + case 10: return Qt::VerPattern; + case 11: return Qt::CrossPattern; + case 12: return Qt::BDiagPattern; + case 13: return Qt::FDiagPattern; + case 14: return Qt::DiagCrossPattern; + } + return Qt::NoBrush; +} + +const BrushPropertyManager::EnumIndexIconMap &BrushPropertyManager::brushStyleIcons() +{ + // Create a map of icons for the brush style editor + static EnumIndexIconMap rc; + if (rc.empty()) { + const int brushStyleCount = sizeof(brushStyles)/sizeof(const char *); + QBrush brush(Qt::black); + const QIcon solidIcon = QtPropertyBrowserUtils::brushValueIcon(brush); + for (int i = 0; i < brushStyleCount; i++) { + const Qt::BrushStyle style = brushStyleIndexToStyle(i); + brush.setStyle(style); + rc.insert(i, QtPropertyBrowserUtils::brushValueIcon(brush)); + } + } + return rc; +} + +QString BrushPropertyManager::brushStyleIndexToString(int brushStyleIndex) +{ + const int brushStyleCount = sizeof(brushStyles)/sizeof(const char *); + return brushStyleIndex < brushStyleCount ? QCoreApplication::translate("BrushPropertyManager", brushStyles[brushStyleIndex]) : QString(); +} + +void BrushPropertyManager::initializeProperty(QtVariantPropertyManager *vm, QtProperty *property, int enumTypeId) +{ + m_brushValues.insert(property, QBrush()); + // style + QtVariantProperty *styleSubProperty = vm->addProperty(enumTypeId, QCoreApplication::translate("BrushPropertyManager", "Style")); + property->addSubProperty(styleSubProperty); + QStringList styles; + const int brushStyleCount = sizeof(brushStyles)/sizeof(const char *); + for (int i = 0; i < brushStyleCount; i++) + styles.push_back(QCoreApplication::translate("BrushPropertyManager", brushStyles[i])); + styleSubProperty->setAttribute(QLatin1String("enumNames"), styles); + styleSubProperty->setAttribute(QLatin1String("enumIcons"), qVariantFromValue(brushStyleIcons())); + m_brushPropertyToStyleSubProperty.insert(property, styleSubProperty); + m_brushStyleSubPropertyToProperty.insert(styleSubProperty, property); + // color + QtVariantProperty *colorSubProperty = vm->addProperty(QVariant::Color, QCoreApplication::translate("BrushPropertyManager", "Color")); + property->addSubProperty(colorSubProperty); + m_brushPropertyToColorSubProperty.insert(property, colorSubProperty); + m_brushColorSubPropertyToProperty.insert(colorSubProperty, property); +} + +bool BrushPropertyManager::uninitializeProperty(QtProperty *property) +{ + const PropertyBrushMap::iterator brit = m_brushValues.find(property); // Brushes + if (brit == m_brushValues.end()) + return false; + m_brushValues.erase(brit); + // style + PropertyToPropertyMap::iterator subit = m_brushPropertyToStyleSubProperty.find(property); + if (subit != m_brushPropertyToStyleSubProperty.end()) { + QtProperty *styleProp = subit.value(); + m_brushStyleSubPropertyToProperty.remove(styleProp); + m_brushPropertyToStyleSubProperty.erase(subit); + delete styleProp; + } + // color + subit = m_brushPropertyToColorSubProperty.find(property); + if (subit != m_brushPropertyToColorSubProperty.end()) { + QtProperty *colorProp = subit.value(); + m_brushColorSubPropertyToProperty.remove(colorProp); + m_brushPropertyToColorSubProperty.erase(subit); + delete colorProp; + } + return true; +} + +void BrushPropertyManager::slotPropertyDestroyed(QtProperty *property) +{ + PropertyToPropertyMap::iterator subit = m_brushStyleSubPropertyToProperty.find(property); + if (subit != m_brushStyleSubPropertyToProperty.end()) { + m_brushPropertyToStyleSubProperty[subit.value()] = 0; + m_brushStyleSubPropertyToProperty.erase(subit); + } + subit = m_brushColorSubPropertyToProperty.find(property); + if (subit != m_brushColorSubPropertyToProperty.end()) { + m_brushPropertyToColorSubProperty[subit.value()] = 0; + m_brushColorSubPropertyToProperty.erase(subit); + } +} + + +BrushPropertyManager::ValueChangedResult BrushPropertyManager::valueChanged(QtVariantPropertyManager *vm, QtProperty *property, const QVariant &value) +{ + switch (value.type()) { + case QVariant::Int: // Style subproperty? + if (QtProperty *brushProperty = m_brushStyleSubPropertyToProperty.value(property, 0)) { + const QBrush oldValue = m_brushValues.value(brushProperty); + QBrush newBrush = oldValue; + const int index = value.toInt(); + newBrush.setStyle(brushStyleIndexToStyle(index)); + if (newBrush == oldValue) + return Unchanged; + vm->variantProperty(brushProperty)->setValue(newBrush); + return Changed; + } + break; + case QVariant::Color: // Color subproperty? + if (QtProperty *brushProperty = m_brushColorSubPropertyToProperty.value(property, 0)) { + const QBrush oldValue = m_brushValues.value(brushProperty); + QBrush newBrush = oldValue; + newBrush.setColor(qvariant_cast<QColor>(value)); + if (newBrush == oldValue) + return Unchanged; + vm->variantProperty(brushProperty)->setValue(newBrush); + return Changed; + } + break; + default: + break; + } + return NoMatch; +} + +BrushPropertyManager::ValueChangedResult BrushPropertyManager::setValue(QtVariantPropertyManager *vm, QtProperty *property, const QVariant &value) +{ + if (value.type() != QVariant::Brush) + return NoMatch; + const PropertyBrushMap::iterator brit = m_brushValues.find(property); + if (brit == m_brushValues.end()) + return NoMatch; + + const QBrush newBrush = qvariant_cast<QBrush>(value); + if (newBrush == brit.value()) + return Unchanged; + brit.value() = newBrush; + if (QtProperty *styleProperty = m_brushPropertyToStyleSubProperty.value(property)) + vm->variantProperty(styleProperty)->setValue(brushStyleToIndex(newBrush.style())); + if (QtProperty *colorProperty = m_brushPropertyToColorSubProperty.value(property)) + vm->variantProperty(colorProperty)->setValue(newBrush.color()); + + return Changed; +} + +bool BrushPropertyManager::valueText(const QtProperty *property, QString *text) const +{ + const PropertyBrushMap::const_iterator brit = m_brushValues.constFind(const_cast<QtProperty *>(property)); + if (brit == m_brushValues.constEnd()) + return false; + const QBrush &brush = brit.value(); + const QString styleName = brushStyleIndexToString(brushStyleToIndex(brush.style())); + *text = QCoreApplication::translate("BrushPropertyManager", "[%1, %2]").arg(styleName).arg(QtPropertyBrowserUtils::colorValueText(brush.color())); + return true; +} + +bool BrushPropertyManager::valueIcon(const QtProperty *property, QIcon *icon) const +{ + const PropertyBrushMap::const_iterator brit = m_brushValues.constFind(const_cast<QtProperty *>(property)); + if (brit == m_brushValues.constEnd()) + return false; + *icon = QtPropertyBrowserUtils::brushValueIcon(brit.value()); + return true; +} + +bool BrushPropertyManager::value(const QtProperty *property, QVariant *v) const +{ + const PropertyBrushMap::const_iterator brit = m_brushValues.constFind(const_cast<QtProperty *>(property)); + if (brit == m_brushValues.constEnd()) + return false; + qVariantSetValue(*v, brit.value()); + return true; +} +} + +QT_END_NAMESPACE diff --git a/tools/designer/src/components/propertyeditor/brushpropertymanager.h b/tools/designer/src/components/propertyeditor/brushpropertymanager.h new file mode 100644 index 0000000..2bb4933 --- /dev/null +++ b/tools/designer/src/components/propertyeditor/brushpropertymanager.h @@ -0,0 +1,105 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the Qt Designer of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef BRUSHPROPERTYMANAGER_H +#define BRUSHPROPERTYMANAGER_H + +#include <QtCore/QMap> +#include <QtGui/QBrush> +#include <QtGui/QIcon> + +QT_BEGIN_NAMESPACE + +class QtProperty; +class QtVariantPropertyManager; + +class QString; +class QVariant; + +namespace qdesigner_internal { + +// BrushPropertyManager: A mixin for DesignerPropertyManager that manages brush properties. + +class BrushPropertyManager { + BrushPropertyManager(const BrushPropertyManager&); + BrushPropertyManager &operator=(const BrushPropertyManager&); + +public: + BrushPropertyManager(); + + void initializeProperty(QtVariantPropertyManager *vm, QtProperty *property, int enumTypeId); + bool uninitializeProperty(QtProperty *property); + + // Call from slotValueChanged(). + enum ValueChangedResult { NoMatch, Unchanged, Changed }; + ValueChangedResult valueChanged(QtVariantPropertyManager *vm, QtProperty *property, const QVariant &value); + ValueChangedResult setValue(QtVariantPropertyManager *vm, QtProperty *property, const QVariant &value); + + bool valueText(const QtProperty *property, QString *text) const; + bool valueIcon(const QtProperty *property, QIcon *icon) const; + bool value(const QtProperty *property, QVariant *v) const; + + // Call from QtPropertyManager's propertyDestroyed signal + void slotPropertyDestroyed(QtProperty *property); + +private: + static int brushStyleToIndex(Qt::BrushStyle st); + static Qt::BrushStyle brushStyleIndexToStyle(int brushStyleIndex); + static QString brushStyleIndexToString(int brushStyleIndex); + + typedef QMap<int, QIcon> EnumIndexIconMap; + static const EnumIndexIconMap &brushStyleIcons(); + + typedef QMap<QtProperty *, QtProperty *> PropertyToPropertyMap; + PropertyToPropertyMap m_brushPropertyToStyleSubProperty; + PropertyToPropertyMap m_brushPropertyToColorSubProperty; + PropertyToPropertyMap m_brushStyleSubPropertyToProperty; + PropertyToPropertyMap m_brushColorSubPropertyToProperty; + + typedef QMap<QtProperty *, QBrush> PropertyBrushMap; + PropertyBrushMap m_brushValues; +}; + +} + +QT_END_NAMESPACE + +#endif // BRUSHPROPERTYMANAGER_H diff --git a/tools/designer/src/components/propertyeditor/defs.cpp b/tools/designer/src/components/propertyeditor/defs.cpp new file mode 100644 index 0000000..ebee40a --- /dev/null +++ b/tools/designer/src/components/propertyeditor/defs.cpp @@ -0,0 +1,107 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the Qt Designer of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "defs.h" + +QT_BEGIN_NAMESPACE + +namespace qdesigner_internal { + +int size_type_to_int( QSizePolicy::Policy t ) +{ + if ( t == QSizePolicy::Fixed ) + return 0; + if ( t == QSizePolicy::Minimum ) + return 1; + if ( t == QSizePolicy::Maximum ) + return 2; + if ( t == QSizePolicy::Preferred ) + return 3; + if ( t == QSizePolicy::MinimumExpanding ) + return 4; + if ( t == QSizePolicy::Expanding ) + return 5; + if ( t == QSizePolicy::Ignored ) + return 6; + return 0; +} + +QString size_type_to_string( QSizePolicy::Policy t ) +{ + if ( t == QSizePolicy::Fixed ) + return QString::fromUtf8("Fixed"); + if ( t == QSizePolicy::Minimum ) + return QString::fromUtf8("Minimum"); + if ( t == QSizePolicy::Maximum ) + return QString::fromUtf8("Maximum"); + if ( t == QSizePolicy::Preferred ) + return QString::fromUtf8("Preferred"); + if ( t == QSizePolicy::MinimumExpanding ) + return QString::fromUtf8("MinimumExpanding"); + if ( t == QSizePolicy::Expanding ) + return QString::fromUtf8("Expanding"); + if ( t == QSizePolicy::Ignored ) + return QString::fromUtf8("Ignored"); + return QString(); +} + +QSizePolicy::Policy int_to_size_type( int i ) +{ + if ( i == 0 ) + return QSizePolicy::Fixed; + if ( i == 1 ) + return QSizePolicy::Minimum; + if ( i == 2 ) + return QSizePolicy::Maximum; + if ( i == 3 ) + return QSizePolicy::Preferred; + if ( i == 4 ) + return QSizePolicy::MinimumExpanding; + if ( i == 5 ) + return QSizePolicy::Expanding; + if ( i == 6 ) + return QSizePolicy::Ignored; + return QSizePolicy::Preferred; +} + +} // namespace qdesigner_internal + +QT_END_NAMESPACE diff --git a/tools/designer/src/components/propertyeditor/defs.h b/tools/designer/src/components/propertyeditor/defs.h new file mode 100644 index 0000000..e7a48d6 --- /dev/null +++ b/tools/designer/src/components/propertyeditor/defs.h @@ -0,0 +1,60 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the Qt Designer of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef DEFS_H +#define DEFS_H + +#include <QtGui/QSizePolicy> +#include <QtCore/QString> + +QT_BEGIN_NAMESPACE + +namespace qdesigner_internal { + +int size_type_to_int(QSizePolicy::Policy t); +QString size_type_to_string(QSizePolicy::Policy t); +QSizePolicy::Policy int_to_size_type(int i); + +} // namespace qdesigner_internal + +QT_END_NAMESPACE + +#endif // DEFS_H diff --git a/tools/designer/src/components/propertyeditor/designerpropertymanager.cpp b/tools/designer/src/components/propertyeditor/designerpropertymanager.cpp new file mode 100644 index 0000000..1b267aa --- /dev/null +++ b/tools/designer/src/components/propertyeditor/designerpropertymanager.cpp @@ -0,0 +1,2604 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the Qt Designer of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "designerpropertymanager.h" +#include "qtpropertymanager.h" +#include "paletteeditorbutton.h" +#include "qlonglongvalidator.h" +#include "stringlisteditorbutton.h" +#include "qtresourceview_p.h" +#include "qtpropertybrowserutils_p.h" + +#include <formwindowbase_p.h> +#include <textpropertyeditor_p.h> +#include <stylesheeteditor_p.h> +#include <richtexteditor_p.h> +#include <plaintexteditor_p.h> +#include <iconloader_p.h> +#include <iconselector_p.h> +#include <abstractdialoggui_p.h> + +#include <QtDesigner/QDesignerIconCacheInterface> + +#include <QtGui/QLabel> +#include <QtGui/QToolButton> +#include <QtGui/QHBoxLayout> +#include <QtCore/QFileInfo> +#include <QtGui/QClipboard> +#include <QtGui/QLineEdit> +#include <QtGui/QDialogButtonBox> +#include <QtGui/QPushButton> +#include <QtGui/QFileDialog> +#include <QtGui/QAction> +#include <QtGui/QMenu> +#include <QtGui/QContextMenuEvent> +#include <QtGui/QApplication> +#include <QtCore/QUrl> + +#include <QtCore/QDebug> + +QT_BEGIN_NAMESPACE + +static const char *resettableAttributeC = "resettable"; +static const char *flagsAttributeC = "flags"; +static const char *validationModesAttributeC = "validationMode"; +static const char *superPaletteAttributeC = "superPalette"; +static const char *defaultResourceAttributeC = "defaultResource"; +static const char *fontAttributeC = "font"; + +class DesignerFlagPropertyType +{ +}; + + +class DesignerAlignmentPropertyType +{ +}; + +QT_END_NAMESPACE + +Q_DECLARE_METATYPE(DesignerFlagPropertyType) +Q_DECLARE_METATYPE(DesignerAlignmentPropertyType) + +QT_BEGIN_NAMESPACE + +namespace qdesigner_internal { + +// ------------ TextEditor +class TextEditor : public QWidget +{ + Q_OBJECT +public: + TextEditor(QDesignerFormEditorInterface *core, QWidget *parent); + + TextPropertyValidationMode textPropertyValidationMode() const; + void setTextPropertyValidationMode(TextPropertyValidationMode vm); + + void setRichTextDefaultFont(const QFont &font) { m_richTextDefaultFont = font; } + QFont richTextDefaultFont() const { return m_richTextDefaultFont; } + + void setSpacing(int spacing); + + TextPropertyEditor::UpdateMode updateMode() const { return m_editor->updateMode(); } + void setUpdateMode(TextPropertyEditor::UpdateMode um) { m_editor->setUpdateMode(um); } + +public slots: + void setText(const QString &text); + +signals: + void textChanged(const QString &text); + +private slots: + void buttonClicked(); + void resourceActionActivated(); + void fileActionActivated(); +private: + TextPropertyEditor *m_editor; + QFont m_richTextDefaultFont; + QToolButton *m_button; + QMenu *m_menu; + QAction *m_resourceAction; + QAction *m_fileAction; + QHBoxLayout *m_layout; + QDesignerFormEditorInterface *m_core; +}; + +TextEditor::TextEditor(QDesignerFormEditorInterface *core, QWidget *parent) : + QWidget(parent), + m_editor(new TextPropertyEditor(this)), + m_richTextDefaultFont(QApplication::font()), + m_button(new QToolButton(this)), + m_menu(new QMenu(this)), + m_resourceAction(new QAction(tr("Choose Resource..."), this)), + m_fileAction(new QAction(tr("Choose File..."), this)), + m_layout(new QHBoxLayout(this)), + m_core(core) +{ + m_layout->addWidget(m_editor); + m_button->setText(tr("...")); + m_button->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Ignored); + m_button->setFixedWidth(20); + m_layout->addWidget(m_button); + m_layout->setMargin(0); + m_layout->setSpacing(0); + + connect(m_resourceAction, SIGNAL(triggered()), this, SLOT(resourceActionActivated())); + connect(m_fileAction, SIGNAL(triggered()), this, SLOT(fileActionActivated())); + connect(m_editor, SIGNAL(textChanged(QString)), this, SIGNAL(textChanged(QString))); + connect(m_button, SIGNAL(clicked()), this, SLOT(buttonClicked())); + setSizePolicy(QSizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed)); + m_button->setVisible(false); + setFocusProxy(m_editor); + + m_menu->addAction(m_resourceAction); + m_menu->addAction(m_fileAction); +} + +void TextEditor::setSpacing(int spacing) +{ + m_layout->setSpacing(spacing); +} + +TextPropertyValidationMode TextEditor::textPropertyValidationMode() const +{ + return m_editor->textPropertyValidationMode(); +} + +void TextEditor::setTextPropertyValidationMode(TextPropertyValidationMode vm) +{ + m_editor->setTextPropertyValidationMode(vm); + if (vm == ValidationURL) { + m_button->setMenu(m_menu); + m_button->setFixedWidth(30); + m_button->setPopupMode(QToolButton::MenuButtonPopup); + } else { + m_button->setMenu(0); + m_button->setFixedWidth(20); + m_button->setPopupMode(QToolButton::DelayedPopup); + } + m_button->setVisible(vm == ValidationStyleSheet || vm == ValidationRichText || vm == ValidationMultiLine || vm == ValidationURL); +} + +void TextEditor::setText(const QString &text) +{ + m_editor->setText(text); +} + +void TextEditor::buttonClicked() +{ + const QString oldText = m_editor->text(); + QString newText; + switch (textPropertyValidationMode()) { + case ValidationStyleSheet: { + StyleSheetEditorDialog dlg(m_core, this); + dlg.setText(oldText); + if (dlg.exec() != QDialog::Accepted) + return; + newText = dlg.text(); + } + break; + case ValidationRichText: { + RichTextEditorDialog dlg(m_core, this); + dlg.setDefaultFont(m_richTextDefaultFont); + dlg.setText(oldText); + if (dlg.showDialog() != QDialog::Accepted) + return; + newText = dlg.text(Qt::AutoText); + } + break; + case ValidationMultiLine: { + PlainTextEditorDialog dlg(m_core, this); + dlg.setDefaultFont(m_richTextDefaultFont); + dlg.setText(oldText); + if (dlg.showDialog() != QDialog::Accepted) + return; + newText = dlg.text(); + } + break; + case ValidationURL: { + QString oldPath = oldText; + if (oldPath.isEmpty() || oldPath.startsWith(QLatin1String("qrc:"))) + resourceActionActivated(); + else + fileActionActivated(); + } + return; + default: + return; + } + if (newText != oldText) { + m_editor->setText(newText); + emit textChanged(newText); + } +} + +void TextEditor::resourceActionActivated() +{ + QString oldPath = m_editor->text(); + if (oldPath.startsWith(QLatin1String("qrc:"))) + oldPath = oldPath.mid(4); + const QString newPath = IconSelector::choosePixmapResource(m_core, m_core->resourceModel(), oldPath, this); + if (newPath.isEmpty() || newPath == oldPath) + return; + const QString newText = QLatin1String("qrc:") + newPath; + m_editor->setText(newText); + emit textChanged(newText); +} + +void TextEditor::fileActionActivated() +{ + QString oldPath = m_editor->text(); + if (oldPath.startsWith(QLatin1String("file:"))) + oldPath = oldPath.mid(5); + const QString newPath = m_core->dialogGui()->getOpenFileName(this, tr("Choose a File"), oldPath); + if (newPath.isEmpty() || newPath == oldPath) + return; + const QString newText = QLatin1String("file:") + newPath; + m_editor->setText(newText); + emit textChanged(newText); +} + +// ------------ PixmapEditor +class PixmapEditor : public QWidget +{ + Q_OBJECT +public: + PixmapEditor(QDesignerFormEditorInterface *core, QWidget *parent); + + void setSpacing(int spacing); + void setPixmapCache(DesignerPixmapCache *cache); +public slots: + void setPath(const QString &path); + void setDefaultPixmap(const QPixmap &pixmap); + +signals: + void pathChanged(const QString &path); + +protected: + void contextMenuEvent(QContextMenuEvent *event); + +private slots: + void defaultActionActivated(); + void resourceActionActivated(); + void fileActionActivated(); + void copyActionActivated(); + void pasteActionActivated(); + void clipboardDataChanged(); +private: + QDesignerFormEditorInterface *m_core; + QLabel *m_pixmapLabel; + QLabel *m_pathLabel; + QToolButton *m_button; + QAction *m_resourceAction; + QAction *m_fileAction; + QAction *m_copyAction; + QAction *m_pasteAction; + QHBoxLayout *m_layout; + QPixmap m_defaultPixmap; + QString m_path; + DesignerPixmapCache *m_pixmapCache; +}; + +PixmapEditor::PixmapEditor(QDesignerFormEditorInterface *core, QWidget *parent) : + QWidget(parent), + m_core(core), + m_pixmapLabel(new QLabel(this)), + m_pathLabel(new QLabel(this)), + m_button(new QToolButton(this)), + m_resourceAction(new QAction(tr("Choose Resource..."), this)), + m_fileAction(new QAction(tr("Choose File..."), this)), + m_copyAction(new QAction(createIconSet(QLatin1String("editcopy.png")), tr("Copy Path"), this)), + m_pasteAction(new QAction(createIconSet(QLatin1String("editpaste.png")), tr("Paste Path"), this)), + m_layout(new QHBoxLayout(this)), + m_pixmapCache(0) +{ + m_layout->addWidget(m_pixmapLabel); + m_layout->addWidget(m_pathLabel); + m_button->setText(tr("...")); + m_button->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Ignored); + m_button->setFixedWidth(30); + m_button->setPopupMode(QToolButton::MenuButtonPopup); + m_layout->addWidget(m_button); + m_layout->setMargin(0); + m_layout->setSpacing(0); + m_pixmapLabel->setFixedWidth(16); + m_pixmapLabel->setAlignment(Qt::AlignCenter); + m_pathLabel->setSizePolicy(QSizePolicy(QSizePolicy::Ignored, QSizePolicy::Fixed)); + + QMenu *menu = new QMenu(this); + menu->addAction(m_resourceAction); + menu->addAction(m_fileAction); + + m_button->setMenu(menu); + m_button->setText(tr("...")); + + connect(m_button, SIGNAL(clicked()), this, SLOT(defaultActionActivated())); + connect(m_resourceAction, SIGNAL(triggered()), this, SLOT(resourceActionActivated())); + connect(m_fileAction, SIGNAL(triggered()), this, SLOT(fileActionActivated())); + connect(m_copyAction, SIGNAL(triggered()), this, SLOT(copyActionActivated())); + connect(m_pasteAction, SIGNAL(triggered()), this, SLOT(pasteActionActivated())); + setSizePolicy(QSizePolicy(QSizePolicy::Preferred, QSizePolicy::Ignored)); + setFocusProxy(m_button); + + connect(QApplication::clipboard(), SIGNAL(dataChanged()), this, SLOT(clipboardDataChanged())); + clipboardDataChanged(); +} + +void PixmapEditor::setPixmapCache(DesignerPixmapCache *cache) +{ + m_pixmapCache = cache; +} + +void PixmapEditor::setSpacing(int spacing) +{ + m_layout->setSpacing(spacing); +} + +void PixmapEditor::setPath(const QString &path) +{ + m_path = path; + if (m_path.isEmpty()) { + m_pathLabel->setText(path); + m_pixmapLabel->setPixmap(m_defaultPixmap); + m_copyAction->setEnabled(false); + } else { + m_pathLabel->setText(QFileInfo(m_path).fileName()); + if (m_pixmapCache) + m_pixmapLabel->setPixmap(QIcon(m_pixmapCache->pixmap(PropertySheetPixmapValue(path))).pixmap(16, 16)); + m_copyAction->setEnabled(true); + } +} + +void PixmapEditor::setDefaultPixmap(const QPixmap &pixmap) +{ + m_defaultPixmap = QIcon(pixmap).pixmap(16, 16); + if (m_path.isEmpty()) + m_pixmapLabel->setPixmap(m_defaultPixmap); +} + +void PixmapEditor::contextMenuEvent(QContextMenuEvent *event) +{ + QMenu menu(this); + menu.addAction(m_copyAction); + menu.addAction(m_pasteAction); + menu.exec(event->globalPos()); + event->accept(); +} + +void PixmapEditor::defaultActionActivated() +{ + // Default to resource + const PropertySheetPixmapValue::PixmapSource ps = m_path.isEmpty() ? PropertySheetPixmapValue::ResourcePixmap : PropertySheetPixmapValue::getPixmapSource(m_core, m_path); + switch (ps) { + case PropertySheetPixmapValue::LanguageResourcePixmap: + case PropertySheetPixmapValue::ResourcePixmap: + resourceActionActivated(); + break; + case PropertySheetPixmapValue::FilePixmap: + fileActionActivated(); + break; + } +} + +void PixmapEditor::resourceActionActivated() +{ + const QString oldPath = m_path; + const QString newPath = IconSelector::choosePixmapResource(m_core, m_core->resourceModel(), oldPath, this); + if (!newPath.isEmpty() && newPath != oldPath) { + setPath(newPath); + emit pathChanged(newPath); + } +} + +void PixmapEditor::fileActionActivated() +{ + const QString newPath = IconSelector::choosePixmapFile(m_path, m_core->dialogGui(), this); + if (!newPath.isEmpty() && newPath != m_path) { + setPath(newPath); + emit pathChanged(newPath); + } +} + +void PixmapEditor::copyActionActivated() +{ + QClipboard *clipboard = QApplication::clipboard(); + clipboard->setText(m_path); +} + +void PixmapEditor::pasteActionActivated() +{ + QClipboard *clipboard = QApplication::clipboard(); + QString subtype = QLatin1String("plain"); + QString text = clipboard->text(subtype); + if (!text.isNull()) { + QStringList list = text.split(QLatin1Char('\n')); + if (list.size() > 0) { + text = list.at(0); + setPath(text); + emit pathChanged(text); + } + } +} + +void PixmapEditor::clipboardDataChanged() +{ + QClipboard *clipboard = QApplication::clipboard(); + QString subtype = QLatin1String("plain"); + const QString text = clipboard->text(subtype); + m_pasteAction->setEnabled(!text.isNull()); +} + +// --------------- ResetWidget +class ResetWidget : public QWidget +{ + Q_OBJECT +public: + ResetWidget(QtProperty *property, QWidget *parent = 0); + + void setWidget(QWidget *widget); + void setResetEnabled(bool enabled); + void setValueText(const QString &text); + void setValueIcon(const QIcon &icon); + void setSpacing(int spacing); +signals: + void resetProperty(QtProperty *property); +private slots: + void slotClicked(); +private: + QtProperty *m_property; + QLabel *m_textLabel; + QLabel *m_iconLabel; + QToolButton *m_button; + int m_spacing; +}; + +ResetWidget::ResetWidget(QtProperty *property, QWidget *parent) : + QWidget(parent), + m_property(property), + m_textLabel(new QLabel(this)), + m_iconLabel(new QLabel(this)), + m_button(new QToolButton(this)), + m_spacing(-1) +{ + m_textLabel->setSizePolicy(QSizePolicy(QSizePolicy::Ignored, QSizePolicy::Fixed)); + m_iconLabel->setSizePolicy(QSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed)); + m_button->setToolButtonStyle(Qt::ToolButtonIconOnly); + m_button->setIcon(createIconSet(QLatin1String("resetproperty.png"))); + m_button->setIconSize(QSize(8,8)); + m_button->setSizePolicy(QSizePolicy(QSizePolicy::Fixed, QSizePolicy::MinimumExpanding)); + connect(m_button, SIGNAL(clicked()), this, SLOT(slotClicked())); + QLayout *layout = new QHBoxLayout(this); + layout->setMargin(0); + layout->setSpacing(m_spacing); + layout->addWidget(m_iconLabel); + layout->addWidget(m_textLabel); + layout->addWidget(m_button); + setFocusProxy(m_textLabel); + setSizePolicy(QSizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed)); +} + +void ResetWidget::setSpacing(int spacing) +{ + m_spacing = spacing; + layout()->setSpacing(m_spacing); +} + +void ResetWidget::setWidget(QWidget *widget) +{ + if (m_textLabel) { + delete m_textLabel; + m_textLabel = 0; + } + if (m_iconLabel) { + delete m_iconLabel; + m_iconLabel = 0; + } + delete layout(); + QLayout *layout = new QHBoxLayout(this); + layout->setMargin(0); + layout->setSpacing(m_spacing); + layout->addWidget(widget); + layout->addWidget(m_button); + setFocusProxy(widget); +} + +void ResetWidget::setResetEnabled(bool enabled) +{ + m_button->setEnabled(enabled); +} + +void ResetWidget::setValueText(const QString &text) +{ + if (m_textLabel) + m_textLabel->setText(text); +} + +void ResetWidget::setValueIcon(const QIcon &icon) +{ + QPixmap pix = icon.pixmap(QSize(16, 16)); + if (m_iconLabel) { + m_iconLabel->setVisible(!pix.isNull()); + m_iconLabel->setPixmap(pix); + } +} + +void ResetWidget::slotClicked() +{ + emit resetProperty(m_property); +} + + +// ------------ DesignerPropertyManager: + +DesignerPropertyManager::DesignerPropertyManager(QDesignerFormEditorInterface *core, QObject *parent) : + QtVariantPropertyManager(parent), + m_changingSubValue(false), + m_core(core), + m_sourceOfChange(0) +{ + connect(this, SIGNAL(valueChanged(QtProperty*,QVariant)), this, SLOT(slotValueChanged(QtProperty*, QVariant))); + connect(this, SIGNAL(propertyDestroyed(QtProperty*)), this, SLOT(slotPropertyDestroyed(QtProperty*))); +} + +DesignerPropertyManager::~DesignerPropertyManager() +{ + clear(); +} + +int DesignerPropertyManager::bitCount(int mask) const +{ + int count = 0; + for (; mask; count++) + mask &= mask - 1; // clear the least significant bit set + return count; +} + +int DesignerPropertyManager::alignToIndexH(uint align) const +{ + if (align & Qt::AlignLeft) + return 0; + if (align & Qt::AlignHCenter) + return 1; + if (align & Qt::AlignRight) + return 2; + if (align & Qt::AlignJustify) + return 3; + return 0; +} + +int DesignerPropertyManager::alignToIndexV(uint align) const +{ + if (align & Qt::AlignTop) + return 0; + if (align & Qt::AlignVCenter) + return 1; + if (align & Qt::AlignBottom) + return 2; + return 1; +} + +uint DesignerPropertyManager::indexHToAlign(int idx) const +{ + switch (idx) { + case 0: return Qt::AlignLeft; + case 1: return Qt::AlignHCenter; + case 2: return Qt::AlignRight; + case 3: return Qt::AlignJustify; + default: break; + } + return Qt::AlignLeft; +} + +uint DesignerPropertyManager::indexVToAlign(int idx) const +{ + switch (idx) { + case 0: return Qt::AlignTop; + case 1: return Qt::AlignVCenter; + case 2: return Qt::AlignBottom; + default: break; + } + return Qt::AlignVCenter; +} + +QString DesignerPropertyManager::indexHToString(int idx) const +{ + switch (idx) { + case 0: return tr("AlignLeft"); + case 1: return tr("AlignHCenter"); + case 2: return tr("AlignRight"); + case 3: return tr("AlignJustify"); + default: break; + } + return tr("AlignLeft"); +} + +QString DesignerPropertyManager::indexVToString(int idx) const +{ + switch (idx) { + case 0: return tr("AlignTop"); + case 1: return tr("AlignVCenter"); + case 2: return tr("AlignBottom"); + default: break; + } + return tr("AlignVCenter"); +} + +void DesignerPropertyManager::slotValueChanged(QtProperty *property, const QVariant &value) +{ + if (m_changingSubValue) + return; + bool enableSubPropertyHandling = true; + + if (QtProperty *flagProperty = m_flagToProperty.value(property, 0)) { + const QList<QtProperty *> subFlags = m_propertyToFlags.value(flagProperty); + const int subFlagCount = subFlags.count(); + // flag changed + const bool subValue = variantProperty(property)->value().toBool(); + const int subIndex = subFlags.indexOf(property); + if (subIndex < 0) + return; + + uint newValue = 0; + + m_changingSubValue = true; + + FlagData data = m_flagValues.value(flagProperty); + const QList<uint> values = data.values; + // Compute new value, without including (additional) supermasks + if (values.at(subIndex) == 0) { + for (int i = 0; i < subFlagCount; ++i) { + QtVariantProperty *subFlag = variantProperty(subFlags.at(i)); + subFlag->setValue(i == subIndex); + } + } else { + if (subValue) + newValue = values.at(subIndex); // value mask of subValue + for (int i = 0; i < subFlagCount; ++i) { + QtVariantProperty *subFlag = variantProperty(subFlags.at(i)); + if (subFlag->value().toBool() && bitCount(values.at(i)) == 1) + newValue |= values.at(i); + } + if (newValue == 0) { + // Uncheck all items except 0-mask + for (int i = 0; i < subFlagCount; ++i) { + QtVariantProperty *subFlag = variantProperty(subFlags.at(i)); + subFlag->setValue(values.at(i) == 0); + } + } else if (newValue == data.val) { + if (!subValue && bitCount(values.at(subIndex)) > 1) { + // We unchecked something, but the original value still holds + variantProperty(property)->setValue(true); + } + } else { + // Make sure 0-mask is not selected + for (int i = 0; i < subFlagCount; ++i) { + QtVariantProperty *subFlag = variantProperty(subFlags.at(i)); + if (values.at(i) == 0) + subFlag->setValue(false); + } + // Check/uncheck proper masks + if (subValue) { + // Make sure submasks and supermasks are selected + for (int i = 0; i < subFlagCount; ++i) { + QtVariantProperty *subFlag = variantProperty(subFlags.at(i)); + const uint vi = values.at(i); + if ((vi != 0) && ((vi & newValue) == vi) && !subFlag->value().toBool()) + subFlag->setValue(true); + } + } else { + // Make sure supermasks are not selected if they're no longer valid + for (int i = 0; i < subFlagCount; ++i) { + QtVariantProperty *subFlag = variantProperty(subFlags.at(i)); + const uint vi = values.at(i); + if (subFlag->value().toBool() && ((vi & newValue) != vi)) + subFlag->setValue(false); + } + } + } + } + m_changingSubValue = false; + data.val = newValue; + QVariant v; + qVariantSetValue(v, data.val); + variantProperty(flagProperty)->setValue(v); + } else if (QtProperty *alignProperty = m_alignHToProperty.value(property, 0)) { + const uint v = m_alignValues.value(alignProperty); + const uint newValue = indexHToAlign(value.toInt()) | indexVToAlign(alignToIndexV(v)); + if (v == newValue) + return; + + variantProperty(alignProperty)->setValue(newValue); + } else if (QtProperty *alignProperty = m_alignVToProperty.value(property, 0)) { + const uint v = m_alignValues.value(alignProperty); + const uint newValue = indexVToAlign(value.toInt()) | indexHToAlign(alignToIndexH(v)); + if (v == newValue) + return; + + variantProperty(alignProperty)->setValue(newValue); + } else if (QtProperty *stringProperty = m_commentToString.value(property, 0)) { + const PropertySheetStringValue v = m_stringValues.value(stringProperty); + PropertySheetStringValue newValue = v; + newValue.setComment(value.toString()); + if (v == newValue) + return; + + variantProperty(stringProperty)->setValue(qVariantFromValue(newValue)); + } else if (QtProperty *stringProperty = m_translatableToString.value(property, 0)) { + const PropertySheetStringValue v = m_stringValues.value(stringProperty); + PropertySheetStringValue newValue = v; + newValue.setTranslatable(value.toBool()); + if (v == newValue) + return; + + variantProperty(stringProperty)->setValue(qVariantFromValue(newValue)); + } else if (QtProperty *stringProperty = m_disambiguationToString.value(property, 0)) { + const PropertySheetStringValue v = m_stringValues.value(stringProperty); + PropertySheetStringValue newValue = v; + newValue.setDisambiguation(value.toString()); + if (v == newValue) + return; + + variantProperty(stringProperty)->setValue(qVariantFromValue(newValue)); + } else if (QtProperty *keySequenceProperty = m_commentToKeySequence.value(property, 0)) { + const PropertySheetKeySequenceValue v = m_keySequenceValues.value(keySequenceProperty); + PropertySheetKeySequenceValue newValue = v; + newValue.setComment(value.toString()); + if (v == newValue) + return; + + variantProperty(keySequenceProperty)->setValue(qVariantFromValue(newValue)); + } else if (QtProperty *keySequenceProperty = m_translatableToKeySequence.value(property, 0)) { + const PropertySheetKeySequenceValue v = m_keySequenceValues.value(keySequenceProperty); + PropertySheetKeySequenceValue newValue = v; + newValue.setTranslatable(value.toBool()); + if (v == newValue) + return; + + variantProperty(keySequenceProperty)->setValue(qVariantFromValue(newValue)); + } else if (QtProperty *keySequenceProperty = m_disambiguationToKeySequence.value(property, 0)) { + const PropertySheetKeySequenceValue v = m_keySequenceValues.value(keySequenceProperty); + PropertySheetKeySequenceValue newValue = v; + newValue.setDisambiguation(value.toString()); + if (v == newValue) + return; + + variantProperty(keySequenceProperty)->setValue(qVariantFromValue(newValue)); + } else if (QtProperty *iProperty = m_iconSubPropertyToProperty.value(property, 0)) { + QtVariantProperty *iconProperty = variantProperty(iProperty); + PropertySheetIconValue icon = qVariantValue<PropertySheetIconValue>(iconProperty->value()); + QPair<QIcon::Mode, QIcon::State> pair = m_iconSubPropertyToState.value(property); + icon.setPixmap(pair.first, pair.second, qVariantValue<PropertySheetPixmapValue>(value)); + QtProperty *origSourceOfChange = m_sourceOfChange; + if (!origSourceOfChange) + m_sourceOfChange = property; + iconProperty->setValue(qVariantFromValue(icon)); + if (!origSourceOfChange) + m_sourceOfChange = origSourceOfChange; + } else if (m_iconValues.contains(property)) { + enableSubPropertyHandling = m_sourceOfChange; + } else { + if (m_brushManager.valueChanged(this, property, value) == BrushPropertyManager::Unchanged) + return; + if (m_fontManager.valueChanged(this, property, value) == FontPropertyManager::Unchanged) + return; + } + + emit valueChanged(property, value, enableSubPropertyHandling); +} + +void DesignerPropertyManager::slotPropertyDestroyed(QtProperty *property) +{ + if (QtProperty *flagProperty = m_flagToProperty.value(property, 0)) { + PropertyToPropertyListMap::iterator it = m_propertyToFlags.find(flagProperty); + QList<QtProperty *> &propertyList = it.value(); + propertyList.replace(propertyList.indexOf(property), 0); + m_flagToProperty.remove(property); + } else if (QtProperty *alignProperty = m_alignHToProperty.value(property, 0)) { + m_propertyToAlignH.remove(alignProperty); + m_alignHToProperty.remove(property); + } else if (QtProperty *alignProperty = m_alignVToProperty.value(property, 0)) { + m_propertyToAlignV.remove(alignProperty); + m_alignVToProperty.remove(property); + } else if (QtProperty *stringCommentProperty = m_commentToString.value(property, 0)) { + m_stringToComment.remove(stringCommentProperty); + m_commentToString.remove(property); + } else if (QtProperty *stringTranslatableProperty = m_translatableToString.value(property, 0)) { + m_stringToTranslatable.remove(stringTranslatableProperty); + m_translatableToString.remove(property); + } else if (QtProperty *stringDisambiguationProperty = m_disambiguationToString.value(property, 0)) { + m_stringToDisambiguation.remove(stringDisambiguationProperty); + m_disambiguationToString.remove(property); + } else if (QtProperty *keySequenceCommentProperty = m_commentToKeySequence.value(property, 0)) { + m_keySequenceToComment.remove(keySequenceCommentProperty); + m_commentToKeySequence.remove(property); + } else if (QtProperty *keySequenceTranslatableProperty = m_translatableToKeySequence.value(property, 0)) { + m_keySequenceToTranslatable.remove(keySequenceTranslatableProperty); + m_translatableToKeySequence.remove(property); + } else if (QtProperty *keySequenceDisambiguationProperty = m_disambiguationToKeySequence.value(property, 0)) { + m_keySequenceToDisambiguation.remove(keySequenceDisambiguationProperty); + m_disambiguationToKeySequence.remove(property); + } else if (QtProperty *iconProperty = m_iconSubPropertyToProperty.value(property, 0)) { + QMap<QtProperty *, QMap<QPair<QIcon::Mode, QIcon::State>, QtProperty *> >::iterator it = + m_propertyToIconSubProperties.find(iconProperty); + QPair<QIcon::Mode, QIcon::State> state = m_iconSubPropertyToState.value(property); + QMap<QPair<QIcon::Mode, QIcon::State>, QtProperty *> &propertyList = it.value(); + propertyList.remove(state); + m_iconSubPropertyToState.remove(property); + m_iconSubPropertyToProperty.remove(property); + } else { + m_fontManager.slotPropertyDestroyed(property); + m_brushManager.slotPropertyDestroyed(property); + } +} + +QStringList DesignerPropertyManager::attributes(int propertyType) const +{ + if (!isPropertyTypeSupported(propertyType)) + return QStringList(); + + QStringList list = QtVariantPropertyManager::attributes(propertyType); + if (propertyType == designerFlagTypeId()) { + list.append(QLatin1String(flagsAttributeC)); + } else if (propertyType == designerPixmapTypeId()) { + list.append(QLatin1String(defaultResourceAttributeC)); + } else if (propertyType == designerIconTypeId()) { + list.append(QLatin1String(defaultResourceAttributeC)); + } else if (propertyType == designerStringTypeId() || propertyType == QVariant::String) { + list.append(QLatin1String(validationModesAttributeC)); + list.append(QLatin1String(fontAttributeC)); + } else if (propertyType == QVariant::Palette) { + list.append(QLatin1String(superPaletteAttributeC)); + } + list.append(QLatin1String(resettableAttributeC)); + return list; +} + +int DesignerPropertyManager::attributeType(int propertyType, const QString &attribute) const +{ + if (!isPropertyTypeSupported(propertyType)) + return 0; + + if (propertyType == designerFlagTypeId() && attribute == QLatin1String(flagsAttributeC)) + return designerFlagListTypeId(); + if (propertyType == designerPixmapTypeId() && attribute == QLatin1String(defaultResourceAttributeC)) + return QVariant::Pixmap; + if (propertyType == designerIconTypeId() && attribute == QLatin1String(defaultResourceAttributeC)) + return QVariant::Icon; + if (attribute == QLatin1String(resettableAttributeC)) + return QVariant::Bool; + if (propertyType == designerStringTypeId() || propertyType == QVariant::String) { + if (attribute == QLatin1String(validationModesAttributeC)) + return QVariant::Int; + if (attribute == QLatin1String(fontAttributeC)) + return QVariant::Font; + } + if (propertyType == QVariant::Palette && attribute == QLatin1String(superPaletteAttributeC)) + return QVariant::Palette; + + return QtVariantPropertyManager::attributeType(propertyType, attribute); +} + +QVariant DesignerPropertyManager::attributeValue(const QtProperty *property, const QString &attribute) const +{ + QtProperty *prop = const_cast<QtProperty *>(property); + + if (attribute == QLatin1String(resettableAttributeC)) { + const PropertyBoolMap::const_iterator it = m_resetMap.constFind(prop); + if (it != m_resetMap.constEnd()) + return it.value(); + } + + if (attribute == QLatin1String(flagsAttributeC)) { + PropertyFlagDataMap::const_iterator it = m_flagValues.constFind(prop); + if (it != m_flagValues.constEnd()) { + QVariant v; + qVariantSetValue(v, it.value().flags); + return v; + } + } + if (attribute == QLatin1String(validationModesAttributeC)) { + const PropertyIntMap::const_iterator it = m_stringAttributes.constFind(prop); + if (it != m_stringAttributes.constEnd()) + return it.value(); + } + + if (attribute == QLatin1String(fontAttributeC)) { + const PropertyFontMap::const_iterator it = m_stringFontAttributes.constFind(prop); + if (it != m_stringFontAttributes.constEnd()) + return it.value(); + } + + if (attribute == QLatin1String(superPaletteAttributeC)) { + PropertyPaletteDataMap::const_iterator it = m_paletteValues.constFind(prop); + if (it != m_paletteValues.constEnd()) + return it.value().superPalette; + } + + if (attribute == QLatin1String(defaultResourceAttributeC)) { + QMap<QtProperty *, QPixmap>::const_iterator itPix = m_defaultPixmaps.constFind(prop); + if (itPix != m_defaultPixmaps.constEnd()) + return itPix.value(); + + QMap<QtProperty *, QIcon>::const_iterator itIcon = m_defaultIcons.constFind(prop); + if (itIcon != m_defaultIcons.constEnd()) + return itIcon.value(); + } + + return QtVariantPropertyManager::attributeValue(property, attribute); +} + +void DesignerPropertyManager::setAttribute(QtProperty *property, + const QString &attribute, const QVariant &value) +{ + if (attribute == QLatin1String(resettableAttributeC) && m_resetMap.contains(property)) { + if (value.userType() != QVariant::Bool) + return; + const bool val = value.toBool(); + const PropertyBoolMap::iterator it = m_resetMap.find(property); + if (it.value() == val) + return; + it.value() = val; + emit attributeChanged(variantProperty(property), attribute, value); + return; + } else if (attribute == QLatin1String(flagsAttributeC) && m_flagValues.contains(property)) { + if (value.userType() != designerFlagListTypeId()) + return; + + const DesignerFlagList flags = qVariantValue<DesignerFlagList>(value); + PropertyFlagDataMap::iterator fit = m_flagValues.find(property); + FlagData data = fit.value(); + if (data.flags == flags) + return; + + PropertyToPropertyListMap::iterator pfit = m_propertyToFlags.find(property); + QListIterator<QtProperty *> itProp(pfit.value()); + while (itProp.hasNext()) { + if (QtProperty *prop = itProp.next()) { + delete prop; + m_flagToProperty.remove(prop); + } + } + pfit.value().clear(); + + QList<uint> values; + + QListIterator<QPair<QString, uint> > itFlag(flags); + while (itFlag.hasNext()) { + const QPair<QString, uint> pair = itFlag.next(); + const QString flagName = pair.first; + QtProperty *prop = addProperty(QVariant::Bool); + prop->setPropertyName(flagName); + property->addSubProperty(prop); + m_propertyToFlags[property].append(prop); + m_flagToProperty[prop] = property; + values.append(pair.second); + } + + data.val = 0; + data.flags = flags; + data.values = values; + + fit.value() = data; + + QVariant v; + qVariantSetValue(v, flags); + emit attributeChanged(property, attribute, v); + + emit propertyChanged(property); + emit QtVariantPropertyManager::valueChanged(property, data.val); + } else if (attribute == QLatin1String(validationModesAttributeC) && m_stringAttributes.contains(property)) { + if (value.userType() != QVariant::Int) + return; + + const PropertyIntMap::iterator it = m_stringAttributes.find(property); + const int oldValue = it.value(); + + const int newValue = value.toInt(); + + if (oldValue == newValue) + return; + + it.value() = newValue; + + emit attributeChanged(property, attribute, newValue); + } else if (attribute == QLatin1String(fontAttributeC) && m_stringFontAttributes.contains(property)) { + if (value.userType() != QVariant::Font) + return; + + const PropertyFontMap::iterator it = m_stringFontAttributes.find(property); + const QFont oldValue = it.value(); + + const QFont newValue = qvariant_cast<QFont>(value); + + if (oldValue == newValue) + return; + + it.value() = newValue; + + emit attributeChanged(property, attribute, newValue); + } else if (attribute == QLatin1String(superPaletteAttributeC) && m_paletteValues.contains(property)) { + if (value.userType() != QVariant::Palette) + return; + + QPalette superPalette = qVariantValue<QPalette>(value); + + const PropertyPaletteDataMap::iterator it = m_paletteValues.find(property); + PaletteData data = it.value(); + if (data.superPalette == superPalette) + return; + + data.superPalette = superPalette; + // resolve here + const uint mask = data.val.resolve(); + data.val = data.val.resolve(superPalette); + data.val.resolve(mask); + + it.value() = data; + + QVariant v; + qVariantSetValue(v, superPalette); + emit attributeChanged(property, attribute, v); + + emit propertyChanged(property); + emit QtVariantPropertyManager::valueChanged(property, data.val); // if resolve was done, this is also for consistency + } else if (attribute == QLatin1String(defaultResourceAttributeC) && m_defaultPixmaps.contains(property)) { + if (value.userType() != QVariant::Pixmap) + return; + + QPixmap defaultPixmap = qVariantValue<QPixmap>(value); + + const QMap<QtProperty *, QPixmap>::iterator it = m_defaultPixmaps.find(property); + QPixmap oldDefaultPixmap = it.value(); + if (defaultPixmap.cacheKey() == oldDefaultPixmap.cacheKey()) + return; + + it.value() = defaultPixmap; + + QVariant v = qVariantFromValue(defaultPixmap); + emit attributeChanged(property, attribute, v); + + emit propertyChanged(property); + } else if (attribute == QLatin1String(defaultResourceAttributeC) && m_defaultIcons.contains(property)) { + if (value.userType() != QVariant::Icon) + return; + + QIcon defaultIcon = qVariantValue<QIcon>(value); + + const QMap<QtProperty *, QIcon>::iterator it = m_defaultIcons.find(property); + QIcon oldDefaultIcon = it.value(); + if (defaultIcon.cacheKey() == oldDefaultIcon.cacheKey()) + return; + + it.value() = defaultIcon; + + qdesigner_internal::PropertySheetIconValue icon = m_iconValues.value(property); + if (icon.paths().isEmpty()) { + QMap<QPair<QIcon::Mode, QIcon::State>, QtProperty *> subIconProperties = m_propertyToIconSubProperties.value(property); + QMapIterator<QPair<QIcon::Mode, QIcon::State>, QtProperty *> itSub(subIconProperties); + while (itSub.hasNext()) { + QPair<QIcon::Mode, QIcon::State> pair = itSub.next().key(); + QtProperty *subProp = itSub.value(); + setAttribute(subProp, QLatin1String(defaultResourceAttributeC), + defaultIcon.pixmap(16, 16, pair.first, pair.second)); + } + } + + QVariant v = qVariantFromValue(defaultIcon); + emit attributeChanged(property, attribute, v); + + emit propertyChanged(property); + } + QtVariantPropertyManager::setAttribute(property, attribute, value); +} + +int DesignerPropertyManager::designerFlagTypeId() +{ + static const int rc = qMetaTypeId<DesignerFlagPropertyType>(); + return rc; +} + +int DesignerPropertyManager::designerFlagListTypeId() +{ + static const int rc = qMetaTypeId<DesignerFlagList>(); + return rc; +} + +int DesignerPropertyManager::designerAlignmentTypeId() +{ + static const int rc = qMetaTypeId<DesignerAlignmentPropertyType>(); + return rc; +} + +int DesignerPropertyManager::designerPixmapTypeId() +{ + return qMetaTypeId<PropertySheetPixmapValue>(); +} + +int DesignerPropertyManager::designerIconTypeId() +{ + return qMetaTypeId<PropertySheetIconValue>(); +} + +int DesignerPropertyManager::designerStringTypeId() +{ + return qMetaTypeId<PropertySheetStringValue>(); +} + +int DesignerPropertyManager::designerKeySequenceTypeId() +{ + return qMetaTypeId<PropertySheetKeySequenceValue>(); +} + +bool DesignerPropertyManager::isPropertyTypeSupported(int propertyType) const +{ + switch (propertyType) { + case QVariant::Palette: + case QVariant::UInt: + case QVariant::LongLong: + case QVariant::ULongLong: + case QVariant::Url: + case QVariant::ByteArray: + case QVariant::StringList: + case QVariant::Brush: + return true; + default: + break; + } + + if (propertyType == designerFlagTypeId()) + return true; + if (propertyType == designerAlignmentTypeId()) + return true; + if (propertyType == designerPixmapTypeId()) + return true; + if (propertyType == designerIconTypeId()) + return true; + if (propertyType == designerStringTypeId()) + return true; + if (propertyType == designerKeySequenceTypeId()) + return true; + return QtVariantPropertyManager::isPropertyTypeSupported(propertyType); +} + +QString DesignerPropertyManager::valueText(const QtProperty *property) const +{ + if (m_flagValues.contains(const_cast<QtProperty *>(property))) { + const FlagData data = m_flagValues.value(const_cast<QtProperty *>(property)); + const uint v = data.val; + const QChar bar = QLatin1Char('|'); + QString valueStr; + const QList<QPair<QString, uint> > flags = data.flags; + const QList<QPair<QString, uint> >::const_iterator fcend = flags.constEnd(); + for (QList<QPair<QString, uint> >::const_iterator it = flags.constBegin(); it != fcend; ++it) { + const uint val = it->second; + const bool checked = (val == 0) ? (v == 0) : ((val & v) == val); + if (checked) { + if (!valueStr.isEmpty()) + valueStr += bar; + valueStr += it->first; + } + } + return valueStr; + } + if (m_alignValues.contains(const_cast<QtProperty *>(property))) { + const uint v = m_alignValues.value(const_cast<QtProperty *>(property)); + return tr("%1, %2").arg(indexHToString(alignToIndexH(v))).arg(indexVToString(alignToIndexV(v))); + } + if (m_paletteValues.contains(const_cast<QtProperty *>(property))) { + const PaletteData data = m_paletteValues.value(const_cast<QtProperty *>(property)); + const uint mask = data.val.resolve(); + if (mask) + return tr("Customized (%n roles)", 0, bitCount(mask)); + static const QString inherited = tr("Inherited"); + return inherited; + } + if (m_iconValues.contains(const_cast<QtProperty *>(property))) { + const PropertySheetIconValue::ModeStateToPixmapMap paths = m_iconValues.value(const_cast<QtProperty *>(property)).paths(); + const PropertySheetIconValue::ModeStateToPixmapMap::const_iterator it = paths.constFind(qMakePair(QIcon::Normal, QIcon::Off)); + if (it == paths.constEnd()) + return QString(); + return QFileInfo(it.value().path()).fileName(); + } + if (m_pixmapValues.contains(const_cast<QtProperty *>(property))) { + const QString path = m_pixmapValues.value(const_cast<QtProperty *>(property)).path(); + if (path.isEmpty()) + return QString(); + return QFileInfo(path).fileName(); + } + if (m_uintValues.contains(const_cast<QtProperty *>(property))) { + return QString::number(m_uintValues.value(const_cast<QtProperty *>(property))); + } + if (m_longLongValues.contains(const_cast<QtProperty *>(property))) { + return QString::number(m_longLongValues.value(const_cast<QtProperty *>(property))); + } + if (m_uLongLongValues.contains(const_cast<QtProperty *>(property))) { + return QString::number(m_uLongLongValues.value(const_cast<QtProperty *>(property))); + } + if (m_urlValues.contains(const_cast<QtProperty *>(property))) { + return m_urlValues.value(const_cast<QtProperty *>(property)).toString(); + } + if (m_byteArrayValues.contains(const_cast<QtProperty *>(property))) { + return QString::fromUtf8(m_byteArrayValues.value(const_cast<QtProperty *>(property))); + } + if (m_stringListValues.contains(const_cast<QtProperty *>(property))) { + return m_stringListValues.value(const_cast<QtProperty *>(property)).join(QLatin1String("; ")); + } + if (QtVariantPropertyManager::valueType(property) == QVariant::String || QtVariantPropertyManager::valueType(property) == designerStringTypeId()) { + const QString str = (QtVariantPropertyManager::valueType(property) == QVariant::String) ? value(property).toString() : qVariantValue<PropertySheetStringValue>(value(property)).value(); + const int validationMode = attributeValue(property, QLatin1String(validationModesAttributeC)).toInt(); + return TextPropertyEditor::stringToEditorString(str, static_cast<TextPropertyValidationMode>(validationMode)); + } + if (QtVariantPropertyManager::valueType(property) == designerKeySequenceTypeId()) { + return qVariantValue<PropertySheetKeySequenceValue>(value(property)).value(); + } + if (QtVariantPropertyManager::valueType(property) == QVariant::Bool) { + return QString(); + } + + QString rc; + if (m_brushManager.valueText(property, &rc)) + return rc; + return QtVariantPropertyManager::valueText(property); +} + +void DesignerPropertyManager::reloadResourceProperties() +{ + DesignerIconCache *iconCache = 0; + QMapIterator<QtProperty *, qdesigner_internal::PropertySheetIconValue> itIcon(m_iconValues); + while (itIcon.hasNext()) { + QtProperty *property = itIcon.next().key(); + PropertySheetIconValue icon = itIcon.value(); + + QIcon defaultIcon = m_defaultIcons.value(property); + if (!icon.paths().isEmpty()) { + if (!iconCache) { + QDesignerFormWindowInterface *formWindow = QDesignerFormWindowInterface::findFormWindow(m_object); + qdesigner_internal::FormWindowBase *fwb = qobject_cast<qdesigner_internal::FormWindowBase *>(formWindow); + iconCache = fwb->iconCache(); + } + if (iconCache) + defaultIcon = iconCache->icon(icon); + } + + QMap<QPair<QIcon::Mode, QIcon::State>, PropertySheetPixmapValue> iconPaths = icon.paths(); + + QMap<QPair<QIcon::Mode, QIcon::State>, QtProperty *> subProperties = m_propertyToIconSubProperties.value(property); + QMapIterator<QPair<QIcon::Mode, QIcon::State>, QtProperty *> itSub(subProperties); + while (itSub.hasNext()) { + const QPair<QIcon::Mode, QIcon::State> pair = itSub.next().key(); + QtVariantProperty *subProperty = variantProperty(itSub.value()); + subProperty->setAttribute(QLatin1String(defaultResourceAttributeC), + defaultIcon.pixmap(16, 16, pair.first, pair.second)); + } + + emit propertyChanged(property); + emit QtVariantPropertyManager::valueChanged(property, qVariantFromValue(itIcon.value())); + } + QMapIterator<QtProperty *, qdesigner_internal::PropertySheetPixmapValue> itPix(m_pixmapValues); + while (itPix.hasNext()) { + QtProperty *property = itPix.next().key(); + emit propertyChanged(property); + emit QtVariantPropertyManager::valueChanged(property, qVariantFromValue(itPix.value())); + } +} + +QIcon DesignerPropertyManager::valueIcon(const QtProperty *property) const +{ + if (m_iconValues.contains(const_cast<QtProperty *>(property))) { + if (!property->isModified()) + return m_defaultIcons.value(const_cast<QtProperty *>(property)).pixmap(16, 16); + QDesignerFormWindowInterface *formWindow = QDesignerFormWindowInterface::findFormWindow(m_object); + qdesigner_internal::FormWindowBase *fwb = qobject_cast<qdesigner_internal::FormWindowBase *>(formWindow); + if (fwb) + return fwb->iconCache()->icon(m_iconValues.value(const_cast<QtProperty *>(property))).pixmap(16, 16); + } else if (m_pixmapValues.contains(const_cast<QtProperty *>(property))) { + if (!property->isModified()) + return m_defaultPixmaps.value(const_cast<QtProperty *>(property)); + QDesignerFormWindowInterface *formWindow = QDesignerFormWindowInterface::findFormWindow(m_object); + qdesigner_internal::FormWindowBase *fwb = qobject_cast<qdesigner_internal::FormWindowBase *>(formWindow); + if (fwb) + return fwb->pixmapCache()->pixmap(m_pixmapValues.value(const_cast<QtProperty *>(property))); + } else { + QIcon rc; + if (m_brushManager.valueIcon(property, &rc)) + return rc; + } + + return QtVariantPropertyManager::valueIcon(property); +} + +QVariant DesignerPropertyManager::value(const QtProperty *property) const +{ + if (m_flagValues.contains(const_cast<QtProperty *>(property))) + return m_flagValues.value(const_cast<QtProperty *>(property)).val; + if (m_alignValues.contains(const_cast<QtProperty *>(property))) + return m_alignValues.value(const_cast<QtProperty *>(property)); + if (m_paletteValues.contains(const_cast<QtProperty *>(property))) + return m_paletteValues.value(const_cast<QtProperty *>(property)).val; + if (m_iconValues.contains(const_cast<QtProperty *>(property))) + return qVariantFromValue(m_iconValues.value(const_cast<QtProperty *>(property))); + if (m_pixmapValues.contains(const_cast<QtProperty *>(property))) + return qVariantFromValue(m_pixmapValues.value(const_cast<QtProperty *>(property))); + if (m_stringValues.contains(const_cast<QtProperty *>(property))) + return qVariantFromValue(m_stringValues.value(const_cast<QtProperty *>(property))); + if (m_keySequenceValues.contains(const_cast<QtProperty *>(property))) + return qVariantFromValue(m_keySequenceValues.value(const_cast<QtProperty *>(property))); + if (m_uintValues.contains(const_cast<QtProperty *>(property))) + return m_uintValues.value(const_cast<QtProperty *>(property)); + if (m_longLongValues.contains(const_cast<QtProperty *>(property))) + return m_longLongValues.value(const_cast<QtProperty *>(property)); + if (m_uLongLongValues.contains(const_cast<QtProperty *>(property))) + return m_uLongLongValues.value(const_cast<QtProperty *>(property)); + if (m_urlValues.contains(const_cast<QtProperty *>(property))) + return m_urlValues.value(const_cast<QtProperty *>(property)); + if (m_byteArrayValues.contains(const_cast<QtProperty *>(property))) + return m_byteArrayValues.value(const_cast<QtProperty *>(property)); + if (m_stringListValues.contains(const_cast<QtProperty *>(property))) + return m_stringListValues.value(const_cast<QtProperty *>(property)); + + QVariant rc; + if (m_brushManager.value(property, &rc)) + return rc; + return QtVariantPropertyManager::value(property); +} + +int DesignerPropertyManager::valueType(int propertyType) const +{ + switch (propertyType) { + case QVariant::Palette: + case QVariant::UInt: + case QVariant::LongLong: + case QVariant::ULongLong: + case QVariant::Url: + case QVariant::ByteArray: + case QVariant::StringList: + case QVariant::Brush: + return propertyType; + default: + break; + } + if (propertyType == designerFlagTypeId()) + return QVariant::UInt; + if (propertyType == designerAlignmentTypeId()) + return QVariant::UInt; + if (propertyType == designerPixmapTypeId()) + return propertyType; + if (propertyType == designerIconTypeId()) + return propertyType; + if (propertyType == designerStringTypeId()) + return propertyType; + if (propertyType == designerKeySequenceTypeId()) + return propertyType; + return QtVariantPropertyManager::valueType(propertyType); +} + +void DesignerPropertyManager::setValue(QtProperty *property, const QVariant &value) +{ + const PropertyFlagDataMap::iterator fit = m_flagValues.find(property); + + if (fit != m_flagValues.end()) { + if (value.type() != QVariant::UInt && !value.canConvert(QVariant::UInt)) + return; + + const uint v = value.toUInt(); + + FlagData data = fit.value(); + if (data.val == v) + return; + + // set Value + + const QList<uint> values = data.values; + const QList<QtProperty *> subFlags = m_propertyToFlags.value(property); + const int subFlagCount = subFlags.count(); + for (int i = 0; i < subFlagCount; ++i) { + QtVariantProperty *subFlag = variantProperty(subFlags.at(i)); + const uint val = values.at(i); + const bool checked = (val == 0) ? (v == 0) : ((val & v) == val); + subFlag->setValue(checked); + } + + for (int i = 0; i < subFlagCount; ++i) { + QtVariantProperty *subFlag = variantProperty(subFlags.at(i)); + const uint val = values.at(i); + const bool checked = (val == 0) ? (v == 0) : ((val & v) == val); + bool enabled = true; + if (val == 0) { + if (checked) + enabled = false; + } else if (bitCount(val) > 1) { + // Disabled if all flags contained in the mask are checked + uint currentMask = 0; + for (int j = 0; j < subFlagCount; ++j) { + QtVariantProperty *subFlag = variantProperty(subFlags.at(j)); + if (bitCount(values.at(j)) == 1) + currentMask |= subFlag->value().toBool() ? values.at(j) : 0; + } + if ((currentMask & values.at(i)) == values.at(i)) + enabled = false; + } + subFlag->setEnabled(enabled); + } + + data.val = v; + fit.value() = data; + + emit QtVariantPropertyManager::valueChanged(property, data.val); + emit propertyChanged(property); + + return; + } else if (m_alignValues.contains(property)) { + if (value.type() != QVariant::UInt && !value.canConvert(QVariant::UInt)) + return; + + const uint v = value.toUInt(); + + uint val = m_alignValues.value(property); + + if (val == v) + return; + + QtVariantProperty *alignH = variantProperty(m_propertyToAlignH.value(property)); + QtVariantProperty *alignV = variantProperty(m_propertyToAlignV.value(property)); + + if (alignH) + alignH->setValue(alignToIndexH(v)); + if (alignV) + alignV->setValue(alignToIndexV(v)); + + m_alignValues[property] = v; + + emit QtVariantPropertyManager::valueChanged(property, v); + emit propertyChanged(property); + + return; + } else if (m_stringValues.contains(property)) { + if (value.userType() != designerStringTypeId()) + return; + + const PropertySheetStringValue v = qVariantValue<PropertySheetStringValue>(value); + + const PropertySheetStringValue val = m_stringValues.value(property); + + if (val == v) + return; + + QtVariantProperty *comment = variantProperty(m_stringToComment.value(property)); + QtVariantProperty *translatable = variantProperty(m_stringToTranslatable.value(property)); + QtVariantProperty *disambiguation = variantProperty(m_stringToDisambiguation.value(property)); + + if (comment) + comment->setValue(v.comment()); + if (translatable) + translatable->setValue(v.translatable()); + if (disambiguation) + disambiguation->setValue(v.disambiguation()); + + m_stringValues[property] = v; + + emit QtVariantPropertyManager::valueChanged(property, qVariantFromValue(v)); + emit propertyChanged(property); + + return; + } else if (m_keySequenceValues.contains(property)) { + if (value.userType() != designerKeySequenceTypeId()) + return; + + const PropertySheetKeySequenceValue v = qVariantValue<PropertySheetKeySequenceValue>(value); + + const PropertySheetKeySequenceValue val = m_keySequenceValues.value(property); + + if (val == v) + return; + + QtVariantProperty *comment = variantProperty(m_keySequenceToComment.value(property)); + QtVariantProperty *translatable = variantProperty(m_keySequenceToTranslatable.value(property)); + QtVariantProperty *disambiguation = variantProperty(m_keySequenceToDisambiguation.value(property)); + + if (comment) + comment->setValue(v.comment()); + if (translatable) + translatable->setValue(v.translatable()); + if (disambiguation) + disambiguation->setValue(v.disambiguation()); + + m_keySequenceValues[property] = v; + + emit QtVariantPropertyManager::valueChanged(property, qVariantFromValue(v)); + emit propertyChanged(property); + + return; + } else if (m_paletteValues.contains(property)) { + if (value.type() != QVariant::Palette && !value.canConvert(QVariant::Palette)) + return; + + QPalette p = qVariantValue<QPalette>(value); + + PaletteData data = m_paletteValues.value(property); + + const uint mask = p.resolve(); + p = p.resolve(data.superPalette); + p.resolve(mask); + + if (data.val == p && data.val.resolve() == p.resolve()) + return; + + data.val = p; + m_paletteValues[property] = data; + + emit QtVariantPropertyManager::valueChanged(property, data.val); + emit propertyChanged(property); + + return; + } else if (m_iconValues.contains(property)) { + if (value.userType() != designerIconTypeId()) + return; + + const PropertySheetIconValue icon = qVariantValue<PropertySheetIconValue>(value); + + const PropertySheetIconValue oldIcon = m_iconValues.value(property); + if (icon == oldIcon) + return; + + m_iconValues[property] = icon; + + QIcon defaultIcon = m_defaultIcons.value(property); + if (!icon.paths().isEmpty()) { + QDesignerFormWindowInterface *formWindow = QDesignerFormWindowInterface::findFormWindow(m_object); + qdesigner_internal::FormWindowBase *fwb = qobject_cast<qdesigner_internal::FormWindowBase *>(formWindow); + if (fwb) + defaultIcon = fwb->iconCache()->icon(icon); + } + + QMap<QPair<QIcon::Mode, QIcon::State>, PropertySheetPixmapValue> iconPaths = icon.paths(); + + QMap<QPair<QIcon::Mode, QIcon::State>, QtProperty *> subProperties = m_propertyToIconSubProperties.value(property); + QMapIterator<QPair<QIcon::Mode, QIcon::State>, QtProperty *> itSub(subProperties); + while (itSub.hasNext()) { + const QPair<QIcon::Mode, QIcon::State> pair = itSub.next().key(); + QtVariantProperty *subProperty = variantProperty(itSub.value()); + bool hasPath = iconPaths.contains(pair); + subProperty->setModified(hasPath); + subProperty->setValue(qVariantFromValue(iconPaths.value(pair))); + subProperty->setAttribute(QLatin1String(defaultResourceAttributeC), + defaultIcon.pixmap(16, 16, pair.first, pair.second)); + } + + emit QtVariantPropertyManager::valueChanged(property, qVariantFromValue(icon)); + emit propertyChanged(property); + + QString toolTip; + const QMap<QPair<QIcon::Mode, QIcon::State>, PropertySheetPixmapValue>::ConstIterator itNormalOff = + iconPaths.constFind(qMakePair(QIcon::Normal, QIcon::Off)); + if (itNormalOff != iconPaths.constEnd()) + toolTip = itNormalOff.value().path(); + property->setToolTip(toolTip); + + return; + } else if (m_pixmapValues.contains(property)) { + if (value.userType() != designerPixmapTypeId()) + return; + + const PropertySheetPixmapValue pixmap = qVariantValue<PropertySheetPixmapValue>(value); + + const PropertySheetPixmapValue oldPixmap = m_pixmapValues.value(property); + if (pixmap == oldPixmap) + return; + + m_pixmapValues[property] = pixmap; + + emit QtVariantPropertyManager::valueChanged(property, qVariantFromValue(pixmap)); + emit propertyChanged(property); + + property->setToolTip(pixmap.path()); + + return; + } else if (m_uintValues.contains(property)) { + if (value.type() != QVariant::UInt && !value.canConvert(QVariant::UInt)) + return; + + const uint v = value.toUInt(0); + + const uint oldValue = m_uintValues.value(property); + if (v == oldValue) + return; + + m_uintValues[property] = v; + + emit QtVariantPropertyManager::valueChanged(property, v); + emit propertyChanged(property); + + return; + } else if (m_longLongValues.contains(property)) { + if (value.type() != QVariant::LongLong && !value.canConvert(QVariant::LongLong)) + return; + + const qlonglong v = value.toLongLong(0); + + const qlonglong oldValue = m_longLongValues.value(property); + if (v == oldValue) + return; + + m_longLongValues[property] = v; + + emit QtVariantPropertyManager::valueChanged(property, v); + emit propertyChanged(property); + + return; + } else if (m_uLongLongValues.contains(property)) { + if (value.type() != QVariant::ULongLong && !value.canConvert(QVariant::ULongLong)) + return; + + qulonglong v = value.toULongLong(0); + + qulonglong oldValue = m_uLongLongValues.value(property); + if (v == oldValue) + return; + + m_uLongLongValues[property] = v; + + emit QtVariantPropertyManager::valueChanged(property, v); + emit propertyChanged(property); + + return; + } else if (m_urlValues.contains(property)) { + if (value.type() != QVariant::Url && !value.canConvert(QVariant::Url)) + return; + + const QUrl v = value.toUrl(); + + const QUrl oldValue = m_urlValues.value(property); + if (v == oldValue) + return; + + m_urlValues[property] = v; + + emit QtVariantPropertyManager::valueChanged(property, v); + emit propertyChanged(property); + + return; + } else if (m_byteArrayValues.contains(property)) { + if (value.type() != QVariant::ByteArray && !value.canConvert(QVariant::ByteArray)) + return; + + const QByteArray v = value.toByteArray(); + + const QByteArray oldValue = m_byteArrayValues.value(property); + if (v == oldValue) + return; + + m_byteArrayValues[property] = v; + + emit QtVariantPropertyManager::valueChanged(property, v); + emit propertyChanged(property); + + return; + } else if (m_stringListValues.contains(property)) { + if (value.type() != QVariant::StringList && !value.canConvert(QVariant::StringList)) + return; + + const QStringList v = value.toStringList(); + + const QStringList oldValue = m_stringListValues.value(property); + if (v == oldValue) + return; + + m_stringListValues[property] = v; + + emit QtVariantPropertyManager::valueChanged(property, v); + emit propertyChanged(property); + + return; + } + switch (m_brushManager.setValue(this, property, value)) { + case BrushPropertyManager::Unchanged: + return; + case BrushPropertyManager::Changed: + emit QtVariantPropertyManager::valueChanged(property, value); + emit propertyChanged(property); + return; + default: + break; + } + m_fontManager.setValue(this, property, value); + QtVariantPropertyManager::setValue(property, value); + if (QtVariantPropertyManager::valueType(property) == QVariant::String) + property->setToolTip(DesignerPropertyManager::value(property).toString()); + else if (QtVariantPropertyManager::valueType(property) == designerStringTypeId()) + property->setToolTip(qVariantValue<PropertySheetStringValue>(DesignerPropertyManager::value(property)).value()); + else if (QtVariantPropertyManager::valueType(property) == designerKeySequenceTypeId()) + property->setToolTip(qVariantValue<PropertySheetKeySequenceValue>(DesignerPropertyManager::value(property)).value()); + else if (QtVariantPropertyManager::valueType(property) == QVariant::Bool) + property->setToolTip(QtVariantPropertyManager::valueText(property)); +} + +void DesignerPropertyManager::initializeProperty(QtProperty *property) +{ + m_resetMap[property] = false; + + const int type = propertyType(property); + m_fontManager.preInitializeProperty(property, type, m_resetMap); + switch (type) { + case QVariant::Palette: + m_paletteValues[property] = PaletteData(); + break; + case QVariant::String: + m_stringAttributes[property] = ValidationSingleLine; + m_stringFontAttributes[property] = QApplication::font(); + break; + case QVariant::UInt: + m_uintValues[property] = 0; + break; + case QVariant::LongLong: + m_longLongValues[property] = 0; + break; + case QVariant::ULongLong: + m_uLongLongValues[property] = 0; + break; + case QVariant::Url: + m_urlValues[property] = QUrl(); + break; + case QVariant::ByteArray: + m_byteArrayValues[property] = 0; + break; + case QVariant::StringList: + m_stringListValues[property] = QStringList(); + break; + case QVariant::Brush: + m_brushManager.initializeProperty(this, property, enumTypeId()); + break; + default: + if (type == designerFlagTypeId()) { + m_flagValues[property] = FlagData(); + m_propertyToFlags[property] = QList<QtProperty *>(); + } else if (type == designerAlignmentTypeId()) { + const uint align = Qt::AlignLeft | Qt::AlignVCenter; + m_alignValues[property] = align; + + QtVariantProperty *alignH = addProperty(enumTypeId(), tr("Horizontal")); + QStringList namesH; + namesH << indexHToString(0) << indexHToString(1) << indexHToString(2) << indexHToString(3); + alignH->setAttribute(QLatin1String("enumNames"), namesH); + alignH->setValue(alignToIndexH(align)); + m_propertyToAlignH[property] = alignH; + m_alignHToProperty[alignH] = property; + property->addSubProperty(alignH); + + QtVariantProperty *alignV = addProperty(enumTypeId(), tr("Vertical")); + QStringList namesV; + namesV << indexVToString(0) << indexVToString(1) << indexVToString(2); + alignV->setAttribute(QLatin1String("enumNames"), namesV); + alignV->setValue(alignToIndexV(align)); + m_propertyToAlignV[property] = alignV; + m_alignVToProperty[alignV] = property; + property->addSubProperty(alignV); + } else if (type == designerPixmapTypeId()) { + m_pixmapValues[property] = PropertySheetPixmapValue(); + m_defaultPixmaps[property] = QPixmap(); + } else if (type == designerIconTypeId()) { + m_iconValues[property] = PropertySheetIconValue(); + m_defaultIcons[property] = QIcon(); + + createIconSubProperty(property, QIcon::Normal, QIcon::Off, tr("Normal Off")); + createIconSubProperty(property, QIcon::Normal, QIcon::On, tr("Normal On")); + createIconSubProperty(property, QIcon::Disabled, QIcon::Off, tr("Disabled Off")); + createIconSubProperty(property, QIcon::Disabled, QIcon::On, tr("Disabled On")); + createIconSubProperty(property, QIcon::Active, QIcon::Off, tr("Active Off")); + createIconSubProperty(property, QIcon::Active, QIcon::On, tr("Active On")); + createIconSubProperty(property, QIcon::Selected, QIcon::Off, tr("Selected Off")); + createIconSubProperty(property, QIcon::Selected, QIcon::On, tr("Selected On")); + } else if (type == designerStringTypeId()) { + PropertySheetStringValue val; + m_stringValues[property] = val; + m_stringAttributes[property] = ValidationMultiLine; + m_stringFontAttributes[property] = QApplication::font(); + + QtVariantProperty *translatable = addProperty(QVariant::Bool, tr("translatable")); + translatable->setValue(val.translatable()); + m_stringToTranslatable[property] = translatable; + m_translatableToString[translatable] = property; + property->addSubProperty(translatable); + + QtVariantProperty *disambiguation = addProperty(QVariant::String, tr("disambiguation")); + disambiguation->setValue(val.disambiguation()); + m_stringToDisambiguation[property] = disambiguation; + m_disambiguationToString[disambiguation] = property; + property->addSubProperty(disambiguation); + + QtVariantProperty *comment = addProperty(QVariant::String, tr("comment")); + comment->setValue(val.comment()); + m_stringToComment[property] = comment; + m_commentToString[comment] = property; + property->addSubProperty(comment); + } else if (type == designerKeySequenceTypeId()) { + PropertySheetKeySequenceValue val; + m_keySequenceValues[property] = val; + + QtVariantProperty *translatable = addProperty(QVariant::Bool, tr("translatable")); + translatable->setValue(val.translatable()); + m_keySequenceToTranslatable[property] = translatable; + m_translatableToKeySequence[translatable] = property; + property->addSubProperty(translatable); + + QtVariantProperty *disambiguation = addProperty(QVariant::String, tr("disambiguation")); + disambiguation->setValue(val.disambiguation()); + m_keySequenceToDisambiguation[property] = disambiguation; + m_disambiguationToKeySequence[disambiguation] = property; + property->addSubProperty(disambiguation); + + QtVariantProperty *comment = addProperty(QVariant::String, tr("comment")); + comment->setValue(val.comment()); + m_keySequenceToComment[property] = comment; + m_commentToKeySequence[comment] = property; + property->addSubProperty(comment); + } + } + + QtVariantPropertyManager::initializeProperty(property); + m_fontManager.postInitializeProperty(this, property, type, DesignerPropertyManager::enumTypeId()); + if (type == QVariant::Double) + setAttribute(property, QLatin1String("decimals"), 6); +} + +void DesignerPropertyManager::createIconSubProperty(QtProperty *iconProperty, QIcon::Mode mode, QIcon::State state, const QString &subName) +{ + QPair<QIcon::Mode, QIcon::State> pair = qMakePair(mode, state); + QtVariantProperty *subProp = addProperty(DesignerPropertyManager::designerPixmapTypeId(), subName); + m_propertyToIconSubProperties[iconProperty][pair] = subProp; + m_iconSubPropertyToState[subProp] = pair; + m_iconSubPropertyToProperty[subProp] = iconProperty; + m_resetMap[subProp] = true; + iconProperty->addSubProperty(subProp); +} + +void DesignerPropertyManager::uninitializeProperty(QtProperty *property) +{ + m_resetMap.remove(property); + + QListIterator<QtProperty *> itProp(m_propertyToFlags[property]); + while (itProp.hasNext()) { + QtProperty *prop = itProp.next(); + if (prop) { + delete prop; + m_flagToProperty.remove(prop); + } + } + m_propertyToFlags.remove(property); + m_flagValues.remove(property); + + QtProperty *alignH = m_propertyToAlignH.value(property); + if (alignH) { + delete alignH; + m_alignHToProperty.remove(alignH); + } + QtProperty *alignV = m_propertyToAlignV.value(property); + if (alignV) { + delete alignV; + m_alignVToProperty.remove(alignV); + } + + QtProperty *stringComment = m_stringToComment.value(property); + if (stringComment) { + delete stringComment; + m_stringToComment.remove(stringComment); + } + + QtProperty *stringTranslatable = m_stringToTranslatable.value(property); + if (stringTranslatable) { + delete stringTranslatable; + m_stringToTranslatable.remove(stringTranslatable); + } + + QtProperty *stringDisambiguation = m_stringToDisambiguation.value(property); + if (stringDisambiguation) { + delete stringDisambiguation; + m_stringToDisambiguation.remove(stringDisambiguation); + } + + QtProperty *keySequenceComment = m_keySequenceToComment.value(property); + if (keySequenceComment) { + delete keySequenceComment; + m_keySequenceToComment.remove(keySequenceComment); + } + + QtProperty *keySequenceTranslatable = m_keySequenceToTranslatable.value(property); + if (keySequenceTranslatable) { + delete keySequenceTranslatable; + m_keySequenceToTranslatable.remove(keySequenceTranslatable); + } + + QtProperty *keySequenceDisambiguation = m_keySequenceToDisambiguation.value(property); + if (keySequenceDisambiguation) { + delete keySequenceDisambiguation; + m_keySequenceToDisambiguation.remove(keySequenceDisambiguation); + } + + m_propertyToAlignH.remove(property); + m_propertyToAlignV.remove(property); + + m_stringToComment.remove(property); + m_stringToTranslatable.remove(property); + m_stringToDisambiguation.remove(property); + m_stringValues.remove(property); + m_stringAttributes.remove(property); + m_stringFontAttributes.remove(property); + + m_keySequenceToComment.remove(property); + m_keySequenceToTranslatable.remove(property); + m_keySequenceToDisambiguation.remove(property); + m_keySequenceValues.remove(property); + + m_paletteValues.remove(property); + + m_iconValues.remove(property); + m_defaultIcons.remove(property); + + m_pixmapValues.remove(property); + m_defaultPixmaps.remove(property); + + QMap<QPair<QIcon::Mode, QIcon::State>, QtProperty *> iconSubProperties = m_propertyToIconSubProperties.value(property); + QMapIterator<QPair<QIcon::Mode, QIcon::State>, QtProperty *> itIcon(iconSubProperties); + while (itIcon.hasNext()) { + QtProperty *subIcon = itIcon.next().value(); + delete subIcon; + m_iconSubPropertyToState.remove(subIcon); + m_iconSubPropertyToProperty.remove(subIcon); + } + m_propertyToIconSubProperties.remove(property); + m_iconSubPropertyToState.remove(property); + m_iconSubPropertyToProperty.remove(property); + + m_uintValues.remove(property); + m_longLongValues.remove(property); + m_uLongLongValues.remove(property); + m_urlValues.remove(property); + m_byteArrayValues.remove(property); + m_stringListValues.remove(property); + + m_fontManager.uninitializeProperty(property); + m_brushManager.uninitializeProperty(property); + + QtVariantPropertyManager::uninitializeProperty(property); +} + + +bool DesignerPropertyManager::resetFontSubProperty(QtProperty *property) +{ + return m_fontManager.resetFontSubProperty(this, property); +} + +bool DesignerPropertyManager::resetIconSubProperty(QtProperty *property) +{ + if (!m_iconSubPropertyToProperty.contains(property)) + return false; + + if (!m_pixmapValues.contains(property)) + return false; + + QtVariantProperty *pixmapProperty = variantProperty(property); + pixmapProperty->setValue(qVariantFromValue(PropertySheetPixmapValue())); + return true; +} + +// -------- DesignerEditorFactory +DesignerEditorFactory::DesignerEditorFactory(QDesignerFormEditorInterface *core, QObject *parent) : + QtVariantEditorFactory(parent), + m_resetDecorator(new ResetDecorator(this)), + m_changingPropertyValue(false), + m_core(core), + m_spacing(-1) +{ + connect(m_resetDecorator, SIGNAL(resetProperty(QtProperty*)), this, SIGNAL(resetProperty(QtProperty*))); +} + +DesignerEditorFactory::~DesignerEditorFactory() +{ +} + +void DesignerEditorFactory::setSpacing(int spacing) +{ + m_spacing = spacing; + m_resetDecorator->setSpacing(spacing); +} + +void DesignerEditorFactory::setFormWindowBase(qdesigner_internal::FormWindowBase *fwb) +{ + m_fwb = fwb; + DesignerPixmapCache *cache = 0; + if (fwb) + cache = fwb->pixmapCache(); + QMapIterator<PixmapEditor *, QtProperty *> itPixmapEditor(m_editorToPixmapProperty); + while (itPixmapEditor.hasNext()) { + PixmapEditor *pe = itPixmapEditor.next().key(); + pe->setPixmapCache(cache); + } + QMapIterator<PixmapEditor *, QtProperty *> itIconEditor(m_editorToIconProperty); + while (itIconEditor.hasNext()) { + PixmapEditor *pe = itIconEditor.next().key(); + pe->setPixmapCache(cache); + } +} + +void DesignerEditorFactory::connectPropertyManager(QtVariantPropertyManager *manager) +{ + m_resetDecorator->connectPropertyManager(manager); + connect(manager, SIGNAL(attributeChanged(QtProperty*,QString,QVariant)), + this, SLOT(slotAttributeChanged(QtProperty*,QString,QVariant))); + connect(manager, SIGNAL(valueChanged(QtProperty*,QVariant)), + this, SLOT(slotValueChanged(QtProperty*,QVariant))); + connect(manager, SIGNAL(propertyChanged(QtProperty*)), + this, SLOT(slotPropertyChanged(QtProperty*))); + QtVariantEditorFactory::connectPropertyManager(manager); +} + +void DesignerEditorFactory::disconnectPropertyManager(QtVariantPropertyManager *manager) +{ + m_resetDecorator->disconnectPropertyManager(manager); + disconnect(manager, SIGNAL(attributeChanged(QtProperty*,QString,QVariant)), + this, SLOT(slotAttributeChanged(QtProperty*,QString,QVariant))); + disconnect(manager, SIGNAL(valueChanged(QtProperty*,QVariant)), + this, SLOT(slotValueChanged(QtProperty*,QVariant))); + disconnect(manager, SIGNAL(propertyChanged(QtProperty*)), + this, SLOT(slotPropertyChanged(QtProperty*))); + QtVariantEditorFactory::disconnectPropertyManager(manager); +} + +// A helper that calls a setter with a value on a pointer list of editor objects. +// Could use QList<Editor*> instead of EditorContainer/Editor, but that crashes VS 6. +template <class EditorContainer, class Editor, class SetterParameter, class Value> +static inline void applyToEditors(const EditorContainer &list, void (Editor::*setter)(SetterParameter), const Value &value) +{ + typedef Q_TYPENAME EditorContainer::const_iterator ListIterator; + if (list.empty()) { + return; + } + const ListIterator end = list.constEnd(); + for (ListIterator it = list.constBegin(); it != end; ++it) { + Editor &editor = *(*it); + (editor.*setter)(value); + } +} + +void DesignerEditorFactory::slotAttributeChanged(QtProperty *property, const QString &attribute, const QVariant &value) +{ + QtVariantPropertyManager *manager = propertyManager(property); + const int type = manager->propertyType(property); + if (type == DesignerPropertyManager::designerPixmapTypeId() && attribute == QLatin1String(defaultResourceAttributeC)) { + const QPixmap pixmap = qvariant_cast<QPixmap>(value); + applyToEditors(m_pixmapPropertyToEditors.value(property), &PixmapEditor::setDefaultPixmap, pixmap); + } else if (type == DesignerPropertyManager::designerStringTypeId() || type == QVariant::String) { + if (attribute == QLatin1String(validationModesAttributeC)) { + const TextPropertyValidationMode validationMode = static_cast<TextPropertyValidationMode>(value.toInt()); + applyToEditors(m_stringPropertyToEditors.value(property), &TextEditor::setTextPropertyValidationMode, validationMode); + } + if (attribute == QLatin1String(fontAttributeC)) { + const QFont font = qvariant_cast<QFont>(value); + applyToEditors(m_stringPropertyToEditors.value(property), &TextEditor::setRichTextDefaultFont, font); + } + } else if (type == QVariant::Palette && attribute == QLatin1String(superPaletteAttributeC)) { + const QPalette palette = qvariant_cast<QPalette>(value); + applyToEditors(m_palettePropertyToEditors.value(property), &PaletteEditorButton::setSuperPalette, palette); + } +} + +void DesignerEditorFactory::slotPropertyChanged(QtProperty *property) +{ + QtVariantPropertyManager *manager = propertyManager(property); + const int type = manager->propertyType(property); + if (type == DesignerPropertyManager::designerIconTypeId()) { + QPixmap defaultPixmap; + if (!property->isModified()) + defaultPixmap = qvariant_cast<QIcon>(manager->attributeValue(property, QLatin1String(defaultResourceAttributeC))).pixmap(16, 16); + else if (m_fwb) + defaultPixmap = m_fwb->iconCache()->icon(qVariantValue<PropertySheetIconValue>(manager->value(property))).pixmap(16, 16); + QList<PixmapEditor *> editors = m_iconPropertyToEditors.value(property); + QListIterator<PixmapEditor *> it(editors); + while (it.hasNext()) { + PixmapEditor *editor = it.next(); + editor->setDefaultPixmap(defaultPixmap); + } + } +} + +void DesignerEditorFactory::slotValueChanged(QtProperty *property, const QVariant &value) +{ + if (m_changingPropertyValue) + return; + + QtVariantPropertyManager *manager = propertyManager(property); + const int type = manager->propertyType(property); + switch (type) { + case QVariant::String: + applyToEditors(m_stringPropertyToEditors.value(property), &TextEditor::setText, value.toString()); + break; + case QVariant::Palette: + applyToEditors(m_palettePropertyToEditors.value(property), &PaletteEditorButton::setPalette, qvariant_cast<QPalette>(value)); + break; + case QVariant::UInt: + applyToEditors(m_uintPropertyToEditors.value(property), &QLineEdit::setText, QString::number(value.toUInt())); + break; + case QVariant::LongLong: + applyToEditors(m_longLongPropertyToEditors.value(property), &QLineEdit::setText, QString::number(value.toLongLong())); + break; + case QVariant::ULongLong: + applyToEditors(m_uLongLongPropertyToEditors.value(property), &QLineEdit::setText, QString::number(value.toULongLong())); + break; + case QVariant::Url: + applyToEditors(m_urlPropertyToEditors.value(property), &TextEditor::setText, value.toUrl().toString()); + break; + case QVariant::ByteArray: + applyToEditors(m_byteArrayPropertyToEditors.value(property), &TextEditor::setText, QString::fromUtf8(value.toByteArray())); + break; + case QVariant::StringList: + applyToEditors(m_stringListPropertyToEditors.value(property), &StringListEditorButton::setStringList, value.toStringList()); + break; + default: + if (type == DesignerPropertyManager::designerIconTypeId()) + applyToEditors(m_iconPropertyToEditors.value(property), &PixmapEditor::setPath, qVariantValue<PropertySheetIconValue>(value).pixmap(QIcon::Normal, QIcon::Off).path()); + else if (type == DesignerPropertyManager::designerPixmapTypeId()) + applyToEditors(m_pixmapPropertyToEditors.value(property), &PixmapEditor::setPath, qVariantValue<PropertySheetPixmapValue>(value).path()); + else if (type == DesignerPropertyManager::designerStringTypeId()) + applyToEditors(m_stringPropertyToEditors.value(property), &TextEditor::setText, qVariantValue<PropertySheetStringValue>(value).value()); + else if (type == DesignerPropertyManager::designerKeySequenceTypeId()) + applyToEditors(m_keySequencePropertyToEditors.value(property), &QtKeySequenceEdit::setKeySequence, qVariantValue<PropertySheetKeySequenceValue>(value).value()); + break; + } +} + +TextEditor *DesignerEditorFactory::createTextEditor(QWidget *parent, TextPropertyValidationMode vm, const QString &value) +{ + TextEditor *rc = new TextEditor(m_core, parent); + rc->setText(value); + rc->setSpacing(m_spacing); + rc->setTextPropertyValidationMode(vm); + connect(rc, SIGNAL(destroyed(QObject*)), this, SLOT(slotEditorDestroyed(QObject*))); + return rc; +} + +QWidget *DesignerEditorFactory::createEditor(QtVariantPropertyManager *manager, QtProperty *property, + QWidget *parent) +{ + QWidget *editor = 0; + const int type = manager->propertyType(property); + switch (type) { + case QVariant::Bool: { + editor = QtVariantEditorFactory::createEditor(manager, property, parent); + QtBoolEdit *boolEdit = qobject_cast<QtBoolEdit *>(editor); + if (boolEdit) + boolEdit->setTextVisible(false); + } + break; + case QVariant::String: { + const TextPropertyValidationMode tvm = static_cast<TextPropertyValidationMode>(manager->attributeValue(property, QLatin1String(validationModesAttributeC)).toInt()); + TextEditor *ed = createTextEditor(parent, tvm, manager->value(property).toString()); + const QVariant richTextDefaultFont = manager->attributeValue(property, QLatin1String(fontAttributeC)); + if (richTextDefaultFont.type() == QVariant::Font) + ed->setRichTextDefaultFont(qvariant_cast<QFont>(richTextDefaultFont)); + m_stringPropertyToEditors[property].append(ed); + m_editorToStringProperty[ed] = property; + connect(ed, SIGNAL(destroyed(QObject *)), this, SLOT(slotEditorDestroyed(QObject *))); + connect(ed, SIGNAL(textChanged(QString)), this, SLOT(slotStringTextChanged(QString))); + editor = ed; + } + break; + case QVariant::Palette: { + PaletteEditorButton *ed = new PaletteEditorButton(m_core, qvariant_cast<QPalette>(manager->value(property)), parent); + ed->setSuperPalette(qvariant_cast<QPalette>(manager->attributeValue(property, QLatin1String(superPaletteAttributeC)))); + m_palettePropertyToEditors[property].append(ed); + m_editorToPaletteProperty[ed] = property; + connect(ed, SIGNAL(destroyed(QObject*)), this, SLOT(slotEditorDestroyed(QObject*))); + connect(ed, SIGNAL(paletteChanged(QPalette)), this, SLOT(slotPaletteChanged(QPalette))); + editor = ed; + } + break; + case QVariant::UInt: { + QLineEdit *ed = new QLineEdit(parent); + ed->setValidator(new QULongLongValidator(0, UINT_MAX, ed)); + ed->setText(QString::number(manager->value(property).toUInt())); + m_uintPropertyToEditors[property].append(ed); + m_editorToUintProperty[ed] = property; + connect(ed, SIGNAL(destroyed(QObject*)), this, SLOT(slotEditorDestroyed(QObject*))); + connect(ed, SIGNAL(textChanged(QString)), this, SLOT(slotUintChanged(QString))); + editor = ed; + } + break; + case QVariant::LongLong: { + QLineEdit *ed = new QLineEdit(parent); + ed->setValidator(new QLongLongValidator(ed)); + ed->setText(QString::number(manager->value(property).toLongLong())); + m_longLongPropertyToEditors[property].append(ed); + m_editorToLongLongProperty[ed] = property; + connect(ed, SIGNAL(destroyed(QObject*)), this, SLOT(slotEditorDestroyed(QObject*))); + connect(ed, SIGNAL(textChanged(QString)), this, SLOT(slotLongLongChanged(QString))); + editor = ed; + } + break; + case QVariant::ULongLong: { + QLineEdit *ed = new QLineEdit(parent); + ed->setValidator(new QULongLongValidator(ed)); + ed->setText(QString::number(manager->value(property).toULongLong())); + m_uLongLongPropertyToEditors[property].append(ed); + m_editorToULongLongProperty[ed] = property; + connect(ed, SIGNAL(destroyed(QObject*)), this, SLOT(slotEditorDestroyed(QObject*))); + connect(ed, SIGNAL(textChanged(QString)), this, SLOT(slotULongLongChanged(QString))); + editor = ed; + } + break; + case QVariant::Url: { + TextEditor *ed = createTextEditor(parent, ValidationURL, manager->value(property).toUrl().toString()); + ed->setUpdateMode(TextPropertyEditor::UpdateOnFinished); + m_urlPropertyToEditors[property].append(ed); + m_editorToUrlProperty[ed] = property; + connect(ed, SIGNAL(destroyed(QObject*)), this, SLOT(slotEditorDestroyed(QObject*))); + connect(ed, SIGNAL(textChanged(QString)), this, SLOT(slotUrlChanged(QString))); + editor = ed; + } + break; + case QVariant::ByteArray: { + TextEditor *ed = createTextEditor(parent, ValidationMultiLine, QString::fromUtf8(manager->value(property).toByteArray())); + m_byteArrayPropertyToEditors[property].append(ed); + m_editorToByteArrayProperty[ed] = property; + connect(ed, SIGNAL(destroyed(QObject*)), this, SLOT(slotEditorDestroyed(QObject*))); + connect(ed, SIGNAL(textChanged(QString)), this, SLOT(slotByteArrayChanged(QString))); + editor = ed; + } + break; + case QVariant::StringList: { + StringListEditorButton *ed = new StringListEditorButton(manager->value(property).toStringList(), parent); + m_stringListPropertyToEditors[property].append(ed); + m_editorToStringListProperty[ed] = property; + connect(ed, SIGNAL(destroyed(QObject*)), this, SLOT(slotEditorDestroyed(QObject*))); + connect(ed, SIGNAL(stringListChanged(QStringList)), this, SLOT(slotStringListChanged(QStringList))); + editor = ed; + } + break; + default: + if (type == DesignerPropertyManager::designerPixmapTypeId()) { + PixmapEditor *ed = new PixmapEditor(m_core, parent); + ed->setPixmapCache(m_fwb->pixmapCache()); + ed->setPath(qvariant_cast<PropertySheetPixmapValue>(manager->value(property)).path()); + ed->setDefaultPixmap(qvariant_cast<QPixmap>(manager->attributeValue(property, QLatin1String(defaultResourceAttributeC)))); + ed->setSpacing(m_spacing); + m_pixmapPropertyToEditors[property].append(ed); + m_editorToPixmapProperty[ed] = property; + connect(ed, SIGNAL(destroyed(QObject *)), this, SLOT(slotEditorDestroyed(QObject *))); + connect(ed, SIGNAL(pathChanged(const QString &)), this, SLOT(slotPixmapChanged(const QString &))); + editor = ed; + } else if (type == DesignerPropertyManager::designerIconTypeId()) { + PixmapEditor *ed = new PixmapEditor(m_core, parent); + ed->setPixmapCache(m_fwb->pixmapCache()); + PropertySheetIconValue value = qvariant_cast<PropertySheetIconValue>(manager->value(property)); + ed->setPath(value.pixmap(QIcon::Normal, QIcon::Off).path()); + QPixmap defaultPixmap; + if (!property->isModified()) + defaultPixmap = qvariant_cast<QIcon>(manager->attributeValue(property, QLatin1String(defaultResourceAttributeC))).pixmap(16, 16); + else if (m_fwb) + defaultPixmap = m_fwb->iconCache()->icon(value).pixmap(16, 16); + ed->setDefaultPixmap(defaultPixmap); + ed->setSpacing(m_spacing); + m_iconPropertyToEditors[property].append(ed); + m_editorToIconProperty[ed] = property; + connect(ed, SIGNAL(destroyed(QObject *)), this, SLOT(slotEditorDestroyed(QObject *))); + connect(ed, SIGNAL(pathChanged(const QString &)), this, SLOT(slotIconChanged(const QString &))); + editor = ed; + } else if (type == DesignerPropertyManager::designerStringTypeId()) { + const TextPropertyValidationMode tvm = static_cast<TextPropertyValidationMode>(manager->attributeValue(property, QLatin1String(validationModesAttributeC)).toInt()); + TextEditor *ed = createTextEditor(parent, tvm, qVariantValue<PropertySheetStringValue>(manager->value(property)).value()); + const QVariant richTextDefaultFont = manager->attributeValue(property, QLatin1String(fontAttributeC)); + if (richTextDefaultFont.type() == QVariant::Font) + ed->setRichTextDefaultFont(qvariant_cast<QFont>(richTextDefaultFont)); + m_stringPropertyToEditors[property].append(ed); + m_editorToStringProperty[ed] = property; + connect(ed, SIGNAL(destroyed(QObject *)), this, SLOT(slotEditorDestroyed(QObject *))); + connect(ed, SIGNAL(textChanged(QString)), this, SLOT(slotStringTextChanged(QString))); + editor = ed; + } else if (type == DesignerPropertyManager::designerKeySequenceTypeId()) { + QtKeySequenceEdit *ed = new QtKeySequenceEdit(parent); + ed->setKeySequence(qVariantValue<PropertySheetKeySequenceValue>(manager->value(property)).value()); + m_keySequencePropertyToEditors[property].append(ed); + m_editorToKeySequenceProperty[ed] = property; + connect(ed, SIGNAL(destroyed(QObject *)), this, SLOT(slotEditorDestroyed(QObject *))); + connect(ed, SIGNAL(keySequenceChanged(QKeySequence)), this, SLOT(slotKeySequenceChanged(QKeySequence))); + editor = ed; + } else { + editor = QtVariantEditorFactory::createEditor(manager, property, parent); + } + break; + } + return m_resetDecorator->editor(editor, + manager->variantProperty(property)->attributeValue(QLatin1String(resettableAttributeC)).toBool(), + manager, property, parent); +} + +template <class Editor> +bool removeEditor(QObject *object, + QMap<QtProperty *, QList<Editor> > *propertyToEditors, + QMap<Editor, QtProperty *> *editorToProperty) +{ + if (!propertyToEditors) + return false; + if (!editorToProperty) + return false; + QMapIterator<Editor, QtProperty *> it(*editorToProperty); + while (it.hasNext()) { + Editor editor = it.next().key(); + if (editor == object) { + QtProperty *prop = it.value(); + (*propertyToEditors)[prop].removeAll(editor); + if ((*propertyToEditors)[prop].count() == 0) + propertyToEditors->remove(prop); + editorToProperty->remove(editor); + return true; + } + } + return false; +} + +void DesignerEditorFactory::slotEditorDestroyed(QObject *object) +{ + if (removeEditor(object, &m_stringPropertyToEditors, &m_editorToStringProperty)) + return; + if (removeEditor(object, &m_keySequencePropertyToEditors, &m_editorToKeySequenceProperty)) + return; + if (removeEditor(object, &m_palettePropertyToEditors, &m_editorToPaletteProperty)) + return; + if (removeEditor(object, &m_pixmapPropertyToEditors, &m_editorToPixmapProperty)) + return; + if (removeEditor(object, &m_iconPropertyToEditors, &m_editorToIconProperty)) + return; + if (removeEditor(object, &m_uintPropertyToEditors, &m_editorToUintProperty)) + return; + if (removeEditor(object, &m_longLongPropertyToEditors, &m_editorToLongLongProperty)) + return; + if (removeEditor(object, &m_uLongLongPropertyToEditors, &m_editorToULongLongProperty)) + return; + if (removeEditor(object, &m_urlPropertyToEditors, &m_editorToUrlProperty)) + return; + if (removeEditor(object, &m_byteArrayPropertyToEditors, &m_editorToByteArrayProperty)) + return; + if (removeEditor(object, &m_stringListPropertyToEditors, &m_editorToStringListProperty)) + return; +} + +template<class Editor> +bool updateManager(QtVariantEditorFactory *factory, bool *changingPropertyValue, + const QMap<Editor, QtProperty *> &editorToProperty, QWidget *editor, const QVariant &value) +{ + if (!editor) + return false; + QMapIterator<Editor, QtProperty *> it(editorToProperty); + while (it.hasNext()) { + if (it.next().key() == editor) { + QtProperty *prop = it.value(); + QtVariantPropertyManager *manager = factory->propertyManager(prop); + *changingPropertyValue = true; + manager->variantProperty(prop)->setValue(value); + *changingPropertyValue = false; + return true; + } + } + return false; +} + +void DesignerEditorFactory::slotUintChanged(const QString &value) +{ + updateManager(this, &m_changingPropertyValue, m_editorToUintProperty, qobject_cast<QWidget *>(sender()), value.toUInt()); +} + +void DesignerEditorFactory::slotLongLongChanged(const QString &value) +{ + updateManager(this, &m_changingPropertyValue, m_editorToLongLongProperty, qobject_cast<QWidget *>(sender()), value.toLongLong()); +} + +void DesignerEditorFactory::slotULongLongChanged(const QString &value) +{ + updateManager(this, &m_changingPropertyValue, m_editorToULongLongProperty, qobject_cast<QWidget *>(sender()), value.toULongLong()); +} + +void DesignerEditorFactory::slotUrlChanged(const QString &value) +{ + updateManager(this, &m_changingPropertyValue, m_editorToUrlProperty, qobject_cast<QWidget *>(sender()), QUrl(value)); +} + +void DesignerEditorFactory::slotByteArrayChanged(const QString &value) +{ + updateManager(this, &m_changingPropertyValue, m_editorToByteArrayProperty, qobject_cast<QWidget *>(sender()), value.toUtf8()); +} + +void DesignerEditorFactory::slotStringTextChanged(const QString &value) +{ + QMapIterator<TextEditor *, QtProperty *> it(m_editorToStringProperty); + while (it.hasNext()) { + if (it.next().key() == sender()) { + QtProperty *prop = it.value(); + QtVariantPropertyManager *manager = propertyManager(prop); + QtVariantProperty *varProp = manager->variantProperty(prop); + QVariant val = varProp->value(); + if (val.userType() == DesignerPropertyManager::designerStringTypeId()) { + PropertySheetStringValue strVal = qVariantValue<PropertySheetStringValue>(val); + strVal.setValue(value); + val = qVariantFromValue(strVal); + } else { + val = QVariant(value); + } + m_changingPropertyValue = true; + manager->variantProperty(prop)->setValue(val); + m_changingPropertyValue = false; + } + } +} + +void DesignerEditorFactory::slotKeySequenceChanged(const QKeySequence &value) +{ + QMapIterator<QtKeySequenceEdit *, QtProperty *> it(m_editorToKeySequenceProperty); + while (it.hasNext()) { + if (it.next().key() == sender()) { + QtProperty *prop = it.value(); + QtVariantPropertyManager *manager = propertyManager(prop); + QtVariantProperty *varProp = manager->variantProperty(prop); + QVariant val = varProp->value(); + if (val.userType() == DesignerPropertyManager::designerKeySequenceTypeId()) { + PropertySheetKeySequenceValue keyVal = qVariantValue<PropertySheetKeySequenceValue>(val); + keyVal.setValue(value); + val = qVariantFromValue(keyVal); + } else { + val = qVariantFromValue(value); + } + m_changingPropertyValue = true; + manager->variantProperty(prop)->setValue(val); + m_changingPropertyValue = false; + } + } +} + +void DesignerEditorFactory::slotPaletteChanged(const QPalette &value) +{ + updateManager(this, &m_changingPropertyValue, m_editorToPaletteProperty, qobject_cast<QWidget *>(sender()), qVariantFromValue(value)); +} + +void DesignerEditorFactory::slotPixmapChanged(const QString &value) +{ + updateManager(this, &m_changingPropertyValue, m_editorToPixmapProperty, qobject_cast<QWidget *>(sender()), + qVariantFromValue(PropertySheetPixmapValue(value))); +} + +void DesignerEditorFactory::slotIconChanged(const QString &value) +{ + updateManager(this, &m_changingPropertyValue, m_editorToIconProperty, qobject_cast<QWidget *>(sender()), + qVariantFromValue(PropertySheetIconValue(PropertySheetPixmapValue(value)))); +} + +void DesignerEditorFactory::slotStringListChanged(const QStringList &value) +{ + updateManager(this, &m_changingPropertyValue, m_editorToStringListProperty, qobject_cast<QWidget *>(sender()), qVariantFromValue(value)); +} + +ResetDecorator::~ResetDecorator() +{ + QList<ResetWidget *> editors = m_resetWidgetToProperty.keys(); + QListIterator<ResetWidget *> it(editors); + while (it.hasNext()) + delete it.next(); +} + +void ResetDecorator::connectPropertyManager(QtAbstractPropertyManager *manager) +{ + connect(manager, SIGNAL(propertyChanged(QtProperty *)), + this, SLOT(slotPropertyChanged(QtProperty *))); +} + +void ResetDecorator::disconnectPropertyManager(QtAbstractPropertyManager *manager) +{ + disconnect(manager, SIGNAL(propertyChanged(QtProperty *)), + this, SLOT(slotPropertyChanged(QtProperty *))); +} + +void ResetDecorator::setSpacing(int spacing) +{ + m_spacing = spacing; +} + +QWidget *ResetDecorator::editor(QWidget *subEditor, bool resettable, QtAbstractPropertyManager *manager, QtProperty *property, + QWidget *parent) +{ + Q_UNUSED(manager) + + ResetWidget *resetWidget = 0; + if (resettable) { + resetWidget = new ResetWidget(property, parent); + resetWidget->setSpacing(m_spacing); + resetWidget->setResetEnabled(property->isModified()); + resetWidget->setValueText(property->valueText()); + resetWidget->setValueIcon(property->valueIcon()); + resetWidget->setAutoFillBackground(true); + connect(resetWidget, SIGNAL(destroyed(QObject*)), this, SLOT(slotEditorDestroyed(QObject*))); + connect(resetWidget, SIGNAL(resetProperty(QtProperty *)), this, SIGNAL(resetProperty(QtProperty *))); + m_createdResetWidgets[property].append(resetWidget); + m_resetWidgetToProperty[resetWidget] = property; + } + if (subEditor) { + if (resetWidget) { + subEditor->setParent(resetWidget); + resetWidget->setWidget(subEditor); + } + } + if (resetWidget) + return resetWidget; + return subEditor; +} + +void ResetDecorator::slotPropertyChanged(QtProperty *property) +{ + QMap<QtProperty *, QList<ResetWidget *> >::ConstIterator prIt = m_createdResetWidgets.constFind(property); + if (prIt == m_createdResetWidgets.constEnd()) + return; + + const QList<ResetWidget *> editors = prIt.value(); + const QList<ResetWidget *>::ConstIterator cend = editors.constEnd(); + for (QList<ResetWidget *>::ConstIterator itEditor = editors.constBegin(); itEditor != cend; ++itEditor) { + ResetWidget *widget = *itEditor; + widget->setResetEnabled(property->isModified()); + widget->setValueText(property->valueText()); + widget->setValueIcon(property->valueIcon()); + } +} + +void ResetDecorator::slotEditorDestroyed(QObject *object) +{ + const QMap<ResetWidget *, QtProperty *>::ConstIterator rcend = m_resetWidgetToProperty.constEnd(); + for (QMap<ResetWidget *, QtProperty *>::ConstIterator itEditor = m_resetWidgetToProperty.constBegin(); itEditor != rcend; ++itEditor) { + if (itEditor.key() == object) { + ResetWidget *editor = itEditor.key(); + QtProperty *property = itEditor.value(); + m_resetWidgetToProperty.remove(editor); + m_createdResetWidgets[property].removeAll(editor); + if (m_createdResetWidgets[property].isEmpty()) + m_createdResetWidgets.remove(property); + return; + } + } +} + +} + +QT_END_NAMESPACE + +#include "designerpropertymanager.moc" diff --git a/tools/designer/src/components/propertyeditor/designerpropertymanager.h b/tools/designer/src/components/propertyeditor/designerpropertymanager.h new file mode 100644 index 0000000..78ab8e6 --- /dev/null +++ b/tools/designer/src/components/propertyeditor/designerpropertymanager.h @@ -0,0 +1,312 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the Qt Designer of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef DESIGNERPROPERTYMANAGER_H +#define DESIGNERPROPERTYMANAGER_H + +#include "qtvariantproperty.h" +#include "brushpropertymanager.h" +#include "fontpropertymanager.h" + +#include <qdesigner_utils_p.h> +#include <shared_enums_p.h> + +#include <QtCore/QUrl> +#include <QtCore/QMap> +#include <QtGui/QFont> +#include <QtGui/QIcon> + +QT_BEGIN_NAMESPACE + +typedef QPair<QString, uint> DesignerIntPair; +typedef QList<DesignerIntPair> DesignerFlagList; + +class QDesignerFormEditorInterface; +class QLineEdit; +class QUrl; +class QtKeySequenceEdit; + +namespace qdesigner_internal +{ + +class ResetWidget; + +class TextEditor; +class PaletteEditorButton; +class PixmapEditor; +class StringListEditorButton; +class FormWindowBase; + +class ResetDecorator : public QObject +{ + Q_OBJECT +public: + ResetDecorator(QObject *parent = 0) : QObject(parent), m_spacing(-1) {} + ~ResetDecorator(); + + void connectPropertyManager(QtAbstractPropertyManager *manager); + QWidget *editor(QWidget *subEditor, bool resettable, QtAbstractPropertyManager *manager, QtProperty *property, + QWidget *parent); + void disconnectPropertyManager(QtAbstractPropertyManager *manager); + void setSpacing(int spacing); +signals: + void resetProperty(QtProperty *property); +private slots: + void slotPropertyChanged(QtProperty *property); + void slotEditorDestroyed(QObject *object); +private: + QMap<QtProperty *, QList<ResetWidget *> > m_createdResetWidgets; + QMap<ResetWidget *, QtProperty *> m_resetWidgetToProperty; + int m_spacing; +}; + +class DesignerPropertyManager : public QtVariantPropertyManager +{ + Q_OBJECT +public: + DesignerPropertyManager(QDesignerFormEditorInterface *core, QObject *parent = 0); + ~DesignerPropertyManager(); + + virtual QStringList attributes(int propertyType) const; + virtual int attributeType(int propertyType, const QString &attribute) const; + + virtual QVariant attributeValue(const QtProperty *property, const QString &attribute) const; + virtual bool isPropertyTypeSupported(int propertyType) const; + virtual QVariant value(const QtProperty *property) const; + virtual int valueType(int propertyType) const; + virtual QString valueText(const QtProperty *property) const; + virtual QIcon valueIcon(const QtProperty *property) const; + + bool resetFontSubProperty(QtProperty *property); + bool resetIconSubProperty(QtProperty *subProperty); + + void reloadResourceProperties(); + + static int designerFlagTypeId(); + static int designerFlagListTypeId(); + static int designerAlignmentTypeId(); + static int designerPixmapTypeId(); + static int designerIconTypeId(); + static int designerStringTypeId(); + static int designerKeySequenceTypeId(); + + void setObject(QObject *object) { m_object = object; } + +public Q_SLOTS: + virtual void setAttribute(QtProperty *property, + const QString &attribute, const QVariant &value); + virtual void setValue(QtProperty *property, const QVariant &value); +Q_SIGNALS: + // sourceOfChange - a subproperty (or just property) which caused a change + //void valueChanged(QtProperty *property, const QVariant &value, QtProperty *sourceOfChange); + void valueChanged(QtProperty *property, const QVariant &value, bool enableSubPropertyHandling); +protected: + virtual void initializeProperty(QtProperty *property); + virtual void uninitializeProperty(QtProperty *property); +private Q_SLOTS: + void slotValueChanged(QtProperty *property, const QVariant &value); + void slotPropertyDestroyed(QtProperty *property); +private: + void createIconSubProperty(QtProperty *iconProperty, QIcon::Mode mode, QIcon::State state, const QString &subName); + + typedef QMap<QtProperty *, bool> PropertyBoolMap; + PropertyBoolMap m_resetMap; + + int bitCount(int mask) const; + struct FlagData + { + FlagData() : val(0) {} + uint val; + DesignerFlagList flags; + QList<uint> values; + }; + typedef QMap<QtProperty *, FlagData> PropertyFlagDataMap; + PropertyFlagDataMap m_flagValues; + typedef QMap<QtProperty *, QList<QtProperty *> > PropertyToPropertyListMap; + PropertyToPropertyListMap m_propertyToFlags; + QMap<QtProperty *, QtProperty *> m_flagToProperty; + + int alignToIndexH(uint align) const; + int alignToIndexV(uint align) const; + uint indexHToAlign(int idx) const; + uint indexVToAlign(int idx) const; + QString indexHToString(int idx) const; + QString indexVToString(int idx) const; + QMap<QtProperty *, uint> m_alignValues; + typedef QMap<QtProperty *, QtProperty *> PropertyToPropertyMap; + PropertyToPropertyMap m_propertyToAlignH; + PropertyToPropertyMap m_propertyToAlignV; + PropertyToPropertyMap m_alignHToProperty; + PropertyToPropertyMap m_alignVToProperty; + + QMap<QtProperty *, QMap<QPair<QIcon::Mode, QIcon::State>, QtProperty *> > m_propertyToIconSubProperties; + QMap<QtProperty *, QPair<QIcon::Mode, QIcon::State> > m_iconSubPropertyToState; + PropertyToPropertyMap m_iconSubPropertyToProperty; + + QMap<QtProperty *, qdesigner_internal::PropertySheetStringValue> m_stringValues; + QMap<QtProperty *, QtProperty *> m_stringToComment; + QMap<QtProperty *, QtProperty *> m_stringToTranslatable; + QMap<QtProperty *, QtProperty *> m_stringToDisambiguation; + + QMap<QtProperty *, QtProperty *> m_commentToString; + QMap<QtProperty *, QtProperty *> m_translatableToString; + QMap<QtProperty *, QtProperty *> m_disambiguationToString; + + QMap<QtProperty *, qdesigner_internal::PropertySheetKeySequenceValue> m_keySequenceValues; + QMap<QtProperty *, QtProperty *> m_keySequenceToComment; + QMap<QtProperty *, QtProperty *> m_keySequenceToTranslatable; + QMap<QtProperty *, QtProperty *> m_keySequenceToDisambiguation; + + QMap<QtProperty *, QtProperty *> m_commentToKeySequence; + QMap<QtProperty *, QtProperty *> m_translatableToKeySequence; + QMap<QtProperty *, QtProperty *> m_disambiguationToKeySequence; + + struct PaletteData + { + QPalette val; + QPalette superPalette; + }; + typedef QMap<QtProperty *, PaletteData> PropertyPaletteDataMap; + PropertyPaletteDataMap m_paletteValues; + + QMap<QtProperty *, qdesigner_internal::PropertySheetPixmapValue> m_pixmapValues; + QMap<QtProperty *, qdesigner_internal::PropertySheetIconValue> m_iconValues; + + QMap<QtProperty *, uint> m_uintValues; + QMap<QtProperty *, qlonglong> m_longLongValues; + QMap<QtProperty *, qulonglong> m_uLongLongValues; + QMap<QtProperty *, QUrl> m_urlValues; + QMap<QtProperty *, QByteArray> m_byteArrayValues; + QMap<QtProperty *, QStringList> m_stringListValues; + + typedef QMap<QtProperty *, int> PropertyIntMap; + PropertyIntMap m_stringAttributes; + typedef QMap<QtProperty *, QFont> PropertyFontMap; + PropertyFontMap m_stringFontAttributes; + + BrushPropertyManager m_brushManager; + FontPropertyManager m_fontManager; + + QMap<QtProperty *, QPixmap> m_defaultPixmaps; + QMap<QtProperty *, QIcon> m_defaultIcons; + + bool m_changingSubValue; + QDesignerFormEditorInterface *m_core; + + QObject *m_object; + + QtProperty *m_sourceOfChange; +}; + +class DesignerEditorFactory : public QtVariantEditorFactory +{ + Q_OBJECT +public: + explicit DesignerEditorFactory(QDesignerFormEditorInterface *core, QObject *parent = 0); + ~DesignerEditorFactory(); + void setSpacing(int spacing); + void setFormWindowBase(FormWindowBase *fwb); +signals: + void resetProperty(QtProperty *property); +protected: + void connectPropertyManager(QtVariantPropertyManager *manager); + QWidget *createEditor(QtVariantPropertyManager *manager, QtProperty *property, + QWidget *parent); + void disconnectPropertyManager(QtVariantPropertyManager *manager); +private slots: + void slotEditorDestroyed(QObject *object); + void slotAttributeChanged(QtProperty *property, const QString &attribute, const QVariant &value); + void slotPropertyChanged(QtProperty *property); + void slotValueChanged(QtProperty *property, const QVariant &value); + void slotStringTextChanged(const QString &value); + void slotKeySequenceChanged(const QKeySequence &value); + void slotPaletteChanged(const QPalette &value); + void slotPixmapChanged(const QString &value); + void slotIconChanged(const QString &value); + void slotUintChanged(const QString &value); + void slotLongLongChanged(const QString &value); + void slotULongLongChanged(const QString &value); + void slotUrlChanged(const QString &value); + void slotByteArrayChanged(const QString &value); + void slotStringListChanged(const QStringList &value); +private: + TextEditor *createTextEditor(QWidget *parent, TextPropertyValidationMode vm, const QString &value); + + ResetDecorator *m_resetDecorator; + bool m_changingPropertyValue; + QDesignerFormEditorInterface *m_core; + FormWindowBase *m_fwb; + + int m_spacing; + + QMap<QtProperty *, QList<TextEditor *> > m_stringPropertyToEditors; + QMap<TextEditor *, QtProperty *> m_editorToStringProperty; + QMap<QtProperty *, QList<QtKeySequenceEdit *> > m_keySequencePropertyToEditors; + QMap<QtKeySequenceEdit *, QtProperty *> m_editorToKeySequenceProperty; + QMap<QtProperty *, QList<PaletteEditorButton *> > m_palettePropertyToEditors; + QMap<PaletteEditorButton *, QtProperty *> m_editorToPaletteProperty; + QMap<QtProperty *, QList<PixmapEditor *> > m_pixmapPropertyToEditors; + QMap<PixmapEditor *, QtProperty *> m_editorToPixmapProperty; + QMap<QtProperty *, QList<PixmapEditor *> > m_iconPropertyToEditors; + QMap<PixmapEditor *, QtProperty *> m_editorToIconProperty; + QMap<QtProperty *, QList<QLineEdit *> > m_uintPropertyToEditors; + QMap<QLineEdit *, QtProperty *> m_editorToUintProperty; + QMap<QtProperty *, QList<QLineEdit *> > m_longLongPropertyToEditors; + QMap<QLineEdit *, QtProperty *> m_editorToLongLongProperty; + QMap<QtProperty *, QList<QLineEdit *> > m_uLongLongPropertyToEditors; + QMap<QLineEdit *, QtProperty *> m_editorToULongLongProperty; + QMap<QtProperty *, QList<TextEditor *> > m_urlPropertyToEditors; + QMap<TextEditor *, QtProperty *> m_editorToUrlProperty; + QMap<QtProperty *, QList<TextEditor *> > m_byteArrayPropertyToEditors; + QMap<TextEditor *, QtProperty *> m_editorToByteArrayProperty; + QMap<QtProperty *, QList<StringListEditorButton *> > m_stringListPropertyToEditors; + QMap<StringListEditorButton *, QtProperty *> m_editorToStringListProperty; +}; + +} + +QT_END_NAMESPACE + +Q_DECLARE_METATYPE(DesignerIntPair) +Q_DECLARE_METATYPE(DesignerFlagList) + +#endif + diff --git a/tools/designer/src/components/propertyeditor/fontmapping.xml b/tools/designer/src/components/propertyeditor/fontmapping.xml new file mode 100644 index 0000000..c19f7a3 --- /dev/null +++ b/tools/designer/src/components/propertyeditor/fontmapping.xml @@ -0,0 +1,73 @@ +<?xml version="1.0" encoding="UTF-8"?> + +<!--************************************************************************ +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the Qt Designer of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +**************************************************************************--> + +<!DOCTYPE fontmapping +[ +<!ENTITY ce "Windows CE" > +<!ENTITY qe "Qt Embedded" > +]> + +<fontmappings> +<mapping><family>DejaVu Sans</family><display>DejaVu Sans [&qe;]</display></mapping> +<mapping><family>DejaVu Sans</family><display>DejaVu Sans [&qe;]</display></mapping> +<mapping><family>DejaVu Sans</family><display>DejaVu Sans [&qe;]</display></mapping> +<mapping><family>DejaVu Sans</family><display>DejaVu Sans [&qe;]</display></mapping> +<mapping><family>DejaVu Sans Mono</family><display>DejaVu Sans Mono [&qe;]</display></mapping> +<mapping><family>DejaVu Sans Mono</family><display>DejaVu Sans Mono [&qe;]</display></mapping> +<mapping><family>DejaVu Sans Mono</family><display>DejaVu Sans Mono [&qe;]</display></mapping> +<mapping><family>DejaVu Sans Mono</family><display>DejaVu Sans Mono [&qe;]</display></mapping> +<mapping><family>DejaVu Serif</family><display>DejaVu Serif [&qe;]</display></mapping> +<mapping><family>DejaVu Serif</family><display>DejaVu Serif [&qe;]</display></mapping> +<mapping><family>DejaVu Serif</family><display>DejaVu Serif [&qe;]</display></mapping> +<mapping><family>DejaVu Serif</family><display>DejaVu Serif [&qe;]</display></mapping> +<mapping><family>Bitstream Vera Sans</family><display>Bitstream Vera Sans [&qe;]</display></mapping> +<mapping><family>Bitstream Vera Sans</family><display>Bitstream Vera Sans [&qe;]</display></mapping> +<mapping><family>Bitstream Vera Sans</family><display>Bitstream Vera Sans [&qe;]</display></mapping> +<mapping><family>Bitstream Vera Sans</family><display>Bitstream Vera Sans [&qe;]</display></mapping> +<mapping><family>Bitstream Vera Sans Mono</family><display>Bitstream Vera Sans Mono [&qe;]</display></mapping> +<mapping><family>Bitstream Vera Sans Mono</family><display>Bitstream Vera Sans Mono [&qe;]</display></mapping> +<mapping><family>Bitstream Vera Sans Mono</family><display>Bitstream Vera Sans Mono [&qe;]</display></mapping> +<mapping><family>Bitstream Vera Sans Mono</family><display>Bitstream Vera Sans Mono [&qe;]</display></mapping> +<mapping><family>Bitstream Vera Serif</family><display>Bitstream Vera Serif [&qe;]</display></mapping> +<mapping><family>Bitstream Vera Serif</family><display>Bitstream Vera Serif [&qe;]</display></mapping> +</fontmappings> diff --git a/tools/designer/src/components/propertyeditor/fontpropertymanager.cpp b/tools/designer/src/components/propertyeditor/fontpropertymanager.cpp new file mode 100644 index 0000000..ab980aa --- /dev/null +++ b/tools/designer/src/components/propertyeditor/fontpropertymanager.cpp @@ -0,0 +1,377 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the Qt Designer of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "fontpropertymanager.h" +#include "qtpropertymanager.h" +#include "qtvariantproperty.h" +#include "qtpropertybrowserutils_p.h" + +#include <qdesigner_utils_p.h> + +#include <QtCore/QCoreApplication> +#include <QtCore/QVariant> +#include <QtCore/QString> +#include <QtCore/QDebug> +#include <QtCore/QFile> +#include <QtCore/QTextStream> +#include <QtXml/QXmlStreamReader> + +QT_BEGIN_NAMESPACE + +namespace qdesigner_internal { + + static const char *aliasingC[] = { + QT_TRANSLATE_NOOP("FontPropertyManager", "PreferDefault"), + QT_TRANSLATE_NOOP("FontPropertyManager", "NoAntialias"), + QT_TRANSLATE_NOOP("FontPropertyManager", "PreferAntialias") + }; + + FontPropertyManager::FontPropertyManager() : + m_createdFontProperty(0) + { + const int nameCount = sizeof(aliasingC)/sizeof(const char *); + for (int i = 0; i < nameCount; i++) + m_aliasingEnumNames.push_back(QCoreApplication::translate("FontPropertyManager", aliasingC[i])); + + QString errorMessage; + if (!readFamilyMapping(&m_familyMappings, &errorMessage)) { + designerWarning(errorMessage); + } + + } + + void FontPropertyManager::preInitializeProperty(QtProperty *property, + int type, + ResetMap &resetMap) + { + if (m_createdFontProperty) { + PropertyToSubPropertiesMap::iterator it = m_propertyToFontSubProperties.find(m_createdFontProperty); + if (it == m_propertyToFontSubProperties.end()) + it = m_propertyToFontSubProperties.insert(m_createdFontProperty, PropertyList()); + const int index = it.value().size(); + m_fontSubPropertyToFlag.insert(property, index); + it.value().push_back(property); + m_fontSubPropertyToProperty[property] = m_createdFontProperty; + resetMap[property] = true; + } + + if (type == QVariant::Font) + m_createdFontProperty = property; + } + + // Map the font family names to display names retrieved from the XML configuration + static QStringList designerFamilyNames(QStringList families, const FontPropertyManager::NameMap &nm) + { + if (nm.empty()) + return families; + + const FontPropertyManager::NameMap::const_iterator ncend = nm.constEnd(); + const QStringList::iterator end = families.end(); + for (QStringList::iterator it = families.begin(); it != end; ++it) { + const FontPropertyManager::NameMap::const_iterator nit = nm.constFind(*it); + if (nit != ncend) + *it = nit.value(); + } + return families; + } + + void FontPropertyManager::postInitializeProperty(QtVariantPropertyManager *vm, + QtProperty *property, + int type, + int enumTypeId) + { + if (type != QVariant::Font) + return; + + // This will cause a recursion + QtVariantProperty *antialiasing = vm->addProperty(enumTypeId, QCoreApplication::translate("FontPropertyManager", "Antialiasing")); + const QFont font = qVariantValue<QFont>(vm->variantProperty(property)->value()); + + antialiasing->setAttribute(QLatin1String("enumNames"), m_aliasingEnumNames); + antialiasing->setValue(antialiasingToIndex(font.styleStrategy())); + property->addSubProperty(antialiasing); + + m_propertyToAntialiasing[property] = antialiasing; + m_antialiasingToProperty[antialiasing] = property; + // Fiddle family names + if (!m_familyMappings.empty()) { + const PropertyToSubPropertiesMap::iterator it = m_propertyToFontSubProperties.find(m_createdFontProperty); + QtVariantProperty *familyProperty = vm->variantProperty(it.value().front()); + const QString enumNamesAttribute = QLatin1String("enumNames"); + QStringList plainFamilyNames = familyProperty->attributeValue(enumNamesAttribute).toStringList(); + // Did someone load fonts or something? + if (m_designerFamilyNames.size() != plainFamilyNames.size()) + m_designerFamilyNames = designerFamilyNames(plainFamilyNames, m_familyMappings); + familyProperty->setAttribute(enumNamesAttribute, m_designerFamilyNames); + } + // Next + m_createdFontProperty = 0; + } + + bool FontPropertyManager::uninitializeProperty(QtProperty *property) + { + const PropertyToPropertyMap::iterator ait = m_propertyToAntialiasing.find(property); + if (ait != m_propertyToAntialiasing.end()) { + QtProperty *antialiasing = ait.value(); + m_antialiasingToProperty.remove(antialiasing); + m_propertyToAntialiasing.erase(ait); + delete antialiasing; + } + + PropertyToSubPropertiesMap::iterator sit = m_propertyToFontSubProperties.find(property); + if (sit == m_propertyToFontSubProperties.end()) + return false; + + m_propertyToFontSubProperties.erase(sit); + m_fontSubPropertyToFlag.remove(property); + m_fontSubPropertyToProperty.remove(property); + + return true; + } + + void FontPropertyManager::slotPropertyDestroyed(QtProperty *property) + { + removeAntialiasingProperty(property); + } + + void FontPropertyManager::removeAntialiasingProperty(QtProperty *property) + { + const PropertyToPropertyMap::iterator ait = m_antialiasingToProperty.find(property); + if (ait == m_antialiasingToProperty.end()) + return; + m_propertyToAntialiasing[ait.value()] = 0; + m_antialiasingToProperty.erase(ait); + } + + bool FontPropertyManager::resetFontSubProperty(QtVariantPropertyManager *vm, QtProperty *property) + { + const PropertyToPropertyMap::iterator it = m_fontSubPropertyToProperty.find(property); + if (it == m_fontSubPropertyToProperty.end()) + return false; + + QtVariantProperty *fontProperty = vm->variantProperty(it.value()); + + QVariant v = fontProperty->value(); + QFont font = qvariant_cast<QFont>(v); + unsigned mask = font.resolve(); + const unsigned flag = fontFlag(m_fontSubPropertyToFlag.value(property)); + + mask &= ~flag; + font.resolve(mask); + qVariantSetValue(v, font); + fontProperty->setValue(v); + return true; + } + + int FontPropertyManager::antialiasingToIndex(QFont::StyleStrategy antialias) + { + switch (antialias) { + case QFont::PreferDefault: return 0; + case QFont::NoAntialias: return 1; + case QFont::PreferAntialias: return 2; + default: break; + } + return 0; + } + + QFont::StyleStrategy FontPropertyManager::indexToAntialiasing(int idx) + { + switch (idx) { + case 0: return QFont::PreferDefault; + case 1: return QFont::NoAntialias; + case 2: return QFont::PreferAntialias; + } + return QFont::PreferDefault; + } + + unsigned FontPropertyManager::fontFlag(int idx) + { + switch (idx) { + case 0: return QFont::FamilyResolved; + case 1: return QFont::SizeResolved; + case 2: return QFont::WeightResolved; + case 3: return QFont::StyleResolved; + case 4: return QFont::UnderlineResolved; + case 5: return QFont::StrikeOutResolved; + case 6: return QFont::KerningResolved; + case 7: return QFont::StyleStrategyResolved; + } + return 0; + } + + FontPropertyManager::ValueChangedResult FontPropertyManager::valueChanged(QtVariantPropertyManager *vm, QtProperty *property, const QVariant &value) + { + QtProperty *antialiasingProperty = m_antialiasingToProperty.value(property, 0); + if (!antialiasingProperty) { + if (m_propertyToFontSubProperties.contains(property)) { + updateModifiedState(property, value); + } + return NoMatch; + } + + QtVariantProperty *fontProperty = vm->variantProperty(antialiasingProperty); + const QFont::StyleStrategy newValue = indexToAntialiasing(value.toInt()); + + QFont font = qVariantValue<QFont>(fontProperty->value()); + const QFont::StyleStrategy oldValue = font.styleStrategy(); + if (newValue == oldValue) + return Unchanged; + + font.setStyleStrategy(newValue); + fontProperty->setValue(qVariantFromValue(font)); + return Changed; + } + + void FontPropertyManager::updateModifiedState(QtProperty *property, const QVariant &value) + { + const PropertyToSubPropertiesMap::iterator it = m_propertyToFontSubProperties.find(property); + if (it == m_propertyToFontSubProperties.end()) + return; + + const PropertyList &subProperties = it.value(); + + QFont font = qVariantValue<QFont>(value); + const unsigned mask = font.resolve(); + + const int count = subProperties.size(); + for (int index = 0; index < count; index++) { + const unsigned flag = fontFlag(index); + subProperties.at(index)->setModified(mask & flag); + } + } + + void FontPropertyManager::setValue(QtVariantPropertyManager *vm, QtProperty *property, const QVariant &value) + { + updateModifiedState(property, value); + + if (QtProperty *antialiasingProperty = m_propertyToAntialiasing.value(property, 0)) { + QtVariantProperty *antialiasing = vm->variantProperty(antialiasingProperty); + if (antialiasing) { + QFont font = qVariantValue<QFont>(value); + antialiasing->setValue(antialiasingToIndex(font.styleStrategy())); + } + } + } + + /* Parse a mappings file of the form: + * <fontmappings> + * <mapping><family>DejaVu Sans</family><display>DejaVu Sans [CE]</display></mapping> + * ... which is used to display on which platforms fonts are available.*/ + + static const char *rootTagC = "fontmappings"; + static const char *mappingTagC = "mapping"; + static const char *familyTagC = "family"; + static const char *displayTagC = "display"; + + static QString msgXmlError(const QXmlStreamReader &r, const QString& fileName) + { + return QString::fromUtf8("An error has been encountered at line %1 of %2: %3:").arg(r.lineNumber()).arg(fileName, r.errorString()); + } + + /* Switch stages when encountering a start element (state table) */ + enum ParseStage { ParseBeginning, ParseWithinRoot, ParseWithinMapping, ParseWithinFamily, + ParseWithinDisplay, ParseError }; + + static ParseStage nextStage(ParseStage currentStage, const QStringRef &startElement) + { + switch (currentStage) { + case ParseBeginning: + return startElement == QLatin1String(rootTagC) ? ParseWithinRoot : ParseError; + case ParseWithinRoot: + case ParseWithinDisplay: // Next mapping, was in <display> + return startElement == QLatin1String(mappingTagC) ? ParseWithinMapping : ParseError; + case ParseWithinMapping: + return startElement == QLatin1String(familyTagC) ? ParseWithinFamily : ParseError; + case ParseWithinFamily: + return startElement == QLatin1String(displayTagC) ? ParseWithinDisplay : ParseError; + case ParseError: + break; + } + return ParseError; + } + + bool FontPropertyManager::readFamilyMapping(NameMap *rc, QString *errorMessage) + { + rc->clear(); + const QString fileName = QLatin1String(":/trolltech/propertyeditor/fontmapping.xml"); + QFile file(fileName); + if (!file.open(QIODevice::ReadOnly)) { + *errorMessage = QString::fromUtf8("Unable to open %1: %2").arg(fileName, file.errorString()); + return false; + } + + QXmlStreamReader reader(&file); + QXmlStreamReader::TokenType token; + + QString family; + ParseStage stage = ParseBeginning; + do { + token = reader.readNext(); + switch (token) { + case QXmlStreamReader::Invalid: + *errorMessage = msgXmlError(reader, fileName); + return false; + case QXmlStreamReader::StartElement: + stage = nextStage(stage, reader.name()); + switch (stage) { + case ParseError: + reader.raiseError(QString::fromUtf8("Unexpected element <%1>.").arg(reader.name().toString())); + *errorMessage = msgXmlError(reader, fileName); + return false; + case ParseWithinFamily: + family = reader.readElementText(); + break; + case ParseWithinDisplay: + rc->insert(family, reader.readElementText()); + break; + default: + break; + } + default: + break; + } + } while (token != QXmlStreamReader::EndDocument); + return true; + } + +} + +QT_END_NAMESPACE diff --git a/tools/designer/src/components/propertyeditor/fontpropertymanager.h b/tools/designer/src/components/propertyeditor/fontpropertymanager.h new file mode 100644 index 0000000..915dcd9 --- /dev/null +++ b/tools/designer/src/components/propertyeditor/fontpropertymanager.h @@ -0,0 +1,124 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the Qt Designer of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef FONTPROPERTYMANAGER_H +#define FONTPROPERTYMANAGER_H + +#include <QtCore/QMap> +#include <QtCore/QStringList> +#include <QtGui/QFont> + +QT_BEGIN_NAMESPACE + +class QtProperty; +class QtVariantPropertyManager; + +class QString; +class QVariant; + +namespace qdesigner_internal { + +/* FontPropertyManager: A mixin for DesignerPropertyManager that manages font + * properties. Adds an antialiasing subproperty and reset flags/mask handling + * for the other subproperties. It also modifies the font family + * enumeration names, which it reads from an XML mapping file that + * contains annotations indicating the platform the font is available on. */ + +class FontPropertyManager { + Q_DISABLE_COPY(FontPropertyManager) + +public: + FontPropertyManager(); + + typedef QMap<QtProperty *, bool> ResetMap; + typedef QMap<QString, QString> NameMap; + + // Call before QtVariantPropertyManager::initializeProperty. + void preInitializeProperty(QtProperty *property, int type, ResetMap &resetMap); + // Call after QtVariantPropertyManager::initializeProperty. This will trigger + // a recursion for the sub properties + void postInitializeProperty(QtVariantPropertyManager *vm, QtProperty *property, int type, int enumTypeId); + + bool uninitializeProperty(QtProperty *property); + + // Call from QtPropertyManager's propertyDestroyed signal + void slotPropertyDestroyed(QtProperty *property); + + bool resetFontSubProperty(QtVariantPropertyManager *vm, QtProperty *subProperty); + + // Call from slotValueChanged(). + enum ValueChangedResult { NoMatch, Unchanged, Changed }; + ValueChangedResult valueChanged(QtVariantPropertyManager *vm, QtProperty *property, const QVariant &value); + + // Call from setValue() before calling setValue() on QtVariantPropertyManager. + void setValue(QtVariantPropertyManager *vm, QtProperty *property, const QVariant &value); + + static bool readFamilyMapping(NameMap *rc, QString *errorMessage); + +private: + typedef QMap<QtProperty *, QtProperty *> PropertyToPropertyMap; + typedef QList<QtProperty *> PropertyList; + typedef QMap<QtProperty *, PropertyList> PropertyToSubPropertiesMap; + + void removeAntialiasingProperty(QtProperty *); + void updateModifiedState(QtProperty *property, const QVariant &value); + static int antialiasingToIndex(QFont::StyleStrategy antialias); + static QFont::StyleStrategy indexToAntialiasing(int idx); + static unsigned fontFlag(int idx); + + PropertyToPropertyMap m_propertyToAntialiasing; + PropertyToPropertyMap m_antialiasingToProperty; + + PropertyToSubPropertiesMap m_propertyToFontSubProperties; + QMap<QtProperty *, int> m_fontSubPropertyToFlag; + PropertyToPropertyMap m_fontSubPropertyToProperty; + QtProperty *m_createdFontProperty; + QStringList m_aliasingEnumNames; + // Font families with Designer annotations + QStringList m_designerFamilyNames; + NameMap m_familyMappings; +}; + +} + +QT_END_NAMESPACE + +#endif // FONTPROPERTYMANAGER_H diff --git a/tools/designer/src/components/propertyeditor/newdynamicpropertydialog.cpp b/tools/designer/src/components/propertyeditor/newdynamicpropertydialog.cpp new file mode 100644 index 0000000..b9f0227 --- /dev/null +++ b/tools/designer/src/components/propertyeditor/newdynamicpropertydialog.cpp @@ -0,0 +1,170 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the Qt Designer of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "newdynamicpropertydialog.h" +#include "ui_newdynamicpropertydialog.h" +#include <abstractdialoggui_p.h> +#include <qdesigner_propertysheet_p.h> + +#include <QtGui/QPushButton> + +QT_BEGIN_NAMESPACE + +namespace qdesigner_internal { + +NewDynamicPropertyDialog::NewDynamicPropertyDialog(QDesignerDialogGuiInterface *dialogGui, + QWidget *parent) : + QDialog(parent), + m_dialogGui(dialogGui), + m_ui(new Ui::NewDynamicPropertyDialog) +{ + m_ui->setupUi(this); + connect(m_ui->m_lineEdit, SIGNAL(textChanged(QString)), this, SLOT(nameChanged(QString))); + + setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint); + + m_ui->m_comboBox->addItem(QLatin1String("String"), QVariant(QVariant::String)); + m_ui->m_comboBox->addItem(QLatin1String("StringList"), QVariant(QVariant::StringList)); + m_ui->m_comboBox->addItem(QLatin1String("Char"), QVariant(QVariant::Char)); + m_ui->m_comboBox->addItem(QLatin1String("ByteArray"), QVariant(QVariant::ByteArray)); + m_ui->m_comboBox->addItem(QLatin1String("Url"), QVariant(QVariant::Url)); + m_ui->m_comboBox->addItem(QLatin1String("Bool"), QVariant(QVariant::Bool)); + m_ui->m_comboBox->addItem(QLatin1String("Int"), QVariant(QVariant::Int)); + m_ui->m_comboBox->addItem(QLatin1String("UInt"), QVariant(QVariant::UInt)); + m_ui->m_comboBox->addItem(QLatin1String("LongLong"), QVariant(QVariant::LongLong)); + m_ui->m_comboBox->addItem(QLatin1String("ULongLong"), QVariant(QVariant::ULongLong)); + m_ui->m_comboBox->addItem(QLatin1String("Double"), QVariant(QVariant::Double)); + m_ui->m_comboBox->addItem(QLatin1String("Size"), QVariant(QVariant::Size)); + m_ui->m_comboBox->addItem(QLatin1String("SizeF"), QVariant(QVariant::SizeF)); + m_ui->m_comboBox->addItem(QLatin1String("Point"), QVariant(QVariant::Point)); + m_ui->m_comboBox->addItem(QLatin1String("PointF"), QVariant(QVariant::PointF)); + m_ui->m_comboBox->addItem(QLatin1String("Rect"), QVariant(QVariant::Rect)); + m_ui->m_comboBox->addItem(QLatin1String("RectF"), QVariant(QVariant::RectF)); + m_ui->m_comboBox->addItem(QLatin1String("Date"), QVariant(QVariant::Date)); + m_ui->m_comboBox->addItem(QLatin1String("Time"), QVariant(QVariant::Time)); + m_ui->m_comboBox->addItem(QLatin1String("DateTime"), QVariant(QVariant::DateTime)); + m_ui->m_comboBox->addItem(QLatin1String("Font"), QVariant(QVariant::Font)); + m_ui->m_comboBox->addItem(QLatin1String("Palette"), QVariant(QVariant::Palette)); + m_ui->m_comboBox->addItem(QLatin1String("Color"), QVariant(QVariant::Color)); + m_ui->m_comboBox->addItem(QLatin1String("Pixmap"), QVariant(QVariant::Pixmap)); + m_ui->m_comboBox->addItem(QLatin1String("Icon"), QVariant(QVariant::Icon)); + m_ui->m_comboBox->addItem(QLatin1String("Cursor"), QVariant(QVariant::Cursor)); + m_ui->m_comboBox->addItem(QLatin1String("SizePolicy"), QVariant(QVariant::SizePolicy)); + m_ui->m_comboBox->addItem(QLatin1String("KeySequence"), QVariant(QVariant::KeySequence)); + + m_ui->m_comboBox->setCurrentIndex(0); // String + setOkButtonEnabled(false); +} + +void NewDynamicPropertyDialog::setOkButtonEnabled(bool e) +{ + m_ui->m_buttonBox->button(QDialogButtonBox::Ok)->setEnabled(e); +} + +NewDynamicPropertyDialog::~NewDynamicPropertyDialog() +{ + delete m_ui; +} + +void NewDynamicPropertyDialog::setReservedNames(const QStringList &names) +{ + m_reservedNames = names; +} + +void NewDynamicPropertyDialog::setPropertyType(QVariant::Type t) +{ + const int index = m_ui->m_comboBox->findData(QVariant(t)); + if (index != -1) + m_ui->m_comboBox->setCurrentIndex(index); +} + +QString NewDynamicPropertyDialog::propertyName() const +{ + return m_ui->m_lineEdit->text(); +} + +QVariant NewDynamicPropertyDialog::propertyValue() const +{ + const int index = m_ui->m_comboBox->currentIndex(); + if (index == -1) + return QVariant(); + return m_ui->m_comboBox->itemData(index); +} + +void NewDynamicPropertyDialog::information(const QString &message) +{ + m_dialogGui->message(this, QDesignerDialogGuiInterface::PropertyEditorMessage, QMessageBox::Information, tr("Set Property Name"), message); +} + +void NewDynamicPropertyDialog::nameChanged(const QString &s) +{ + setOkButtonEnabled(!s.isEmpty()); +} + +bool NewDynamicPropertyDialog::validatePropertyName(const QString& name) +{ + if (m_reservedNames.contains(name)) { + information(tr("The current object already has a property named '%1'.\nPlease select another, unique one.").arg(name)); + return false; + } + if (!QDesignerPropertySheet::internalDynamicPropertiesEnabled() && name.startsWith(QLatin1String("_q_"))) { + information(tr("The '_q_' prefix is reserved for the Qt library.\nPlease select another name.")); + return false; + } + return true; +} + +void NewDynamicPropertyDialog::on_m_buttonBox_clicked(QAbstractButton *btn) +{ + const int role = m_ui->m_buttonBox->buttonRole(btn); + switch (role) { + case QDialogButtonBox::RejectRole: + reject(); + break; + case QDialogButtonBox::AcceptRole: + if (validatePropertyName(propertyName())) + accept(); + break; + } +} +} + +QT_END_NAMESPACE diff --git a/tools/designer/src/components/propertyeditor/newdynamicpropertydialog.h b/tools/designer/src/components/propertyeditor/newdynamicpropertydialog.h new file mode 100644 index 0000000..025f4fd --- /dev/null +++ b/tools/designer/src/components/propertyeditor/newdynamicpropertydialog.h @@ -0,0 +1,104 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the Qt Designer of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef NEWDYNAMICPROPERTYDIALOG_P_H +#define NEWDYNAMICPROPERTYDIALOG_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include "propertyeditor_global.h" +#include <QtGui/QDialog> +#include <QtCore/QVariant> + +QT_BEGIN_NAMESPACE + +class QAbstractButton; +class QDesignerDialogGuiInterface; + +namespace qdesigner_internal { + +namespace Ui +{ + class NewDynamicPropertyDialog; +} + +class QT_PROPERTYEDITOR_EXPORT NewDynamicPropertyDialog: public QDialog +{ + Q_OBJECT +public: + explicit NewDynamicPropertyDialog(QDesignerDialogGuiInterface *dialogGui, QWidget *parent = 0); + ~NewDynamicPropertyDialog(); + + void setReservedNames(const QStringList &names); + void setPropertyType(QVariant::Type t); + + QString propertyName() const; + QVariant propertyValue() const; + +private slots: + + void on_m_buttonBox_clicked(QAbstractButton *btn); + void nameChanged(const QString &); + +private: + bool validatePropertyName(const QString& name); + void setOkButtonEnabled(bool e); + void information(const QString &message); + + QDesignerDialogGuiInterface *m_dialogGui; + Ui::NewDynamicPropertyDialog *m_ui; + QStringList m_reservedNames; +}; + +} // namespace qdesigner_internal + +QT_END_NAMESPACE + +#endif // NEWDYNAMICPROPERTYDIALOG_P_H diff --git a/tools/designer/src/components/propertyeditor/newdynamicpropertydialog.ui b/tools/designer/src/components/propertyeditor/newdynamicpropertydialog.ui new file mode 100644 index 0000000..2aa91f3 --- /dev/null +++ b/tools/designer/src/components/propertyeditor/newdynamicpropertydialog.ui @@ -0,0 +1,106 @@ +<ui version="4.0" > + <class>qdesigner_internal::NewDynamicPropertyDialog</class> + <widget class="QDialog" name="qdesigner_internal::NewDynamicPropertyDialog" > + <property name="geometry" > + <rect> + <x>0</x> + <y>0</y> + <width>340</width> + <height>118</height> + </rect> + </property> + <property name="windowTitle" > + <string>Create Dynamic Property</string> + </property> + <layout class="QVBoxLayout" name="verticalLayout" > + <item> + <layout class="QFormLayout" name="formLayout" > + <item row="0" column="1" > + <widget class="QLineEdit" name="m_lineEdit" > + <property name="minimumSize" > + <size> + <width>220</width> + <height>0</height> + </size> + </property> + </widget> + </item> + <item row="0" column="0" > + <widget class="QLabel" name="label" > + <property name="sizePolicy" > + <sizepolicy vsizetype="Fixed" hsizetype="Preferred" > + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="text" > + <string>Property Name</string> + </property> + </widget> + </item> + <item row="1" column="1" > + <layout class="QHBoxLayout" name="horizontalLayout" > + <item> + <widget class="QComboBox" name="m_comboBox" /> + </item> + <item> + <spacer name="horizontalSpacer" > + <property name="spacerName" stdset="0" > + <string>horizontalSpacer</string> + </property> + <property name="orientation" > + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeHint" > + <size> + <width>40</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + </layout> + </item> + <item row="1" column="0" > + <widget class="QLabel" name="label_2" > + <property name="sizePolicy" > + <sizepolicy vsizetype="Fixed" hsizetype="Preferred" > + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="text" > + <string>Property Type</string> + </property> + </widget> + </item> + </layout> + </item> + <item> + <spacer> + <property name="spacerName" stdset="0" > + <string/> + </property> + <property name="orientation" > + <enum>Qt::Vertical</enum> + </property> + </spacer> + </item> + <item> + <widget class="QDialogButtonBox" name="m_buttonBox" > + <property name="orientation" > + <enum>Qt::Horizontal</enum> + </property> + <property name="standardButtons" > + <set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set> + </property> + <property name="centerButtons" > + <bool>false</bool> + </property> + </widget> + </item> + </layout> + </widget> + <resources/> + <connections/> +</ui> diff --git a/tools/designer/src/components/propertyeditor/paletteeditor.cpp b/tools/designer/src/components/propertyeditor/paletteeditor.cpp new file mode 100644 index 0000000..b0dc82b --- /dev/null +++ b/tools/designer/src/components/propertyeditor/paletteeditor.cpp @@ -0,0 +1,623 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the Qt Designer of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +/* +TRANSLATOR qdesigner_internal::PaletteEditor +*/ +/* +TRANSLATOR qdesigner_internal::PaletteModel +*/ + +#include "paletteeditor.h" + +#include <iconloader_p.h> +#include <qtcolorbutton.h> + +#include <QtDesigner/QDesignerFormEditorInterface> +#include <QtDesigner/QDesignerFormWindowManagerInterface> +#include <QtDesigner/QDesignerIconCacheInterface> + +#include <QtCore/QMetaProperty> +#include <QtGui/QPainter> +#include <QtGui/QToolButton> +#include <QtGui/QLabel> +#include <QtGui/QHeaderView> + +QT_BEGIN_NAMESPACE + +namespace qdesigner_internal { + +enum { BrushRole = 33 }; + +PaletteEditor::PaletteEditor(QDesignerFormEditorInterface *core, QWidget *parent) : + QDialog(parent), + m_currentColorGroup(QPalette::Active), + m_paletteModel(new PaletteModel(this)), + m_modelUpdated(false), + m_paletteUpdated(false), + m_compute(true), + m_core(core) +{ + ui.setupUi(this); + ui.paletteView->setModel(m_paletteModel); + updatePreviewPalette(); + updateStyledButton(); + ui.paletteView->setModel(m_paletteModel); + ColorDelegate *delegate = new ColorDelegate(core, this); + ui.paletteView->setItemDelegate(delegate); + ui.paletteView->setEditTriggers(QAbstractItemView::AllEditTriggers); + connect(m_paletteModel, SIGNAL(paletteChanged(const QPalette &)), + this, SLOT(paletteChanged(const QPalette &))); + ui.paletteView->setSelectionBehavior(QAbstractItemView::SelectRows); + ui.paletteView->setDragEnabled(true); + ui.paletteView->setDropIndicatorShown(true); + ui.paletteView->setRootIsDecorated(false); + ui.paletteView->setColumnHidden(2, true); + ui.paletteView->setColumnHidden(3, true); +} + +PaletteEditor::~PaletteEditor() +{ +} + +QPalette PaletteEditor::palette() const +{ + return m_editPalette; +} + +void PaletteEditor::setPalette(const QPalette &palette) +{ + m_editPalette = palette; + const uint mask = palette.resolve(); + for (int i = 0; i < (int)QPalette::NColorRoles; i++) { + if (!(mask & (1 << i))) { + m_editPalette.setBrush(QPalette::Active, static_cast<QPalette::ColorRole>(i), + m_parentPalette.brush(QPalette::Active, static_cast<QPalette::ColorRole>(i))); + m_editPalette.setBrush(QPalette::Inactive, static_cast<QPalette::ColorRole>(i), + m_parentPalette.brush(QPalette::Inactive, static_cast<QPalette::ColorRole>(i))); + m_editPalette.setBrush(QPalette::Disabled, static_cast<QPalette::ColorRole>(i), + m_parentPalette.brush(QPalette::Disabled, static_cast<QPalette::ColorRole>(i))); + } + } + m_editPalette.resolve(mask); + updatePreviewPalette(); + updateStyledButton(); + m_paletteUpdated = true; + if (!m_modelUpdated) + m_paletteModel->setPalette(m_editPalette, m_parentPalette); + m_paletteUpdated = false; +} + +void PaletteEditor::setPalette(const QPalette &palette, const QPalette &parentPalette) +{ + m_parentPalette = parentPalette; + setPalette(palette); +} + +void PaletteEditor::on_buildButton_colorChanged(const QColor &) +{ + buildPalette(); +} + +void PaletteEditor::on_activeRadio_clicked() +{ + m_currentColorGroup = QPalette::Active; + updatePreviewPalette(); +} + +void PaletteEditor::on_inactiveRadio_clicked() +{ + m_currentColorGroup = QPalette::Inactive; + updatePreviewPalette(); +} + +void PaletteEditor::on_disabledRadio_clicked() +{ + m_currentColorGroup = QPalette::Disabled; + updatePreviewPalette(); +} + +void PaletteEditor::on_computeRadio_clicked() +{ + if (m_compute) + return; + ui.paletteView->setColumnHidden(2, true); + ui.paletteView->setColumnHidden(3, true); + m_compute = true; + m_paletteModel->setCompute(true); +} + +void PaletteEditor::on_detailsRadio_clicked() +{ + if (!m_compute) + return; + const int w = ui.paletteView->columnWidth(1); + ui.paletteView->setColumnHidden(2, false); + ui.paletteView->setColumnHidden(3, false); + QHeaderView *header = ui.paletteView->header(); + header->resizeSection(1, w / 3); + header->resizeSection(2, w / 3); + header->resizeSection(3, w / 3); + m_compute = false; + m_paletteModel->setCompute(false); +} + +void PaletteEditor::paletteChanged(const QPalette &palette) +{ + m_modelUpdated = true; + if (!m_paletteUpdated) + setPalette(palette); + m_modelUpdated = false; +} + +void PaletteEditor::buildPalette() +{ + const QColor btn = ui.buildButton->color(); + const QPalette temp = QPalette(btn); + setPalette(temp); +} + +void PaletteEditor::updatePreviewPalette() +{ + const QPalette::ColorGroup g = currentColorGroup(); + // build the preview palette + const QPalette currentPalette = palette(); + QPalette previewPalette; + for (int i = QPalette::WindowText; i < QPalette::NColorRoles; i++) { + const QPalette::ColorRole r = static_cast<QPalette::ColorRole>(i); + const QBrush br = currentPalette.brush(g, r); + previewPalette.setBrush(QPalette::Active, r, br); + previewPalette.setBrush(QPalette::Inactive, r, br); + previewPalette.setBrush(QPalette::Disabled, r, br); + } + ui.previewFrame->setPreviewPalette(previewPalette); + + const bool enabled = g != QPalette::Disabled; + ui.previewFrame->setEnabled(enabled); + ui.previewFrame->setSubWindowActive(g != QPalette::Inactive); +} + +void PaletteEditor::updateStyledButton() +{ + ui.buildButton->setColor(palette().color(QPalette::Active, QPalette::Button)); +} + +QPalette PaletteEditor::getPalette(QDesignerFormEditorInterface *core, QWidget* parent, const QPalette &init, + const QPalette &parentPal, int *ok) +{ + PaletteEditor dlg(core, parent); + QPalette parentPalette(parentPal); + uint mask = init.resolve(); + for (int i = 0; i < (int)QPalette::NColorRoles; i++) { + if (!(mask & (1 << i))) { + parentPalette.setBrush(QPalette::Active, static_cast<QPalette::ColorRole>(i), + init.brush(QPalette::Active, static_cast<QPalette::ColorRole>(i))); + parentPalette.setBrush(QPalette::Inactive, static_cast<QPalette::ColorRole>(i), + init.brush(QPalette::Inactive, static_cast<QPalette::ColorRole>(i))); + parentPalette.setBrush(QPalette::Disabled, static_cast<QPalette::ColorRole>(i), + init.brush(QPalette::Disabled, static_cast<QPalette::ColorRole>(i))); + } + } + dlg.setPalette(init, parentPalette); + + const int result = dlg.exec(); + if (ok) *ok = result; + + return result == QDialog::Accepted ? dlg.palette() : init; +} + +////////////////////// + +PaletteModel::PaletteModel(QObject *parent) : + QAbstractTableModel(parent), + m_compute(true) +{ + const QMetaObject *meta = metaObject(); + const int index = meta->indexOfProperty("colorRole"); + const QMetaProperty p = meta->property(index); + const QMetaEnum e = p.enumerator(); + for (int r = QPalette::WindowText; r < QPalette::NColorRoles; r++) { + m_roleNames[static_cast<QPalette::ColorRole>(r)] = QLatin1String(e.key(r)); + } +} + +int PaletteModel::rowCount(const QModelIndex &) const +{ + return m_roleNames.count(); +} + +int PaletteModel::columnCount(const QModelIndex &) const +{ + return 4; +} + +QVariant PaletteModel::data(const QModelIndex &index, int role) const +{ + if (!index.isValid()) + return QVariant(); + if (index.row() < 0 || index.row() >= QPalette::NColorRoles) + return QVariant(); + if (index.column() < 0 || index.column() >= 4) + return QVariant(); + + if (index.column() == 0) { + if (role == Qt::DisplayRole) + return m_roleNames[static_cast<QPalette::ColorRole>(index.row())]; + if (role == Qt::EditRole) { + const uint mask = m_palette.resolve(); + if (mask & (1 << index.row())) + return true; + return false; + } + return QVariant(); + } + if (role == BrushRole) + return m_palette.brush(columnToGroup(index.column()), + static_cast<QPalette::ColorRole>(index.row())); + return QVariant(); +} + +bool PaletteModel::setData(const QModelIndex &index, const QVariant &value, int role) +{ + if (!index.isValid()) + return false; + + if (index.column() != 0 && role == BrushRole) { + const QBrush br = qVariantValue<QBrush>(value); + const QPalette::ColorRole r = static_cast<QPalette::ColorRole>(index.row()); + const QPalette::ColorGroup g = columnToGroup(index.column()); + m_palette.setBrush(g, r, br); + + QModelIndex idxBegin = PaletteModel::index(r, 0); + QModelIndex idxEnd = PaletteModel::index(r, 3); + if (m_compute) { + m_palette.setBrush(QPalette::Inactive, r, br); + switch (r) { + case QPalette::WindowText: + case QPalette::Text: + case QPalette::ButtonText: + case QPalette::Base: + break; + case QPalette::Dark: + m_palette.setBrush(QPalette::Disabled, QPalette::WindowText, br); + m_palette.setBrush(QPalette::Disabled, QPalette::Dark, br); + m_palette.setBrush(QPalette::Disabled, QPalette::Text, br); + m_palette.setBrush(QPalette::Disabled, QPalette::ButtonText, br); + idxBegin = PaletteModel::index(0, 0); + idxEnd = PaletteModel::index(m_roleNames.count() - 1, 3); + break; + case QPalette::Window: + m_palette.setBrush(QPalette::Disabled, QPalette::Base, br); + m_palette.setBrush(QPalette::Disabled, QPalette::Window, br); + idxBegin = PaletteModel::index(QPalette::Base, 0); + break; + case QPalette::Highlight: + //m_palette.setBrush(QPalette::Disabled, QPalette::Highlight, c.dark(120)); + break; + default: + m_palette.setBrush(QPalette::Disabled, r, br); + break; + } + } + emit paletteChanged(m_palette); + emit dataChanged(idxBegin, idxEnd); + return true; + } + if (index.column() == 0 && role == Qt::EditRole) { + uint mask = m_palette.resolve(); + const bool isMask = qVariantValue<bool>(value); + const int r = index.row(); + if (isMask) + mask |= (1 << r); + else { + m_palette.setBrush(QPalette::Active, static_cast<QPalette::ColorRole>(r), + m_parentPalette.brush(QPalette::Active, static_cast<QPalette::ColorRole>(r))); + m_palette.setBrush(QPalette::Inactive, static_cast<QPalette::ColorRole>(r), + m_parentPalette.brush(QPalette::Inactive, static_cast<QPalette::ColorRole>(r))); + m_palette.setBrush(QPalette::Disabled, static_cast<QPalette::ColorRole>(r), + m_parentPalette.brush(QPalette::Disabled, static_cast<QPalette::ColorRole>(r))); + + mask &= ~(1 << index.row()); + } + m_palette.resolve(mask); + emit paletteChanged(m_palette); + const QModelIndex idxEnd = PaletteModel::index(r, 3); + emit dataChanged(index, idxEnd); + return true; + } + return false; +} + +Qt::ItemFlags PaletteModel::flags(const QModelIndex &index) const +{ + if (!index.isValid()) + return Qt::ItemIsEnabled; + return Qt::ItemIsEditable | Qt::ItemIsEnabled; +} + +QVariant PaletteModel::headerData(int section, Qt::Orientation orientation, + int role) const +{ + if (orientation == Qt::Horizontal && role == Qt::DisplayRole) { + if (section == 0) + return tr("Color Role"); + if (section == groupToColumn(QPalette::Active)) + return tr("Active"); + if (section == groupToColumn(QPalette::Inactive)) + return tr("Inactive"); + if (section == groupToColumn(QPalette::Disabled)) + return tr("Disabled"); + } + return QVariant(); +} + +QPalette PaletteModel::getPalette() const +{ + return m_palette; +} + +void PaletteModel::setPalette(const QPalette &palette, const QPalette &parentPalette) +{ + m_parentPalette = parentPalette; + m_palette = palette; + const QModelIndex idxBegin = index(0, 0); + const QModelIndex idxEnd = index(m_roleNames.count() - 1, 3); + emit dataChanged(idxBegin, idxEnd); +} + +QPalette::ColorGroup PaletteModel::columnToGroup(int index) const +{ + if (index == 1) + return QPalette::Active; + if (index == 2) + return QPalette::Inactive; + return QPalette::Disabled; +} + +int PaletteModel::groupToColumn(QPalette::ColorGroup group) const +{ + if (group == QPalette::Active) + return 1; + if (group == QPalette::Inactive) + return 2; + return 3; +} + +////////////////////////// + +BrushEditor::BrushEditor(QDesignerFormEditorInterface *core, QWidget *parent) : + QWidget(parent), + m_button(new QtColorButton(this)), + m_changed(false), + m_core(core) +{ + QLayout *layout = new QHBoxLayout(this); + layout->setMargin(0); + layout->addWidget(m_button); + connect(m_button, SIGNAL(colorChanged(const QColor &)), this, SLOT(brushChanged())); + setFocusProxy(m_button); +} + +void BrushEditor::setBrush(const QBrush &brush) +{ + m_button->setColor(brush.color()); + m_changed = false; +} + +QBrush BrushEditor::brush() const +{ + return QBrush(m_button->color()); +} + +void BrushEditor::brushChanged() +{ + m_changed = true; + emit changed(this); +} + +bool BrushEditor::changed() const +{ + return m_changed; +} + +////////////////////////// + +RoleEditor::RoleEditor(QWidget *parent) : + QWidget(parent), + m_label(new QLabel(this)), + m_edited(false) +{ + QHBoxLayout *layout = new QHBoxLayout(this); + layout->setMargin(0); + layout->setSpacing(0); + + layout->addWidget(m_label); + m_label->setAutoFillBackground(true); + m_label->setIndent(3); // ### hardcode it should have the same value of textMargin in QItemDelegate + setFocusProxy(m_label); + + QToolButton *button = new QToolButton(this); + button->setToolButtonStyle(Qt::ToolButtonIconOnly); + button->setIcon(createIconSet(QLatin1String("resetproperty.png"))); + button->setIconSize(QSize(8,8)); + button->setSizePolicy(QSizePolicy(QSizePolicy::Fixed, QSizePolicy::MinimumExpanding)); + layout->addWidget(button); + connect(button, SIGNAL(clicked()), this, SLOT(emitResetProperty())); +} + +void RoleEditor::setLabel(const QString &label) +{ + m_label->setText(label); +} + +void RoleEditor::setEdited(bool on) +{ + QFont font; + if (on == true) { + font.setBold(on); + } + m_label->setFont(font); + m_edited = on; +} + +bool RoleEditor::edited() const +{ + return m_edited; +} + +void RoleEditor::emitResetProperty() +{ + setEdited(false); + emit changed(this); +} + +////////////////////////// +ColorDelegate::ColorDelegate(QDesignerFormEditorInterface *core, QObject *parent) : + QItemDelegate(parent), + m_core(core) +{ +} + +QWidget *ColorDelegate::createEditor(QWidget *parent, const QStyleOptionViewItem &, + const QModelIndex &index) const +{ + QWidget *ed = 0; + if (index.column() == 0) { + RoleEditor *editor = new RoleEditor(parent); + connect(editor, SIGNAL(changed(QWidget *)), this, SIGNAL(commitData(QWidget *))); + //editor->setFocusPolicy(Qt::NoFocus); + //editor->installEventFilter(const_cast<ColorDelegate *>(this)); + ed = editor; + } else { + BrushEditor *editor = new BrushEditor(m_core, parent); + connect(editor, SIGNAL(changed(QWidget *)), this, SIGNAL(commitData(QWidget *))); + editor->setFocusPolicy(Qt::NoFocus); + editor->installEventFilter(const_cast<ColorDelegate *>(this)); + ed = editor; + } + return ed; +} + +void ColorDelegate::setEditorData(QWidget *ed, const QModelIndex &index) const +{ + if (index.column() == 0) { + const bool mask = qVariantValue<bool>(index.model()->data(index, Qt::EditRole)); + RoleEditor *editor = static_cast<RoleEditor *>(ed); + editor->setEdited(mask); + const QString colorName = qVariantValue<QString>(index.model()->data(index, Qt::DisplayRole)); + editor->setLabel(colorName); + } else { + const QBrush br = qVariantValue<QBrush>(index.model()->data(index, BrushRole)); + BrushEditor *editor = static_cast<BrushEditor *>(ed); + editor->setBrush(br); + } +} + +void ColorDelegate::setModelData(QWidget *ed, QAbstractItemModel *model, + const QModelIndex &index) const +{ + if (index.column() == 0) { + RoleEditor *editor = static_cast<RoleEditor *>(ed); + const bool mask = editor->edited(); + model->setData(index, mask, Qt::EditRole); + } else { + BrushEditor *editor = static_cast<BrushEditor *>(ed); + if (editor->changed()) { + QBrush br = editor->brush(); + model->setData(index, br, BrushRole); + } + } +} + +void ColorDelegate::updateEditorGeometry(QWidget *ed, + const QStyleOptionViewItem &option, const QModelIndex &index) const +{ + QItemDelegate::updateEditorGeometry(ed, option, index); + ed->setGeometry(ed->geometry().adjusted(0, 0, -1, -1)); +} + +void ColorDelegate::paint(QPainter *painter, const QStyleOptionViewItem &opt, + const QModelIndex &index) const +{ + QStyleOptionViewItem option = opt; + const bool mask = qVariantValue<bool>(index.model()->data(index, Qt::EditRole)); + if (index.column() == 0 && mask) { + option.font.setBold(true); + } + QBrush br = qVariantValue<QBrush>(index.model()->data(index, BrushRole)); + if (br.style() == Qt::LinearGradientPattern || + br.style() == Qt::RadialGradientPattern || + br.style() == Qt::ConicalGradientPattern) { + painter->save(); + painter->translate(option.rect.x(), option.rect.y()); + painter->scale(option.rect.width(), option.rect.height()); + QGradient gr = *(br.gradient()); + gr.setCoordinateMode(QGradient::LogicalMode); + br = QBrush(gr); + painter->fillRect(0, 0, 1, 1, br); + painter->restore(); + } else { + painter->save(); + painter->setBrushOrigin(option.rect.x(), option.rect.y()); + painter->fillRect(option.rect, br); + painter->restore(); + } + QItemDelegate::paint(painter, option, index); + + + const QColor color = static_cast<QRgb>(QApplication::style()->styleHint(QStyle::SH_Table_GridLineColor, &option)); + const QPen oldPen = painter->pen(); + painter->setPen(QPen(color)); + + painter->drawLine(option.rect.right(), option.rect.y(), + option.rect.right(), option.rect.bottom()); + painter->drawLine(option.rect.x(), option.rect.bottom(), + option.rect.right(), option.rect.bottom()); + painter->setPen(oldPen); +} + +QSize ColorDelegate::sizeHint(const QStyleOptionViewItem &opt, const QModelIndex &index) const +{ + return QItemDelegate::sizeHint(opt, index) + QSize(4, 4); +} +} + +QT_END_NAMESPACE diff --git a/tools/designer/src/components/propertyeditor/paletteeditor.h b/tools/designer/src/components/propertyeditor/paletteeditor.h new file mode 100644 index 0000000..f501968 --- /dev/null +++ b/tools/designer/src/components/propertyeditor/paletteeditor.h @@ -0,0 +1,204 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the Qt Designer of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef PALETTEEDITOR_H +#define PALETTEEDITOR_H + +#include "ui_paletteeditor.h" +#include <QtGui/QItemDelegate> + +QT_BEGIN_NAMESPACE + +class QListView; +class QLabel; +class QtColorButton; +class QDesignerFormEditorInterface; + +namespace qdesigner_internal { + +class PaletteEditor: public QDialog +{ + Q_OBJECT +public: + virtual ~PaletteEditor(); + + static QPalette getPalette(QDesignerFormEditorInterface *core, + QWidget* parent, const QPalette &init = QPalette(), + const QPalette &parentPal = QPalette(), int *result = 0); + + QPalette palette() const; + void setPalette(const QPalette &palette); + void setPalette(const QPalette &palette, const QPalette &parentPalette); + +private slots: + + void on_buildButton_colorChanged(const QColor &); + void on_activeRadio_clicked(); + void on_inactiveRadio_clicked(); + void on_disabledRadio_clicked(); + void on_computeRadio_clicked(); + void on_detailsRadio_clicked(); + + void paletteChanged(const QPalette &palette); + +protected: + +private: + PaletteEditor(QDesignerFormEditorInterface *core, QWidget *parent); + void buildPalette(); + + void updatePreviewPalette(); + void updateStyledButton(); + + QPalette::ColorGroup currentColorGroup() const + { return m_currentColorGroup; } + + Ui::PaletteEditor ui; + QPalette m_editPalette; + QPalette m_parentPalette; + QPalette::ColorGroup m_currentColorGroup; + class PaletteModel *m_paletteModel; + bool m_modelUpdated; + bool m_paletteUpdated; + bool m_compute; + QDesignerFormEditorInterface *m_core; +}; + + +class PaletteModel : public QAbstractTableModel +{ + Q_OBJECT + Q_PROPERTY(QPalette::ColorRole colorRole READ colorRole) +public: + explicit PaletteModel(QObject *parent = 0); + + int rowCount(const QModelIndex &parent = QModelIndex()) const; + int columnCount(const QModelIndex &parent = QModelIndex()) const; + QVariant data(const QModelIndex &index, int role) const; + bool setData(const QModelIndex &index, const QVariant &value, int role); + Qt::ItemFlags flags(const QModelIndex &index) const; + QVariant headerData(int section, Qt::Orientation orientation, + int role = Qt::DisplayRole) const; + + QPalette getPalette() const; + void setPalette(const QPalette &palette, const QPalette &parentPalette); + + QPalette::ColorRole colorRole() const { return QPalette::NoRole; } + void setCompute(bool on) { m_compute = on; } +signals: + void paletteChanged(const QPalette &palette); +private: + + QPalette::ColorGroup columnToGroup(int index) const; + int groupToColumn(QPalette::ColorGroup group) const; + + QPalette m_palette; + QPalette m_parentPalette; + QMap<QPalette::ColorRole, QString> m_roleNames; + bool m_compute; +}; + +class BrushEditor : public QWidget +{ + Q_OBJECT +public: + explicit BrushEditor(QDesignerFormEditorInterface *core, QWidget *parent = 0); + + void setBrush(const QBrush &brush); + QBrush brush() const; + bool changed() const; +signals: + void changed(QWidget *widget); +private slots: + void brushChanged(); +private: + QtColorButton *m_button; + bool m_changed; + QDesignerFormEditorInterface *m_core; +}; + +class RoleEditor : public QWidget +{ + Q_OBJECT +public: + explicit RoleEditor(QWidget *parent = 0); + + void setLabel(const QString &label); + void setEdited(bool on); + bool edited() const; +signals: + void changed(QWidget *widget); +private slots: + void emitResetProperty(); +private: + QLabel *m_label; + bool m_edited; +}; + +class ColorDelegate : public QItemDelegate +{ + Q_OBJECT + +public: + explicit ColorDelegate(QDesignerFormEditorInterface *core, QObject *parent = 0); + + QWidget *createEditor(QWidget *parent, const QStyleOptionViewItem &option, + const QModelIndex &index) const; + + void setEditorData(QWidget *ed, const QModelIndex &index) const; + void setModelData(QWidget *ed, QAbstractItemModel *model, + const QModelIndex &index) const; + + void updateEditorGeometry(QWidget *ed, + const QStyleOptionViewItem &option, const QModelIndex &index) const; + + virtual void paint(QPainter *painter, const QStyleOptionViewItem &opt, + const QModelIndex &index) const; + virtual QSize sizeHint(const QStyleOptionViewItem &opt, const QModelIndex &index) const; +private: + QDesignerFormEditorInterface *m_core; +}; + +} // namespace qdesigner_internal + +QT_END_NAMESPACE + +#endif // PALETTEEDITOR_H diff --git a/tools/designer/src/components/propertyeditor/paletteeditor.ui b/tools/designer/src/components/propertyeditor/paletteeditor.ui new file mode 100644 index 0000000..55ef5ac --- /dev/null +++ b/tools/designer/src/components/propertyeditor/paletteeditor.ui @@ -0,0 +1,264 @@ +<ui version="4.0" > + <comment>********************************************************************* +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the Qt Designer of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +*********************************************************************</comment> + <class>qdesigner_internal::PaletteEditor</class> + <widget class="QDialog" name="qdesigner_internal::PaletteEditor" > + <property name="geometry" > + <rect> + <x>0</x> + <y>0</y> + <width>365</width> + <height>409</height> + </rect> + </property> + <property name="sizePolicy" > + <sizepolicy> + <hsizetype>7</hsizetype> + <vsizetype>7</vsizetype> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="windowTitle" > + <string>Edit Palette</string> + </property> + <layout class="QVBoxLayout" > + <property name="margin" > + <number>9</number> + </property> + <property name="spacing" > + <number>6</number> + </property> + <item> + <widget class="QGroupBox" name="advancedBox" > + <property name="minimumSize" > + <size> + <width>0</width> + <height>0</height> + </size> + </property> + <property name="maximumSize" > + <size> + <width>16777215</width> + <height>16777215</height> + </size> + </property> + <property name="title" > + <string>Tune Palette</string> + </property> + <layout class="QGridLayout" > + <property name="margin" > + <number>9</number> + </property> + <property name="spacing" > + <number>6</number> + </property> + <item row="0" column="1" > + <widget class="QtColorButton" name="buildButton" > + <property name="sizePolicy" > + <sizepolicy> + <hsizetype>7</hsizetype> + <vsizetype>13</vsizetype> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="text" > + <string/> + </property> + </widget> + </item> + <item row="1" column="0" colspan="4" > + <widget class="QTreeView" name="paletteView" > + <property name="minimumSize" > + <size> + <width>0</width> + <height>200</height> + </size> + </property> + </widget> + </item> + <item row="0" column="3" > + <widget class="QRadioButton" name="detailsRadio" > + <property name="text" > + <string>Show Details</string> + </property> + </widget> + </item> + <item row="0" column="2" > + <widget class="QRadioButton" name="computeRadio" > + <property name="text" > + <string>Compute Details</string> + </property> + <property name="checked" > + <bool>true</bool> + </property> + </widget> + </item> + <item row="0" column="0" > + <widget class="QLabel" name="label" > + <property name="text" > + <string>Quick</string> + </property> + </widget> + </item> + </layout> + </widget> + </item> + <item> + <widget class="QGroupBox" name="GroupBox126" > + <property name="sizePolicy" > + <sizepolicy> + <hsizetype>5</hsizetype> + <vsizetype>7</vsizetype> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="title" > + <string>Preview</string> + </property> + <layout class="QGridLayout" > + <property name="margin" > + <number>8</number> + </property> + <property name="spacing" > + <number>6</number> + </property> + <item row="0" column="2" > + <widget class="QRadioButton" name="disabledRadio" > + <property name="text" > + <string>Disabled</string> + </property> + </widget> + </item> + <item row="0" column="1" > + <widget class="QRadioButton" name="inactiveRadio" > + <property name="text" > + <string>Inactive</string> + </property> + </widget> + </item> + <item row="0" column="0" > + <widget class="QRadioButton" name="activeRadio" > + <property name="text" > + <string>Active</string> + </property> + <property name="checked" > + <bool>true</bool> + </property> + </widget> + </item> + <item row="1" column="0" colspan="3" > + <widget class="qdesigner_internal::PreviewFrame" native="1" name="previewFrame" > + <property name="sizePolicy" > + <sizepolicy> + <hsizetype>7</hsizetype> + <vsizetype>7</vsizetype> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + </widget> + </item> + </layout> + </widget> + </item> + <item> + <widget class="QDialogButtonBox" name="buttonBox" > + <property name="orientation" > + <enum>Qt::Horizontal</enum> + </property> + <property name="standardButtons" > + <set>QDialogButtonBox::Cancel|QDialogButtonBox::NoButton|QDialogButtonBox::Ok</set> + </property> + </widget> + </item> + </layout> + </widget> + <customwidgets> + <customwidget> + <class>QtColorButton</class> + <extends>QToolButton</extends> + <header>qtcolorbutton.h</header> + </customwidget> + <customwidget> + <class>qdesigner_internal::PreviewFrame</class> + <extends>QWidget</extends> + <header>previewframe.h</header> + </customwidget> + </customwidgets> + <resources/> + <connections> + <connection> + <sender>buttonBox</sender> + <signal>accepted()</signal> + <receiver>qdesigner_internal::PaletteEditor</receiver> + <slot>accept()</slot> + <hints> + <hint type="sourcelabel" > + <x>180</x> + <y>331</y> + </hint> + <hint type="destinationlabel" > + <x>134</x> + <y>341</y> + </hint> + </hints> + </connection> + <connection> + <sender>buttonBox</sender> + <signal>rejected()</signal> + <receiver>qdesigner_internal::PaletteEditor</receiver> + <slot>reject()</slot> + <hints> + <hint type="sourcelabel" > + <x>287</x> + <y>329</y> + </hint> + <hint type="destinationlabel" > + <x>302</x> + <y>342</y> + </hint> + </hints> + </connection> + </connections> +</ui> diff --git a/tools/designer/src/components/propertyeditor/paletteeditorbutton.cpp b/tools/designer/src/components/propertyeditor/paletteeditorbutton.cpp new file mode 100644 index 0000000..d7a76b9 --- /dev/null +++ b/tools/designer/src/components/propertyeditor/paletteeditorbutton.cpp @@ -0,0 +1,92 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the Qt Designer of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +/* +TRANSLATOR qdesigner_internal::PaletteEditorButton +*/ + +#include "paletteeditorbutton.h" +#include "paletteeditor.h" + +#include <QtCore/qdebug.h> + +QT_BEGIN_NAMESPACE + +using namespace qdesigner_internal; + +PaletteEditorButton::PaletteEditorButton(QDesignerFormEditorInterface *core, const QPalette &palette, QWidget *parent) + : QToolButton(parent), + m_palette(palette) +{ + m_core = core; + setFocusPolicy(Qt::NoFocus); + setText(tr("Change Palette")); + setSizePolicy(QSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed)); + + connect(this, SIGNAL(clicked()), this, SLOT(showPaletteEditor())); +} + +PaletteEditorButton::~PaletteEditorButton() +{ +} + +void PaletteEditorButton::setPalette(const QPalette &palette) +{ + m_palette = palette; +} + +void PaletteEditorButton::setSuperPalette(const QPalette &palette) +{ + m_superPalette = palette; +} + +void PaletteEditorButton::showPaletteEditor() +{ + int result; + QPalette p = QPalette(); + QPalette pal = PaletteEditor::getPalette(m_core, 0, m_palette, m_superPalette, &result); + if (result == QDialog::Accepted) { + m_palette = pal; + emit paletteChanged(m_palette); + } +} + +QT_END_NAMESPACE diff --git a/tools/designer/src/components/propertyeditor/paletteeditorbutton.h b/tools/designer/src/components/propertyeditor/paletteeditorbutton.h new file mode 100644 index 0000000..dea9221 --- /dev/null +++ b/tools/designer/src/components/propertyeditor/paletteeditorbutton.h @@ -0,0 +1,86 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the Qt Designer of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef PALETTEEDITORBUTTON_H +#define PALETTEEDITORBUTTON_H + +#include "propertyeditor_global.h" + +#include <QtGui/QPalette> +#include <QtGui/QToolButton> + +#include "abstractformeditor.h" + +QT_BEGIN_NAMESPACE + +namespace qdesigner_internal { + +class QT_PROPERTYEDITOR_EXPORT PaletteEditorButton: public QToolButton +{ + Q_OBJECT +public: + PaletteEditorButton(QDesignerFormEditorInterface *core, const QPalette &palette, QWidget *parent = 0); + virtual ~PaletteEditorButton(); + + void setSuperPalette(const QPalette &palette); + inline QPalette palette() const + { return m_palette; } + +signals: + void paletteChanged(const QPalette &palette); + +public slots: + void setPalette(const QPalette &palette); + +private slots: + void showPaletteEditor(); + +private: + QPalette m_palette; + QPalette m_superPalette; + QDesignerFormEditorInterface *m_core; +}; + +} // namespace qdesigner_internal + +QT_END_NAMESPACE + +#endif // PALETTEEDITORBUTTON_H diff --git a/tools/designer/src/components/propertyeditor/previewframe.cpp b/tools/designer/src/components/propertyeditor/previewframe.cpp new file mode 100644 index 0000000..95d533d --- /dev/null +++ b/tools/designer/src/components/propertyeditor/previewframe.cpp @@ -0,0 +1,123 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the Qt Designer of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +/* +TRANSLATOR qdesigner_internal::PreviewWorkspace +*/ + +#include "previewframe.h" +#include "previewwidget.h" + +#include <QtGui/QPainter> +#include <QtGui/QMdiArea> +#include <QtGui/QMdiSubWindow> +#include <QtGui/QPaintEvent> +#include <qdebug.h> + +QT_BEGIN_NAMESPACE + +namespace { + class PreviewMdiArea: public QMdiArea { + public: + PreviewMdiArea(QWidget *parent = 0) : QMdiArea(parent) {} + protected: + bool viewportEvent ( QEvent * event ); + }; + + bool PreviewMdiArea::viewportEvent (QEvent * event) { + if (event->type() != QEvent::Paint) + return QMdiArea::viewportEvent (event); + QWidget *paintWidget = viewport(); + QPainter p(paintWidget); + p.fillRect(rect(), paintWidget->palette().color(backgroundRole()).dark()); + p.setPen(QPen(Qt::white)); + p.drawText(0, height() / 2, width(), height(), Qt::AlignHCenter, + tr("The moose in the noose\nate the goose who was loose.")); + return true; + } +} + +namespace qdesigner_internal { + +PreviewFrame::PreviewFrame(QWidget *parent) : + QFrame(parent), + m_mdiArea(new PreviewMdiArea(this)) +{ + m_mdiArea->setHorizontalScrollBarPolicy(Qt::ScrollBarAsNeeded); + m_mdiArea->setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded); + setFrameStyle(QFrame::StyledPanel | QFrame::Sunken); + setLineWidth(1); + + QVBoxLayout *vbox = new QVBoxLayout(this); + vbox->setMargin(0); + vbox->addWidget(m_mdiArea); + + setMinimumSize(ensureMdiSubWindow()->minimumSizeHint()); +} + +void PreviewFrame::setPreviewPalette(const QPalette &pal) +{ + ensureMdiSubWindow()->widget()->setPalette(pal); +} + +void PreviewFrame::setSubWindowActive(bool active) +{ + m_mdiArea->setActiveSubWindow (active ? ensureMdiSubWindow() : static_cast<QMdiSubWindow *>(0)); +} + +QMdiSubWindow *PreviewFrame::ensureMdiSubWindow() +{ + if (!m_mdiSubWindow) { + PreviewWidget *previewWidget = new PreviewWidget(m_mdiArea); + m_mdiSubWindow = m_mdiArea->addSubWindow(previewWidget, Qt::WindowTitleHint | Qt::WindowMinimizeButtonHint | Qt::WindowMaximizeButtonHint); + m_mdiSubWindow->move(10,10); + m_mdiSubWindow->showMaximized(); + } + + const Qt::WindowStates state = m_mdiSubWindow->windowState(); + if (state & Qt::WindowMinimized) + m_mdiSubWindow->setWindowState(state & ~Qt::WindowMinimized); + + return m_mdiSubWindow; +} +} + +QT_END_NAMESPACE diff --git a/tools/designer/src/components/propertyeditor/previewframe.h b/tools/designer/src/components/propertyeditor/previewframe.h new file mode 100644 index 0000000..678a7ab --- /dev/null +++ b/tools/designer/src/components/propertyeditor/previewframe.h @@ -0,0 +1,76 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the Qt Designer of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef PREVIEWFRAME_H +#define PREVIEWFRAME_H + +#include <QtGui/QFrame> +#include <QtCore/QPointer> + +QT_BEGIN_NAMESPACE + +class QMdiArea; +class QMdiSubWindow; + +namespace qdesigner_internal { + +class PreviewFrame: public QFrame +{ + Q_OBJECT +public: + explicit PreviewFrame(QWidget *parent); + + void setPreviewPalette(const QPalette &palette); + void setSubWindowActive(bool active); + +private: + // The user can on some platforms close the mdi child by invoking the system menu. + // Ensure a child is present. + QMdiSubWindow *ensureMdiSubWindow(); + QMdiArea *m_mdiArea; + QPointer<QMdiSubWindow> m_mdiSubWindow; +}; + +} // namespace qdesigner_internal + +QT_END_NAMESPACE + +#endif diff --git a/tools/designer/src/components/propertyeditor/previewwidget.cpp b/tools/designer/src/components/propertyeditor/previewwidget.cpp new file mode 100644 index 0000000..fa458e7 --- /dev/null +++ b/tools/designer/src/components/propertyeditor/previewwidget.cpp @@ -0,0 +1,59 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the Qt Designer of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "previewwidget.h" + +QT_BEGIN_NAMESPACE + +using namespace qdesigner_internal; + +PreviewWidget::PreviewWidget(QWidget *parent) + : QWidget(parent) +{ + ui.setupUi(this); +} + +PreviewWidget::~PreviewWidget() +{ +} + + +QT_END_NAMESPACE diff --git a/tools/designer/src/components/propertyeditor/previewwidget.h b/tools/designer/src/components/propertyeditor/previewwidget.h new file mode 100644 index 0000000..38690d5 --- /dev/null +++ b/tools/designer/src/components/propertyeditor/previewwidget.h @@ -0,0 +1,66 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the Qt Designer of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef PREVIEWWIDGET_H +#define PREVIEWWIDGET_H + +#include "ui_previewwidget.h" + +QT_BEGIN_NAMESPACE + +namespace qdesigner_internal { + +class PreviewWidget: public QWidget +{ + Q_OBJECT +public: + explicit PreviewWidget(QWidget *parent); + virtual ~PreviewWidget(); + +private: + Ui::PreviewWidget ui; +}; + +} // namespace qdesigner_internal + +QT_END_NAMESPACE + +#endif // PREVIEWWIDGET_H diff --git a/tools/designer/src/components/propertyeditor/previewwidget.ui b/tools/designer/src/components/propertyeditor/previewwidget.ui new file mode 100644 index 0000000..c61f0d6 --- /dev/null +++ b/tools/designer/src/components/propertyeditor/previewwidget.ui @@ -0,0 +1,238 @@ +<ui version="4.0" > + <comment>********************************************************************* +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the Qt Designer of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +*********************************************************************</comment> + <class>qdesigner_internal::PreviewWidget</class> + <widget class="QWidget" name="qdesigner_internal::PreviewWidget" > + <property name="geometry" > + <rect> + <x>0</x> + <y>0</y> + <width>471</width> + <height>251</height> + </rect> + </property> + <property name="sizePolicy" > + <sizepolicy> + <hsizetype>1</hsizetype> + <vsizetype>1</vsizetype> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="windowTitle" > + <string>Preview Window</string> + </property> + <layout class="QGridLayout" > + <property name="margin" > + <number>9</number> + </property> + <property name="spacing" > + <number>6</number> + </property> + <item rowspan="3" row="0" column="1" > + <layout class="QVBoxLayout" > + <property name="margin" > + <number>0</number> + </property> + <property name="spacing" > + <number>6</number> + </property> + <item> + <widget class="QLineEdit" name="LineEdit1" > + <property name="text" > + <string>LineEdit</string> + </property> + </widget> + </item> + <item> + <widget class="QComboBox" name="ComboBox1" > + <item> + <property name="text" > + <string>ComboBox</string> + </property> + </item> + </widget> + </item> + <item> + <layout class="QHBoxLayout" > + <property name="margin" > + <number>0</number> + </property> + <property name="spacing" > + <number>6</number> + </property> + <item> + <widget class="QSpinBox" name="SpinBox1" /> + </item> + <item> + <widget class="QPushButton" name="PushButton1" > + <property name="text" > + <string>PushButton</string> + </property> + </widget> + </item> + </layout> + </item> + <item> + <widget class="QScrollBar" name="ScrollBar1" > + <property name="orientation" > + <enum>Qt::Horizontal</enum> + </property> + </widget> + </item> + <item> + <widget class="QSlider" name="Slider1" > + <property name="orientation" > + <enum>Qt::Horizontal</enum> + </property> + </widget> + </item> + <item> + <widget class="QListWidget" name="listWidget" > + <property name="maximumSize" > + <size> + <width>32767</width> + <height>50</height> + </size> + </property> + </widget> + </item> + </layout> + </item> + <item row="3" column="0" colspan="2" > + <spacer> + <property name="orientation" > + <enum>Qt::Vertical</enum> + </property> + <property name="sizeType" > + <enum>QSizePolicy::Expanding</enum> + </property> + <property name="sizeHint" > + <size> + <width>20</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + <item row="2" column="0" > + <widget class="QProgressBar" name="ProgressBar1" > + <property name="orientation" > + <enum>Qt::Horizontal</enum> + </property> + </widget> + </item> + <item row="1" column="0" > + <widget class="QGroupBox" name="ButtonGroup2" > + <property name="title" > + <string>ButtonGroup2</string> + </property> + <layout class="QVBoxLayout" > + <property name="margin" > + <number>9</number> + </property> + <property name="spacing" > + <number>6</number> + </property> + <item> + <widget class="QCheckBox" name="CheckBox1" > + <property name="text" > + <string>CheckBox1</string> + </property> + <property name="checked" > + <bool>true</bool> + </property> + </widget> + </item> + <item> + <widget class="QCheckBox" name="CheckBox2" > + <property name="text" > + <string>CheckBox2</string> + </property> + </widget> + </item> + </layout> + </widget> + </item> + <item row="0" column="0" > + <widget class="QGroupBox" name="ButtonGroup1" > + <property name="title" > + <string>ButtonGroup</string> + </property> + <layout class="QVBoxLayout" > + <property name="margin" > + <number>9</number> + </property> + <property name="spacing" > + <number>6</number> + </property> + <item> + <widget class="QRadioButton" name="RadioButton1" > + <property name="text" > + <string>RadioButton1</string> + </property> + <property name="checked" > + <bool>true</bool> + </property> + </widget> + </item> + <item> + <widget class="QRadioButton" name="RadioButton2" > + <property name="text" > + <string>RadioButton2</string> + </property> + </widget> + </item> + <item> + <widget class="QRadioButton" name="RadioButton3" > + <property name="text" > + <string>RadioButton3</string> + </property> + </widget> + </item> + </layout> + </widget> + </item> + </layout> + </widget> + <resources/> + <connections/> +</ui> diff --git a/tools/designer/src/components/propertyeditor/propertyeditor.cpp b/tools/designer/src/components/propertyeditor/propertyeditor.cpp new file mode 100644 index 0000000..63b57d8 --- /dev/null +++ b/tools/designer/src/components/propertyeditor/propertyeditor.cpp @@ -0,0 +1,1245 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the Qt Designer of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "propertyeditor.h" + +#include "qttreepropertybrowser.h" +#include "qtbuttonpropertybrowser.h" +#include "qtvariantproperty.h" +#include "designerpropertymanager.h" +#include "qdesigner_propertysheet_p.h" +#include "formwindowbase_p.h" +#include "filterwidget_p.h" // For FilterWidget + +#include "newdynamicpropertydialog.h" +#include "dynamicpropertysheet.h" +#include "shared_enums_p.h" + +// sdk +#include <QtDesigner/QDesignerFormEditorInterface> +#include <QtDesigner/QDesignerFormWindowManagerInterface> +#include <QtDesigner/QExtensionManager> +#include <QtDesigner/QDesignerPropertySheetExtension> +#include <QtDesigner/QDesignerWidgetDataBaseInterface> +#include <QtDesigner/private/abstractsettings_p.h> +// shared +#include <qdesigner_utils_p.h> +#include <qdesigner_propertycommand_p.h> +#include <metadatabase_p.h> +#include <iconloader_p.h> +#ifdef Q_OS_WIN +# include <widgetfactory_p.h> +#endif +#include <QtGui/QAction> +#include <QtGui/QLineEdit> +#include <QtGui/QMenu> +#include <QtGui/QApplication> +#include <QtGui/QVBoxLayout> +#include <QtGui/QScrollArea> +#include <QtGui/QStackedWidget> +#include <QtGui/QToolBar> +#include <QtGui/QToolButton> +#include <QtGui/QActionGroup> +#include <QtGui/QLabel> + +#include <QtCore/QDebug> +#include <QtCore/QTextStream> + +static const char *SettingsGroupC = "PropertyEditor"; +#if QT_VERSION >= 0x040500 +static const char *ViewKeyC = "View"; +#endif +static const char *ColorKeyC = "Colored"; +static const char *SortedKeyC = "Sorted"; +static const char *ExpansionKeyC = "ExpandedItems"; + +enum SettingsView { TreeView, ButtonView }; + +QT_BEGIN_NAMESPACE + +// --------------------------------------------------------------------------------- + +namespace qdesigner_internal { +// ----------- PropertyEditor::Strings + +PropertyEditor::Strings::Strings() : + m_fontProperty(QLatin1String("font")), + m_qLayoutWidget(QLatin1String("QLayoutWidget")), + m_designerPrefix(QLatin1String("QDesigner")), + m_layout(QLatin1String("Layout")), + m_validationModeAttribute(QLatin1String("validationMode")), + m_fontAttribute(QLatin1String("font")), + m_superPaletteAttribute(QLatin1String("superPalette")), + m_enumNamesAttribute(QLatin1String("enumNames")), + m_resettableAttribute(QLatin1String("resettable")), + m_flagsAttribute(QLatin1String("flags")) +{ + m_alignmentProperties.insert(QLatin1String("alignment")); + m_alignmentProperties.insert(QLatin1String("layoutLabelAlignment")); // QFormLayout + m_alignmentProperties.insert(QLatin1String("layoutFormAlignment")); +} + +// ----------- PropertyEditor + +QDesignerMetaDataBaseItemInterface* PropertyEditor::metaDataBaseItem() const +{ + QObject *o = object(); + if (!o) + return 0; + QDesignerMetaDataBaseInterface *db = core()->metaDataBase(); + if (!db) + return 0; + return db->item(o); +} + +void PropertyEditor::setupStringProperty(QtVariantProperty *property, bool isMainContainer) +{ + const StringPropertyParameters params = textPropertyValidationMode(core(), m_object, property->propertyName(), isMainContainer); + // Does a meta DB entry exist - add comment + const bool hasComment = params.second; + property->setAttribute(m_strings.m_validationModeAttribute, params.first); + // assuming comment cannot appear or disappear for the same property in different object instance + if (!hasComment) { + QList<QtProperty *> commentProperties = property->subProperties(); + if (commentProperties.count() > 0) + delete commentProperties.at(0); + if (commentProperties.count() > 1) + delete commentProperties.at(1); + } +} + +void PropertyEditor::setupPaletteProperty(QtVariantProperty *property) +{ + QPalette value = qvariant_cast<QPalette>(property->value()); + QPalette superPalette = QPalette(); + QWidget *currentWidget = qobject_cast<QWidget *>(m_object); + if (currentWidget) { + if (currentWidget->isWindow()) + superPalette = QApplication::palette(currentWidget); + else { + if (currentWidget->parentWidget()) + superPalette = currentWidget->parentWidget()->palette(); + } + } + m_updatingBrowser = true; + property->setAttribute(m_strings.m_superPaletteAttribute, superPalette); + m_updatingBrowser = false; +} + +static inline QToolButton *createDropDownButton(QAction *defaultAction, QWidget *parent = 0) +{ + QToolButton *rc = new QToolButton(parent); + rc->setDefaultAction(defaultAction); + rc->setPopupMode(QToolButton::InstantPopup); + return rc; +} + +PropertyEditor::PropertyEditor(QDesignerFormEditorInterface *core, QWidget *parent, Qt::WindowFlags flags) : + QDesignerPropertyEditor(parent, flags), + m_core(core), + m_propertySheet(0), + m_currentBrowser(0), + m_treeBrowser(0), + m_propertyManager(new DesignerPropertyManager(m_core, this)), + m_dynamicGroup(0), + m_updatingBrowser(false), + m_stackedWidget(new QStackedWidget), + m_filterWidget(new FilterWidget(0, FilterWidget::LayoutAlignNone)), + m_buttonIndex(-1), + m_treeIndex(-1), + m_addDynamicAction(new QAction(createIconSet(QLatin1String("plus.png")), tr("Add Dynamic Property..."), this)), + m_removeDynamicAction(new QAction(createIconSet(QLatin1String("minus.png")), tr("Remove Dynamic Property"), this)), + m_sortingAction(new QAction(createIconSet(QLatin1String("sort.png")), tr("Sorting"), this)), + m_coloringAction(new QAction(createIconSet(QLatin1String("color.png")), tr("Color Groups"), this)), + m_treeAction(new QAction(tr("Tree View"), this)), + m_buttonAction(new QAction(tr("Drop Down Button View"), this)), + m_classLabel(new QLabel), + m_sorting(false), + m_coloring(false), + m_brightness(false) +{ + QVector<QColor> colors; + colors.reserve(6); + colors.push_back(QColor(255, 230, 191)); + colors.push_back(QColor(255, 255, 191)); + colors.push_back(QColor(191, 255, 191)); + colors.push_back(QColor(199, 255, 255)); + colors.push_back(QColor(234, 191, 255)); + colors.push_back(QColor(255, 191, 239)); + m_colors.reserve(colors.count()); + for (int i = 0; i < colors.count(); i++) { + QColor c = colors.at(i); + m_colors.push_back(qMakePair(c, c.darker(150))); + } + QColor dynamicColor(191, 207, 255); + QColor layoutColor(255, 191, 191); + m_dynamicColor = qMakePair(dynamicColor, dynamicColor.darker(150)); + m_layoutColor = qMakePair(layoutColor, layoutColor.darker(150)); + + updateForegroundBrightness(); + + QActionGroup *actionGroup = new QActionGroup(this); + + m_treeAction->setCheckable(true); + m_treeAction->setIcon(createIconSet(QLatin1String("widgets/listview.png"))); + m_buttonAction->setCheckable(true); + m_buttonAction->setIcon(createIconSet(QLatin1String("dropdownbutton.png"))); + + actionGroup->addAction(m_treeAction); + actionGroup->addAction(m_buttonAction); + connect(actionGroup, SIGNAL(triggered(QAction*)), this, SLOT(slotViewTriggered(QAction*))); + + QWidget *classWidget = new QWidget; + QHBoxLayout *l = new QHBoxLayout(classWidget); + l->setContentsMargins(5, 0, 5, 0); + l->addWidget(m_classLabel); + + // Add actions + QActionGroup *addDynamicActionGroup = new QActionGroup(this); + connect(addDynamicActionGroup, SIGNAL(triggered(QAction*)), this, SLOT(slotAddDynamicProperty(QAction*))); + + QMenu *addDynamicActionMenu = new QMenu(this); + m_addDynamicAction->setMenu(addDynamicActionMenu); + m_addDynamicAction->setEnabled(false); + QAction *addDynamicAction = addDynamicActionGroup->addAction(tr("String...")); + addDynamicAction->setData(static_cast<int>(QVariant::String)); + addDynamicActionMenu->addAction(addDynamicAction); + addDynamicAction = addDynamicActionGroup->addAction(tr("Bool...")); + addDynamicAction->setData(static_cast<int>(QVariant::Bool)); + addDynamicActionMenu->addAction(addDynamicAction); + addDynamicActionMenu->addSeparator(); + addDynamicAction = addDynamicActionGroup->addAction(tr("Other...")); + addDynamicAction->setData(static_cast<int>(QVariant::Invalid)); + addDynamicActionMenu->addAction(addDynamicAction); + // remove + m_removeDynamicAction->setEnabled(false); + connect(m_removeDynamicAction, SIGNAL(triggered()), this, SLOT(slotRemoveDynamicProperty())); + // Configure + QAction *configureAction = new QAction(tr("Configure Property Editor"), this); + configureAction->setIcon(createIconSet(QLatin1String("configure.png"))); + QMenu *configureMenu = new QMenu(this); + configureAction->setMenu(configureMenu); + + m_sortingAction->setCheckable(true); + connect(m_sortingAction, SIGNAL(toggled(bool)), this, SLOT(slotSorting(bool))); + + m_coloringAction->setCheckable(true); + connect(m_coloringAction, SIGNAL(toggled(bool)), this, SLOT(slotColoring(bool))); + + configureMenu->addAction(m_sortingAction); + configureMenu->addAction(m_coloringAction); +#if QT_VERSION >= 0x040600 + configureMenu->addSeparator(); + configureMenu->addAction(m_treeAction); + configureMenu->addAction(m_buttonAction); +#endif + // Assemble toolbar + QToolBar *toolBar = new QToolBar; + toolBar->addWidget(classWidget); + toolBar->addWidget(m_filterWidget); + toolBar->addWidget(createDropDownButton(m_addDynamicAction)); + toolBar->addAction(m_removeDynamicAction); + toolBar->addWidget(createDropDownButton(configureAction)); + // Views + QScrollArea *buttonScroll = new QScrollArea(m_stackedWidget); + m_buttonBrowser = new QtButtonPropertyBrowser(buttonScroll); + buttonScroll->setWidgetResizable(true); + buttonScroll->setWidget(m_buttonBrowser); + m_buttonIndex = m_stackedWidget->addWidget(buttonScroll); + connect(m_buttonBrowser, SIGNAL(currentItemChanged(QtBrowserItem*)), this, SLOT(slotCurrentItemChanged(QtBrowserItem*))); + + m_treeBrowser = new QtTreePropertyBrowser(m_stackedWidget); + m_treeBrowser->setRootIsDecorated(false); + m_treeBrowser->setPropertiesWithoutValueMarked(true); + m_treeBrowser->setResizeMode(QtTreePropertyBrowser::Interactive); + m_treeIndex = m_stackedWidget->addWidget(m_treeBrowser); + connect(m_treeBrowser, SIGNAL(currentItemChanged(QtBrowserItem*)), this, SLOT(slotCurrentItemChanged(QtBrowserItem*))); + connect(m_filterWidget, SIGNAL(filterChanged(QString)), this, SLOT(setFilter(QString))); + + QVBoxLayout *layout = new QVBoxLayout(this); + layout->addWidget(toolBar); + layout->addWidget(m_stackedWidget); + layout->setMargin(0); + layout->setSpacing(0); + + m_treeFactory = new DesignerEditorFactory(m_core, this); + m_treeFactory->setSpacing(0); + m_groupFactory = new DesignerEditorFactory(m_core, this); + QtVariantPropertyManager *variantManager = m_propertyManager; + m_buttonBrowser->setFactoryForManager(variantManager, m_groupFactory); + m_treeBrowser->setFactoryForManager(variantManager, m_treeFactory); + + m_stackedWidget->setCurrentIndex(m_treeIndex); + m_currentBrowser = m_treeBrowser; + m_treeAction->setChecked(true); + + connect(m_groupFactory, SIGNAL(resetProperty(QtProperty*)), this, SLOT(slotResetProperty(QtProperty*))); + connect(m_treeFactory, SIGNAL(resetProperty(QtProperty*)), this, SLOT(slotResetProperty(QtProperty*))); + connect(variantManager, SIGNAL(valueChanged(QtProperty*,QVariant,bool)), this, SLOT(slotValueChanged(QtProperty*,QVariant,bool))); + + // retrieve initial settings + QDesignerSettingsInterface *settings = m_core->settingsManager(); + settings->beginGroup(QLatin1String(SettingsGroupC)); +#if QT_VERSION >= 0x040500 + const SettingsView view = settings->value(QLatin1String(ViewKeyC), TreeView).toInt() == TreeView ? TreeView : ButtonView; +#endif + // Coloring not available unless treeview and not sorted + m_sorting = settings->value(QLatin1String(SortedKeyC), false).toBool(); + m_coloring = settings->value(QLatin1String(ColorKeyC), true).toBool(); + const QVariantMap expansionState = settings->value(QLatin1String(ExpansionKeyC), QVariantMap()).toMap(); + settings->endGroup(); + // Apply settings + m_sortingAction->setChecked(m_sorting); + m_coloringAction->setChecked(m_coloring); +#if QT_VERSION >= 0x040500 + switch (view) { + case TreeView: + m_currentBrowser = m_treeBrowser; + m_stackedWidget->setCurrentIndex(m_treeIndex); + m_treeAction->setChecked(true); + break; + case ButtonView: + m_currentBrowser = m_buttonBrowser; + m_stackedWidget->setCurrentIndex(m_buttonIndex); + m_buttonAction->setChecked(true); + break; + } +#endif + // Restore expansionState from QVariant map + if (!expansionState.empty()) { + const QVariantMap::const_iterator cend = expansionState.constEnd(); + for (QVariantMap::const_iterator it = expansionState.constBegin(); it != cend; ++it) + m_expansionState.insert(it.key(), it.value().toBool()); + } + updateActionsState(); +} + +PropertyEditor::~PropertyEditor() +{ + storeExpansionState(); + saveSettings(); +} + +void PropertyEditor::saveSettings() const +{ + QDesignerSettingsInterface *settings = m_core->settingsManager(); + settings->beginGroup(QLatin1String(SettingsGroupC)); +#if QT_VERSION >= 0x040500 + settings->setValue(QLatin1String(ViewKeyC), QVariant(m_treeAction->isChecked() ? TreeView : ButtonView)); +#endif + settings->setValue(QLatin1String(ColorKeyC), QVariant(m_coloring)); + settings->setValue(QLatin1String(SortedKeyC), QVariant(m_sorting)); + // Save last expansionState as QVariant map + QVariantMap expansionState; + if (!m_expansionState.empty()) { + const QMap<QString, bool>::const_iterator cend = m_expansionState.constEnd(); + for (QMap<QString, bool>::const_iterator it = m_expansionState.constBegin(); it != cend; ++it) + expansionState.insert(it.key(), QVariant(it.value())); + } + settings->setValue(QLatin1String(ExpansionKeyC), expansionState); + settings->endGroup(); +} + +void PropertyEditor::setExpanded(QtBrowserItem *item, bool expanded) +{ + if (m_buttonBrowser == m_currentBrowser) + m_buttonBrowser->setExpanded(item, expanded); + else if (m_treeBrowser == m_currentBrowser) + m_treeBrowser->setExpanded(item, expanded); +} + +bool PropertyEditor::isExpanded(QtBrowserItem *item) const +{ + if (m_buttonBrowser == m_currentBrowser) + return m_buttonBrowser->isExpanded(item); + else if (m_treeBrowser == m_currentBrowser) + return m_treeBrowser->isExpanded(item); + return false; +} + +void PropertyEditor::setItemVisible(QtBrowserItem *item, bool visible) +{ + if (m_currentBrowser == m_treeBrowser) { + m_treeBrowser->setItemVisible(item, visible); + } else { + qWarning("** WARNING %s is not implemented for this browser.", Q_FUNC_INFO); + } +} + +bool PropertyEditor::isItemVisible(QtBrowserItem *item) const +{ + return m_currentBrowser == m_treeBrowser ? m_treeBrowser->isItemVisible(item) : true; +} + +/* Default handling of items not found in the map: + * - Top-level items (classes) are assumed to be expanded + * - Anything below (properties) is assumed to be collapsed + * That is, the map is required, the state cannot be stored in a set */ + +void PropertyEditor::storePropertiesExpansionState(const QList<QtBrowserItem *> &items) +{ + const QChar bar = QLatin1Char('|'); + QListIterator<QtBrowserItem *> itProperty(items); + while (itProperty.hasNext()) { + QtBrowserItem *propertyItem = itProperty.next(); + if (!propertyItem->children().empty()) { + QtProperty *property = propertyItem->property(); + const QString propertyName = property->propertyName(); + const QMap<QtProperty *, QString>::const_iterator itGroup = m_propertyToGroup.constFind(property); + if (itGroup != m_propertyToGroup.constEnd()) { + QString key = itGroup.value(); + key += bar; + key += propertyName; + m_expansionState[key] = isExpanded(propertyItem); + } + } + } +} + +void PropertyEditor::storeExpansionState() +{ + const QList<QtBrowserItem *> items = m_currentBrowser->topLevelItems(); + if (m_sorting) { + storePropertiesExpansionState(items); + } else { + QListIterator<QtBrowserItem *> itGroup(items); + while (itGroup.hasNext()) { + QtBrowserItem *item = itGroup.next(); + const QString groupName = item->property()->propertyName(); + QList<QtBrowserItem *> propertyItems = item->children(); + if (!propertyItems.empty()) + m_expansionState[groupName] = isExpanded(item); + + // properties stuff here + storePropertiesExpansionState(propertyItems); + } + } +} + +void PropertyEditor::collapseAll() +{ + QList<QtBrowserItem *> items = m_currentBrowser->topLevelItems(); + QListIterator<QtBrowserItem *> itGroup(items); + while (itGroup.hasNext()) + setExpanded(itGroup.next(), false); +} + +void PropertyEditor::applyPropertiesExpansionState(const QList<QtBrowserItem *> &items) +{ + const QChar bar = QLatin1Char('|'); + QListIterator<QtBrowserItem *> itProperty(items); + while (itProperty.hasNext()) { + const QMap<QString, bool>::const_iterator excend = m_expansionState.constEnd(); + QtBrowserItem *propertyItem = itProperty.next(); + QtProperty *property = propertyItem->property(); + const QString propertyName = property->propertyName(); + const QMap<QtProperty *, QString>::const_iterator itGroup = m_propertyToGroup.constFind(property); + if (itGroup != m_propertyToGroup.constEnd()) { + QString key = itGroup.value(); + key += bar; + key += propertyName; + const QMap<QString, bool>::const_iterator pit = m_expansionState.constFind(key); + if (pit != excend) + setExpanded(propertyItem, pit.value()); + else + setExpanded(propertyItem, false); + } + } +} + +void PropertyEditor::applyExpansionState() +{ + const QList<QtBrowserItem *> items = m_currentBrowser->topLevelItems(); + if (m_sorting) { + applyPropertiesExpansionState(items); + } else { + QListIterator<QtBrowserItem *> itTopLevel(items); + const QMap<QString, bool>::const_iterator excend = m_expansionState.constEnd(); + while (itTopLevel.hasNext()) { + QtBrowserItem *item = itTopLevel.next(); + const QString groupName = item->property()->propertyName(); + const QMap<QString, bool>::const_iterator git = m_expansionState.constFind(groupName); + if (git != excend) + setExpanded(item, git.value()); + else + setExpanded(item, true); + // properties stuff here + applyPropertiesExpansionState(item->children()); + } + } +} + +int PropertyEditor::applyPropertiesFilter(const QList<QtBrowserItem *> &items) +{ + int showCount = 0; + const bool matchAll = m_filterPattern.isEmpty(); + QListIterator<QtBrowserItem *> itProperty(items); + while (itProperty.hasNext()) { + QtBrowserItem *propertyItem = itProperty.next(); + QtProperty *property = propertyItem->property(); + const QString propertyName = property->propertyName(); + const bool showProperty = matchAll || propertyName.contains(m_filterPattern, Qt::CaseInsensitive); + setItemVisible(propertyItem, showProperty); + if (showProperty) + showCount++; + } + return showCount; +} + +void PropertyEditor::applyFilter() +{ + const QList<QtBrowserItem *> items = m_currentBrowser->topLevelItems(); + if (m_sorting) { + applyPropertiesFilter(items); + } else { + QListIterator<QtBrowserItem *> itTopLevel(items); + while (itTopLevel.hasNext()) { + QtBrowserItem *item = itTopLevel.next(); + setItemVisible(item, applyPropertiesFilter(item->children())); + } + } +} + +void PropertyEditor::clearView() +{ + m_currentBrowser->clear(); +} + +bool PropertyEditor::event(QEvent *event) +{ + if (event->type() == QEvent::PaletteChange) + updateForegroundBrightness(); + + return QDesignerPropertyEditor::event(event); +} + +void PropertyEditor::updateForegroundBrightness() +{ + QColor c = palette().color(QPalette::Text); + bool newBrightness = qRound(0.3 * c.redF() + 0.59 * c.greenF() + 0.11 * c.blueF()); + + if (m_brightness == newBrightness) + return; + + m_brightness = newBrightness; + + updateColors(); +} + +QColor PropertyEditor::propertyColor(QtProperty *property) const +{ + if (!m_coloring) + return QColor(); + + QtProperty *groupProperty = property; + + QMap<QtProperty *, QString>::ConstIterator itProp = m_propertyToGroup.constFind(property); + if (itProp != m_propertyToGroup.constEnd()) + groupProperty = m_nameToGroup.value(itProp.value()); + + const int groupIdx = m_groups.indexOf(groupProperty); + QPair<QColor, QColor> pair; + if (groupIdx != -1) { + if (groupProperty == m_dynamicGroup) + pair = m_dynamicColor; + else if (isLayoutGroup(groupProperty)) + pair = m_layoutColor; + else + pair = m_colors[groupIdx % m_colors.count()]; + } + if (!m_brightness) + return pair.first; + return pair.second; +} + +void PropertyEditor::fillView() +{ + if (m_sorting) { + QMapIterator<QString, QtVariantProperty *> itProperty(m_nameToProperty); + while (itProperty.hasNext()) { + QtVariantProperty *property = itProperty.next().value(); + m_currentBrowser->addProperty(property); + } + } else { + QListIterator<QtProperty *> itGroup(m_groups); + while (itGroup.hasNext()) { + QtProperty *group = itGroup.next(); + QtBrowserItem *item = m_currentBrowser->addProperty(group); + if (m_currentBrowser == m_treeBrowser) + m_treeBrowser->setBackgroundColor(item, propertyColor(group)); + group->setModified(m_currentBrowser == m_treeBrowser); + } + } +} + +bool PropertyEditor::isLayoutGroup(QtProperty *group) const +{ + return group->propertyName() == m_strings.m_layout; +} + +void PropertyEditor::updateActionsState() +{ + m_coloringAction->setEnabled(m_treeAction->isChecked() && !m_sortingAction->isChecked()); +} + +void PropertyEditor::slotViewTriggered(QAction *action) +{ + storeExpansionState(); + collapseAll(); + { + UpdateBlocker ub(this); + clearView(); + int idx = 0; + if (action == m_treeAction) { + m_currentBrowser = m_treeBrowser; + idx = m_treeIndex; + } else if (action == m_buttonAction) { + m_currentBrowser = m_buttonBrowser; + idx = m_buttonIndex; + } + fillView(); + m_stackedWidget->setCurrentIndex(idx); + applyExpansionState(); + applyFilter(); + } + updateActionsState(); +} + +void PropertyEditor::slotSorting(bool sort) +{ + if (sort == m_sorting) + return; + + storeExpansionState(); + m_sorting = sort; + collapseAll(); + { + UpdateBlocker ub(this); + clearView(); + m_treeBrowser->setRootIsDecorated(sort); + fillView(); + applyExpansionState(); + applyFilter(); + } + updateActionsState(); +} + +void PropertyEditor::updateColors() +{ + if (m_treeBrowser && m_currentBrowser == m_treeBrowser) { + QList<QtBrowserItem *> items = m_treeBrowser->topLevelItems(); + QListIterator<QtBrowserItem *> itItem(items); + while (itItem.hasNext()) { + QtBrowserItem *item = itItem.next(); + m_treeBrowser->setBackgroundColor(item, propertyColor(item->property())); + } + } +} + +void PropertyEditor::slotColoring(bool coloring) +{ + if (coloring == m_coloring) + return; + + m_coloring = coloring; + + updateColors(); +} + +void PropertyEditor::slotAddDynamicProperty(QAction *action) +{ + if (!m_propertySheet) + return; + + const QDesignerDynamicPropertySheetExtension *dynamicSheet = + qt_extension<QDesignerDynamicPropertySheetExtension*>(m_core->extensionManager(), m_object); + + if (!dynamicSheet) + return; + + QString newName; + QVariant newValue; + { // Make sure the dialog is closed before the signal is emitted. + const QVariant::Type type = static_cast<QVariant::Type>(action->data().toInt()); + NewDynamicPropertyDialog dlg(core()->dialogGui(), m_currentBrowser); + if (type != QVariant::Invalid) + dlg.setPropertyType(type); + + QStringList reservedNames; + const int propertyCount = m_propertySheet->count(); + for (int i = 0; i < propertyCount; i++) { + if (!dynamicSheet->isDynamicProperty(i) || m_propertySheet->isVisible(i)) + reservedNames.append(m_propertySheet->propertyName(i)); + } + dlg.setReservedNames(reservedNames); + if (dlg.exec() == QDialog::Rejected) + return; + newName = dlg.propertyName(); + newValue = dlg.propertyValue(); + } + m_recentlyAddedDynamicProperty = newName; + emit addDynamicProperty(newName, newValue); +} + +QDesignerFormEditorInterface *PropertyEditor::core() const +{ + return m_core; +} + +bool PropertyEditor::isReadOnly() const +{ + return false; +} + +void PropertyEditor::setReadOnly(bool /*readOnly*/) +{ + qDebug() << "PropertyEditor::setReadOnly() request"; +} + +void PropertyEditor::setPropertyValue(const QString &name, const QVariant &value, bool changed) +{ + const QMap<QString, QtVariantProperty*>::const_iterator it = m_nameToProperty.constFind(name); + if (it == m_nameToProperty.constEnd()) + return; + QtVariantProperty *property = it.value(); + updateBrowserValue(property, value); + property->setModified(changed); +} + +/* Quick update that assumes the actual count of properties has not changed + * N/A when for example executing a layout command and margin properties appear. */ +void PropertyEditor::updatePropertySheet() +{ + if (!m_propertySheet) + return; + + updateToolBarLabel(); + + const int propertyCount = m_propertySheet->count(); + const QMap<QString, QtVariantProperty*>::const_iterator npcend = m_nameToProperty.constEnd(); + for (int i = 0; i < propertyCount; ++i) { + const QString propertyName = m_propertySheet->propertyName(i); + QMap<QString, QtVariantProperty*>::const_iterator it = m_nameToProperty.constFind(propertyName); + if (it != npcend) + updateBrowserValue(it.value(), m_propertySheet->property(i)); + } +} + +static inline QLayout *layoutOfQLayoutWidget(QObject *o) +{ + if (o->isWidgetType() && !qstrcmp(o->metaObject()->className(), "QLayoutWidget")) + return static_cast<QWidget*>(o)->layout(); + return 0; +} + +void PropertyEditor::updateToolBarLabel() +{ + QString objectName; + QString className; + if (m_object) { + if (QLayout *l = layoutOfQLayoutWidget(m_object)) + objectName = l->objectName(); + else + objectName = m_object->objectName(); + className = realClassName(m_object); + } + + QString classLabelText = objectName; + classLabelText += QLatin1Char('\n'); + classLabelText += className; + m_classLabel->setText(classLabelText); + m_classLabel->setToolTip(tr("Object: %1\nClass: %2").arg(objectName).arg(className)); +} + +void PropertyEditor::updateBrowserValue(QtVariantProperty *property, const QVariant &value) +{ + QVariant v = value; + const int type = property->propertyType(); + if (type == QtVariantPropertyManager::enumTypeId()) { + const PropertySheetEnumValue e = qvariant_cast<PropertySheetEnumValue>(v); + v = e.metaEnum.keys().indexOf(e.metaEnum.valueToKey(e.value)); + } else if (type == DesignerPropertyManager::designerFlagTypeId()) { + const PropertySheetFlagValue f = qvariant_cast<PropertySheetFlagValue>(v); + v = QVariant(f.value); + } else if (type == DesignerPropertyManager::designerAlignmentTypeId()) { + const PropertySheetFlagValue f = qvariant_cast<PropertySheetFlagValue>(v); + v = QVariant(f.value); + } + QDesignerPropertySheet *sheet = qobject_cast<QDesignerPropertySheet*>(m_core->extensionManager()->extension(m_object, Q_TYPEID(QDesignerPropertySheetExtension))); + int index = -1; + if (sheet) + index = sheet->indexOf(property->propertyName()); + if (sheet && m_propertyToGroup.contains(property)) { // don't do it for comments since property sheet doesn't keep them + property->setEnabled(sheet->isEnabled(index)); + } + + // Rich text string property with comment: Store/Update the font the rich text editor dialog starts out with + if (type == QVariant::String && !property->subProperties().empty()) { + const int fontIndex = m_propertySheet->indexOf(m_strings.m_fontProperty); + if (fontIndex != -1) + property->setAttribute(m_strings.m_fontAttribute, m_propertySheet->property(fontIndex)); + } + + m_updatingBrowser = true; + property->setValue(v); + if (sheet && sheet->isResourceProperty(index)) + property->setAttribute(QLatin1String("defaultResource"), sheet->defaultResourceProperty(index)); + m_updatingBrowser = false; +} + +int PropertyEditor::toBrowserType(const QVariant &value, const QString &propertyName) const +{ + if (qVariantCanConvert<PropertySheetFlagValue>(value)) { + if (m_strings.m_alignmentProperties.contains(propertyName)) + return DesignerPropertyManager::designerAlignmentTypeId(); + return DesignerPropertyManager::designerFlagTypeId(); + } + if (qVariantCanConvert<PropertySheetEnumValue>(value)) + return DesignerPropertyManager::enumTypeId(); + + return value.userType(); +} + +QString PropertyEditor::realClassName(QObject *object) const +{ + if (!object) + return QString(); + + QString className = QLatin1String(object->metaObject()->className()); + const QDesignerWidgetDataBaseInterface *db = core()->widgetDataBase(); + if (QDesignerWidgetDataBaseItemInterface *widgetItem = db->item(db->indexOfObject(object, true))) { + className = widgetItem->name(); + + if (object->isWidgetType() && className == m_strings.m_qLayoutWidget + && static_cast<QWidget*>(object)->layout()) { + className = QLatin1String(static_cast<QWidget*>(object)->layout()->metaObject()->className()); + } + } + + if (className.startsWith(m_strings.m_designerPrefix)) + className.remove(1, m_strings.m_designerPrefix.size() - 1); + + return className; +} + +static QString msgUnsupportedType(const QString &propertyName, unsigned type) +{ + QString rc; + QTextStream str(&rc); + str << "The property \"" << propertyName << "\" of type " << type; + if (type == QVariant::Invalid) { + str << " (invalid) "; + } else { + if (type < QVariant::UserType) { + if (const char *typeName = QVariant::typeToName(static_cast<QVariant::Type>(type))) + str << " (" << typeName << ") "; + } else { + str << " (user type) "; + } + } + str << " is not supported yet!"; + return rc; +} + +void PropertyEditor::setObject(QObject *object) +{ + QDesignerFormWindowInterface *oldFormWindow = QDesignerFormWindowInterface::findFormWindow(m_object); + // In the first setObject() call following the addition of a dynamic property, focus and edit it. + const bool editNewDynamicProperty = object != 0 && m_object == object && !m_recentlyAddedDynamicProperty.isEmpty(); + m_object = object; + m_propertyManager->setObject(object); + QDesignerFormWindowInterface *formWindow = QDesignerFormWindowInterface::findFormWindow(m_object); + FormWindowBase *fwb = qobject_cast<FormWindowBase *>(formWindow); + m_treeFactory->setFormWindowBase(fwb); + m_groupFactory->setFormWindowBase(fwb); + + storeExpansionState(); + + UpdateBlocker ub(this); + + updateToolBarLabel(); + + QMap<QString, QtVariantProperty *> toRemove = m_nameToProperty; + + const QDesignerDynamicPropertySheetExtension *dynamicSheet = + qt_extension<QDesignerDynamicPropertySheetExtension*>(m_core->extensionManager(), m_object); + const QDesignerPropertySheet *sheet = qobject_cast<QDesignerPropertySheet*>(m_core->extensionManager()->extension(m_object, Q_TYPEID(QDesignerPropertySheetExtension))); + + // Optimizization: Instead of rebuilding the complete list every time, compile a list of properties to remove, + // remove them, traverse the sheet, in case property exists just set a value, otherwise - create it. + QExtensionManager *m = m_core->extensionManager(); + + m_propertySheet = qobject_cast<QDesignerPropertySheetExtension*>(m->extension(object, Q_TYPEID(QDesignerPropertySheetExtension))); + if (m_propertySheet) { + const int propertyCount = m_propertySheet->count(); + for (int i = 0; i < propertyCount; ++i) { + if (!m_propertySheet->isVisible(i)) + continue; + + const QString propertyName = m_propertySheet->propertyName(i); + if (m_propertySheet->indexOf(propertyName) != i) + continue; + const QString groupName = m_propertySheet->propertyGroup(i); + const QMap<QString, QtVariantProperty *>::const_iterator rit = toRemove.constFind(propertyName); + if (rit != toRemove.constEnd()) { + QtVariantProperty *property = rit.value(); + if (m_propertyToGroup.value(property) == groupName && toBrowserType(m_propertySheet->property(i), propertyName) == property->propertyType()) + toRemove.remove(propertyName); + } + } + } + + QMapIterator<QString, QtVariantProperty *> itRemove(toRemove); + while (itRemove.hasNext()) { + itRemove.next(); + + QtVariantProperty *property = itRemove.value(); + m_nameToProperty.remove(itRemove.key()); + m_propertyToGroup.remove(property); + delete property; + } + + if (oldFormWindow != formWindow) + reloadResourceProperties(); + + bool isMainContainer = false; + if (QWidget *widget = qobject_cast<QWidget*>(object)) { + if (QDesignerFormWindowInterface *fw = QDesignerFormWindowInterface::findFormWindow(widget)) { + isMainContainer = (fw->mainContainer() == widget); + } + } + m_groups.clear(); + + if (m_propertySheet) { + QtProperty *lastProperty = 0; + QtProperty *lastGroup = 0; + const int propertyCount = m_propertySheet->count(); + for (int i = 0; i < propertyCount; ++i) { + if (!m_propertySheet->isVisible(i)) + continue; + + const QString propertyName = m_propertySheet->propertyName(i); + if (m_propertySheet->indexOf(propertyName) != i) + continue; + const QVariant value = m_propertySheet->property(i); + + const int type = toBrowserType(value, propertyName); + + QtVariantProperty *property = m_nameToProperty.value(propertyName, 0); + bool newProperty = property == 0; + if (newProperty) { + property = m_propertyManager->addProperty(type, propertyName); + if (property) { + newProperty = true; + if (type == DesignerPropertyManager::enumTypeId()) { + const PropertySheetEnumValue e = qvariant_cast<PropertySheetEnumValue>(value); + QStringList names; + QStringListIterator it(e.metaEnum.keys()); + while (it.hasNext()) + names.append(it.next()); + m_updatingBrowser = true; + property->setAttribute(m_strings.m_enumNamesAttribute, names); + m_updatingBrowser = false; + } else if (type == DesignerPropertyManager::designerFlagTypeId()) { + const PropertySheetFlagValue f = qvariant_cast<PropertySheetFlagValue>(value); + QList<QPair<QString, uint> > flags; + QStringListIterator it(f.metaFlags.keys()); + while (it.hasNext()) { + const QString name = it.next(); + const uint val = f.metaFlags.keyToValue(name); + flags.append(qMakePair(name, val)); + } + m_updatingBrowser = true; + QVariant v; + qVariantSetValue(v, flags); + property->setAttribute(m_strings.m_flagsAttribute, v); + m_updatingBrowser = false; + } + } + } + + if (property != 0) { + const bool dynamicProperty = (dynamicSheet && dynamicSheet->isDynamicProperty(i)) + || (sheet && sheet->isDefaultDynamicProperty(i)); + switch (type) { + case QVariant::Palette: + setupPaletteProperty(property); + break; + case QVariant::KeySequence: + //addCommentProperty(property, propertyName); + break; + default: + break; + } + if (type == QVariant::String || type == qMetaTypeId<PropertySheetStringValue>()) + setupStringProperty(property, isMainContainer); + property->setAttribute(m_strings.m_resettableAttribute, m_propertySheet->hasReset(i)); + + const QString groupName = m_propertySheet->propertyGroup(i); + QtVariantProperty *groupProperty = 0; + + if (newProperty) { + QMap<QString, QtVariantProperty*>::const_iterator itPrev = m_nameToProperty.insert(propertyName, property); + m_propertyToGroup[property] = groupName; + if (m_sorting) { + QtProperty *previous = 0; + if (itPrev != m_nameToProperty.constBegin()) + previous = (--itPrev).value(); + m_currentBrowser->insertProperty(property, previous); + } + } + const QMap<QString, QtVariantProperty*>::const_iterator gnit = m_nameToGroup.constFind(groupName); + if (gnit != m_nameToGroup.constEnd()) { + groupProperty = gnit.value(); + } else { + groupProperty = m_propertyManager->addProperty(QtVariantPropertyManager::groupTypeId(), groupName); + QtBrowserItem *item = 0; + if (!m_sorting) + item = m_currentBrowser->insertProperty(groupProperty, lastGroup); + m_nameToGroup[groupName] = groupProperty; + m_groups.append(groupProperty); + if (dynamicProperty) + m_dynamicGroup = groupProperty; + if (m_currentBrowser == m_treeBrowser && item) { + m_treeBrowser->setBackgroundColor(item, propertyColor(groupProperty)); + groupProperty->setModified(true); + } + } + /* Group changed or new group. Append to last subproperty of + * that group. Note that there are cases in which a derived + * property sheet appends fake properties for the class + * which will appear after the layout group properties + * (QWizardPage). To make them appear at the end of the + * actual class group, goto last element. */ + if (lastGroup != groupProperty) { + lastGroup = groupProperty; + lastProperty = 0; // Append at end + const QList<QtProperty*> subProperties = lastGroup->subProperties(); + if (!subProperties.empty()) + lastProperty = subProperties.back(); + lastGroup = groupProperty; + } + if (!m_groups.contains(groupProperty)) + m_groups.append(groupProperty); + if (newProperty) + groupProperty->insertSubProperty(property, lastProperty); + + lastProperty = property; + + updateBrowserValue(property, value); + + property->setModified(m_propertySheet->isChanged(i)); + if (propertyName == QLatin1String("geometry") && type == QVariant::Rect) { + QList<QtProperty *> subProperties = property->subProperties(); + foreach (QtProperty *subProperty, subProperties) { + const QString subPropertyName = subProperty->propertyName(); + if (subPropertyName == QLatin1String("X") || subPropertyName == QLatin1String("Y")) + subProperty->setEnabled(!isMainContainer); + } + } + } else { + qWarning("%s", qPrintable(msgUnsupportedType(propertyName, type))); + } + } + } + QMap<QString, QtVariantProperty *> groups = m_nameToGroup; + QMapIterator<QString, QtVariantProperty *> itGroup(groups); + while (itGroup.hasNext()) { + QtVariantProperty *groupProperty = itGroup.next().value(); + if (groupProperty->subProperties().empty()) { + if (groupProperty == m_dynamicGroup) + m_dynamicGroup = 0; + delete groupProperty; + m_nameToGroup.remove(itGroup.key()); + } + } + const bool addEnabled = dynamicSheet ? dynamicSheet->dynamicPropertiesAllowed() : false; + m_addDynamicAction->setEnabled(addEnabled); + m_removeDynamicAction->setEnabled(false); + applyExpansionState(); + applyFilter(); + // In the first setObject() call following the addition of a dynamic property, focus and edit it. + if (editNewDynamicProperty) { + // Have QApplication process the events related to completely closing the modal 'add' dialog, + // otherwise, we cannot focus the property editor in docked mode. + QApplication::processEvents(QEventLoop::ExcludeUserInputEvents); + editProperty(m_recentlyAddedDynamicProperty); + } + m_recentlyAddedDynamicProperty.clear(); + m_filterWidget->setEnabled(object); +} + +void PropertyEditor::reloadResourceProperties() +{ + m_updatingBrowser = true; + m_propertyManager->reloadResourceProperties(); + m_updatingBrowser = false; +} + +QtBrowserItem *PropertyEditor::nonFakePropertyBrowserItem(QtBrowserItem *item) const +{ + // Top-level properties are QObject/QWidget groups, etc. Find first item property below + // which should be nonfake + const QList<QtBrowserItem *> topLevelItems = m_currentBrowser->topLevelItems(); + do { + if (topLevelItems.contains(item->parent())) + return item; + item = item->parent(); + } while (item); + return 0; +} + +QString PropertyEditor::currentPropertyName() const +{ + if (QtBrowserItem *browserItem = m_currentBrowser->currentItem()) + if (QtBrowserItem *topLevelItem = nonFakePropertyBrowserItem(browserItem)) { + return topLevelItem->property()->propertyName(); + } + return QString(); +} + +void PropertyEditor::slotResetProperty(QtProperty *property) +{ + QDesignerFormWindowInterface *form = m_core->formWindowManager()->activeFormWindow(); + if (!form) + return; + + if (m_propertyManager->resetFontSubProperty(property)) + return; + + if (m_propertyManager->resetIconSubProperty(property)) + return; + + if (!m_propertyToGroup.contains(property)) + return; + + emit resetProperty(property->propertyName()); +} + +void PropertyEditor::slotValueChanged(QtProperty *property, const QVariant &value, bool enableSubPropertyHandling) +{ + if (m_updatingBrowser) + return; + + if (!m_propertySheet) + return; + + QtVariantProperty *varProp = m_propertyManager->variantProperty(property); + + if (!varProp) + return; + + if (!m_propertyToGroup.contains(property)) + return; + + if (varProp->propertyType() == QtVariantPropertyManager::enumTypeId()) { + PropertySheetEnumValue e = qvariant_cast<PropertySheetEnumValue>(m_propertySheet->property(m_propertySheet->indexOf(property->propertyName()))); + const int val = value.toInt(); + const QString valName = varProp->attributeValue(m_strings.m_enumNamesAttribute).toStringList().at(val); + bool ok = false; + e.value = e.metaEnum.parseEnum(valName, &ok); + Q_ASSERT(ok); + QVariant v; + qVariantSetValue(v, e); + emit propertyValueChanged(property->propertyName(), v, true); + return; + } + + emit propertyValueChanged(property->propertyName(), value, enableSubPropertyHandling); +} + +bool PropertyEditor::isDynamicProperty(const QtBrowserItem* item) const +{ + if (!item) + return false; + + const QDesignerDynamicPropertySheetExtension *dynamicSheet = + qt_extension<QDesignerDynamicPropertySheetExtension*>(m_core->extensionManager(), m_object); + + if (!dynamicSheet) + return false; + + if (m_propertyToGroup.contains(item->property()) + && dynamicSheet->isDynamicProperty(m_propertySheet->indexOf(item->property()->propertyName()))) + return true; + return false; +} + +void PropertyEditor::editProperty(const QString &name) +{ + // find the browser item belonging to the property, make it current and edit it + QtBrowserItem *browserItem = 0; + if (QtVariantProperty *property = m_nameToProperty.value(name, 0)) { + const QList<QtBrowserItem *> items = m_currentBrowser->items(property); + if (items.size() == 1) + browserItem = items.front(); + } + if (browserItem == 0) + return; + m_currentBrowser->setFocus(Qt::OtherFocusReason); + if (m_currentBrowser == m_treeBrowser) { // edit is currently only supported in tree view + m_treeBrowser->editItem(browserItem); + } else { + m_currentBrowser->setCurrentItem(browserItem); + } +} + +void PropertyEditor::slotCurrentItemChanged(QtBrowserItem *item) +{ + m_removeDynamicAction->setEnabled(isDynamicProperty(item)); + +} + +void PropertyEditor::slotRemoveDynamicProperty() +{ + if (QtBrowserItem* item = m_currentBrowser->currentItem()) + if (isDynamicProperty(item)) + emit removeDynamicProperty(item->property()->propertyName()); +} + +void PropertyEditor::setFilter(const QString &pattern) +{ + m_filterPattern = pattern; + applyFilter(); +} +} + +QT_END_NAMESPACE diff --git a/tools/designer/src/components/propertyeditor/propertyeditor.h b/tools/designer/src/components/propertyeditor/propertyeditor.h new file mode 100644 index 0000000..21e81dd --- /dev/null +++ b/tools/designer/src/components/propertyeditor/propertyeditor.h @@ -0,0 +1,208 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the Qt Designer of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef PROPERTYEDITOR_H +#define PROPERTYEDITOR_H + +#include "propertyeditor_global.h" +#include <qdesigner_propertyeditor_p.h> + +#include <QtCore/QPointer> +#include <QtCore/QMap> +#include <QtCore/QVector> +#include <QtCore/QSet> + +QT_BEGIN_NAMESPACE + +class DomProperty; +class QDesignerMetaDataBaseItemInterface; +class QDesignerPropertySheetExtension; + +class QtAbstractPropertyBrowser; +class QtButtonPropertyBrowser; +class QtTreePropertyBrowser; +class QtProperty; +class QtVariantProperty; +class QtBrowserItem; + +class QStackedWidget; +class QLabel; + +namespace qdesigner_internal { + +class StringProperty; +class DesignerPropertyManager; +class DesignerEditorFactory; +class FilterWidget; + +class QT_PROPERTYEDITOR_EXPORT PropertyEditor: public QDesignerPropertyEditor +{ + Q_OBJECT +public: + explicit PropertyEditor(QDesignerFormEditorInterface *core, QWidget *parent = 0, Qt::WindowFlags flags = 0); + virtual ~PropertyEditor(); + + virtual QDesignerFormEditorInterface *core() const; + + virtual bool isReadOnly() const; + virtual void setReadOnly(bool readOnly); + virtual void setPropertyValue(const QString &name, const QVariant &value, bool changed = true); + virtual void updatePropertySheet(); + + virtual void setObject(QObject *object); + + void reloadResourceProperties(); + + virtual QObject *object() const + { return m_object; } + + virtual QString currentPropertyName() const; + +protected: + + bool event(QEvent *event); + +private slots: + void slotResetProperty(QtProperty *property); + void slotValueChanged(QtProperty *property, const QVariant &value, bool enableSubPropertyHandling); + void slotViewTriggered(QAction *action); + void slotAddDynamicProperty(QAction *action); + void slotRemoveDynamicProperty(); + void slotSorting(bool sort); + void slotColoring(bool color); + void slotCurrentItemChanged(QtBrowserItem*); + void setFilter(const QString &pattern); + +private: + void updateBrowserValue(QtVariantProperty *property, const QVariant &value); + void updateToolBarLabel(); + int toBrowserType(const QVariant &value, const QString &propertyName) const; + QString removeScope(const QString &value) const; + QDesignerMetaDataBaseItemInterface *metaDataBaseItem() const; + void setupStringProperty(QtVariantProperty *property, bool isMainContainer); + void setupPaletteProperty(QtVariantProperty *property); + QString realClassName(QObject *object) const; + void storeExpansionState(); + void applyExpansionState(); + void storePropertiesExpansionState(const QList<QtBrowserItem *> &items); + void applyPropertiesExpansionState(const QList<QtBrowserItem *> &items); + void applyFilter(); + int applyPropertiesFilter(const QList<QtBrowserItem *> &items); + void setExpanded(QtBrowserItem *item, bool expanded); + bool isExpanded(QtBrowserItem *item) const; + void setItemVisible(QtBrowserItem *item, bool visible); + bool isItemVisible(QtBrowserItem *item) const; + void collapseAll(); + void clearView(); + void fillView(); + bool isLayoutGroup(QtProperty *group) const; + void updateColors(); + void updateForegroundBrightness(); + QColor propertyColor(QtProperty *property) const; + void updateActionsState(); + QtBrowserItem *nonFakePropertyBrowserItem(QtBrowserItem *item) const; + void saveSettings() const; + void editProperty(const QString &name); + bool isDynamicProperty(const QtBrowserItem* item) const; + + struct Strings { + Strings(); + QSet<QString> m_alignmentProperties; + const QString m_fontProperty; + const QString m_qLayoutWidget; + const QString m_designerPrefix; + const QString m_layout; + const QString m_validationModeAttribute; + const QString m_fontAttribute; + const QString m_superPaletteAttribute; + const QString m_enumNamesAttribute; + const QString m_resettableAttribute; + const QString m_flagsAttribute; + }; + + const Strings m_strings; + QDesignerFormEditorInterface *m_core; + QDesignerPropertySheetExtension *m_propertySheet; + QtAbstractPropertyBrowser *m_currentBrowser; + QtButtonPropertyBrowser *m_buttonBrowser; + QtTreePropertyBrowser *m_treeBrowser; + DesignerPropertyManager *m_propertyManager; + DesignerEditorFactory *m_treeFactory; + DesignerEditorFactory *m_groupFactory; + QPointer<QObject> m_object; + QMap<QString, QtVariantProperty*> m_nameToProperty; + QMap<QtProperty*, QString> m_propertyToGroup; + QMap<QString, QtVariantProperty*> m_nameToGroup; + QList<QtProperty *> m_groups; + QtProperty *m_dynamicGroup; + QString m_recentlyAddedDynamicProperty; + bool m_updatingBrowser; + + QStackedWidget *m_stackedWidget; + FilterWidget *m_filterWidget; + int m_buttonIndex; + int m_treeIndex; + QAction *m_addDynamicAction; + QAction *m_removeDynamicAction; + QAction *m_sortingAction; + QAction *m_coloringAction; + QAction *m_treeAction; + QAction *m_buttonAction; + QLabel *m_classLabel; + + bool m_sorting; + bool m_coloring; + + QMap<QString, bool> m_expansionState; + + QString m_filterPattern; + QVector<QPair<QColor, QColor> > m_colors; + QPair<QColor, QColor> m_dynamicColor; + QPair<QColor, QColor> m_layoutColor; + + bool m_brightness; +}; + +} // namespace qdesigner_internal + +QT_END_NAMESPACE + +#endif // PROPERTYEDITOR_H diff --git a/tools/designer/src/components/propertyeditor/propertyeditor.pri b/tools/designer/src/components/propertyeditor/propertyeditor.pri new file mode 100644 index 0000000..d3e44a5 --- /dev/null +++ b/tools/designer/src/components/propertyeditor/propertyeditor.pri @@ -0,0 +1,47 @@ +#the next line prevents non-shadowbuilds from including the same directory twice +#otherwise, the build command would be too long for some win32 shells. +!exists($$QT_BUILD_TREE/tools/designer/src/components/propertyeditor/propertyeditor.h):INCLUDEPATH += $$QT_BUILD_TREE/tools/designer/src/components/propertyeditor + +INCLUDEPATH += $$PWD + +include($$QT_SOURCE_TREE/tools/shared/qtpropertybrowser/qtpropertybrowser.pri) +include($$QT_SOURCE_TREE/tools/shared/qtgradienteditor/qtcolorbutton.pri) + +FORMS += $$PWD/paletteeditor.ui \ + $$PWD/stringlisteditor.ui \ + $$PWD/previewwidget.ui \ + $$PWD/newdynamicpropertydialog.ui + +HEADERS += $$PWD/propertyeditor.h \ + $$PWD/designerpropertymanager.h \ + $$PWD/paletteeditor.h \ + $$PWD/paletteeditorbutton.h \ + $$PWD/stringlisteditor.h \ + $$PWD/stringlisteditorbutton.h \ + $$PWD/previewwidget.h \ + $$PWD/previewframe.h \ + $$PWD/newdynamicpropertydialog.h \ + $$PWD/brushpropertymanager.h \ + $$PWD/fontpropertymanager.h + +SOURCES += $$PWD/propertyeditor.cpp \ + $$PWD/designerpropertymanager.cpp \ + $$PWD/paletteeditor.cpp \ + $$PWD/paletteeditorbutton.cpp \ + $$PWD/stringlisteditor.cpp \ + $$PWD/stringlisteditorbutton.cpp \ + $$PWD/previewwidget.cpp \ + $$PWD/previewframe.cpp \ + $$PWD/newdynamicpropertydialog.cpp \ + $$PWD/brushpropertymanager.cpp \ + $$PWD/fontpropertymanager.cpp + +HEADERS += \ + $$PWD/propertyeditor_global.h \ + $$PWD/defs.h \ + $$PWD/qlonglongvalidator.h + +SOURCES += $$PWD/defs.cpp \ + $$PWD/qlonglongvalidator.cpp + +RESOURCES += $$PWD/propertyeditor.qrc diff --git a/tools/designer/src/components/propertyeditor/propertyeditor.qrc b/tools/designer/src/components/propertyeditor/propertyeditor.qrc new file mode 100644 index 0000000..68008ec --- /dev/null +++ b/tools/designer/src/components/propertyeditor/propertyeditor.qrc @@ -0,0 +1,5 @@ +<RCC> + <qresource prefix="/trolltech/propertyeditor"> + <file>fontmapping.xml</file> + </qresource> +</RCC> diff --git a/tools/designer/src/components/propertyeditor/propertyeditor_global.h b/tools/designer/src/components/propertyeditor/propertyeditor_global.h new file mode 100644 index 0000000..c7c4780 --- /dev/null +++ b/tools/designer/src/components/propertyeditor/propertyeditor_global.h @@ -0,0 +1,61 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the Qt Designer of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef PROPERTYEDITOR_GLOBAL_H +#define PROPERTYEDITOR_GLOBAL_H + +#include <QtCore/qglobal.h> + +QT_BEGIN_NAMESPACE + +#ifdef Q_OS_WIN +#ifdef QT_PROPERTYEDITOR_LIBRARY +# define QT_PROPERTYEDITOR_EXPORT +#else +# define QT_PROPERTYEDITOR_EXPORT +#endif +#else +#define QT_PROPERTYEDITOR_EXPORT +#endif + +QT_END_NAMESPACE + +#endif // PROPERTYEDITOR_GLOBAL_H diff --git a/tools/designer/src/components/propertyeditor/qlonglongvalidator.cpp b/tools/designer/src/components/propertyeditor/qlonglongvalidator.cpp new file mode 100644 index 0000000..a6663cf --- /dev/null +++ b/tools/designer/src/components/propertyeditor/qlonglongvalidator.cpp @@ -0,0 +1,153 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the Qt Designer of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qlonglongvalidator.h" + +QT_BEGIN_NAMESPACE + +using namespace qdesigner_internal; + +// ---------------------------------------------------------------------------- +QLongLongValidator::QLongLongValidator(QObject * parent) + : QValidator(parent), + b(Q_UINT64_C(0x8000000000000000)), t(Q_UINT64_C(0x7FFFFFFFFFFFFFFF)) +{ +} + +QLongLongValidator::QLongLongValidator(qlonglong minimum, qlonglong maximum, + QObject * parent) + : QValidator(parent), b(minimum), t(maximum) +{ +} + +QLongLongValidator::~QLongLongValidator() +{ + // nothing +} + +QValidator::State QLongLongValidator::validate(QString & input, int &) const +{ + if (input.contains(QLatin1Char(' '))) + return Invalid; + if (input.isEmpty() || (b < 0 && input == QString(QLatin1Char('-')))) + return Intermediate; + bool ok; + qlonglong entered = input.toLongLong(&ok); + if (!ok || (entered < 0 && b >= 0)) { + return Invalid; + } else if (entered >= b && entered <= t) { + return Acceptable; + } else { + if (entered >= 0) + return (entered > t) ? Invalid : Intermediate; + else + return (entered < b) ? Invalid : Intermediate; + } +} + +void QLongLongValidator::setRange(qlonglong bottom, qlonglong top) +{ + b = bottom; + t = top; +} + +void QLongLongValidator::setBottom(qlonglong bottom) +{ + setRange(bottom, top()); +} + +void QLongLongValidator::setTop(qlonglong top) +{ + setRange(bottom(), top); +} + + +// ---------------------------------------------------------------------------- +QULongLongValidator::QULongLongValidator(QObject * parent) + : QValidator(parent), + b(0), t(Q_UINT64_C(0xFFFFFFFFFFFFFFFF)) +{ +} + +QULongLongValidator::QULongLongValidator(qulonglong minimum, qulonglong maximum, + QObject * parent) + : QValidator(parent), b(minimum), t(maximum) +{ +} + +QULongLongValidator::~QULongLongValidator() +{ + // nothing +} + +QValidator::State QULongLongValidator::validate(QString & input, int &) const +{ + if (input.isEmpty()) + return Intermediate; + + bool ok; + qulonglong entered = input.toULongLong(&ok); + if (input.contains(QLatin1Char(' ')) || input.contains(QLatin1Char('-')) || !ok) + return Invalid; + + if (entered >= b && entered <= t) + return Acceptable; + + return Invalid; +} + +void QULongLongValidator::setRange(qulonglong bottom, qulonglong top) +{ + b = bottom; + t = top; +} + +void QULongLongValidator::setBottom(qulonglong bottom) +{ + setRange(bottom, top()); +} + +void QULongLongValidator::setTop(qulonglong top) +{ + setRange(bottom(), top); +} + +QT_END_NAMESPACE diff --git a/tools/designer/src/components/propertyeditor/qlonglongvalidator.h b/tools/designer/src/components/propertyeditor/qlonglongvalidator.h new file mode 100644 index 0000000..2b3174b --- /dev/null +++ b/tools/designer/src/components/propertyeditor/qlonglongvalidator.h @@ -0,0 +1,110 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the Qt Designer of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QLONGLONGVALIDATOR_H +#define QLONGLONGVALIDATOR_H + +#include <QtGui/QValidator> + +QT_BEGIN_NAMESPACE + +namespace qdesigner_internal { + +class QLongLongValidator : public QValidator +{ + Q_OBJECT + Q_PROPERTY(qlonglong bottom READ bottom WRITE setBottom) + Q_PROPERTY(qlonglong top READ top WRITE setTop) + +public: + explicit QLongLongValidator(QObject * parent); + QLongLongValidator(qlonglong bottom, qlonglong top, QObject * parent); + ~QLongLongValidator(); + + QValidator::State validate(QString &, int &) const; + + void setBottom(qlonglong); + void setTop(qlonglong); + virtual void setRange(qlonglong bottom, qlonglong top); + + qlonglong bottom() const { return b; } + qlonglong top() const { return t; } + +private: + Q_DISABLE_COPY(QLongLongValidator) + + qlonglong b; + qlonglong t; +}; + +// ---------------------------------------------------------------------------- +class QULongLongValidator : public QValidator +{ + Q_OBJECT + Q_PROPERTY(qulonglong bottom READ bottom WRITE setBottom) + Q_PROPERTY(qulonglong top READ top WRITE setTop) + +public: + explicit QULongLongValidator(QObject * parent); + QULongLongValidator(qulonglong bottom, qulonglong top, QObject * parent); + ~QULongLongValidator(); + + QValidator::State validate(QString &, int &) const; + + void setBottom(qulonglong); + void setTop(qulonglong); + virtual void setRange(qulonglong bottom, qulonglong top); + + qulonglong bottom() const { return b; } + qulonglong top() const { return t; } + +private: + Q_DISABLE_COPY(QULongLongValidator) + + qulonglong b; + qulonglong t; +}; + +} // namespace qdesigner_internal + +QT_END_NAMESPACE + +#endif // QLONGLONGVALIDATOR_H diff --git a/tools/designer/src/components/propertyeditor/stringlisteditor.cpp b/tools/designer/src/components/propertyeditor/stringlisteditor.cpp new file mode 100644 index 0000000..861e699 --- /dev/null +++ b/tools/designer/src/components/propertyeditor/stringlisteditor.cpp @@ -0,0 +1,212 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the Qt Designer of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "stringlisteditor.h" +#include <iconloader_p.h> +#include <QtGui/QStringListModel> + +QT_BEGIN_NAMESPACE + +using namespace qdesigner_internal; + +StringListEditor::StringListEditor(QWidget *parent) + : QDialog(parent), m_model(new QStringListModel(this)) +{ + setupUi(this); + setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint); + listView->setModel(m_model); + + connect(listView->selectionModel(), + SIGNAL(currentChanged(const QModelIndex &, const QModelIndex &)), + this, SLOT(currentIndexChanged(const QModelIndex &, const QModelIndex &))); + connect(listView->itemDelegate(), + SIGNAL(closeEditor(QWidget *, QAbstractItemDelegate::EndEditHint)), + this, SLOT(currentValueChanged())); + + QIcon upIcon = createIconSet(QString::fromUtf8("up.png")); + QIcon downIcon = createIconSet(QString::fromUtf8("down.png")); + QIcon minusIcon = createIconSet(QString::fromUtf8("minus.png")); + QIcon plusIcon = createIconSet(QString::fromUtf8("plus.png")); + upButton->setIcon(upIcon); + downButton->setIcon(downIcon); + newButton->setIcon(plusIcon); + deleteButton->setIcon(minusIcon); + + updateUi(); +} + +StringListEditor::~StringListEditor() +{ +} + +QStringList StringListEditor::getStringList(QWidget *parent, const QStringList &init, int *result) +{ + StringListEditor dlg(parent); + dlg.setStringList(init); + int res = dlg.exec(); + if (result) + *result = res; + return (res == QDialog::Accepted) ? dlg.stringList() : init; +} + +void StringListEditor::setStringList(const QStringList &stringList) +{ + m_model->setStringList(stringList); + updateUi(); +} + +QStringList StringListEditor::stringList() const +{ + return m_model->stringList(); +} + +void StringListEditor::currentIndexChanged(const QModelIndex ¤t, const QModelIndex &previous) +{ + Q_UNUSED(previous); + setCurrentIndex(current.row()); + updateUi(); +} + +void StringListEditor::currentValueChanged() +{ + setCurrentIndex(currentIndex()); + updateUi(); +} + +void StringListEditor::on_upButton_clicked() +{ + int from = currentIndex(); + int to = currentIndex() - 1; + QString value = stringAt(from); + removeString(from); + insertString(to, value); + setCurrentIndex(to); + updateUi(); +} + +void StringListEditor::on_downButton_clicked() +{ + int from = currentIndex(); + int to = currentIndex() + 1; + QString value = stringAt(from); + removeString(from); + insertString(to, value); + setCurrentIndex(to); + updateUi(); +} + +void StringListEditor::on_newButton_clicked() +{ + int to = currentIndex(); + if (to == -1) + to = count() - 1; + ++to; + insertString(to, QString()); + setCurrentIndex(to); + updateUi(); + editString(to); +} + +void StringListEditor::on_deleteButton_clicked() +{ + removeString(currentIndex()); + setCurrentIndex(currentIndex()); + updateUi(); +} + +void StringListEditor::on_valueEdit_textEdited(const QString &text) +{ + setStringAt(currentIndex(), text); +} + +void StringListEditor::updateUi() +{ + upButton->setEnabled((count() > 1) && (currentIndex() > 0)); + downButton->setEnabled((count() > 1) && (currentIndex() >= 0) && (currentIndex() < (count() - 1))); + deleteButton->setEnabled(currentIndex() != -1); + valueEdit->setEnabled(currentIndex() != -1); +} + +int StringListEditor::currentIndex() const +{ + return listView->currentIndex().row(); +} + +void StringListEditor::setCurrentIndex(int index) +{ + QModelIndex modelIndex = m_model->index(index, 0); + if (listView->currentIndex() != modelIndex) + listView->setCurrentIndex(modelIndex); + valueEdit->setText(stringAt(index)); +} + +int StringListEditor::count() const +{ + return m_model->rowCount(); +} + +QString StringListEditor::stringAt(int index) const +{ + return qvariant_cast<QString>(m_model->data(m_model->index(index, 0), Qt::DisplayRole)); +} + +void StringListEditor::setStringAt(int index, const QString &value) +{ + m_model->setData(m_model->index(index, 0), value); +} + +void StringListEditor::removeString(int index) +{ + m_model->removeRows(index, 1); +} + +void StringListEditor::insertString(int index, const QString &value) +{ + m_model->insertRows(index, 1); + m_model->setData(m_model->index(index, 0), value); +} + +void StringListEditor::editString(int index) +{ + listView->edit(m_model->index(index, 0)); +} + +QT_END_NAMESPACE diff --git a/tools/designer/src/components/propertyeditor/stringlisteditor.h b/tools/designer/src/components/propertyeditor/stringlisteditor.h new file mode 100644 index 0000000..86b48ff --- /dev/null +++ b/tools/designer/src/components/propertyeditor/stringlisteditor.h @@ -0,0 +1,92 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the Qt Designer of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef STRINGLISTEDITOR_H +#define STRINGLISTEDITOR_H + +#include "ui_stringlisteditor.h" +#include <QtCore/QStringList> + +QT_BEGIN_NAMESPACE +class QStringListModel; + +namespace qdesigner_internal { + +class StringListEditor : public QDialog, private Ui::Dialog +{ + Q_OBJECT +public: + ~StringListEditor(); + void setStringList(const QStringList &stringList); + QStringList stringList() const; + + static QStringList getStringList( + QWidget *parent, const QStringList &init = QStringList(), int *result = 0); + +private slots: + void on_upButton_clicked(); + void on_downButton_clicked(); + void on_newButton_clicked(); + void on_deleteButton_clicked(); + void on_valueEdit_textEdited(const QString &text); + void currentIndexChanged(const QModelIndex ¤t, const QModelIndex &previous); + void currentValueChanged(); + +private: + StringListEditor(QWidget *parent = 0); + void updateUi(); + int currentIndex() const; + void setCurrentIndex(int index); + int count() const; + QString stringAt(int index) const; + void setStringAt(int index, const QString &value); + void removeString(int index); + void insertString(int index, const QString &value); + void editString(int index); + + QStringListModel *m_model; +}; + +} // namespace qdesigner_internal + +QT_END_NAMESPACE + +#endif // STRINGLISTEDITOR_H diff --git a/tools/designer/src/components/propertyeditor/stringlisteditor.ui b/tools/designer/src/components/propertyeditor/stringlisteditor.ui new file mode 100644 index 0000000..fdcdabc --- /dev/null +++ b/tools/designer/src/components/propertyeditor/stringlisteditor.ui @@ -0,0 +1,265 @@ +<ui version="4.0" > + <comment>********************************************************************* +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the Qt Designer of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +*********************************************************************</comment> + <class>qdesigner_internal::Dialog</class> + <widget class="QDialog" name="qdesigner_internal::Dialog" > + <property name="geometry" > + <rect> + <x>0</x> + <y>0</y> + <width>400</width> + <height>300</height> + </rect> + </property> + <property name="windowTitle" > + <string>Dialog</string> + </property> + <layout class="QVBoxLayout" > + <property name="margin" > + <number>9</number> + </property> + <property name="spacing" > + <number>6</number> + </property> + <item> + <widget class="QGroupBox" name="groupBox" > + <property name="title" > + <string>StringList</string> + </property> + <layout class="QGridLayout" > + <property name="margin" > + <number>9</number> + </property> + <property name="spacing" > + <number>6</number> + </property> + <item row="1" column="0" colspan="2" > + <layout class="QVBoxLayout" > + <property name="margin" > + <number>0</number> + </property> + <property name="spacing" > + <number>6</number> + </property> + <item> + <layout class="QHBoxLayout" > + <property name="margin" > + <number>0</number> + </property> + <property name="spacing" > + <number>6</number> + </property> + <item> + <widget class="QToolButton" name="newButton" > + <property name="toolTip" > + <string>New String</string> + </property> + <property name="text" > + <string>&New</string> + </property> + <property name="toolButtonStyle" > + <enum>Qt::ToolButtonTextBesideIcon</enum> + </property> + </widget> + </item> + <item> + <widget class="QToolButton" name="deleteButton" > + <property name="toolTip" > + <string>Delete String</string> + </property> + <property name="text" > + <string>&Delete</string> + </property> + <property name="toolButtonStyle" > + <enum>Qt::ToolButtonTextBesideIcon</enum> + </property> + </widget> + </item> + <item> + <spacer> + <property name="orientation" > + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeHint" > + <size> + <width>40</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + </layout> + </item> + <item> + <layout class="QHBoxLayout" > + <property name="margin" > + <number>0</number> + </property> + <property name="spacing" > + <number>6</number> + </property> + <item> + <widget class="QLabel" name="label" > + <property name="text" > + <string>&Value:</string> + </property> + <property name="buddy" > + <cstring>valueEdit</cstring> + </property> + </widget> + </item> + <item> + <widget class="QLineEdit" name="valueEdit" /> + </item> + </layout> + </item> + </layout> + </item> + <item row="0" column="1" > + <layout class="QVBoxLayout" > + <property name="margin" > + <number>0</number> + </property> + <property name="spacing" > + <number>6</number> + </property> + <item> + <spacer> + <property name="orientation" > + <enum>Qt::Vertical</enum> + </property> + <property name="sizeHint" > + <size> + <width>20</width> + <height>40</height> + </size> + </property> + </spacer> + </item> + <item> + <widget class="QToolButton" name="upButton" > + <property name="toolTip" > + <string>Move String Up</string> + </property> + <property name="text" > + <string>Up</string> + </property> + </widget> + </item> + <item> + <widget class="QToolButton" name="downButton" > + <property name="toolTip" > + <string>Move String Down</string> + </property> + <property name="text" > + <string>Down</string> + </property> + </widget> + </item> + <item> + <spacer> + <property name="orientation" > + <enum>Qt::Vertical</enum> + </property> + <property name="sizeHint" > + <size> + <width>20</width> + <height>40</height> + </size> + </property> + </spacer> + </item> + </layout> + </item> + <item row="0" column="0" > + <widget class="QListView" name="listView" /> + </item> + </layout> + </widget> + </item> + <item> + <widget class="QDialogButtonBox" name="buttonBox" > + <property name="orientation" > + <enum>Qt::Horizontal</enum> + </property> + <property name="standardButtons" > + <set>QDialogButtonBox::Cancel|QDialogButtonBox::NoButton|QDialogButtonBox::Ok</set> + </property> + </widget> + </item> + </layout> + </widget> + <resources/> + <connections> + <connection> + <sender>buttonBox</sender> + <signal>accepted()</signal> + <receiver>qdesigner_internal::Dialog</receiver> + <slot>accept()</slot> + <hints> + <hint type="sourcelabel" > + <x>258</x> + <y>283</y> + </hint> + <hint type="destinationlabel" > + <x>138</x> + <y>294</y> + </hint> + </hints> + </connection> + <connection> + <sender>buttonBox</sender> + <signal>rejected()</signal> + <receiver>qdesigner_internal::Dialog</receiver> + <slot>reject()</slot> + <hints> + <hint type="sourcelabel" > + <x>350</x> + <y>284</y> + </hint> + <hint type="destinationlabel" > + <x>369</x> + <y>295</y> + </hint> + </hints> + </connection> + </connections> +</ui> diff --git a/tools/designer/src/components/propertyeditor/stringlisteditorbutton.cpp b/tools/designer/src/components/propertyeditor/stringlisteditorbutton.cpp new file mode 100644 index 0000000..440015c --- /dev/null +++ b/tools/designer/src/components/propertyeditor/stringlisteditorbutton.cpp @@ -0,0 +1,85 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the Qt Designer of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +/* +TRANSLATOR qdesigner_internal::StringListEditorButton +*/ + +#include "stringlisteditorbutton.h" +#include "stringlisteditor.h" + +#include <QtCore/qdebug.h> + +QT_BEGIN_NAMESPACE + +using namespace qdesigner_internal; + +StringListEditorButton::StringListEditorButton( + const QStringList &stringList, QWidget *parent) + : QToolButton(parent), m_stringList(stringList) +{ + setFocusPolicy(Qt::NoFocus); + setText(tr("Change String List")); + setSizePolicy(QSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed)); + + connect(this, SIGNAL(clicked()), this, SLOT(showStringListEditor())); +} + +StringListEditorButton::~StringListEditorButton() +{ +} + +void StringListEditorButton::setStringList(const QStringList &stringList) +{ + m_stringList = stringList; +} + +void StringListEditorButton::showStringListEditor() +{ + int result; + QStringList lst = StringListEditor::getStringList(0, m_stringList, &result); + if (result == QDialog::Accepted) { + m_stringList = lst; + emit stringListChanged(m_stringList); + } +} + +QT_END_NAMESPACE diff --git a/tools/designer/src/components/propertyeditor/stringlisteditorbutton.h b/tools/designer/src/components/propertyeditor/stringlisteditorbutton.h new file mode 100644 index 0000000..c843980 --- /dev/null +++ b/tools/designer/src/components/propertyeditor/stringlisteditorbutton.h @@ -0,0 +1,81 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the Qt Designer of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef STRINGLISTEDITORBUTTON_H +#define STRINGLISTEDITORBUTTON_H + +#include "propertyeditor_global.h" + +#include <QtCore/QStringList> +#include <QtGui/QToolButton> + +QT_BEGIN_NAMESPACE + +namespace qdesigner_internal { + +class QT_PROPERTYEDITOR_EXPORT StringListEditorButton: public QToolButton +{ + Q_OBJECT +public: + explicit StringListEditorButton(const QStringList &stringList, QWidget *parent = 0); + virtual ~StringListEditorButton(); + + inline QStringList stringList() const + { return m_stringList; } + +signals: + void stringListChanged(const QStringList &stringList); + +public slots: + void setStringList(const QStringList &stringList); + +private slots: + void showStringListEditor(); + +private: + QStringList m_stringList; +}; + +} // namespace qdesigner_internal + +QT_END_NAMESPACE + +#endif // STRINGLISTEDITORBUTTON_H |