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#include "qdesigner_utils_p.h"
30#include "qdesigner_propertycommand_p.h"
31#include "abstractformbuilder.h"
32#include "formwindowbase_p.h"
33
34#include <QtDesigner/abstractformeditor.h>
35#include <QtDesigner/abstractformwindow.h>
36#include <QtDesigner/abstractresourcebrowser.h>
37#include <QtDesigner/abstractlanguage.h>
38#include <QtDesigner/taskmenu.h>
39#include <QtDesigner/qextensionmanager.h>
40
41#include <QtCore/qdir.h>
42#include <QtCore/qprocess.h>
43#include <QtCore/qlibraryinfo.h>
44#include <QtCore/qdebug.h>
45#include <QtCore/qqueue.h>
46#include <QtCore/qshareddata.h>
47
48#include <QtWidgets/qapplication.h>
49#include <QtGui/qicon.h>
50#include <QtGui/qpixmap.h>
51#include <QtWidgets/qlistwidget.h>
52#include <QtWidgets/qtreewidget.h>
53#include <QtWidgets/qtablewidget.h>
54#include <QtWidgets/qcombobox.h>
55
56QT_BEGIN_NAMESPACE
57
58namespace qdesigner_internal
59{
60 QDESIGNER_SHARED_EXPORT void designerWarning(const QString &message)
61 {
62 qWarning(msg: "Designer: %s", qPrintable(message));
63 }
64
65 void reloadTreeItem(DesignerIconCache *iconCache, QTreeWidgetItem *item)
66 {
67 if (!item)
68 return;
69
70 for (int c = 0; c < item->columnCount(); c++) {
71 const QVariant v = item->data(column: c, role: Qt::DecorationPropertyRole);
72 if (v.canConvert<PropertySheetIconValue>())
73 item->setIcon(column: c, aicon: iconCache->icon(value: qvariant_cast<PropertySheetIconValue>(v)));
74 }
75 }
76
77 void reloadListItem(DesignerIconCache *iconCache, QListWidgetItem *item)
78 {
79 if (!item)
80 return;
81
82 const QVariant v = item->data(role: Qt::DecorationPropertyRole);
83 if (v.canConvert<PropertySheetIconValue>())
84 item->setIcon(iconCache->icon(value: qvariant_cast<PropertySheetIconValue>(v)));
85 }
86
87 void reloadTableItem(DesignerIconCache *iconCache, QTableWidgetItem *item)
88 {
89 if (!item)
90 return;
91
92 const QVariant v = item->data(role: Qt::DecorationPropertyRole);
93 if (v.canConvert<PropertySheetIconValue>())
94 item->setIcon(iconCache->icon(value: qvariant_cast<PropertySheetIconValue>(v)));
95 }
96
97 void reloadIconResources(DesignerIconCache *iconCache, QObject *object)
98 {
99 if (QListWidget *listWidget = qobject_cast<QListWidget *>(object)) {
100 for (int i = 0; i < listWidget->count(); i++)
101 reloadListItem(iconCache, item: listWidget->item(row: i));
102 } else if (QComboBox *comboBox = qobject_cast<QComboBox *>(object)) {
103 for (int i = 0; i < comboBox->count(); i++) {
104 const QVariant v = comboBox->itemData(index: i, role: Qt::DecorationPropertyRole);
105 if (v.canConvert<PropertySheetIconValue>()) {
106 QIcon icon = iconCache->icon(value: qvariant_cast<PropertySheetIconValue>(v));
107 comboBox->setItemIcon(index: i, icon);
108 comboBox->setItemData(index: i, value: icon);
109 }
110 }
111 } else if (QTreeWidget *treeWidget = qobject_cast<QTreeWidget *>(object)) {
112 reloadTreeItem(iconCache, item: treeWidget->headerItem());
113 QQueue<QTreeWidgetItem *> itemsQueue;
114 for (int i = 0; i < treeWidget->topLevelItemCount(); i++)
115 itemsQueue.enqueue(t: treeWidget->topLevelItem(index: i));
116 while (!itemsQueue.isEmpty()) {
117 QTreeWidgetItem *item = itemsQueue.dequeue();
118 for (int i = 0; i < item->childCount(); i++)
119 itemsQueue.enqueue(t: item->child(index: i));
120 reloadTreeItem(iconCache, item);
121 }
122 } else if (QTableWidget *tableWidget = qobject_cast<QTableWidget *>(object)) {
123 const int columnCount = tableWidget->columnCount();
124 const int rowCount = tableWidget->rowCount();
125 for (int c = 0; c < columnCount; c++)
126 reloadTableItem(iconCache, item: tableWidget->horizontalHeaderItem(column: c));
127 for (int r = 0; r < rowCount; r++)
128 reloadTableItem(iconCache, item: tableWidget->verticalHeaderItem(row: r));
129 for (int c = 0; c < columnCount; c++)
130 for (int r = 0; r < rowCount; r++)
131 reloadTableItem(iconCache, item: tableWidget->item(row: r, column: c));
132 }
133 }
134
135 // ------------- DesignerMetaEnum
136 DesignerMetaEnum::DesignerMetaEnum(const QString &name, const QString &scope, const QString &separator) :
137 MetaEnum<int>(name, scope, separator)
138 {
139 }
140
141
142 QString DesignerMetaEnum::toString(int value, SerializationMode sm, bool *ok) const
143 {
144 // find value
145 bool valueOk;
146 const QString item = valueToKey(value, ok: &valueOk);
147 if (ok)
148 *ok = valueOk;
149
150 if (!valueOk || sm == NameOnly)
151 return item;
152
153 QString qualifiedItem;
154 appendQualifiedName(key: item, target&: qualifiedItem);
155 return qualifiedItem;
156 }
157
158 QString DesignerMetaEnum::messageToStringFailed(int value) const
159 {
160 return QCoreApplication::translate(context: "DesignerMetaEnum",
161 key: "%1 is not a valid enumeration value of '%2'.")
162 .arg(a: value).arg(a: name());
163 }
164
165 QString DesignerMetaEnum::messageParseFailed(const QString &s) const
166 {
167 return QCoreApplication::translate(context: "DesignerMetaEnum",
168 key: "'%1' could not be converted to an enumeration value of type '%2'.")
169 .arg(a1: s, a2: name());
170 }
171 // -------------- DesignerMetaFlags
172 DesignerMetaFlags::DesignerMetaFlags(const QString &name, const QString &scope, const QString &separator) :
173 MetaEnum<uint>(name, scope, separator)
174 {
175 }
176
177 QStringList DesignerMetaFlags::flags(int ivalue) const
178 {
179 QStringList rc;
180 const uint v = static_cast<uint>(ivalue);
181 for (auto it = keyToValueMap().constBegin(), cend = keyToValueMap().constEnd(); it != cend; ++it ) {
182 const uint itemValue = it.value();
183 // Check for equality first as flag values can be 0 or -1, too. Takes preference over a bitwise flag
184 if (v == itemValue) {
185 rc.clear();
186 rc.push_back(t: it.key());
187 return rc;
188 }
189 // Do not add 0-flags (None-flags)
190 if (itemValue)
191 if ((v & itemValue) == itemValue)
192 rc.push_back(t: it.key());
193 }
194 return rc;
195 }
196
197
198 QString DesignerMetaFlags::toString(int value, SerializationMode sm) const
199 {
200 const QStringList flagIds = flags(ivalue: value);
201 if (flagIds.isEmpty())
202 return QString();
203
204 const QChar delimiter = QLatin1Char('|');
205 QString rc;
206 const QStringList::const_iterator cend = flagIds.constEnd();
207 for (QStringList::const_iterator it = flagIds.constBegin(); it != cend; ++it) {
208 if (!rc.isEmpty())
209 rc += delimiter ;
210 if (sm == FullyQualified)
211 appendQualifiedName(key: *it, target&: rc);
212 else
213 rc += *it;
214 }
215 return rc;
216 }
217
218
219 int DesignerMetaFlags::parseFlags(const QString &s, bool *ok) const
220 {
221 if (s.isEmpty()) {
222 if (ok)
223 *ok = true;
224 return 0;
225 }
226 uint flags = 0;
227 bool valueOk = true;
228 QStringList keys = s.split(sep: QString(QLatin1Char('|')));
229 for (auto it = keys.constBegin(), cend = keys.constEnd(); it != cend; ++it) {
230 const uint flagValue = keyToValue(key: *it, ok: &valueOk);
231 if (!valueOk) {
232 flags = 0;
233 break;
234 }
235 flags |= flagValue;
236 }
237 if (ok)
238 *ok = valueOk;
239 return static_cast<int>(flags);
240 }
241
242 QString DesignerMetaFlags::messageParseFailed(const QString &s) const
243 {
244 return QCoreApplication::translate(context: "DesignerMetaFlags",
245 key: "'%1' could not be converted to a flag value of type '%2'.")
246 .arg(a1: s, a2: name());
247 }
248
249 // ---------- PropertySheetEnumValue
250
251 PropertySheetEnumValue::PropertySheetEnumValue(int v, const DesignerMetaEnum &me) :
252 value(v),
253 metaEnum(me)
254 {
255 }
256
257 PropertySheetEnumValue::PropertySheetEnumValue() = default;
258
259 // ---------------- PropertySheetFlagValue
260 PropertySheetFlagValue::PropertySheetFlagValue(int v, const DesignerMetaFlags &mf) :
261 value(v),
262 metaFlags(mf)
263 {
264 }
265
266 PropertySheetFlagValue::PropertySheetFlagValue() = default;
267
268 // ---------------- PropertySheetPixmapValue
269 PropertySheetPixmapValue::PropertySheetPixmapValue(const QString &path) : m_path(path)
270 {
271 }
272
273 PropertySheetPixmapValue::PropertySheetPixmapValue() = default;
274
275 PropertySheetPixmapValue::PixmapSource PropertySheetPixmapValue::getPixmapSource(QDesignerFormEditorInterface *core, const QString & path)
276 {
277 if (const QDesignerLanguageExtension *lang = qt_extension<QDesignerLanguageExtension *>(manager: core->extensionManager(), object: core))
278 return lang->isLanguageResource(path) ? LanguageResourcePixmap : FilePixmap;
279 return path.startsWith(c: QLatin1Char(':')) ? ResourcePixmap : FilePixmap;
280 }
281
282 int PropertySheetPixmapValue::compare(const PropertySheetPixmapValue &other) const
283 {
284 return m_path.compare(s: other.m_path);
285 }
286
287 QString PropertySheetPixmapValue::path() const
288 {
289 return m_path;
290 }
291
292 void PropertySheetPixmapValue::setPath(const QString &path)
293 {
294 if (m_path == path)
295 return;
296 m_path = path;
297 }
298
299 // ---------- PropertySheetIconValue
300
301 class PropertySheetIconValueData : public QSharedData {
302 public:
303 PropertySheetIconValue::ModeStateToPixmapMap m_paths;
304 QString m_theme;
305 };
306
307 PropertySheetIconValue::PropertySheetIconValue(const PropertySheetPixmapValue &pixmap) :
308 m_data(new PropertySheetIconValueData)
309 {
310 setPixmap(mode: QIcon::Normal, state: QIcon::Off, path: pixmap);
311 }
312
313 PropertySheetIconValue::PropertySheetIconValue() :
314 m_data(new PropertySheetIconValueData)
315 {
316 }
317
318 PropertySheetIconValue::~PropertySheetIconValue() = default;
319
320 PropertySheetIconValue::PropertySheetIconValue(const PropertySheetIconValue &rhs) :
321 m_data(rhs.m_data)
322 {
323 }
324
325 PropertySheetIconValue &PropertySheetIconValue::operator=(const PropertySheetIconValue &rhs)
326 {
327 if (this != &rhs)
328 m_data.operator=(o: rhs.m_data);
329 return *this;
330 }
331
332 bool PropertySheetIconValue::equals(const PropertySheetIconValue &rhs) const
333 {
334 return m_data->m_theme == rhs.m_data->m_theme && m_data->m_paths == rhs.m_data->m_paths;
335 }
336
337 bool PropertySheetIconValue::operator<(const PropertySheetIconValue &other) const
338 {
339 if (const int themeCmp = m_data->m_theme.compare(s: other.m_data->m_theme))
340 return themeCmp < 0;
341 auto itThis = m_data->m_paths.cbegin();
342 auto itThisEnd = m_data->m_paths.cend();
343 auto itOther = other.m_data->m_paths.cbegin();
344 auto itOtherEnd = other.m_data->m_paths.cend();
345 while (itThis != itThisEnd && itOther != itOtherEnd) {
346 const ModeStateKey thisPair = itThis.key();
347 const ModeStateKey otherPair = itOther.key();
348 if (thisPair < otherPair)
349 return true;
350 if (otherPair < thisPair)
351 return false;
352 const int crc = itThis.value().compare(other: itOther.value());
353 if (crc < 0)
354 return true;
355 if (crc > 0)
356 return false;
357 ++itThis;
358 ++itOther;
359 }
360 return itOther != itOtherEnd;
361 }
362
363 bool PropertySheetIconValue::isEmpty() const
364 {
365 return m_data->m_theme.isEmpty() && m_data->m_paths.isEmpty();
366 }
367
368 QString PropertySheetIconValue::theme() const
369 {
370 return m_data->m_theme;
371 }
372
373 void PropertySheetIconValue::setTheme(const QString &t)
374 {
375 m_data->m_theme = t;
376 }
377
378 PropertySheetPixmapValue PropertySheetIconValue::pixmap(QIcon::Mode mode, QIcon::State state) const
379 {
380 const ModeStateKey pair = qMakePair(x: mode, y: state);
381 return m_data->m_paths.value(akey: pair);
382 }
383
384 void PropertySheetIconValue::setPixmap(QIcon::Mode mode, QIcon::State state, const PropertySheetPixmapValue &pixmap)
385 {
386 const ModeStateKey pair = qMakePair(x: mode, y: state);
387 if (pixmap.path().isEmpty())
388 m_data->m_paths.remove(akey: pair);
389 else
390 m_data->m_paths.insert(akey: pair, avalue: pixmap);
391 }
392
393 QPixmap DesignerPixmapCache::pixmap(const PropertySheetPixmapValue &value) const
394 {
395 QMap<PropertySheetPixmapValue, QPixmap>::const_iterator it = m_cache.constFind(akey: value);
396 if (it != m_cache.constEnd())
397 return it.value();
398
399 QPixmap pix = QPixmap(value.path());
400 m_cache.insert(akey: value, avalue: pix);
401 return pix;
402 }
403
404 void DesignerPixmapCache::clear()
405 {
406 m_cache.clear();
407 }
408
409 DesignerPixmapCache::DesignerPixmapCache(QObject *parent)
410 : QObject(parent)
411 {
412 }
413
414 QIcon DesignerIconCache::icon(const PropertySheetIconValue &value) const
415 {
416 const auto it = m_cache.constFind(akey: value);
417 if (it != m_cache.constEnd())
418 return it.value();
419
420 // Match on the theme first if it is available.
421 if (!value.theme().isEmpty()) {
422 const QString theme = value.theme();
423 if (QIcon::hasThemeIcon(name: theme)) {
424 const QIcon themeIcon = QIcon::fromTheme(name: theme);
425 m_cache.insert(akey: value, avalue: themeIcon);
426 return themeIcon;
427 }
428 }
429
430 QIcon icon;
431 const PropertySheetIconValue::ModeStateToPixmapMap &paths = value.paths();
432 for (auto it = paths.constBegin(), cend = paths.constEnd(); it != cend; ++it) {
433 const auto pair = it.key();
434 icon.addFile(fileName: it.value().path(), size: QSize(), mode: pair.first, state: pair.second);
435 }
436 m_cache.insert(akey: value, avalue: icon);
437 return icon;
438 }
439
440 void DesignerIconCache::clear()
441 {
442 m_cache.clear();
443 }
444
445 DesignerIconCache::DesignerIconCache(DesignerPixmapCache *pixmapCache, QObject *parent)
446 : QObject(parent),
447 m_pixmapCache(pixmapCache)
448 {
449
450 }
451
452 PropertySheetTranslatableData::PropertySheetTranslatableData(bool translatable, const QString &disambiguation, const QString &comment) :
453 m_translatable(translatable), m_disambiguation(disambiguation), m_comment(comment) { }
454
455 bool PropertySheetTranslatableData::equals(const PropertySheetTranslatableData &rhs) const
456 {
457 return m_translatable == rhs.m_translatable
458 && m_disambiguation == rhs.m_disambiguation
459 && m_comment == rhs.m_comment
460 && m_id == rhs.m_id;
461 }
462
463 PropertySheetStringValue::PropertySheetStringValue(const QString &value,
464 bool translatable, const QString &disambiguation, const QString &comment) :
465 PropertySheetTranslatableData(translatable, disambiguation, comment), m_value(value) {}
466
467 QString PropertySheetStringValue::value() const
468 {
469 return m_value;
470 }
471
472 void PropertySheetStringValue::setValue(const QString &value)
473 {
474 m_value = value;
475 }
476
477 bool PropertySheetStringValue::equals(const PropertySheetStringValue &rhs) const
478 {
479 return m_value == rhs.m_value && PropertySheetTranslatableData::equals(rhs);
480 }
481
482 PropertySheetStringListValue::PropertySheetStringListValue(const QStringList &value,
483 bool translatable,
484 const QString &disambiguation,
485 const QString &comment) :
486 PropertySheetTranslatableData(translatable, disambiguation, comment), m_value(value)
487 {
488 }
489
490 QStringList PropertySheetStringListValue::value() const
491 {
492 return m_value;
493 }
494
495 void PropertySheetStringListValue::setValue(const QStringList &value)
496 {
497 m_value = value;
498 }
499
500 bool PropertySheetStringListValue::equals(const PropertySheetStringListValue &rhs) const
501 {
502 return m_value == rhs.m_value && PropertySheetTranslatableData::equals(rhs);
503 }
504
505 QStringList m_value;
506
507
508 PropertySheetKeySequenceValue::PropertySheetKeySequenceValue(const QKeySequence &value,
509 bool translatable, const QString &disambiguation, const QString &comment)
510 : PropertySheetTranslatableData(translatable, disambiguation, comment),
511 m_value(value), m_standardKey(QKeySequence::UnknownKey) {}
512
513 PropertySheetKeySequenceValue::PropertySheetKeySequenceValue(const QKeySequence::StandardKey &standardKey,
514 bool translatable, const QString &disambiguation, const QString &comment)
515 : PropertySheetTranslatableData(translatable, disambiguation, comment),
516 m_value(QKeySequence(standardKey)), m_standardKey(standardKey) {}
517
518 QKeySequence PropertySheetKeySequenceValue::value() const
519 {
520 return m_value;
521 }
522
523 void PropertySheetKeySequenceValue::setValue(const QKeySequence &value)
524 {
525 m_value = value;
526 m_standardKey = QKeySequence::UnknownKey;
527 }
528
529 QKeySequence::StandardKey PropertySheetKeySequenceValue::standardKey() const
530 {
531 return m_standardKey;
532 }
533
534 void PropertySheetKeySequenceValue::setStandardKey(const QKeySequence::StandardKey &standardKey)
535 {
536 m_value = QKeySequence(standardKey);
537 m_standardKey = standardKey;
538 }
539
540 bool PropertySheetKeySequenceValue::isStandardKey() const
541 {
542 return m_standardKey != QKeySequence::UnknownKey;
543 }
544
545 bool PropertySheetKeySequenceValue::equals(const PropertySheetKeySequenceValue &rhs) const
546 {
547 return m_value == rhs.m_value && m_standardKey == rhs.m_standardKey
548 && PropertySheetTranslatableData::equals(rhs);
549 }
550
551 /* IconSubPropertyMask: Assign each icon sub-property (pixmaps for the
552 * various states/modes and the theme) a flag bit (see QFont) so that they
553 * can be handled individually when assigning property values to
554 * multiselections in the set-property-commands (that is, do not clobber
555 * other subproperties when assigning just one).
556 * Provide back-and-forth mapping functions for the icon states. */
557
558 enum IconSubPropertyMask {
559 NormalOffIconMask = 0x01,
560 NormalOnIconMask = 0x02,
561 DisabledOffIconMask = 0x04,
562 DisabledOnIconMask = 0x08,
563 ActiveOffIconMask = 0x10,
564 ActiveOnIconMask = 0x20,
565 SelectedOffIconMask = 0x40,
566 SelectedOnIconMask = 0x80,
567 ThemeIconMask = 0x10000
568 };
569
570 static inline uint iconStateToSubPropertyFlag(QIcon::Mode mode, QIcon::State state)
571 {
572 switch (mode) {
573 case QIcon::Disabled:
574 return state == QIcon::On ? DisabledOnIconMask : DisabledOffIconMask;
575 case QIcon::Active:
576 return state == QIcon::On ? ActiveOnIconMask : ActiveOffIconMask;
577 case QIcon::Selected:
578 return state == QIcon::On ? SelectedOnIconMask : SelectedOffIconMask;
579 case QIcon::Normal:
580 break;
581 }
582 return state == QIcon::On ? NormalOnIconMask : NormalOffIconMask;
583 }
584
585 static inline QPair<QIcon::Mode, QIcon::State> subPropertyFlagToIconModeState(unsigned flag)
586 {
587 switch (flag) {
588 case NormalOnIconMask:
589 return qMakePair(x: QIcon::Normal, y: QIcon::On);
590 case DisabledOffIconMask:
591 return qMakePair(x: QIcon::Disabled, y: QIcon::Off);
592 case DisabledOnIconMask:
593 return qMakePair(x: QIcon::Disabled, y: QIcon::On);
594 case ActiveOffIconMask:
595 return qMakePair(x: QIcon::Active, y: QIcon::Off);
596 case ActiveOnIconMask:
597 return qMakePair(x: QIcon::Active, y: QIcon::On);
598 case SelectedOffIconMask:
599 return qMakePair(x: QIcon::Selected, y: QIcon::Off);
600 case SelectedOnIconMask:
601 return qMakePair(x: QIcon::Selected, y: QIcon::On);
602 case NormalOffIconMask:
603 default:
604 break;
605 }
606 return qMakePair(x: QIcon::Normal, y: QIcon::Off);
607 }
608
609 uint PropertySheetIconValue::mask() const
610 {
611 uint flags = 0;
612 for (auto it = m_data->m_paths.constBegin(), cend = m_data->m_paths.constEnd(); it != cend; ++it)
613 flags |= iconStateToSubPropertyFlag(mode: it.key().first, state: it.key().second);
614 if (!m_data->m_theme.isEmpty())
615 flags |= ThemeIconMask;
616 return flags;
617 }
618
619 uint PropertySheetIconValue::compare(const PropertySheetIconValue &other) const
620 {
621 uint diffMask = mask() | other.mask();
622 for (int i = 0; i < 8; i++) {
623 const uint flag = 1 << i;
624 if (diffMask & flag) { // if state is set in both icons, compare the values
625 const QPair<QIcon::Mode, QIcon::State> state = subPropertyFlagToIconModeState(flag);
626 if (pixmap(mode: state.first, state: state.second) == other.pixmap(mode: state.first, state: state.second))
627 diffMask &= ~flag;
628 }
629 }
630 if ((diffMask & ThemeIconMask) && theme() == other.theme())
631 diffMask &= ~ThemeIconMask;
632 return diffMask;
633 }
634
635 PropertySheetIconValue PropertySheetIconValue::themed() const
636 {
637 PropertySheetIconValue rc(*this);
638 rc.m_data->m_paths.clear();
639 return rc;
640 }
641
642 PropertySheetIconValue PropertySheetIconValue::unthemed() const
643 {
644 PropertySheetIconValue rc(*this);
645 rc.m_data->m_theme.clear();
646 return rc;
647 }
648
649 void PropertySheetIconValue::assign(const PropertySheetIconValue &other, uint mask)
650 {
651 for (int i = 0; i < 8; i++) {
652 uint flag = 1 << i;
653 if (mask & flag) {
654 const ModeStateKey state = subPropertyFlagToIconModeState(flag);
655 setPixmap(mode: state.first, state: state.second, pixmap: other.pixmap(mode: state.first, state: state.second));
656 }
657 }
658 if (mask & ThemeIconMask)
659 setTheme(other.theme());
660 }
661
662 const PropertySheetIconValue::ModeStateToPixmapMap &PropertySheetIconValue::paths() const
663 {
664 return m_data->m_paths;
665 }
666
667 QDESIGNER_SHARED_EXPORT QDebug operator<<(QDebug d, const PropertySheetIconValue &p)
668 {
669 QDebug nospace = d.nospace();
670 nospace << "PropertySheetIconValue theme='" << p.theme() << "' ";
671
672 const PropertySheetIconValue::ModeStateToPixmapMap &paths = p.paths();
673 for (auto it = paths.constBegin(), cend = paths.constEnd(); it != cend; ++it)
674 nospace << " mode=" << it.key().first << ",state=" << it.key().second
675 << ",'" << it.value().path() << '\'';
676 nospace << " mask=0x" << QString::number(p.mask(), base: 16);
677 return d;
678 }
679
680 QDESIGNER_SHARED_EXPORT QDesignerFormWindowCommand *createTextPropertyCommand(const QString &propertyName, const QString &text, QObject *object, QDesignerFormWindowInterface *fw)
681 {
682 if (text.isEmpty()) {
683 ResetPropertyCommand *cmd = new ResetPropertyCommand(fw);
684 cmd->init(object, propertyName);
685 return cmd;
686 }
687 SetPropertyCommand *cmd = new SetPropertyCommand(fw);
688 cmd->init(object, propertyName, newValue: text);
689 return cmd;
690 }
691
692 QDESIGNER_SHARED_EXPORT QAction *preferredEditAction(QDesignerFormEditorInterface *core, QWidget *managedWidget)
693 {
694 QAction *action = nullptr;
695 if (const QDesignerTaskMenuExtension *taskMenu = qt_extension<QDesignerTaskMenuExtension*>(manager: core->extensionManager(), object: managedWidget)) {
696 action = taskMenu->preferredEditAction();
697 if (!action) {
698 const auto actions = taskMenu->taskActions();
699 if (!actions.isEmpty())
700 action = actions.first();
701 }
702 }
703 if (!action) {
704 if (const QDesignerTaskMenuExtension *taskMenu = qobject_cast<QDesignerTaskMenuExtension *>(
705 object: core->extensionManager()->extension(object: managedWidget, QStringLiteral("QDesignerInternalTaskMenuExtension")))) {
706 action = taskMenu->preferredEditAction();
707 if (!action) {
708 const auto actions = taskMenu->taskActions();
709 if (!actions.isEmpty())
710 action = actions.first();
711 }
712 }
713 }
714 return action;
715 }
716
717 QDESIGNER_SHARED_EXPORT bool runUIC(const QString &fileName, UicLanguage language,
718 QByteArray& ba, QString &errorMessage)
719 {
720 QProcess uic;
721 QStringList arguments;
722 QString binary = QLibraryInfo::location(QLibraryInfo::BinariesPath) + QStringLiteral("/uic");
723 switch (language) {
724 case UicLanguage::Cpp:
725 break;
726 case UicLanguage::Python:
727 arguments << QLatin1String("-g") << QLatin1String("python");
728 break;
729 }
730 arguments << fileName;
731
732 uic.start(program: binary, arguments);
733 if (!uic.waitForStarted()) {
734 errorMessage = QApplication::translate(context: "Designer", key: "Unable to launch %1: %2").
735 arg(args: QDir::toNativeSeparators(pathName: binary), args: uic.errorString());
736 return false;
737 }
738 if (!uic.waitForFinished()) {
739 errorMessage = QApplication::translate(context: "Designer", key: "%1 timed out.").arg(a: binary);
740 return false;
741 }
742 if (uic.exitCode()) {
743 errorMessage = QString::fromLatin1(str: uic.readAllStandardError());
744 return false;
745 }
746 ba = uic.readAllStandardOutput();
747 return true;
748 }
749
750 QDESIGNER_SHARED_EXPORT QString qtify(const QString &name)
751 {
752 QString qname = name;
753
754 Q_ASSERT(qname.isEmpty() == false);
755
756
757 if (qname.count() > 1 && qname.at(i: 1).isUpper()) {
758 const QChar first = qname.at(i: 0);
759 if (first == QLatin1Char('Q') || first == QLatin1Char('K'))
760 qname.remove(i: 0, len: 1);
761 }
762
763 const int len = qname.count();
764 for (int i = 0; i < len && qname.at(i).isUpper(); i++)
765 qname[i] = qname.at(i).toLower();
766
767 return qname;
768 }
769
770 // --------------- UpdateBlocker
771 UpdateBlocker::UpdateBlocker(QWidget *w) :
772 m_widget(w),
773 m_enabled(w->updatesEnabled() && w->isVisible())
774 {
775 if (m_enabled)
776 m_widget->setUpdatesEnabled(false);
777 }
778
779 UpdateBlocker::~UpdateBlocker()
780 {
781 if (m_enabled)
782 m_widget->setUpdatesEnabled(true);
783 }
784
785} // namespace qdesigner_internal
786
787QT_END_NAMESPACE
788

source code of qttools/src/designer/src/lib/shared/qdesigner_utils.cpp