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
54QT_BEGIN_NAMESPACE
55
56class QDebug;
57
58namespace qdesigner_internal {
59class QDesignerFormWindowCommand;
60class DesignerIconCache;
61class FormWindowBase;
62
63
64QDESIGNER_SHARED_EXPORT void designerWarning(const QString &message);
65
66QDESIGNER_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
80template <class IntType>
81class MetaEnum
82{
83public:
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
94 const QString &name() const { return m_name; }
95 const QString &scope() const { return m_scope; }
96 const QString &separator() const { return m_separator; }
97
98 const QStringList &keys() const { return m_keys; }
99 const KeyToValueMap &keyToValueMap() const { return m_keyToValueMap; }
100
101protected:
102 void appendQualifiedName(const QString &key, QString &target) const;
103
104private:
105 QString m_name;
106 QString m_scope;
107 QString m_separator;
108 KeyToValueMap m_keyToValueMap;
109 QStringList m_keys;
110};
111
112template <class IntType>
113MetaEnum<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
120template <class IntType>
121void MetaEnum<IntType>::addKey(IntType value, const QString &name)
122{
123 m_keyToValueMap.insert(name, value);
124 m_keys.append(name);
125}
126
127template <class IntType>
128QString 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
136template <class IntType>
137IntType 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
148template <class IntType>
149void 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
160class QDESIGNER_SHARED_EXPORT DesignerMetaEnum : public MetaEnum<int>
161{
162public:
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
180class QDESIGNER_SHARED_EXPORT DesignerMetaFlags : public MetaEnum<uint>
181{
182public:
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
197struct 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
208struct 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
218class QDESIGNER_SHARED_EXPORT PropertySheetPixmapValue
219{
220public:
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
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
239private:
240 QString m_path;
241};
242
243// -------------- IconValue: Returned by the property sheet for icons
244
245class PropertySheetIconValueData;
246
247class 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
281private:
282 bool equals(const PropertySheetIconValue &rhs) const;
283 QSharedDataPointer<PropertySheetIconValueData> m_data;
284};
285
286QDESIGNER_SHARED_EXPORT QDebug operator<<(QDebug, const PropertySheetIconValue &);
287
288class QDESIGNER_SHARED_EXPORT DesignerPixmapCache : public QObject
289{
290 Q_OBJECT
291public:
292 DesignerPixmapCache(QObject *parent = nullptr);
293 QPixmap pixmap(const PropertySheetPixmapValue &value) const;
294 void clear();
295signals:
296 void reloaded();
297private:
298 mutable QMap<PropertySheetPixmapValue, QPixmap> m_cache;
299 friend class FormWindowBase;
300};
301
302class QDESIGNER_SHARED_EXPORT DesignerIconCache : public QObject
303{
304 Q_OBJECT
305public:
306 explicit DesignerIconCache(DesignerPixmapCache *pixmapCache, QObject *parent = nullptr);
307 QIcon icon(const PropertySheetIconValue &value) const;
308 void clear();
309signals:
310 void reloaded();
311private:
312 mutable QMap<PropertySheetIconValue, QIcon> m_cache;
313 DesignerPixmapCache *m_pixmapCache;
314 friend class FormWindowBase;
315};
316
317// -------------- PropertySheetTranslatableData: Base class for translatable properties.
318class QDESIGNER_SHARED_EXPORT PropertySheetTranslatableData
319{
320protected:
321 PropertySheetTranslatableData(bool translatable = true,
322 const QString &disambiguation = QString(),
323 const QString &comment = QString());
324 bool equals(const PropertySheetTranslatableData &rhs) const;
325
326public:
327 bool translatable() const { return m_translatable; }
328 void setTranslatable(bool translatable) { m_translatable = translatable; }
329 QString disambiguation() const { return m_disambiguation; }
330 void setDisambiguation(const QString &d) { m_disambiguation = d; }
331 QString comment() const { return m_comment; }
332 void setComment(const QString &comment) { m_comment = comment; }
333 QString id() const { return m_id; }
334 void setId(const QString &id) { m_id = id; }
335
336private:
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
344class QDESIGNER_SHARED_EXPORT PropertySheetStringValue : public PropertySheetTranslatableData
345{
346public:
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
356private:
357 bool equals(const PropertySheetStringValue &rhs) const;
358
359 QString m_value;
360};
361
362// -------------- StringValue: Returned by the property sheet for string lists
363class QDESIGNER_SHARED_EXPORT PropertySheetStringListValue : public PropertySheetTranslatableData
364{
365public:
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
377private:
378 bool equals(const PropertySheetStringListValue &rhs) const;
379
380 QStringList m_value;
381};
382
383// -------------- StringValue: Returned by the property sheet for strings
384class QDESIGNER_SHARED_EXPORT PropertySheetKeySequenceValue : public PropertySheetTranslatableData
385{
386public:
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
405private:
406 bool equals(const PropertySheetKeySequenceValue &rhs) const;
407
408 QKeySequence m_value;
409 QKeySequence::StandardKey m_standardKey;
410};
411
412} // namespace qdesigner_internal
413
414QT_END_NAMESPACE
415
416
417// NOTE: Do not move this code, needed for GCC 3.3
418Q_DECLARE_METATYPE(qdesigner_internal::PropertySheetEnumValue)
419Q_DECLARE_METATYPE(qdesigner_internal::PropertySheetFlagValue)
420Q_DECLARE_METATYPE(qdesigner_internal::PropertySheetPixmapValue)
421Q_DECLARE_METATYPE(qdesigner_internal::PropertySheetIconValue)
422Q_DECLARE_METATYPE(qdesigner_internal::PropertySheetStringValue)
423Q_DECLARE_METATYPE(qdesigner_internal::PropertySheetStringListValue)
424Q_DECLARE_METATYPE(qdesigner_internal::PropertySheetKeySequenceValue)
425
426
427QT_BEGIN_NAMESPACE
428
429namespace 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)
433QDESIGNER_SHARED_EXPORT QDesignerFormWindowCommand *createTextPropertyCommand(const QString &propertyName, const QString &text, QObject *object, QDesignerFormWindowInterface *fw);
434
435// Returns preferred task menu action for managed widget
436QDESIGNER_SHARED_EXPORT QAction *preferredEditAction(QDesignerFormEditorInterface *core, QWidget *managedWidget);
437
438enum class UicLanguage
439{
440 Cpp,
441 Python,
442};
443
444// Convenience to run UIC
445QDESIGNER_SHARED_EXPORT bool runUIC(const QString &fileName, UicLanguage language,
446 QByteArray& ba, QString &errorMessage);
447
448// Find a suitable variable name for a class.
449QDESIGNER_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
455class QDESIGNER_SHARED_EXPORT UpdateBlocker {
456 Q_DISABLE_COPY_MOVE(UpdateBlocker)
457
458public:
459 UpdateBlocker(QWidget *w);
460 ~UpdateBlocker();
461
462private:
463 QWidget *m_widget;
464 const bool m_enabled;
465};
466
467namespace Utils {
468
469inline 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
484inline 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
495inline 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
515QT_END_NAMESPACE
516
517#endif // QDESIGNER_UTILS_H
518