1 /****************************************************************************
2 **
3 ** Copyright (C) 2015 The Qt Company Ltd.
4 ** Contact: http://www.qt.io/licensing/
5 **
6 ** This file is part of the Qt Designer of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** Commercial License Usage
10 ** Licensees holding valid commercial Qt licenses may use this file in
11 ** accordance with the commercial license agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and The Qt Company. For licensing terms
14 ** and conditions see http://www.qt.io/terms-conditions. For further
15 ** information use the contact form at http://www.qt.io/contact-us.
16 **
17 ** GNU Lesser General Public License Usage
18 ** Alternatively, this file may be used under the terms of the GNU Lesser
19 ** General Public License version 2.1 or version 3 as published by the Free
20 ** Software Foundation and appearing in the file LICENSE.LGPLv21 and
21 ** LICENSE.LGPLv3 included in the packaging of this file. Please review the
22 ** following information to ensure the GNU Lesser General Public License
23 ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
24 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
25 **
26 ** As a special exception, The Qt Company gives you certain additional
27 ** rights. These rights are described in The Qt Company LGPL Exception
28 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
29 **
30 ** GNU General Public License Usage
31 ** Alternatively, this file may be used under the terms of the GNU
32 ** General Public License version 3.0 as published by the Free Software
33 ** Foundation and appearing in the file LICENSE.GPL included in the
34 ** packaging of this file.  Please review the following information to
35 ** ensure the GNU General Public License version 3.0 requirements will be
36 ** met: http://www.gnu.org/copyleft/gpl.html.
37 **
38 ** $QT_END_LICENSE$
39 **
40 ****************************************************************************/
41 
42 #include "qdesigner_utils_p.h"
43 #include "qdesigner_propertycommand_p.h"
44 #include "abstractformbuilder.h"
45 #include "formwindowbase_p.h"
46 
47 #include <QtDesigner/QDesignerFormEditorInterface>
48 #include <QtDesigner/QDesignerFormWindowInterface>
49 #include <QtDesigner/QDesignerIconCacheInterface>
50 #include <QtDesigner/QDesignerResourceBrowserInterface>
51 #include <QtDesigner/QDesignerLanguageExtension>
52 #include <QtDesigner/QDesignerTaskMenuExtension>
53 #include <QtDesigner/QExtensionManager>
54 
55 #include <QtCore/QDir>
56 #include <QtCore/QProcess>
57 #include <QtCore/QLibraryInfo>
58 #include <QtCore/QDebug>
59 #include <QtCore/QQueue>
60 #include <QtCore/QSharedData>
61 
62 #include <QtGui/QApplication>
63 #include <QtGui/QIcon>
64 #include <QtGui/QPixmap>
65 #include <QtGui/QListWidget>
66 #include <QtGui/QTreeWidget>
67 #include <QtGui/QTableWidget>
68 #include <QtGui/QComboBox>
69 
70 QT_BEGIN_NAMESPACE
71 
72 namespace qdesigner_internal
73 {
designerWarning(const QString & message)74     QDESIGNER_SHARED_EXPORT void designerWarning(const QString &message)
75     {
76         qWarning("Designer: %s", qPrintable(message));
77     }
78 
reloadTreeItem(DesignerIconCache * iconCache,QTreeWidgetItem * item)79     void reloadTreeItem(DesignerIconCache *iconCache, QTreeWidgetItem *item)
80     {
81         if (!item)
82             return;
83 
84         for (int c = 0; c < item->columnCount(); c++) {
85             const QVariant v = item->data(c, Qt::DecorationPropertyRole);
86             if (v.canConvert<PropertySheetIconValue>())
87                 item->setIcon(c, iconCache->icon(qvariant_cast<PropertySheetIconValue>(v)));
88         }
89     }
90 
reloadListItem(DesignerIconCache * iconCache,QListWidgetItem * item)91     void reloadListItem(DesignerIconCache *iconCache, QListWidgetItem *item)
92     {
93         if (!item)
94             return;
95 
96         const QVariant v = item->data(Qt::DecorationPropertyRole);
97         if (v.canConvert<PropertySheetIconValue>())
98             item->setIcon(iconCache->icon(qvariant_cast<PropertySheetIconValue>(v)));
99     }
100 
reloadTableItem(DesignerIconCache * iconCache,QTableWidgetItem * item)101     void reloadTableItem(DesignerIconCache *iconCache, QTableWidgetItem *item)
102     {
103         if (!item)
104             return;
105 
106         const QVariant v = item->data(Qt::DecorationPropertyRole);
107         if (v.canConvert<PropertySheetIconValue>())
108             item->setIcon(iconCache->icon(qvariant_cast<PropertySheetIconValue>(v)));
109     }
110 
reloadIconResources(DesignerIconCache * iconCache,QObject * object)111     void reloadIconResources(DesignerIconCache *iconCache, QObject *object)
112     {
113         if (QListWidget *listWidget = qobject_cast<QListWidget *>(object)) {
114             for (int i = 0; i < listWidget->count(); i++)
115                 reloadListItem(iconCache, listWidget->item(i));
116         } else if (QComboBox *comboBox = qobject_cast<QComboBox *>(object)) {
117             for (int i = 0; i < comboBox->count(); i++) {
118                 const QVariant v = comboBox->itemData(i, Qt::DecorationPropertyRole);
119                 if (v.canConvert<PropertySheetIconValue>()) {
120                     QIcon icon = iconCache->icon(qvariant_cast<PropertySheetIconValue>(v));
121                     comboBox->setItemIcon(i, icon);
122                     comboBox->setItemData(i, icon);
123                 }
124             }
125         } else if (QTreeWidget *treeWidget = qobject_cast<QTreeWidget *>(object)) {
126             reloadTreeItem(iconCache, treeWidget->headerItem());
127             QQueue<QTreeWidgetItem *> itemsQueue;
128             for (int i = 0; i < treeWidget->topLevelItemCount(); i++)
129                 itemsQueue.enqueue(treeWidget->topLevelItem(i));
130             while (!itemsQueue.isEmpty()) {
131                 QTreeWidgetItem *item = itemsQueue.dequeue();
132                 for (int i = 0; i < item->childCount(); i++)
133                     itemsQueue.enqueue(item->child(i));
134                 reloadTreeItem(iconCache, item);
135             }
136         } else if (QTableWidget *tableWidget = qobject_cast<QTableWidget *>(object)) {
137             const int columnCount = tableWidget->columnCount();
138             const int rowCount = tableWidget->rowCount();
139             for (int c = 0; c < columnCount; c++)
140                 reloadTableItem(iconCache, tableWidget->horizontalHeaderItem(c));
141             for (int r = 0; r < rowCount; r++)
142                 reloadTableItem(iconCache, tableWidget->verticalHeaderItem(r));
143             for (int c = 0; c < columnCount; c++)
144                 for (int r = 0; r < rowCount; r++)
145                     reloadTableItem(iconCache, tableWidget->item(r, c));
146         }
147     }
148 
149     // ------------- DesignerMetaEnum
DesignerMetaEnum(const QString & name,const QString & scope,const QString & separator)150     DesignerMetaEnum::DesignerMetaEnum(const QString &name, const QString &scope, const QString &separator) :
151         MetaEnum<int>(name, scope, separator)
152     {
153     }
154 
155 
toString(int value,SerializationMode sm,bool * ok) const156     QString DesignerMetaEnum::toString(int value, SerializationMode sm, bool *ok) const
157     {
158         // find value
159         bool valueOk;
160         const QString item = valueToKey(value, &valueOk);
161         if (ok)
162             *ok = valueOk;
163 
164         if (!valueOk || sm == NameOnly)
165             return item;
166 
167         QString qualifiedItem;
168         appendQualifiedName(item,  qualifiedItem);
169         return qualifiedItem;
170     }
171 
messageToStringFailed(int value) const172     QString DesignerMetaEnum::messageToStringFailed(int value) const
173     {
174         return QCoreApplication::translate("DesignerMetaEnum", "%1 is not a valid enumeration value of '%2'.").arg(value).arg(name());
175     }
176 
messageParseFailed(const QString & s) const177     QString DesignerMetaEnum::messageParseFailed(const QString &s) const
178     {
179         return QCoreApplication::translate("DesignerMetaEnum", "'%1' could not be converted to an enumeration value of type '%2'.").arg(s).arg(name());
180     }
181     // -------------- DesignerMetaFlags
DesignerMetaFlags(const QString & name,const QString & scope,const QString & separator)182     DesignerMetaFlags::DesignerMetaFlags(const QString &name, const QString &scope, const QString &separator) :
183        MetaEnum<uint>(name, scope, separator)
184     {
185     }
186 
flags(int ivalue) const187     QStringList DesignerMetaFlags::flags(int ivalue) const
188     {
189         typedef MetaEnum<uint>::KeyToValueMap::const_iterator KeyToValueMapIterator;
190         QStringList rc;
191         const uint v = static_cast<uint>(ivalue);
192         const KeyToValueMapIterator cend = keyToValueMap().constEnd();
193         for (KeyToValueMapIterator it = keyToValueMap().constBegin();it != cend; ++it )  {
194             const uint itemValue = it.value();
195             // Check for equality first as flag values can be 0 or -1, too. Takes preference over a bitwise flag
196             if (v == itemValue) {
197                 rc.clear();
198                 rc.push_back(it.key());
199                 return rc;
200             }
201             // Do not add 0-flags (None-flags)
202             if (itemValue)
203                 if ((v & itemValue) == itemValue)
204                     rc.push_back(it.key());
205         }
206         return rc;
207     }
208 
209 
toString(int value,SerializationMode sm) const210     QString DesignerMetaFlags::toString(int value, SerializationMode sm) const
211     {
212         const QStringList flagIds = flags(value);
213         if (flagIds.empty())
214             return QString();
215 
216         const QChar delimiter = QLatin1Char('|');
217         QString rc;
218         const QStringList::const_iterator cend = flagIds.constEnd();
219         for (QStringList::const_iterator it = flagIds.constBegin(); it != cend; ++it) {
220             if (!rc.isEmpty())
221                 rc += delimiter ;
222             if (sm == FullyQualified)
223                 appendQualifiedName(*it, rc);
224             else
225                 rc += *it;
226         }
227         return rc;
228     }
229 
230 
parseFlags(const QString & s,bool * ok) const231     int DesignerMetaFlags::parseFlags(const QString &s, bool *ok) const
232     {
233         if (s.isEmpty()) {
234             if (ok)
235                 *ok = true;
236             return 0;
237         }
238         uint flags = 0;
239         bool valueOk = true;
240         QStringList keys = s.split(QString(QLatin1Char('|')));
241         const QStringList::iterator cend = keys.end();
242         for (QStringList::iterator it = keys.begin(); it != cend; ++it) {
243             const uint flagValue = keyToValue(*it, &valueOk);
244             if (!valueOk) {
245                 flags = 0;
246                 break;
247             }
248             flags |= flagValue;
249         }
250         if (ok)
251             *ok = valueOk;
252         return static_cast<int>(flags);
253     }
254 
messageParseFailed(const QString & s) const255     QString DesignerMetaFlags::messageParseFailed(const QString &s) const
256     {
257         return QCoreApplication::translate("DesignerMetaFlags", "'%1' could not be converted to a flag value of type '%2'.").arg(s).arg(name());
258     }
259 
260     // ---------- PropertySheetEnumValue
261 
PropertySheetEnumValue(int v,const DesignerMetaEnum & me)262     PropertySheetEnumValue::PropertySheetEnumValue(int v, const DesignerMetaEnum &me) :
263        value(v),
264        metaEnum(me)
265     {
266     }
PropertySheetEnumValue()267     PropertySheetEnumValue::PropertySheetEnumValue() :
268        value(0)
269     {
270     }
271 
272     // ---------------- PropertySheetFlagValue
PropertySheetFlagValue(int v,const DesignerMetaFlags & mf)273     PropertySheetFlagValue::PropertySheetFlagValue(int v, const DesignerMetaFlags &mf) :
274         value(v),
275         metaFlags(mf)
276     {
277     }
278 
PropertySheetFlagValue()279     PropertySheetFlagValue::PropertySheetFlagValue() :
280         value(0)
281     {
282     }
283 
284     // ---------------- PropertySheetPixmapValue
PropertySheetPixmapValue(const QString & path)285     PropertySheetPixmapValue::PropertySheetPixmapValue(const QString &path) : m_path(path)
286     {
287     }
288 
PropertySheetPixmapValue()289     PropertySheetPixmapValue::PropertySheetPixmapValue()
290     {
291     }
292 
getPixmapSource(QDesignerFormEditorInterface * core,const QString & path)293     PropertySheetPixmapValue::PixmapSource PropertySheetPixmapValue::getPixmapSource(QDesignerFormEditorInterface *core, const QString & path)
294     {
295         if (const QDesignerLanguageExtension *lang = qt_extension<QDesignerLanguageExtension *>(core->extensionManager(), core))
296             return lang->isLanguageResource(path) ?  LanguageResourcePixmap : FilePixmap;
297         return path.startsWith(QLatin1Char(':')) ? ResourcePixmap : FilePixmap;
298     }
299 
compare(const PropertySheetPixmapValue & other) const300     int PropertySheetPixmapValue::compare(const PropertySheetPixmapValue &other) const
301     {
302         return m_path.compare(other.m_path);
303     }
304 
path() const305     QString PropertySheetPixmapValue::path() const
306     {
307         return m_path;
308     }
309 
setPath(const QString & path)310     void PropertySheetPixmapValue::setPath(const QString &path)
311     {
312         if (m_path == path)
313             return;
314         m_path = path;
315     }
316 
317     // ---------- PropertySheetIconValue
318 
319     class PropertySheetIconValueData : public QSharedData {
320     public:
321         PropertySheetIconValue::ModeStateToPixmapMap m_paths;
322         QString m_theme;
323     };
324 
PropertySheetIconValue(const PropertySheetPixmapValue & pixmap)325     PropertySheetIconValue::PropertySheetIconValue(const PropertySheetPixmapValue &pixmap) :
326         m_data(new PropertySheetIconValueData)
327     {
328         setPixmap(QIcon::Normal, QIcon::Off, pixmap);
329     }
330 
PropertySheetIconValue()331     PropertySheetIconValue::PropertySheetIconValue() :
332         m_data(new PropertySheetIconValueData)
333     {
334     }
335 
~PropertySheetIconValue()336     PropertySheetIconValue::~PropertySheetIconValue()
337     {
338     }
339 
PropertySheetIconValue(const PropertySheetIconValue & rhs)340     PropertySheetIconValue::PropertySheetIconValue(const PropertySheetIconValue &rhs) :
341         m_data(rhs.m_data)
342     {
343     }
344 
operator =(const PropertySheetIconValue & rhs)345     PropertySheetIconValue &PropertySheetIconValue::operator=(const PropertySheetIconValue &rhs)
346     {
347         if (this != &rhs)
348             m_data.operator=(rhs.m_data);
349         return *this;
350     }
351 
equals(const PropertySheetIconValue & rhs) const352     bool PropertySheetIconValue::equals(const PropertySheetIconValue &rhs) const
353     {
354         return m_data->m_theme == rhs.m_data->m_theme && m_data->m_paths == rhs.m_data->m_paths;
355     }
356 
operator <(const PropertySheetIconValue & other) const357     bool PropertySheetIconValue::operator<(const PropertySheetIconValue &other) const
358     {
359         if (const int themeCmp = m_data->m_theme.compare(other.m_data->m_theme))
360             return themeCmp < 0;
361         QMapIterator<ModeStateKey, PropertySheetPixmapValue> itThis(m_data->m_paths);
362         QMapIterator<ModeStateKey, PropertySheetPixmapValue> itOther(other.m_data->m_paths);
363         while (itThis.hasNext() && itOther.hasNext()) {
364             const ModeStateKey thisPair = itThis.next().key();
365             const ModeStateKey otherPair = itOther.next().key();
366             if (thisPair < otherPair)
367                 return true;
368             else if (otherPair < thisPair)
369                 return false;
370             const int crc = itThis.value().compare(itOther.value());
371             if (crc < 0)
372                 return true;
373             if (crc > 0)
374                 return false;
375         }
376         if (itOther.hasNext())
377             return true;
378         return false;
379     }
380 
isEmpty() const381     bool PropertySheetIconValue::isEmpty() const
382     {
383         return m_data->m_theme.isEmpty() && m_data->m_paths.isEmpty();
384     }
385 
theme() const386     QString PropertySheetIconValue::theme() const
387     {
388         return m_data->m_theme;
389     }
390 
setTheme(const QString & t)391     void PropertySheetIconValue::setTheme(const QString &t)
392     {
393         m_data->m_theme = t;
394     }
395 
pixmap(QIcon::Mode mode,QIcon::State state) const396     PropertySheetPixmapValue PropertySheetIconValue::pixmap(QIcon::Mode mode, QIcon::State state) const
397     {
398         const ModeStateKey pair = qMakePair(mode, state);
399         return m_data->m_paths.value(pair);
400     }
401 
setPixmap(QIcon::Mode mode,QIcon::State state,const PropertySheetPixmapValue & pixmap)402     void PropertySheetIconValue::setPixmap(QIcon::Mode mode, QIcon::State state, const PropertySheetPixmapValue &pixmap)
403     {
404         const ModeStateKey pair = qMakePair(mode, state);
405         if (pixmap.path().isEmpty())
406             m_data->m_paths.remove(pair);
407         else
408             m_data->m_paths.insert(pair, pixmap);
409     }
410 
pixmap(const PropertySheetPixmapValue & value) const411     QPixmap DesignerPixmapCache::pixmap(const PropertySheetPixmapValue &value) const
412     {
413         QMap<PropertySheetPixmapValue, QPixmap>::const_iterator it = m_cache.constFind(value);
414         if (it != m_cache.constEnd())
415             return it.value();
416 
417         QPixmap pix = QPixmap(value.path());
418         m_cache.insert(value, pix);
419         return pix;
420     }
421 
clear()422     void DesignerPixmapCache::clear()
423     {
424         m_cache.clear();
425     }
426 
DesignerPixmapCache(QObject * parent)427     DesignerPixmapCache::DesignerPixmapCache(QObject *parent)
428         : QObject(parent)
429     {
430     }
431 
icon(const PropertySheetIconValue & value) const432     QIcon DesignerIconCache::icon(const PropertySheetIconValue &value) const
433     {
434         typedef PropertySheetIconValue::ModeStateToPixmapMap::const_iterator ModeStateToPixmapMapConstIt;
435 
436         QMap<PropertySheetIconValue, QIcon>::const_iterator it = m_cache.constFind(value);
437         if (it != m_cache.constEnd())
438             return it.value();
439 
440         // Match on the theme first if it is available.
441         if (!value.theme().isEmpty()) {
442             const QString theme = value.theme();
443             if (QIcon::hasThemeIcon(theme)) {
444                 const QIcon themeIcon = QIcon::fromTheme(theme);
445                 m_cache.insert(value, themeIcon);
446                 return themeIcon;
447             }
448         }
449 
450         QIcon icon;
451         const PropertySheetIconValue::ModeStateToPixmapMap &paths = value.paths();
452         const ModeStateToPixmapMapConstIt cend = paths.constEnd();
453         for (ModeStateToPixmapMapConstIt it = paths.constBegin(); it != cend; ++it) {
454             const QPair<QIcon::Mode, QIcon::State> pair = it.key();
455             icon.addFile(it.value().path(), QSize(), pair.first, pair.second);
456         }
457         m_cache.insert(value, icon);
458         return icon;
459     }
460 
clear()461     void DesignerIconCache::clear()
462     {
463         m_cache.clear();
464     }
465 
DesignerIconCache(DesignerPixmapCache * pixmapCache,QObject * parent)466     DesignerIconCache::DesignerIconCache(DesignerPixmapCache *pixmapCache, QObject *parent)
467         : QObject(parent),
468         m_pixmapCache(pixmapCache)
469     {
470 
471     }
472 
PropertySheetStringValue(const QString & value,bool translatable,const QString & disambiguation,const QString & comment)473     PropertySheetStringValue::PropertySheetStringValue(const QString &value,
474                     bool translatable, const QString &disambiguation, const QString &comment)
475         : m_value(value), m_translatable(translatable), m_disambiguation(disambiguation), m_comment(comment)
476     {  }
477 
value() const478     QString PropertySheetStringValue::value() const
479     {
480         return m_value;
481     }
482 
setValue(const QString & value)483     void PropertySheetStringValue::setValue(const QString &value)
484     {
485         m_value = value;
486     }
487 
translatable() const488     bool PropertySheetStringValue::translatable() const
489     {
490         return m_translatable;
491     }
492 
setTranslatable(bool translatable)493     void PropertySheetStringValue::setTranslatable(bool translatable)
494     {
495         m_translatable = translatable;
496     }
497 
disambiguation() const498     QString PropertySheetStringValue::disambiguation() const
499     {
500         return m_disambiguation;
501     }
502 
setDisambiguation(const QString & disambiguation)503     void PropertySheetStringValue::setDisambiguation(const QString &disambiguation)
504     {
505         m_disambiguation = disambiguation;
506     }
507 
comment() const508     QString PropertySheetStringValue::comment() const
509     {
510         return m_comment;
511     }
512 
setComment(const QString & comment)513     void PropertySheetStringValue::setComment(const QString &comment)
514     {
515         m_comment = comment;
516     }
517 
equals(const PropertySheetStringValue & rhs) const518     bool PropertySheetStringValue::equals(const PropertySheetStringValue &rhs) const
519     {
520         return (m_value == rhs.m_value) && (m_translatable == rhs.m_translatable)
521             && (m_disambiguation == rhs.m_disambiguation) && (m_comment == rhs.m_comment);
522     }
523 
PropertySheetKeySequenceValue(const QKeySequence & value,bool translatable,const QString & disambiguation,const QString & comment)524     PropertySheetKeySequenceValue::PropertySheetKeySequenceValue(const QKeySequence &value,
525                     bool translatable, const QString &disambiguation, const QString &comment)
526         : m_value(value),
527           m_standardKey(QKeySequence::UnknownKey),
528           m_translatable(translatable),
529           m_disambiguation(disambiguation),
530           m_comment(comment)
531     {  }
532 
PropertySheetKeySequenceValue(const QKeySequence::StandardKey & standardKey,bool translatable,const QString & disambiguation,const QString & comment)533     PropertySheetKeySequenceValue::PropertySheetKeySequenceValue(const QKeySequence::StandardKey &standardKey,
534                     bool translatable, const QString &disambiguation, const QString &comment)
535         : m_value(QKeySequence(standardKey)),
536           m_standardKey(standardKey),
537           m_translatable(translatable),
538           m_disambiguation(disambiguation),
539           m_comment(comment)
540     {  }
541 
value() const542     QKeySequence PropertySheetKeySequenceValue::value() const
543     {
544         return m_value;
545     }
546 
setValue(const QKeySequence & value)547     void PropertySheetKeySequenceValue::setValue(const QKeySequence &value)
548     {
549         m_value = value;
550         m_standardKey = QKeySequence::UnknownKey;
551     }
552 
standardKey() const553     QKeySequence::StandardKey PropertySheetKeySequenceValue::standardKey() const
554     {
555         return m_standardKey;
556     }
557 
setStandardKey(const QKeySequence::StandardKey & standardKey)558     void PropertySheetKeySequenceValue::setStandardKey(const QKeySequence::StandardKey &standardKey)
559     {
560         m_value = QKeySequence(standardKey);
561         m_standardKey = standardKey;
562     }
563 
isStandardKey() const564     bool PropertySheetKeySequenceValue::isStandardKey() const
565     {
566         return m_standardKey != QKeySequence::UnknownKey;
567     }
568 
comment() const569     QString PropertySheetKeySequenceValue::comment() const
570     {
571         return m_comment;
572     }
573 
setComment(const QString & comment)574     void PropertySheetKeySequenceValue::setComment(const QString &comment)
575     {
576         m_comment = comment;
577     }
578 
disambiguation() const579     QString PropertySheetKeySequenceValue::disambiguation() const
580     {
581         return m_disambiguation;
582     }
583 
setDisambiguation(const QString & disambiguation)584     void PropertySheetKeySequenceValue::setDisambiguation(const QString &disambiguation)
585     {
586         m_disambiguation = disambiguation;
587     }
588 
translatable() const589     bool PropertySheetKeySequenceValue::translatable() const
590     {
591         return m_translatable;
592     }
593 
setTranslatable(bool translatable)594     void PropertySheetKeySequenceValue::setTranslatable(bool translatable)
595     {
596         m_translatable = translatable;
597     }
598 
equals(const PropertySheetKeySequenceValue & rhs) const599     bool PropertySheetKeySequenceValue::equals(const PropertySheetKeySequenceValue &rhs) const
600     {
601         return (m_value == rhs.m_value) && (m_standardKey == rhs.m_standardKey)
602             && (m_translatable == rhs.m_translatable) && (m_disambiguation == rhs.m_disambiguation) && (m_comment == rhs.m_comment);
603     }
604 
605 
606     /* IconSubPropertyMask: Assign each icon sub-property (pixmaps for the
607      * various states/modes and the theme) a flag bit (see QFont) so that they
608      * can be handled individually when assigning property values to
609      * multiselections in the set-property-commands (that is, do not clobber
610      * other subproperties when assigning just one).
611      * Provide back-and-forth mapping functions for the icon states. */
612 
613     enum IconSubPropertyMask {
614         NormalOffIconMask   = 0x01,
615         NormalOnIconMask    = 0x02,
616         DisabledOffIconMask = 0x04,
617         DisabledOnIconMask  = 0x08,
618         ActiveOffIconMask   = 0x10,
619         ActiveOnIconMask    = 0x20,
620         SelectedOffIconMask = 0x40,
621         SelectedOnIconMask  = 0x80,
622         ThemeIconMask       = 0x10000
623     };
624 
iconStateToSubPropertyFlag(QIcon::Mode mode,QIcon::State state)625     static inline uint iconStateToSubPropertyFlag(QIcon::Mode mode, QIcon::State state)
626     {
627         switch (mode) {
628         case QIcon::Disabled:
629             return state == QIcon::On ? DisabledOnIconMask : DisabledOffIconMask;
630         case QIcon::Active:
631             return state == QIcon::On ?   ActiveOnIconMask :   ActiveOffIconMask;
632         case QIcon::Selected:
633             return state == QIcon::On ? SelectedOnIconMask : SelectedOffIconMask;
634         case QIcon::Normal:
635             break;
636         }
637         return     state == QIcon::On ?   NormalOnIconMask :   NormalOffIconMask;
638     }
639 
subPropertyFlagToIconModeState(unsigned flag)640     static inline QPair<QIcon::Mode, QIcon::State> subPropertyFlagToIconModeState(unsigned flag)
641     {
642         switch (flag) {
643         case NormalOnIconMask:
644             return qMakePair(QIcon::Normal,   QIcon::On);
645         case DisabledOffIconMask:
646             return qMakePair(QIcon::Disabled, QIcon::Off);
647         case DisabledOnIconMask:
648             return qMakePair(QIcon::Disabled, QIcon::On);
649         case ActiveOffIconMask:
650             return qMakePair(QIcon::Active,   QIcon::Off);
651         case ActiveOnIconMask:
652             return qMakePair(QIcon::Active,   QIcon::On);
653         case SelectedOffIconMask:
654             return qMakePair(QIcon::Selected, QIcon::Off);
655         case SelectedOnIconMask:
656             return qMakePair(QIcon::Selected, QIcon::On);
657         case NormalOffIconMask:
658         default:
659             break;
660         }
661         return     qMakePair(QIcon::Normal,   QIcon::Off);
662     }
663 
mask() const664     uint PropertySheetIconValue::mask() const
665     {
666         typedef ModeStateToPixmapMap::const_iterator ModeStateToPixmapMapConstIt;
667 
668         uint flags = 0;
669         const ModeStateToPixmapMapConstIt cend = m_data->m_paths.constEnd();
670         for (ModeStateToPixmapMapConstIt it = m_data->m_paths.constBegin(); it != cend; ++it)
671             flags |= iconStateToSubPropertyFlag(it.key().first, it.key().second);
672         if (!m_data->m_theme.isEmpty())
673             flags |= ThemeIconMask;
674         return flags;
675     }
676 
compare(const PropertySheetIconValue & other) const677     uint PropertySheetIconValue::compare(const PropertySheetIconValue &other) const
678     {
679         uint diffMask = mask() | other.mask();
680         for (int i = 0; i < 8; i++) {
681             const uint flag = 1 << i;
682             if (diffMask & flag) { // if state is set in both icons, compare the values
683                 const QPair<QIcon::Mode, QIcon::State> state = subPropertyFlagToIconModeState(flag);
684                 if (pixmap(state.first, state.second) == other.pixmap(state.first, state.second))
685                     diffMask &= ~flag;
686             }
687         }
688         if ((diffMask & ThemeIconMask) && theme() == other.theme())
689             diffMask &= ~ThemeIconMask;
690         return diffMask;
691     }
692 
themed() const693     PropertySheetIconValue PropertySheetIconValue::themed() const
694     {
695         PropertySheetIconValue rc(*this);
696         rc.m_data->m_paths.clear();
697         return rc;
698     }
699 
unthemed() const700     PropertySheetIconValue PropertySheetIconValue::unthemed() const
701     {
702         PropertySheetIconValue rc(*this);
703         rc.m_data->m_theme.clear();
704         return rc;
705     }
706 
assign(const PropertySheetIconValue & other,uint mask)707     void PropertySheetIconValue::assign(const PropertySheetIconValue &other, uint mask)
708     {
709         for (int i = 0; i < 8; i++) {
710             uint flag = 1 << i;
711             if (mask & flag) {
712                 const ModeStateKey state = subPropertyFlagToIconModeState(flag);
713                 setPixmap(state.first, state.second, other.pixmap(state.first, state.second));
714             }
715         }
716         if (mask & ThemeIconMask)
717             setTheme(other.theme());
718     }
719 
paths() const720     const PropertySheetIconValue::ModeStateToPixmapMap &PropertySheetIconValue::paths() const
721     {
722         return m_data->m_paths;
723     }
724 
operator <<(QDebug d,const PropertySheetIconValue & p)725     QDESIGNER_SHARED_EXPORT QDebug operator<<(QDebug d, const PropertySheetIconValue &p)
726     {
727         typedef PropertySheetIconValue::ModeStateToPixmapMap::const_iterator ModeStateToPixmapMapConstIt;
728 
729         QDebug nospace = d.nospace();
730         nospace << "PropertySheetIconValue theme='" << p.theme() << "' ";
731 
732         const PropertySheetIconValue::ModeStateToPixmapMap &paths = p.paths();
733         const ModeStateToPixmapMapConstIt cend = paths.constEnd();
734         for (ModeStateToPixmapMapConstIt it = paths.constBegin(); it != cend; ++it)
735             nospace << " mode=" << it.key().first << ",state=" << it.key().second
736                        << ",'" << it.value().path() << '\'';
737         nospace << " mask=0x" << QString::number(p.mask(), 16);
738         return d;
739     }
740 
createTextPropertyCommand(const QString & propertyName,const QString & text,QObject * object,QDesignerFormWindowInterface * fw)741     QDESIGNER_SHARED_EXPORT QDesignerFormWindowCommand *createTextPropertyCommand(const QString &propertyName, const QString &text, QObject *object, QDesignerFormWindowInterface *fw)
742     {
743         if (text.isEmpty()) {
744             ResetPropertyCommand *cmd = new ResetPropertyCommand(fw);
745             cmd->init(object, propertyName);
746             return cmd;
747         }
748         SetPropertyCommand *cmd = new SetPropertyCommand(fw);
749         cmd->init(object, propertyName, text);
750         return cmd;
751     }
752 
preferredEditAction(QDesignerFormEditorInterface * core,QWidget * managedWidget)753     QDESIGNER_SHARED_EXPORT QAction *preferredEditAction(QDesignerFormEditorInterface *core, QWidget *managedWidget)
754     {
755         QAction *action = 0;
756         if (const QDesignerTaskMenuExtension *taskMenu = qt_extension<QDesignerTaskMenuExtension*>(core->extensionManager(), managedWidget)) {
757             action = taskMenu->preferredEditAction();
758             if (!action) {
759                 const QList<QAction *> actions = taskMenu->taskActions();
760                 if (!actions.isEmpty())
761                     action = actions.first();
762             }
763         }
764         if (!action) {
765             if (const QDesignerTaskMenuExtension *taskMenu = qobject_cast<QDesignerTaskMenuExtension *>(
766                         core->extensionManager()->extension(managedWidget, QLatin1String("QDesignerInternalTaskMenuExtension")))) {
767                 action = taskMenu->preferredEditAction();
768                 if (!action) {
769                     const QList<QAction *> actions = taskMenu->taskActions();
770                     if (!actions.isEmpty())
771                         action = actions.first();
772                 }
773             }
774         }
775         return action;
776     }
777 
runUIC(const QString & fileName,UIC_Mode mode,QByteArray & ba,QString & errorMessage)778     QDESIGNER_SHARED_EXPORT bool runUIC(const QString &fileName, UIC_Mode mode, QByteArray& ba, QString &errorMessage)
779     {
780         QStringList argv;
781         QString binary = QLibraryInfo::location(QLibraryInfo::BinariesPath);
782         binary += QDir::separator();
783         switch (mode) {
784         case UIC_GenerateCode:
785             binary += QLatin1String("uic");
786             break;
787         case UIC_ConvertV3:
788             binary += QLatin1String("uic3");
789             argv += QLatin1String("-convert");
790             break;
791         }
792         argv += fileName;
793         QProcess uic;
794         uic.start(binary, argv);
795         if (!uic.waitForStarted()) {
796             errorMessage = QApplication::translate("Designer", "Unable to launch %1.").arg(binary);
797             return false;
798         }
799         if (!uic.waitForFinished()) {
800             errorMessage = QApplication::translate("Designer", "%1 timed out.").arg(binary);
801             return false;
802         }
803         if (uic.exitCode()) {
804             errorMessage =  QString::fromAscii(uic.readAllStandardError());
805             return false;
806         }
807         ba = uic.readAllStandardOutput();
808         return true;
809     }
810 
qtify(const QString & name)811     QDESIGNER_SHARED_EXPORT QString qtify(const QString &name)
812     {
813         QString qname = name;
814 
815         Q_ASSERT(qname.isEmpty() == false);
816 
817 
818         if (qname.count() > 1 && qname.at(1).isUpper()) {
819             const QChar first = qname.at(0);
820             if (first == QLatin1Char('Q') || first == QLatin1Char('K'))
821                 qname.remove(0, 1);
822         }
823 
824         const int len = qname.count();
825         for (int i = 0; i < len && qname.at(i).isUpper(); i++)
826             qname[i] = qname.at(i).toLower();
827 
828         return qname;
829     }
830 
831     // --------------- UpdateBlocker
UpdateBlocker(QWidget * w)832     UpdateBlocker::UpdateBlocker(QWidget *w) :
833         m_widget(w),
834         m_enabled(w->updatesEnabled() && w->isVisible())
835     {
836         if (m_enabled)
837             m_widget->setUpdatesEnabled(false);
838     }
839 
~UpdateBlocker()840     UpdateBlocker::~UpdateBlocker()
841     {
842         if (m_enabled)
843             m_widget->setUpdatesEnabled(true);
844     }
845 
846 } // namespace qdesigner_internal
847 
848 QT_END_NAMESPACE
849