diff options
author | Friedemann Kleint <Friedemann.Kleint@nokia.com> | 2010-09-08 08:51:31 (GMT) |
---|---|---|
committer | Friedemann Kleint <Friedemann.Kleint@nokia.com> | 2010-09-08 08:51:31 (GMT) |
commit | 6bcdb38b5bdf8f0176db3f372d4b8c8b14ba459f (patch) | |
tree | 0705d016f6b5b5d506aff73d2c966b7b3682ff32 /tools/designer/src/lib | |
parent | 0901337e0c23910f265f0991b9fc6875efafedaf (diff) | |
download | Qt-6bcdb38b5bdf8f0176db3f372d4b8c8b14ba459f.zip Qt-6bcdb38b5bdf8f0176db3f372d4b8c8b14ba459f.tar.gz Qt-6bcdb38b5bdf8f0176db3f372d4b8c8b14ba459f.tar.bz2 |
Designer/uic: Start on support for QIcon::fromTheme().
Schemas: Add "theme" attribute to <iconset> element of the UI format.
uic: Extend it to generate the code for icons with themes and/or resource
paths, add auto-test for it.
Designer: Add 'theme'-member to PropertySheetIconValue + convenience
functions including subproperty mask handling and simplify the existing
code. Add new class IconThemeEditor to be used in action editor dialog and
property editor. Theme names can now be specified in the action editor
dialog.
Reviewed-by: Jarek Kobus <jaroslaw.kobus@nokia.com>
Task-number: QTBUG-7777
Diffstat (limited to 'tools/designer/src/lib')
-rw-r--r-- | tools/designer/src/lib/shared/actioneditor.cpp | 3 | ||||
-rw-r--r-- | tools/designer/src/lib/shared/iconselector.cpp | 124 | ||||
-rw-r--r-- | tools/designer/src/lib/shared/iconselector_p.h | 30 | ||||
-rw-r--r-- | tools/designer/src/lib/shared/newactiondialog.cpp | 4 | ||||
-rw-r--r-- | tools/designer/src/lib/shared/newactiondialog.ui | 54 | ||||
-rw-r--r-- | tools/designer/src/lib/shared/qdesigner_propertysheet.cpp | 4 | ||||
-rw-r--r-- | tools/designer/src/lib/shared/qdesigner_utils.cpp | 232 | ||||
-rw-r--r-- | tools/designer/src/lib/shared/qdesigner_utils_p.h | 24 | ||||
-rw-r--r-- | tools/designer/src/lib/uilib/resourcebuilder.cpp | 11 | ||||
-rw-r--r-- | tools/designer/src/lib/uilib/ui4.cpp | 11 | ||||
-rw-r--r-- | tools/designer/src/lib/uilib/ui4_p.h | 8 |
11 files changed, 423 insertions, 82 deletions
diff --git a/tools/designer/src/lib/shared/actioneditor.cpp b/tools/designer/src/lib/shared/actioneditor.cpp index d3716ca..9664a22 100644 --- a/tools/designer/src/lib/shared/actioneditor.cpp +++ b/tools/designer/src/lib/shared/actioneditor.cpp @@ -445,7 +445,6 @@ void ActionEditor::slotNewAction() if (dlg.exec() == QDialog::Accepted) { const ActionData actionData = dlg.actionData(); m_actionView->clearSelection(); - QAction *action = new QAction(formWindow()); action->setObjectName(actionData.name); formWindow()->ensureUniqueObjectName(action); @@ -480,7 +479,7 @@ static inline bool isSameIcon(const QIcon &i1, const QIcon &i2) static QDesignerFormWindowCommand *setIconPropertyCommand(const PropertySheetIconValue &newIcon, QAction *action, QDesignerFormWindowInterface *fw) { const QString iconProperty = QLatin1String(iconPropertyC); - if (newIcon.paths().isEmpty()) { + if (newIcon.isEmpty()) { ResetPropertyCommand *cmd = new ResetPropertyCommand(fw); cmd->init(action, iconProperty); return cmd; diff --git a/tools/designer/src/lib/shared/iconselector.cpp b/tools/designer/src/lib/shared/iconselector.cpp index 4bb7430..8931b9f 100644 --- a/tools/designer/src/lib/shared/iconselector.cpp +++ b/tools/designer/src/lib/shared/iconselector.cpp @@ -67,8 +67,12 @@ #include <QtGui/QImageReader> #include <QtGui/QDialogButtonBox> #include <QtGui/QVBoxLayout> +#include <QtGui/QLineEdit> +#include <QtGui/QLabel> +#include <QtGui/QValidator> #include <QtCore/QDebug> + QT_BEGIN_NAMESPACE namespace qdesigner_internal { @@ -181,6 +185,14 @@ LanguageResourceDialog* LanguageResourceDialog::create(QDesignerFormEditorInterf } // ------------ IconSelectorPrivate + +static inline QPixmap emptyPixmap() +{ + QImage img(16, 16, QImage::Format_ARGB32_Premultiplied); + img.fill(0); + return QPixmap::fromImage(img); +} + class IconSelectorPrivate { IconSelector *q_ptr; @@ -201,7 +213,7 @@ public: QMap<QPair<QIcon::Mode, QIcon::State>, int> m_stateToIndex; QMap<int, QPair<QIcon::Mode, QIcon::State> > m_indexToState; - QIcon m_emptyIcon; + const QIcon m_emptyIcon; QComboBox *m_stateComboBox; QToolButton *m_iconButton; QAction *m_resetAction; @@ -215,6 +227,7 @@ public: IconSelectorPrivate::IconSelectorPrivate() : q_ptr(0), + m_emptyIcon(emptyPixmap()), m_stateComboBox(0), m_iconButton(0), m_resetAction(0), @@ -449,10 +462,6 @@ IconSelector::IconSelector(QWidget *parent) : d_ptr->m_stateToName << qMakePair(qMakePair(QIcon::Selected, QIcon::Off), tr("Selected Off") ); d_ptr->m_stateToName << qMakePair(qMakePair(QIcon::Selected, QIcon::On), tr("Selected On") ); - QImage img(16, 16, QImage::Format_ARGB32_Premultiplied); - img.fill(0); - d_ptr->m_emptyIcon = QIcon(QPixmap::fromImage(img)); - QMenu *setMenu = new QMenu(this); QAction *setResourceAction = new QAction(tr("Choose Resource..."), this); @@ -535,9 +544,112 @@ void IconSelector::setPixmapCache(DesignerPixmapCache *pixmapCache) d_ptr->slotUpdate(); } +// --- IconThemeEditor + +// Validator for theme line edit, accepts empty or non-blank strings. +class BlankSuppressingValidator : public QValidator { +public: + explicit BlankSuppressingValidator(QObject * parent = 0) : QValidator(parent) {} + + virtual State validate(QString &input, int &pos) const { + const int blankPos = input.indexOf(QLatin1Char(' ')); + if (blankPos != -1) { + pos = blankPos; + return Invalid; + } + return Acceptable; + } +}; + +struct IconThemeEditorPrivate { + IconThemeEditorPrivate(); + + const QPixmap m_emptyPixmap; + QLineEdit *m_themeLineEdit; + QLabel *m_themeLabel; +}; + +IconThemeEditorPrivate::IconThemeEditorPrivate() : + m_emptyPixmap(emptyPixmap()), + m_themeLineEdit(new QLineEdit), + m_themeLabel(new QLabel) +{ +} + +IconThemeEditor::IconThemeEditor(QWidget *parent, bool wantResetButton) : + QWidget (parent), d(new IconThemeEditorPrivate) +{ + QHBoxLayout *mainHLayout = new QHBoxLayout; + mainHLayout->setMargin(0); + + // Vertically center theme preview label + d->m_themeLabel->setFrameStyle(QFrame::Box); + d->m_themeLabel->setPixmap(d->m_emptyPixmap); + + QVBoxLayout *themeLabelVLayout = new QVBoxLayout; + d->m_themeLabel->setMargin(1); + themeLabelVLayout->setMargin(0); + themeLabelVLayout->addSpacerItem(new QSpacerItem(0, 0, QSizePolicy::Ignored, QSizePolicy::MinimumExpanding)); + themeLabelVLayout->addWidget(d->m_themeLabel); + themeLabelVLayout->addSpacerItem(new QSpacerItem(0, 0, QSizePolicy::Ignored, QSizePolicy::MinimumExpanding)); + mainHLayout->addLayout(themeLabelVLayout); + + d->m_themeLineEdit = new QLineEdit; + d->m_themeLineEdit->setValidator(new BlankSuppressingValidator(d->m_themeLineEdit)); + connect(d->m_themeLineEdit, SIGNAL(textChanged(QString)), this, SLOT(slotChanged(QString))); + connect(d->m_themeLineEdit, SIGNAL(textEdited(QString)), this, SIGNAL(edited(QString))); + mainHLayout->addWidget(d->m_themeLineEdit); + + if (wantResetButton) { + QToolButton *themeResetButton = new QToolButton; + themeResetButton->setIcon(createIconSet(QLatin1String("resetproperty.png"))); + connect(themeResetButton, SIGNAL(clicked()), this, SLOT(reset())); + mainHLayout->addWidget(themeResetButton); + } + + setLayout(mainHLayout); +} + +IconThemeEditor::~IconThemeEditor() +{ +} + +void IconThemeEditor::reset() +{ + d->m_themeLineEdit->clear(); + emit edited(QString()); +} + +void IconThemeEditor::slotChanged(const QString &theme) +{ + updatePreview(theme); +} + +void IconThemeEditor::updatePreview(const QString &t) +{ + // Update preview label with icon. + if (t.isEmpty() || !QIcon::hasThemeIcon(t)) { // Empty + const QPixmap *currentPixmap = d->m_themeLabel->pixmap(); + if (currentPixmap == 0 || currentPixmap->serialNumber() != d->m_emptyPixmap.serialNumber()) + d->m_themeLabel->setPixmap(d->m_emptyPixmap); + } else { + const QIcon icon = QIcon::fromTheme(t); + d->m_themeLabel->setPixmap(icon.pixmap(d->m_emptyPixmap.size())); + } +} + +QString IconThemeEditor::theme() const +{ + return d->m_themeLineEdit->text(); +} + +void IconThemeEditor::setTheme(const QString &t) +{ + d->m_themeLineEdit->setText(t); +} + } // qdesigner_internal QT_END_NAMESPACE #include "moc_iconselector_p.cpp" - diff --git a/tools/designer/src/lib/shared/iconselector_p.h b/tools/designer/src/lib/shared/iconselector_p.h index 3373f80..5fa8f80 100644 --- a/tools/designer/src/lib/shared/iconselector_p.h +++ b/tools/designer/src/lib/shared/iconselector_p.h @@ -55,9 +55,12 @@ #define ICONSELECTOR_H #include "shared_global_p.h" + #include <QtGui/QWidget> #include <QtGui/QDialog> +#include <QtCore/QScopedPointer> + QT_BEGIN_NAMESPACE class QtResourceModel; @@ -70,6 +73,7 @@ namespace qdesigner_internal { class DesignerIconCache; class DesignerPixmapCache; class PropertySheetIconValue; +struct IconThemeEditorPrivate; // Resource Dialog that embeds the language-dependent resource widget as returned by the language extension class QDESIGNER_SHARED_EXPORT LanguageResourceDialog : public QDialog @@ -133,6 +137,32 @@ private: Q_PRIVATE_SLOT(d_func(), void slotUpdate()) }; +// IconThemeEditor: Let's the user input theme icon names and shows a preview label. +class QDESIGNER_SHARED_EXPORT IconThemeEditor : public QWidget +{ + Q_OBJECT + Q_PROPERTY(QString theme READ theme WRITE setTheme DESIGNABLE true) +public: + explicit IconThemeEditor(QWidget *parent = 0, bool wantResetButton = true); + virtual ~IconThemeEditor(); + + QString theme() const; + void setTheme(const QString &theme); + +signals: + void edited(const QString &); + +public slots: + void reset(); + +private slots: + void slotChanged(const QString &); + +private: + void updatePreview(const QString &); + + QScopedPointer<IconThemeEditorPrivate> d; +}; } // namespace qdesigner_internal diff --git a/tools/designer/src/lib/shared/newactiondialog.cpp b/tools/designer/src/lib/shared/newactiondialog.cpp index b411464..e6c95f6 100644 --- a/tools/designer/src/lib/shared/newactiondialog.cpp +++ b/tools/designer/src/lib/shared/newactiondialog.cpp @@ -133,6 +133,7 @@ ActionData NewActionDialog::actionData() const rc.name = actionName(); rc.toolTip = m_ui->tooltipEditor->text(); rc.icon = m_ui->iconSelector->icon(); + rc.icon.setTheme(m_ui->iconThemeEditor->theme()); rc.checkable = m_ui->checkableCheckBox->checkState() == Qt::Checked; rc.keysequence = PropertySheetKeySequenceValue(m_ui->keySequenceEdit->keySequence()); return rc; @@ -142,7 +143,8 @@ void NewActionDialog::setActionData(const ActionData &d) { m_ui->editActionText->setText(d.text); m_ui->editObjectName->setText(d.name); - m_ui->iconSelector->setIcon(d.icon); + m_ui->iconSelector->setIcon(d.icon.unthemed()); + m_ui->iconThemeEditor->setTheme(d.icon.theme()); m_ui->tooltipEditor->setText(d.toolTip); m_ui->keySequenceEdit->setKeySequence(d.keysequence.value()); m_ui->checkableCheckBox->setCheckState(d.checkable ? Qt::Checked : Qt::Unchecked); diff --git a/tools/designer/src/lib/shared/newactiondialog.ui b/tools/designer/src/lib/shared/newactiondialog.ui index f9cafd1..ca5406f 100644 --- a/tools/designer/src/lib/shared/newactiondialog.ui +++ b/tools/designer/src/lib/shared/newactiondialog.ui @@ -42,6 +42,14 @@ *********************************************************************</comment> <class>qdesigner_internal::NewActionDialog</class> <widget class="QDialog" name="qdesigner_internal::NewActionDialog"> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>366</width> + <height>270</height> + </rect> + </property> <property name="windowTitle"> <string>New Action...</string> </property> @@ -81,7 +89,7 @@ <item row="1" column="1"> <widget class="QLineEdit" name="editObjectName"/> </item> - <item row="3" column="0"> + <item row="4" column="0"> <widget class="QLabel" name="iconLabel"> <property name="text"> <string>&Icon:</string> @@ -91,7 +99,7 @@ </property> </widget> </item> - <item row="3" column="1"> + <item row="4" column="1"> <layout class="QHBoxLayout" name="horizontalLayout"> <item> <widget class="qdesigner_internal::IconSelector" name="iconSelector" native="true"/> @@ -111,31 +119,40 @@ </item> </layout> </item> - <item row="5" column="0"> + <item row="6" column="0"> <widget class="QLabel" name="shortcutLabel"> <property name="text"> - <string>Shortcut:</string> + <string>&Shortcut:</string> + </property> + <property name="buddy"> + <cstring>keySequenceEdit</cstring> </property> </widget> </item> - <item row="4" column="1"> + <item row="5" column="1"> <widget class="QCheckBox" name="checkableCheckBox"> <property name="text"> <string/> </property> </widget> </item> - <item row="4" column="0"> + <item row="5" column="0"> <widget class="QLabel" name="checkableLabel"> <property name="text"> - <string>Checkable:</string> + <string>&Checkable:</string> + </property> + <property name="buddy"> + <cstring>checkableCheckBox</cstring> </property> </widget> </item> <item row="2" column="0"> <widget class="QLabel" name="toolTipLabel"> <property name="text"> - <string>ToolTip:</string> + <string>T&oolTip:</string> + </property> + <property name="buddy"> + <cstring>tooltipEditor</cstring> </property> </widget> </item> @@ -160,7 +177,7 @@ </item> </layout> </item> - <item row="5" column="1"> + <item row="6" column="1"> <layout class="QHBoxLayout" name="keysequenceLayout"> <item> <widget class="QtKeySequenceEdit" name="keySequenceEdit" native="true"> @@ -181,6 +198,19 @@ </item> </layout> </item> + <item row="3" column="0"> + <widget class="QLabel" name="iconThemeLabel"> + <property name="text"> + <string>Icon th&eme:</string> + </property> + <property name="buddy"> + <cstring>iconThemeEditor</cstring> + </property> + </widget> + </item> + <item row="3" column="1"> + <widget class="qdesigner_internal::IconThemeEditor" name="iconThemeEditor" native="true"/> + </item> </layout> </item> <item> @@ -234,6 +264,12 @@ <header>textpropertyeditor_p.h</header> <container>1</container> </customwidget> + <customwidget> + <class>qdesigner_internal::IconThemeEditor</class> + <extends>QWidget</extends> + <header>iconselector_p.h</header> + <container>1</container> + </customwidget> </customwidgets> <tabstops> <tabstop>editActionText</tabstop> diff --git a/tools/designer/src/lib/shared/qdesigner_propertysheet.cpp b/tools/designer/src/lib/shared/qdesigner_propertysheet.cpp index 72ecb8f..ee05adf 100644 --- a/tools/designer/src/lib/shared/qdesigner_propertysheet.cpp +++ b/tools/designer/src/lib/shared/qdesigner_propertysheet.cpp @@ -1065,8 +1065,8 @@ QVariant QDesignerPropertySheet::resolvePropertyValue(int index, const QVariant } if (value.canConvert<qdesigner_internal::PropertySheetIconValue>()) { - const int pathCount = qvariant_cast<qdesigner_internal::PropertySheetIconValue>(value).paths().count(); - if (pathCount == 0) + const unsigned mask = qvariant_cast<qdesigner_internal::PropertySheetIconValue>(value).mask(); + if (mask == 0) return defaultResourceProperty(index); if (d->m_iconCache) return d->m_iconCache->icon(qvariant_cast<qdesigner_internal::PropertySheetIconValue>(value)); diff --git a/tools/designer/src/lib/shared/qdesigner_utils.cpp b/tools/designer/src/lib/shared/qdesigner_utils.cpp index de3e387..03d7cfa 100644 --- a/tools/designer/src/lib/shared/qdesigner_utils.cpp +++ b/tools/designer/src/lib/shared/qdesigner_utils.cpp @@ -52,15 +52,16 @@ #include <QtDesigner/QDesignerTaskMenuExtension> #include <QtDesigner/QExtensionManager> -#include <QtGui/QIcon> -#include <QtGui/QPixmap> #include <QtCore/QDir> - -#include <QtGui/QApplication> #include <QtCore/QProcess> #include <QtCore/QLibraryInfo> #include <QtCore/QDebug> #include <QtCore/QQueue> +#include <QtCore/QSharedData> + +#include <QtGui/QApplication> +#include <QtGui/QIcon> +#include <QtGui/QPixmap> #include <QtGui/QListWidget> #include <QtGui/QTreeWidget> #include <QtGui/QTableWidget> @@ -314,24 +315,51 @@ namespace qdesigner_internal } // ---------- PropertySheetIconValue - PropertySheetIconValue::PropertySheetIconValue(const PropertySheetPixmapValue &pixmap) + + class PropertySheetIconValueData : public QSharedData { + public: + PropertySheetIconValue::ModeStateToPixmapMap m_paths; + QString m_theme; + }; + + PropertySheetIconValue::PropertySheetIconValue(const PropertySheetPixmapValue &pixmap) : + m_data(new PropertySheetIconValueData) { setPixmap(QIcon::Normal, QIcon::Off, pixmap); } - PropertySheetIconValue::PropertySheetIconValue() + PropertySheetIconValue::PropertySheetIconValue() : + m_data(new PropertySheetIconValueData) + { + } + + PropertySheetIconValue::~PropertySheetIconValue() { } + PropertySheetIconValue::PropertySheetIconValue(const PropertySheetIconValue &rhs) : + m_data(rhs.m_data) + { + } + + PropertySheetIconValue &PropertySheetIconValue::operator=(const PropertySheetIconValue &rhs) + { + if (this != &rhs) + m_data.operator=(rhs.m_data); + return *this; + } + bool PropertySheetIconValue::equals(const PropertySheetIconValue &rhs) const { - return m_paths == rhs.m_paths; + return m_data->m_theme == rhs.m_data->m_theme && m_data->m_paths == rhs.m_data->m_paths; } bool PropertySheetIconValue::operator<(const PropertySheetIconValue &other) const { - QMapIterator<ModeStateKey, PropertySheetPixmapValue> itThis(m_paths); - QMapIterator<ModeStateKey, PropertySheetPixmapValue> itOther(other.m_paths); + if (const int themeCmp = m_data->m_theme.compare(other.m_data->m_theme)) + return themeCmp < 0; + QMapIterator<ModeStateKey, PropertySheetPixmapValue> itThis(m_data->m_paths); + QMapIterator<ModeStateKey, PropertySheetPixmapValue> itOther(other.m_data->m_paths); while (itThis.hasNext() && itOther.hasNext()) { const ModeStateKey thisPair = itThis.next().key(); const ModeStateKey otherPair = itOther.next().key(); @@ -350,19 +378,34 @@ namespace qdesigner_internal return false; } + bool PropertySheetIconValue::isEmpty() const + { + return m_data->m_theme.isEmpty() && m_data->m_paths.isEmpty(); + } + + QString PropertySheetIconValue::theme() const + { + return m_data->m_theme; + } + + void PropertySheetIconValue::setTheme(const QString &t) + { + m_data->m_theme = t; + } + PropertySheetPixmapValue PropertySheetIconValue::pixmap(QIcon::Mode mode, QIcon::State state) const { const ModeStateKey pair = qMakePair(mode, state); - return m_paths.value(pair); + return m_data->m_paths.value(pair); } void PropertySheetIconValue::setPixmap(QIcon::Mode mode, QIcon::State state, const PropertySheetPixmapValue &pixmap) { const ModeStateKey pair = qMakePair(mode, state); if (pixmap.path().isEmpty()) - m_paths.remove(pair); + m_data->m_paths.remove(pair); else - m_paths.insert(pair, pixmap); + m_data->m_paths.insert(pair, pixmap); } QPixmap DesignerPixmapCache::pixmap(const PropertySheetPixmapValue &value) const @@ -388,16 +431,28 @@ namespace qdesigner_internal QIcon DesignerIconCache::icon(const PropertySheetIconValue &value) const { + typedef PropertySheetIconValue::ModeStateToPixmapMap::const_iterator ModeStateToPixmapMapConstIt; + QMap<PropertySheetIconValue, QIcon>::const_iterator it = m_cache.constFind(value); if (it != m_cache.constEnd()) return it.value(); + // Match on the theme first if it is available. + if (!value.theme().isEmpty()) { + const QString theme = value.theme(); + if (QIcon::hasThemeIcon(theme)) { + const QIcon themeIcon = QIcon::fromTheme(theme); + m_cache.insert(value, themeIcon); + return themeIcon; + } + } + QIcon icon; - QMap<QPair<QIcon::Mode, QIcon::State>, PropertySheetPixmapValue> paths = value.paths(); - QMapIterator<QPair<QIcon::Mode, QIcon::State>, PropertySheetPixmapValue> itPath(paths); - while (itPath.hasNext()) { - QPair<QIcon::Mode, QIcon::State> pair = itPath.next().key(); - icon.addFile(itPath.value().path(), QSize(), pair.first, pair.second); + const PropertySheetIconValue::ModeStateToPixmapMap &paths = value.paths(); + const ModeStateToPixmapMapConstIt cend = paths.constEnd(); + for (ModeStateToPixmapMapConstIt it = paths.constBegin(); it != cend; ++it) { + const QPair<QIcon::Mode, QIcon::State> pair = it.key(); + icon.addFile(it.value().path(), QSize(), pair.first, pair.second); } m_cache.insert(value, icon); return icon; @@ -547,50 +602,75 @@ namespace qdesigner_internal && (m_translatable == rhs.m_translatable) && (m_disambiguation == rhs.m_disambiguation) && (m_comment == rhs.m_comment); } - class StateMap + + /* IconSubPropertyMask: Assign each icon sub-property (pixmaps for the + * various states/modes and the theme) a flag bit (see QFont) so that they + * can be handled individually when assigning property values to + * multiselections in the set-property-commands (that is, do not clobber + * other subproperties when assigning just one). + * Provide back-and-forth mapping functions for the icon states. */ + + enum IconSubPropertyMask { + NormalOffIconMask = 0x01, + NormalOnIconMask = 0x02, + DisabledOffIconMask = 0x04, + DisabledOnIconMask = 0x08, + ActiveOffIconMask = 0x10, + ActiveOnIconMask = 0x20, + SelectedOffIconMask = 0x40, + SelectedOnIconMask = 0x80, + ThemeIconMask = 0x10000 + }; + + static inline uint iconStateToSubPropertyFlag(QIcon::Mode mode, QIcon::State state) { - public: - StateMap() - { - m_stateToFlag.insert(qMakePair(QIcon::Normal, QIcon::Off), 0x01); - m_stateToFlag.insert(qMakePair(QIcon::Normal, QIcon::On), 0x02); - m_stateToFlag.insert(qMakePair(QIcon::Disabled, QIcon::Off), 0x04); - m_stateToFlag.insert(qMakePair(QIcon::Disabled, QIcon::On), 0x08); - m_stateToFlag.insert(qMakePair(QIcon::Active, QIcon::Off), 0x10); - m_stateToFlag.insert(qMakePair(QIcon::Active, QIcon::On), 0x20); - m_stateToFlag.insert(qMakePair(QIcon::Selected, QIcon::Off), 0x40); - m_stateToFlag.insert(qMakePair(QIcon::Selected, QIcon::On), 0x80); - - m_flagToState.insert(0x01, qMakePair(QIcon::Normal, QIcon::Off)); - m_flagToState.insert(0x02, qMakePair(QIcon::Normal, QIcon::On)); - m_flagToState.insert(0x04, qMakePair(QIcon::Disabled, QIcon::Off)); - m_flagToState.insert(0x08, qMakePair(QIcon::Disabled, QIcon::On)); - m_flagToState.insert(0x10, qMakePair(QIcon::Active, QIcon::Off)); - m_flagToState.insert(0x20, qMakePair(QIcon::Active, QIcon::On)); - m_flagToState.insert(0x40, qMakePair(QIcon::Selected, QIcon::Off)); - m_flagToState.insert(0x80, qMakePair(QIcon::Selected, QIcon::On)); - } - uint flag(const QPair<QIcon::Mode, QIcon::State> &pair) const - { - return m_stateToFlag.value(pair); + switch (mode) { + case QIcon::Disabled: + return state == QIcon::On ? DisabledOnIconMask : DisabledOffIconMask; + case QIcon::Active: + return state == QIcon::On ? ActiveOnIconMask : ActiveOffIconMask; + case QIcon::Selected: + return state == QIcon::On ? SelectedOnIconMask : SelectedOffIconMask; + case QIcon::Normal: + break; } - QPair<QIcon::Mode, QIcon::State> state(uint flag) const - { - return m_flagToState.value(flag); + return state == QIcon::On ? NormalOnIconMask : NormalOffIconMask; + } + + static inline QPair<QIcon::Mode, QIcon::State> subPropertyFlagToIconModeState(unsigned flag) + { + switch (flag) { + case NormalOffIconMask: + return qMakePair(QIcon::Normal, QIcon::Off); + case DisabledOffIconMask: + return qMakePair(QIcon::Disabled, QIcon::Off); + case DisabledOnIconMask: + return qMakePair(QIcon::Disabled, QIcon::On); + case ActiveOffIconMask: + return qMakePair(QIcon::Active, QIcon::Off); + case ActiveOnIconMask: + return qMakePair(QIcon::Active, QIcon::On); + case SelectedOffIconMask: + return qMakePair(QIcon::Selected, QIcon::Off); + case SelectedOnIconMask: + return qMakePair(QIcon::Selected, QIcon::On); + case NormalOnIconMask: + default: + break; } - private: - QMap<QPair<QIcon::Mode, QIcon::State>, uint > m_stateToFlag; - QMap<uint, QPair<QIcon::Mode, QIcon::State> > m_flagToState; - }; - - Q_GLOBAL_STATIC(StateMap, stateMap) + return qMakePair(QIcon::Normal, QIcon::On); + } uint PropertySheetIconValue::mask() const { + typedef ModeStateToPixmapMap::const_iterator ModeStateToPixmapMapConstIt; + uint flags = 0; - QMapIterator<ModeStateKey, PropertySheetPixmapValue> itPath(m_paths); - while (itPath.hasNext()) - flags |= stateMap()->flag(itPath.next().key()); + const ModeStateToPixmapMapConstIt cend = m_data->m_paths.constEnd(); + for (ModeStateToPixmapMapConstIt it = m_data->m_paths.constBegin(); it != cend; ++it) + flags |= iconStateToSubPropertyFlag(it.key().first, it.key().second); + if (!m_data->m_theme.isEmpty()) + flags |= ThemeIconMask; return flags; } @@ -598,30 +678,64 @@ namespace qdesigner_internal { uint diffMask = mask() | other.mask(); for (int i = 0; i < 8; i++) { - uint flag = 1 << i; + const uint flag = 1 << i; if (diffMask & flag) { // if state is set in both icons, compare the values - const ModeStateKey state = stateMap()->state(flag); + const QPair<QIcon::Mode, QIcon::State> state = subPropertyFlagToIconModeState(flag); if (pixmap(state.first, state.second) == other.pixmap(state.first, state.second)) diffMask &= ~flag; } } + if ((diffMask & ThemeIconMask) && theme() == other.theme()) + diffMask &= ~ThemeIconMask; return diffMask; } + PropertySheetIconValue PropertySheetIconValue::themed() const + { + PropertySheetIconValue rc(*this); + rc.m_data->m_paths.clear(); + return rc; + } + + PropertySheetIconValue PropertySheetIconValue::unthemed() const + { + PropertySheetIconValue rc(*this); + rc.m_data->m_theme.clear(); + return rc; + } + void PropertySheetIconValue::assign(const PropertySheetIconValue &other, uint mask) { for (int i = 0; i < 8; i++) { uint flag = 1 << i; if (mask & flag) { - const ModeStateKey state = stateMap()->state(flag); + const ModeStateKey state = subPropertyFlagToIconModeState(flag); setPixmap(state.first, state.second, other.pixmap(state.first, state.second)); } } + if (mask & ThemeIconMask) + setTheme(other.theme()); } - PropertySheetIconValue::ModeStateToPixmapMap PropertySheetIconValue::paths() const + const PropertySheetIconValue::ModeStateToPixmapMap &PropertySheetIconValue::paths() const { - return m_paths; + return m_data->m_paths; + } + + QDESIGNER_SHARED_EXPORT QDebug operator<<(QDebug d, const PropertySheetIconValue &p) + { + typedef PropertySheetIconValue::ModeStateToPixmapMap::const_iterator ModeStateToPixmapMapConstIt; + + QDebug nospace = d.nospace(); + nospace << "PropertySheetIconValue theme='" << p.theme() << "' "; + + const PropertySheetIconValue::ModeStateToPixmapMap &paths = p.paths(); + const ModeStateToPixmapMapConstIt cend = paths.constEnd(); + for (ModeStateToPixmapMapConstIt it = paths.constBegin(); it != cend; ++it) + nospace << " mode=" << it.key().first << ",state=" << it.key().second + << ",'" << it.value().path() << '\''; + nospace << " mask=0x" << QString::number(p.mask(), 16); + return d; } QDESIGNER_SHARED_EXPORT QDesignerFormWindowCommand *createTextPropertyCommand(const QString &propertyName, const QString &text, QObject *object, QDesignerFormWindowInterface *fw) diff --git a/tools/designer/src/lib/shared/qdesigner_utils_p.h b/tools/designer/src/lib/shared/qdesigner_utils_p.h index bed1d05..b310208 100644 --- a/tools/designer/src/lib/shared/qdesigner_utils_p.h +++ b/tools/designer/src/lib/shared/qdesigner_utils_p.h @@ -58,6 +58,7 @@ #include <QtDesigner/QDesignerFormWindowInterface> #include <QtCore/QVariant> +#include <QtCore/QSharedDataPointer> #include <QtCore/QMap> #include <QtGui/QMainWindow> #include <QtGui/QIcon> @@ -65,6 +66,8 @@ QT_BEGIN_NAMESPACE +class QDebug; + namespace qdesigner_internal { class QDesignerFormWindowCommand; class DesignerIconCache; @@ -252,16 +255,26 @@ private: // -------------- IconValue: Returned by the property sheet for icons +class PropertySheetIconValueData; + class QDESIGNER_SHARED_EXPORT PropertySheetIconValue { public: PropertySheetIconValue(const PropertySheetPixmapValue &pixmap); PropertySheetIconValue(); + ~PropertySheetIconValue(); + PropertySheetIconValue(const PropertySheetIconValue &); + PropertySheetIconValue &operator=(const PropertySheetIconValue &); bool operator==(const PropertySheetIconValue &other) const { return equals(other); } bool operator!=(const PropertySheetIconValue &other) const { return !equals(other); } bool operator<(const PropertySheetIconValue &other) const; + bool isEmpty() const; + + QString theme() const; + void setTheme(const QString &); + PropertySheetPixmapValue pixmap(QIcon::Mode mode, QIcon::State state) const; void setPixmap(QIcon::Mode mode, QIcon::State state, const PropertySheetPixmapValue &path); // passing the empty path resets the pixmap @@ -269,17 +282,22 @@ class QDESIGNER_SHARED_EXPORT PropertySheetIconValue uint compare(const PropertySheetIconValue &other) const; void assign(const PropertySheetIconValue &other, uint mask); + // Convenience accessors to get themed/unthemed icons. + PropertySheetIconValue themed() const; + PropertySheetIconValue unthemed() const; + typedef QPair<QIcon::Mode, QIcon::State> ModeStateKey; typedef QMap<ModeStateKey, PropertySheetPixmapValue> ModeStateToPixmapMap; - ModeStateToPixmapMap paths() const; + const ModeStateToPixmapMap &paths() const; private: bool equals(const PropertySheetIconValue &rhs) const; - - ModeStateToPixmapMap m_paths; + QSharedDataPointer<PropertySheetIconValueData> m_data; }; +QDESIGNER_SHARED_EXPORT QDebug operator<<(QDebug, const PropertySheetIconValue &); + class QDESIGNER_SHARED_EXPORT DesignerPixmapCache : public QObject { Q_OBJECT diff --git a/tools/designer/src/lib/uilib/resourcebuilder.cpp b/tools/designer/src/lib/uilib/resourcebuilder.cpp index d19a09a..03e2a66 100644 --- a/tools/designer/src/lib/uilib/resourcebuilder.cpp +++ b/tools/designer/src/lib/uilib/resourcebuilder.cpp @@ -44,6 +44,7 @@ #include <QtCore/QVariant> #include <QtCore/QFileInfo> #include <QtCore/QDir> +#include <QtCore/QDebug> #include <QtGui/QPixmap> #include <QtGui/QIcon> @@ -53,6 +54,8 @@ QT_BEGIN_NAMESPACE namespace QFormInternal { #endif +enum { themeDebug = 0 }; + QResourceBuilder::QResourceBuilder() { @@ -95,6 +98,14 @@ QVariant QResourceBuilder::loadResource(const QDir &workingDirectory, const DomP } case DomProperty::IconSet: { const DomResourceIcon *dpi = property->elementIconSet(); + if (!dpi->attributeTheme().isEmpty()) { + const QString theme = dpi->attributeTheme(); + const bool known = QIcon::hasThemeIcon(theme); + if (themeDebug) + qDebug("Theme %s known %d", qPrintable(theme), known); + if (known) + return qVariantFromValue(QIcon::fromTheme(dpi->attributeTheme())); + } // non-empty theme if (const int flags = iconStateFlags(dpi)) { // new, post 4.4 format QIcon icon; if (flags & NormalOff) diff --git a/tools/designer/src/lib/uilib/ui4.cpp b/tools/designer/src/lib/uilib/ui4.cpp index c13bd59..98974e6 100644 --- a/tools/designer/src/lib/uilib/ui4.cpp +++ b/tools/designer/src/lib/uilib/ui4.cpp @@ -7745,6 +7745,7 @@ void DomResourceIcon::clear(bool clear_all) if (clear_all) { m_text = QLatin1String(""); + m_has_attr_theme = false; m_has_attr_resource = false; } @@ -7762,6 +7763,7 @@ void DomResourceIcon::clear(bool clear_all) DomResourceIcon::DomResourceIcon() { m_children = 0; + m_has_attr_theme = false; m_has_attr_resource = false; m_text = QLatin1String(""); m_normalOff = 0; @@ -7791,6 +7793,10 @@ void DomResourceIcon::read(QXmlStreamReader &reader) foreach (const QXmlStreamAttribute &attribute, reader.attributes()) { QStringRef name = attribute.name(); + if (name == QLatin1String("theme")) { + setAttributeTheme(attribute.value().toString()); + continue; + } if (name == QLatin1String("resource")) { setAttributeResource(attribute.value().toString()); continue; @@ -7869,6 +7875,8 @@ void DomResourceIcon::read(QXmlStreamReader &reader) #ifdef QUILOADER_QDOM_READ void DomResourceIcon::read(const QDomElement &node) { + if (node.hasAttribute(QLatin1String("theme"))) + setAttributeTheme(node.attribute(QLatin1String("theme"))); if (node.hasAttribute(QLatin1String("resource"))) setAttributeResource(node.attribute(QLatin1String("resource"))); @@ -7938,6 +7946,9 @@ void DomResourceIcon::write(QXmlStreamWriter &writer, const QString &tagName) co { writer.writeStartElement(tagName.isEmpty() ? QString::fromUtf8("resourceicon") : tagName.toLower()); + if (hasAttributeTheme()) + writer.writeAttribute(QLatin1String("theme"), attributeTheme()); + if (hasAttributeResource()) writer.writeAttribute(QLatin1String("resource"), attributeResource()); diff --git a/tools/designer/src/lib/uilib/ui4_p.h b/tools/designer/src/lib/uilib/ui4_p.h index 1f38f88..a464a89 100644 --- a/tools/designer/src/lib/uilib/ui4_p.h +++ b/tools/designer/src/lib/uilib/ui4_p.h @@ -2809,6 +2809,11 @@ public: inline void setText(const QString &s) { m_text = s; } // attribute accessors + inline bool hasAttributeTheme() const { return m_has_attr_theme; } + inline QString attributeTheme() const { return m_attr_theme; } + inline void setAttributeTheme(const QString& a) { m_attr_theme = a; m_has_attr_theme = true; } + inline void clearAttributeTheme() { m_has_attr_theme = false; } + inline bool hasAttributeResource() const { return m_has_attr_resource; } inline QString attributeResource() const { return m_attr_resource; } inline void setAttributeResource(const QString& a) { m_attr_resource = a; m_has_attr_resource = true; } @@ -2868,6 +2873,9 @@ private: void clear(bool clear_all = true); // attribute data + QString m_attr_theme; + bool m_has_attr_theme; + QString m_attr_resource; bool m_has_attr_resource; |