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

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