1 /****************************************************************************
2 **
3 ** Copyright (C) 2016 The Qt Company Ltd.
4 ** Contact: https://www.qt.io/licensing/
5 **
6 ** This file is part of the Qt Designer of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:GPL-EXCEPT$
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 https://www.qt.io/terms-conditions. For further
15 ** information use the contact form at https://www.qt.io/contact-us.
16 **
17 ** GNU General Public License Usage
18 ** Alternatively, this file may be used under the terms of the GNU
19 ** General Public License version 3 as published by the Free Software
20 ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
21 ** included in the packaging of this file. Please review the following
22 ** information to ensure the GNU General Public License requirements will
23 ** be met: https://www.gnu.org/licenses/gpl-3.0.html.
24 **
25 ** $QT_END_LICENSE$
26 **
27 ****************************************************************************/
28 
29 //
30 //  W A R N I N G
31 //  -------------
32 //
33 // This file is not part of the Qt API.  It exists for the convenience
34 // of Qt Designer.  This header
35 // file may change from version to version without notice, or even be removed.
36 //
37 // We mean it.
38 //
39 
40 #ifndef QDESIGNER_UTILS_H
41 #define QDESIGNER_UTILS_H
42 
43 #include "shared_global_p.h"
44 
45 #include <QtDesigner/abstractformwindow.h>
46 
47 #include <QtCore/qvariant.h>
48 #include <QtCore/qshareddata.h>
49 #include <QtCore/qmap.h>
50 #include <QtWidgets/qmainwindow.h>
51 #include <QtGui/qicon.h>
52 #include <QtGui/qpixmap.h>
53 
54 QT_BEGIN_NAMESPACE
55 
56 class QDebug;
57 
58 namespace qdesigner_internal {
59 class QDesignerFormWindowCommand;
60 class DesignerIconCache;
61 class FormWindowBase;
62 
63 
64 QDESIGNER_SHARED_EXPORT void designerWarning(const QString &message);
65 
66 QDESIGNER_SHARED_EXPORT void reloadIconResources(DesignerIconCache *iconCache, QObject *object);
67 
68 /* Flag/Enumeration helpers for the property sheet: Enumeration or flag values are returned by the property sheet
69  * as a pair of meta type and integer value.
70  * The meta type carries all the information required for the property editor and serialization
71  * by the form builders (names, etc).
72  * Note that the property editor uses unqualified names ("Cancel") while the form builder serialization  (uic)
73  * requires the whole string
74  * ("QDialogButtonBox::Cancel" or "org.qt-project.qt.gui.QDialogButtonBox.StandardButton.Cancel").*/
75 
76 /* --------- MetaEnum: Base class representing a QMetaEnum with lookup functions
77  * in both ways. Template of int type since unsigned is more suitable for flags.
78  * The keyToValue() is ignorant of scopes, it can handle fully qualified or unqualified names. */
79 
80 template <class IntType>
81 class MetaEnum
82 {
83 public:
84     using KeyToValueMap = QMap<QString, IntType>;
85 
86     MetaEnum(const QString &name, const QString &scope, const QString &separator);
87     MetaEnum() = default;
88     void addKey(IntType value, const QString &name);
89 
90     QString valueToKey(IntType value, bool *ok = nullptr) const;
91     // Ignorant of scopes.
92     IntType keyToValue(QString key, bool *ok = nullptr) const;
93 
name()94     const QString &name() const      { return m_name; }
scope()95     const QString &scope() const     { return m_scope; }
separator()96     const QString &separator() const { return m_separator; }
97 
keys()98     const QStringList &keys() const { return m_keys; }
keyToValueMap()99     const KeyToValueMap &keyToValueMap() const { return m_keyToValueMap; }
100 
101 protected:
102     void appendQualifiedName(const QString &key, QString &target) const;
103 
104 private:
105     QString m_name;
106     QString m_scope;
107     QString m_separator;
108     KeyToValueMap m_keyToValueMap;
109     QStringList m_keys;
110 };
111 
112 template <class IntType>
MetaEnum(const QString & name,const QString & scope,const QString & separator)113 MetaEnum<IntType>::MetaEnum(const QString &name, const QString &scope, const QString &separator) :
114     m_name(name),
115     m_scope(scope),
116     m_separator(separator)
117 {
118 }
119 
120 template <class IntType>
addKey(IntType value,const QString & name)121 void MetaEnum<IntType>::addKey(IntType value, const QString &name)
122 {
123     m_keyToValueMap.insert(name, value);
124     m_keys.append(name);
125 }
126 
127 template <class IntType>
valueToKey(IntType value,bool * ok)128 QString MetaEnum<IntType>::valueToKey(IntType value, bool *ok) const
129 {
130     const QString rc = m_keyToValueMap.key(value);
131     if (ok)
132         *ok = !rc.isEmpty();
133     return rc;
134 }
135 
136 template <class IntType>
keyToValue(QString key,bool * ok)137 IntType MetaEnum<IntType>::keyToValue(QString key, bool *ok) const
138 {
139     if (!m_scope.isEmpty() && key.startsWith(m_scope))
140         key.remove(0, m_scope.size() + m_separator.size());
141     const typename KeyToValueMap::const_iterator it = m_keyToValueMap.find(key);
142     const bool found = it != m_keyToValueMap.constEnd();
143     if (ok)
144         *ok = found;
145     return found ? it.value() : IntType(0);
146 }
147 
148 template <class IntType>
appendQualifiedName(const QString & key,QString & target)149 void MetaEnum<IntType>::appendQualifiedName(const QString &key, QString &target) const
150 {
151     if (!m_scope.isEmpty()) {
152         target += m_scope;
153         target += m_separator;
154     }
155     target += key;
156 }
157 
158 // -------------- DesignerMetaEnum: Meta type for enumerations
159 
160 class QDESIGNER_SHARED_EXPORT DesignerMetaEnum : public MetaEnum<int>
161 {
162 public:
163     DesignerMetaEnum(const QString &name, const QString &scope, const QString &separator);
164     DesignerMetaEnum() = default;
165 
166     enum SerializationMode { FullyQualified, NameOnly };
167     QString toString(int value, SerializationMode sm, bool *ok = nullptr) const;
168 
169     QString messageToStringFailed(int value) const;
170     QString messageParseFailed(const QString &s) const;
171 
172     // parse a string (ignorant of scopes)
173     int parseEnum(const QString &s, bool *ok = nullptr) const { return keyToValue(s, ok); }
174 };
175 
176 // -------------- DesignerMetaFlags: Meta type for flags.
177 // Note that while the handling of flags is done using unsigned integers, the actual values returned
178 // by the property system  are integers.
179 
180 class QDESIGNER_SHARED_EXPORT DesignerMetaFlags : public MetaEnum<uint>
181 {
182 public:
183     DesignerMetaFlags(const QString &name, const QString &scope, const QString &separator);
184     DesignerMetaFlags() = default;
185 
186     enum SerializationMode { FullyQualified, NameOnly };
187     QString toString(int value, SerializationMode sm) const;
188     QStringList flags(int value) const;
189 
190     QString messageParseFailed(const QString &s) const;
191     // parse a string (ignorant of scopes)
192     int parseFlags(const QString &s, bool *ok = nullptr) const;
193 };
194 
195 // -------------- EnumValue: Returned by the property sheet for enumerations
196 
197 struct QDESIGNER_SHARED_EXPORT PropertySheetEnumValue
198 {
199     PropertySheetEnumValue(int v, const DesignerMetaEnum &me);
200     PropertySheetEnumValue();
201 
202     int value{0};
203     DesignerMetaEnum metaEnum;
204 };
205 
206 // -------------- FlagValue: Returned by the property sheet for flags
207 
208 struct QDESIGNER_SHARED_EXPORT PropertySheetFlagValue
209 {
210     PropertySheetFlagValue(int v, const DesignerMetaFlags &mf);
211     PropertySheetFlagValue();
212 
213     int value{0};
214     DesignerMetaFlags metaFlags;
215 };
216 
217 // -------------- PixmapValue: Returned by the property sheet for pixmaps
218 class QDESIGNER_SHARED_EXPORT PropertySheetPixmapValue
219 {
220 public:
221     PropertySheetPixmapValue(const QString &path);
222     PropertySheetPixmapValue();
223 
224     bool operator==(const PropertySheetPixmapValue &other) const { return compare(other) == 0; }
225     bool operator!=(const PropertySheetPixmapValue &other) const { return compare(other) != 0; }
226     bool operator<(const PropertySheetPixmapValue &other) const  { return compare(other) <  0; }
227 
228     // Check where a pixmap comes from
229     enum PixmapSource { LanguageResourcePixmap , ResourcePixmap, FilePixmap };
230     static PixmapSource getPixmapSource(QDesignerFormEditorInterface *core, const QString & path);
231 
pixmapSource(QDesignerFormEditorInterface * core)232     PixmapSource pixmapSource(QDesignerFormEditorInterface *core) const { return getPixmapSource(core, m_path); }
233 
234     QString path() const;
235     void setPath(const QString &path); // passing the empty path resets the pixmap
236 
237     int compare(const PropertySheetPixmapValue &other) const;
238 
239 private:
240     QString m_path;
241 };
242 
243 // -------------- IconValue: Returned by the property sheet for icons
244 
245 class PropertySheetIconValueData;
246 
247 class QDESIGNER_SHARED_EXPORT PropertySheetIconValue
248 {
249  public:
250     PropertySheetIconValue(const PropertySheetPixmapValue &pixmap);
251     PropertySheetIconValue();
252     ~PropertySheetIconValue();
253     PropertySheetIconValue(const PropertySheetIconValue &);
254     PropertySheetIconValue &operator=(const PropertySheetIconValue &);
255 
256     bool operator==(const PropertySheetIconValue &other) const { return equals(other); }
257     bool operator!=(const PropertySheetIconValue &other) const { return !equals(other); }
258     bool operator<(const PropertySheetIconValue &other) const;
259 
260     bool isEmpty() const;
261 
262     QString theme() const;
263     void setTheme(const QString &);
264 
265     PropertySheetPixmapValue pixmap(QIcon::Mode mode, QIcon::State state) const;
266     void setPixmap(QIcon::Mode mode, QIcon::State state, const PropertySheetPixmapValue &path); // passing the empty path resets the pixmap
267 
268     uint mask() const;
269     uint compare(const PropertySheetIconValue &other) const;
270     void assign(const PropertySheetIconValue &other, uint mask);
271 
272     // Convenience accessors to get themed/unthemed icons.
273     PropertySheetIconValue themed() const;
274     PropertySheetIconValue unthemed() const;
275 
276     using ModeStateKey = QPair<QIcon::Mode, QIcon::State>;
277     using ModeStateToPixmapMap = QMap<ModeStateKey, PropertySheetPixmapValue>;
278 
279     const ModeStateToPixmapMap &paths() const;
280 
281 private:
282     bool equals(const PropertySheetIconValue &rhs) const;
283     QSharedDataPointer<PropertySheetIconValueData> m_data;
284 };
285 
286 QDESIGNER_SHARED_EXPORT QDebug operator<<(QDebug, const PropertySheetIconValue &);
287 
288 class QDESIGNER_SHARED_EXPORT DesignerPixmapCache : public QObject
289 {
290     Q_OBJECT
291 public:
292     DesignerPixmapCache(QObject *parent = nullptr);
293     QPixmap pixmap(const PropertySheetPixmapValue &value) const;
294     void clear();
295 signals:
296     void reloaded();
297 private:
298     mutable QMap<PropertySheetPixmapValue, QPixmap> m_cache;
299     friend class FormWindowBase;
300 };
301 
302 class QDESIGNER_SHARED_EXPORT DesignerIconCache : public QObject
303 {
304     Q_OBJECT
305 public:
306     explicit DesignerIconCache(DesignerPixmapCache *pixmapCache, QObject *parent = nullptr);
307     QIcon icon(const PropertySheetIconValue &value) const;
308     void clear();
309 signals:
310     void reloaded();
311 private:
312     mutable QMap<PropertySheetIconValue, QIcon> m_cache;
313     DesignerPixmapCache *m_pixmapCache;
314     friend class FormWindowBase;
315 };
316 
317 // -------------- PropertySheetTranslatableData: Base class for translatable properties.
318 class QDESIGNER_SHARED_EXPORT PropertySheetTranslatableData
319 {
320 protected:
321     PropertySheetTranslatableData(bool translatable = true,
322                                   const QString &disambiguation = QString(),
323                                   const QString &comment = QString());
324     bool equals(const PropertySheetTranslatableData &rhs) const;
325 
326 public:
translatable()327     bool translatable() const                { return m_translatable; }
setTranslatable(bool translatable)328     void setTranslatable(bool translatable)  { m_translatable = translatable; }
disambiguation()329     QString disambiguation() const           { return m_disambiguation; }
setDisambiguation(const QString & d)330     void setDisambiguation(const QString &d) { m_disambiguation = d; }
comment()331     QString comment() const                  { return m_comment; }
setComment(const QString & comment)332     void setComment(const QString &comment)  { m_comment = comment; }
id()333     QString id() const                       { return m_id; }
setId(const QString & id)334     void setId(const QString &id)            { m_id = id; }
335 
336 private:
337     bool m_translatable;
338     QString m_disambiguation;
339     QString m_comment;
340     QString m_id;
341 };
342 
343 // -------------- StringValue: Returned by the property sheet for strings
344 class QDESIGNER_SHARED_EXPORT PropertySheetStringValue : public PropertySheetTranslatableData
345 {
346 public:
347     PropertySheetStringValue(const QString &value = QString(), bool translatable = true,
348                              const QString &disambiguation = QString(), const QString &comment = QString());
349 
350     bool operator==(const PropertySheetStringValue &other) const { return equals(other); }
351     bool operator!=(const PropertySheetStringValue &other) const { return !equals(other); }
352 
353     QString value() const;
354     void setValue(const QString &value);
355 
356 private:
357     bool equals(const PropertySheetStringValue &rhs) const;
358 
359     QString m_value;
360 };
361 
362 // -------------- StringValue: Returned by the property sheet for string lists
363 class QDESIGNER_SHARED_EXPORT PropertySheetStringListValue : public PropertySheetTranslatableData
364 {
365 public:
366     PropertySheetStringListValue(const QStringList &value = QStringList(),
367                                  bool translatable = true,
368                                  const QString &disambiguation = QString(),
369                                  const QString &comment = QString());
370 
371     bool operator==(const PropertySheetStringListValue &other) const { return equals(other); }
372     bool operator!=(const PropertySheetStringListValue &other) const { return !equals(other); }
373 
374     QStringList value() const;
375     void setValue(const QStringList &value);
376 
377 private:
378     bool equals(const PropertySheetStringListValue &rhs) const;
379 
380     QStringList m_value;
381 };
382 
383 // -------------- StringValue: Returned by the property sheet for strings
384 class QDESIGNER_SHARED_EXPORT PropertySheetKeySequenceValue : public PropertySheetTranslatableData
385 {
386 public:
387     PropertySheetKeySequenceValue(const QKeySequence &value = QKeySequence(),
388                                   bool translatable = true,
389                                   const QString &disambiguation = QString(),
390                                   const QString &comment = QString());
391     PropertySheetKeySequenceValue(const QKeySequence::StandardKey &standardKey,
392                                   bool translatable = true,
393                                   const QString &disambiguation = QString(),
394                                   const QString &comment = QString());
395 
396     bool operator==(const PropertySheetKeySequenceValue &other) const { return equals(other); }
397     bool operator!=(const PropertySheetKeySequenceValue &other) const { return !equals(other); }
398 
399     QKeySequence value() const;
400     void setValue(const QKeySequence &value);
401     QKeySequence::StandardKey standardKey() const;
402     void setStandardKey(const QKeySequence::StandardKey &standardKey);
403     bool isStandardKey() const;
404 
405 private:
406     bool equals(const PropertySheetKeySequenceValue &rhs) const;
407 
408     QKeySequence m_value;
409     QKeySequence::StandardKey m_standardKey;
410 };
411 
412 } // namespace qdesigner_internal
413 
414 QT_END_NAMESPACE
415 
416 
417 // NOTE: Do not move this code, needed for GCC 3.3
Q_DECLARE_METATYPE(qdesigner_internal::PropertySheetEnumValue)418 Q_DECLARE_METATYPE(qdesigner_internal::PropertySheetEnumValue)
419 Q_DECLARE_METATYPE(qdesigner_internal::PropertySheetFlagValue)
420 Q_DECLARE_METATYPE(qdesigner_internal::PropertySheetPixmapValue)
421 Q_DECLARE_METATYPE(qdesigner_internal::PropertySheetIconValue)
422 Q_DECLARE_METATYPE(qdesigner_internal::PropertySheetStringValue)
423 Q_DECLARE_METATYPE(qdesigner_internal::PropertySheetStringListValue)
424 Q_DECLARE_METATYPE(qdesigner_internal::PropertySheetKeySequenceValue)
425 
426 
427 QT_BEGIN_NAMESPACE
428 
429 namespace qdesigner_internal {
430 
431 
432 // Create a command to change a text property (that is, create a reset property command if the text is empty)
433 QDESIGNER_SHARED_EXPORT QDesignerFormWindowCommand *createTextPropertyCommand(const QString &propertyName, const QString &text, QObject *object, QDesignerFormWindowInterface *fw);
434 
435 // Returns preferred task menu action for managed widget
436 QDESIGNER_SHARED_EXPORT QAction *preferredEditAction(QDesignerFormEditorInterface *core, QWidget *managedWidget);
437 
438 enum class UicLanguage
439 {
440     Cpp,
441     Python,
442 };
443 
444 // Convenience to run UIC
445 QDESIGNER_SHARED_EXPORT bool runUIC(const QString &fileName, UicLanguage language,
446                                     QByteArray& ba, QString &errorMessage);
447 
448 // Find a suitable variable name for a class.
449 QDESIGNER_SHARED_EXPORT QString qtify(const QString &name);
450 
451 /* UpdateBlocker: Blocks the updates of the widget passed on while in scope.
452  * Does nothing if the incoming widget already has updatesEnabled==false
453  * which is important to avoid side-effects when putting it into QStackedLayout. */
454 
455 class QDESIGNER_SHARED_EXPORT UpdateBlocker {
456     Q_DISABLE_COPY_MOVE(UpdateBlocker)
457 
458 public:
459     UpdateBlocker(QWidget *w);
460     ~UpdateBlocker();
461 
462 private:
463     QWidget *m_widget;
464     const bool m_enabled;
465 };
466 
467 namespace Utils {
468 
469 inline int valueOf(const QVariant &value, bool *ok = nullptr)
470 {
471     if (value.canConvert<PropertySheetEnumValue>()) {
472         if (ok)
473             *ok = true;
474         return qvariant_cast<PropertySheetEnumValue>(value).value;
475     }
476     if (value.canConvert<PropertySheetFlagValue>()) {
477         if (ok)
478             *ok = true;
479         return qvariant_cast<PropertySheetFlagValue>(value).value;
480     }
481     return value.toInt(ok);
482 }
483 
484 inline bool isObjectAncestorOf(QObject *ancestor, QObject *child)
485 {
486     QObject *obj = child;
487     while (obj != nullptr) {
488         if (obj == ancestor)
489             return true;
490         obj = obj->parent();
491     }
492     return false;
493 }
494 
495 inline bool isCentralWidget(QDesignerFormWindowInterface *fw, QWidget *widget)
496 {
497     if (! fw || ! widget)
498         return false;
499 
500     if (widget == fw->mainContainer())
501         return true;
502 
503     // ### generalize for other containers
504     if (QMainWindow *mw = qobject_cast<QMainWindow*>(fw->mainContainer())) {
505         return mw->centralWidget() == widget;
506     }
507 
508     return false;
509 }
510 
511 } // namespace Utils
512 
513 } // namespace qdesigner_internal
514 
515 QT_END_NAMESPACE
516 
517 #endif // QDESIGNER_UTILS_H
518