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 56 QT_BEGIN_NAMESPACE 57 58 namespace qdesigner_internal 59 { designerWarning(const QString & message)60 QDESIGNER_SHARED_EXPORT void designerWarning(const QString &message) 61 { 62 qWarning("Designer: %s", qPrintable(message)); 63 } 64 reloadTreeItem(DesignerIconCache * iconCache,QTreeWidgetItem * item)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(c, Qt::DecorationPropertyRole); 72 if (v.canConvert<PropertySheetIconValue>()) 73 item->setIcon(c, iconCache->icon(qvariant_cast<PropertySheetIconValue>(v))); 74 } 75 } 76 reloadListItem(DesignerIconCache * iconCache,QListWidgetItem * item)77 void reloadListItem(DesignerIconCache *iconCache, QListWidgetItem *item) 78 { 79 if (!item) 80 return; 81 82 const QVariant v = item->data(Qt::DecorationPropertyRole); 83 if (v.canConvert<PropertySheetIconValue>()) 84 item->setIcon(iconCache->icon(qvariant_cast<PropertySheetIconValue>(v))); 85 } 86 reloadTableItem(DesignerIconCache * iconCache,QTableWidgetItem * item)87 void reloadTableItem(DesignerIconCache *iconCache, QTableWidgetItem *item) 88 { 89 if (!item) 90 return; 91 92 const QVariant v = item->data(Qt::DecorationPropertyRole); 93 if (v.canConvert<PropertySheetIconValue>()) 94 item->setIcon(iconCache->icon(qvariant_cast<PropertySheetIconValue>(v))); 95 } 96 reloadIconResources(DesignerIconCache * iconCache,QObject * object)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, listWidget->item(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(i, Qt::DecorationPropertyRole); 105 if (v.canConvert<PropertySheetIconValue>()) { 106 QIcon icon = iconCache->icon(qvariant_cast<PropertySheetIconValue>(v)); 107 comboBox->setItemIcon(i, icon); 108 comboBox->setItemData(i, icon); 109 } 110 } 111 } else if (QTreeWidget *treeWidget = qobject_cast<QTreeWidget *>(object)) { 112 reloadTreeItem(iconCache, treeWidget->headerItem()); 113 QQueue<QTreeWidgetItem *> itemsQueue; 114 for (int i = 0; i < treeWidget->topLevelItemCount(); i++) 115 itemsQueue.enqueue(treeWidget->topLevelItem(i)); 116 while (!itemsQueue.isEmpty()) { 117 QTreeWidgetItem *item = itemsQueue.dequeue(); 118 for (int i = 0; i < item->childCount(); i++) 119 itemsQueue.enqueue(item->child(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, tableWidget->horizontalHeaderItem(c)); 127 for (int r = 0; r < rowCount; r++) 128 reloadTableItem(iconCache, tableWidget->verticalHeaderItem(r)); 129 for (int c = 0; c < columnCount; c++) 130 for (int r = 0; r < rowCount; r++) 131 reloadTableItem(iconCache, tableWidget->item(r, c)); 132 } 133 } 134 135 // ------------- DesignerMetaEnum DesignerMetaEnum(const QString & name,const QString & scope,const QString & separator)136 DesignerMetaEnum::DesignerMetaEnum(const QString &name, const QString &scope, const QString &separator) : 137 MetaEnum<int>(name, scope, separator) 138 { 139 } 140 141 toString(int value,SerializationMode sm,bool * ok) const142 QString DesignerMetaEnum::toString(int value, SerializationMode sm, bool *ok) const 143 { 144 // find value 145 bool valueOk; 146 const QString item = valueToKey(value, &valueOk); 147 if (ok) 148 *ok = valueOk; 149 150 if (!valueOk || sm == NameOnly) 151 return item; 152 153 QString qualifiedItem; 154 appendQualifiedName(item, qualifiedItem); 155 return qualifiedItem; 156 } 157 messageToStringFailed(int value) const158 QString DesignerMetaEnum::messageToStringFailed(int value) const 159 { 160 return QCoreApplication::translate("DesignerMetaEnum", 161 "%1 is not a valid enumeration value of '%2'.") 162 .arg(value).arg(name()); 163 } 164 messageParseFailed(const QString & s) const165 QString DesignerMetaEnum::messageParseFailed(const QString &s) const 166 { 167 return QCoreApplication::translate("DesignerMetaEnum", 168 "'%1' could not be converted to an enumeration value of type '%2'.") 169 .arg(s, name()); 170 } 171 // -------------- DesignerMetaFlags DesignerMetaFlags(const QString & name,const QString & scope,const QString & separator)172 DesignerMetaFlags::DesignerMetaFlags(const QString &name, const QString &scope, const QString &separator) : 173 MetaEnum<uint>(name, scope, separator) 174 { 175 } 176 flags(int ivalue) const177 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(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(it.key()); 193 } 194 return rc; 195 } 196 197 toString(int value,SerializationMode sm) const198 QString DesignerMetaFlags::toString(int value, SerializationMode sm) const 199 { 200 const QStringList flagIds = flags(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(*it, rc); 212 else 213 rc += *it; 214 } 215 return rc; 216 } 217 218 parseFlags(const QString & s,bool * ok) const219 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(QString(QLatin1Char('|'))); 229 for (auto it = keys.constBegin(), cend = keys.constEnd(); it != cend; ++it) { 230 const uint flagValue = keyToValue(*it, &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 messageParseFailed(const QString & s) const242 QString DesignerMetaFlags::messageParseFailed(const QString &s) const 243 { 244 return QCoreApplication::translate("DesignerMetaFlags", 245 "'%1' could not be converted to a flag value of type '%2'.") 246 .arg(s, name()); 247 } 248 249 // ---------- PropertySheetEnumValue 250 PropertySheetEnumValue(int v,const DesignerMetaEnum & me)251 PropertySheetEnumValue::PropertySheetEnumValue(int v, const DesignerMetaEnum &me) : 252 value(v), 253 metaEnum(me) 254 { 255 } 256 257 PropertySheetEnumValue::PropertySheetEnumValue() = default; 258 259 // ---------------- PropertySheetFlagValue PropertySheetFlagValue(int v,const DesignerMetaFlags & mf)260 PropertySheetFlagValue::PropertySheetFlagValue(int v, const DesignerMetaFlags &mf) : 261 value(v), 262 metaFlags(mf) 263 { 264 } 265 266 PropertySheetFlagValue::PropertySheetFlagValue() = default; 267 268 // ---------------- PropertySheetPixmapValue PropertySheetPixmapValue(const QString & path)269 PropertySheetPixmapValue::PropertySheetPixmapValue(const QString &path) : m_path(path) 270 { 271 } 272 273 PropertySheetPixmapValue::PropertySheetPixmapValue() = default; 274 getPixmapSource(QDesignerFormEditorInterface * core,const QString & path)275 PropertySheetPixmapValue::PixmapSource PropertySheetPixmapValue::getPixmapSource(QDesignerFormEditorInterface *core, const QString & path) 276 { 277 if (const QDesignerLanguageExtension *lang = qt_extension<QDesignerLanguageExtension *>(core->extensionManager(), core)) 278 return lang->isLanguageResource(path) ? LanguageResourcePixmap : FilePixmap; 279 return path.startsWith(QLatin1Char(':')) ? ResourcePixmap : FilePixmap; 280 } 281 compare(const PropertySheetPixmapValue & other) const282 int PropertySheetPixmapValue::compare(const PropertySheetPixmapValue &other) const 283 { 284 return m_path.compare(other.m_path); 285 } 286 path() const287 QString PropertySheetPixmapValue::path() const 288 { 289 return m_path; 290 } 291 setPath(const QString & path)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 PropertySheetIconValue(const PropertySheetPixmapValue & pixmap)307 PropertySheetIconValue::PropertySheetIconValue(const PropertySheetPixmapValue &pixmap) : 308 m_data(new PropertySheetIconValueData) 309 { 310 setPixmap(QIcon::Normal, QIcon::Off, pixmap); 311 } 312 PropertySheetIconValue()313 PropertySheetIconValue::PropertySheetIconValue() : 314 m_data(new PropertySheetIconValueData) 315 { 316 } 317 318 PropertySheetIconValue::~PropertySheetIconValue() = default; 319 PropertySheetIconValue(const PropertySheetIconValue & rhs)320 PropertySheetIconValue::PropertySheetIconValue(const PropertySheetIconValue &rhs) : 321 m_data(rhs.m_data) 322 { 323 } 324 operator =(const PropertySheetIconValue & rhs)325 PropertySheetIconValue &PropertySheetIconValue::operator=(const PropertySheetIconValue &rhs) 326 { 327 if (this != &rhs) 328 m_data.operator=(rhs.m_data); 329 return *this; 330 } 331 equals(const PropertySheetIconValue & rhs) const332 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 operator <(const PropertySheetIconValue & other) const337 bool PropertySheetIconValue::operator<(const PropertySheetIconValue &other) const 338 { 339 if (const int themeCmp = m_data->m_theme.compare(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(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 isEmpty() const363 bool PropertySheetIconValue::isEmpty() const 364 { 365 return m_data->m_theme.isEmpty() && m_data->m_paths.isEmpty(); 366 } 367 theme() const368 QString PropertySheetIconValue::theme() const 369 { 370 return m_data->m_theme; 371 } 372 setTheme(const QString & t)373 void PropertySheetIconValue::setTheme(const QString &t) 374 { 375 m_data->m_theme = t; 376 } 377 pixmap(QIcon::Mode mode,QIcon::State state) const378 PropertySheetPixmapValue PropertySheetIconValue::pixmap(QIcon::Mode mode, QIcon::State state) const 379 { 380 const ModeStateKey pair = qMakePair(mode, state); 381 return m_data->m_paths.value(pair); 382 } 383 setPixmap(QIcon::Mode mode,QIcon::State state,const PropertySheetPixmapValue & pixmap)384 void PropertySheetIconValue::setPixmap(QIcon::Mode mode, QIcon::State state, const PropertySheetPixmapValue &pixmap) 385 { 386 const ModeStateKey pair = qMakePair(mode, state); 387 if (pixmap.path().isEmpty()) 388 m_data->m_paths.remove(pair); 389 else 390 m_data->m_paths.insert(pair, pixmap); 391 } 392 pixmap(const PropertySheetPixmapValue & value) const393 QPixmap DesignerPixmapCache::pixmap(const PropertySheetPixmapValue &value) const 394 { 395 QMap<PropertySheetPixmapValue, QPixmap>::const_iterator it = m_cache.constFind(value); 396 if (it != m_cache.constEnd()) 397 return it.value(); 398 399 QPixmap pix = QPixmap(value.path()); 400 m_cache.insert(value, pix); 401 return pix; 402 } 403 clear()404 void DesignerPixmapCache::clear() 405 { 406 m_cache.clear(); 407 } 408 DesignerPixmapCache(QObject * parent)409 DesignerPixmapCache::DesignerPixmapCache(QObject *parent) 410 : QObject(parent) 411 { 412 } 413 icon(const PropertySheetIconValue & value) const414 QIcon DesignerIconCache::icon(const PropertySheetIconValue &value) const 415 { 416 const auto it = m_cache.constFind(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(theme)) { 424 const QIcon themeIcon = QIcon::fromTheme(theme); 425 m_cache.insert(value, 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(it.value().path(), QSize(), pair.first, pair.second); 435 } 436 m_cache.insert(value, icon); 437 return icon; 438 } 439 clear()440 void DesignerIconCache::clear() 441 { 442 m_cache.clear(); 443 } 444 DesignerIconCache(DesignerPixmapCache * pixmapCache,QObject * parent)445 DesignerIconCache::DesignerIconCache(DesignerPixmapCache *pixmapCache, QObject *parent) 446 : QObject(parent), 447 m_pixmapCache(pixmapCache) 448 { 449 450 } 451 PropertySheetTranslatableData(bool translatable,const QString & disambiguation,const QString & comment)452 PropertySheetTranslatableData::PropertySheetTranslatableData(bool translatable, const QString &disambiguation, const QString &comment) : 453 m_translatable(translatable), m_disambiguation(disambiguation), m_comment(comment) { } 454 equals(const PropertySheetTranslatableData & rhs) const455 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 PropertySheetStringValue(const QString & value,bool translatable,const QString & disambiguation,const QString & comment)463 PropertySheetStringValue::PropertySheetStringValue(const QString &value, 464 bool translatable, const QString &disambiguation, const QString &comment) : 465 PropertySheetTranslatableData(translatable, disambiguation, comment), m_value(value) {} 466 value() const467 QString PropertySheetStringValue::value() const 468 { 469 return m_value; 470 } 471 setValue(const QString & value)472 void PropertySheetStringValue::setValue(const QString &value) 473 { 474 m_value = value; 475 } 476 equals(const PropertySheetStringValue & rhs) const477 bool PropertySheetStringValue::equals(const PropertySheetStringValue &rhs) const 478 { 479 return m_value == rhs.m_value && PropertySheetTranslatableData::equals(rhs); 480 } 481 PropertySheetStringListValue(const QStringList & value,bool translatable,const QString & disambiguation,const QString & comment)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 value() const490 QStringList PropertySheetStringListValue::value() const 491 { 492 return m_value; 493 } 494 setValue(const QStringList & value)495 void PropertySheetStringListValue::setValue(const QStringList &value) 496 { 497 m_value = value; 498 } 499 equals(const PropertySheetStringListValue & rhs) const500 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 PropertySheetKeySequenceValue(const QKeySequence & value,bool translatable,const QString & disambiguation,const QString & comment)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 PropertySheetKeySequenceValue(const QKeySequence::StandardKey & standardKey,bool translatable,const QString & disambiguation,const QString & comment)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 value() const518 QKeySequence PropertySheetKeySequenceValue::value() const 519 { 520 return m_value; 521 } 522 setValue(const QKeySequence & value)523 void PropertySheetKeySequenceValue::setValue(const QKeySequence &value) 524 { 525 m_value = value; 526 m_standardKey = QKeySequence::UnknownKey; 527 } 528 standardKey() const529 QKeySequence::StandardKey PropertySheetKeySequenceValue::standardKey() const 530 { 531 return m_standardKey; 532 } 533 setStandardKey(const QKeySequence::StandardKey & standardKey)534 void PropertySheetKeySequenceValue::setStandardKey(const QKeySequence::StandardKey &standardKey) 535 { 536 m_value = QKeySequence(standardKey); 537 m_standardKey = standardKey; 538 } 539 isStandardKey() const540 bool PropertySheetKeySequenceValue::isStandardKey() const 541 { 542 return m_standardKey != QKeySequence::UnknownKey; 543 } 544 equals(const PropertySheetKeySequenceValue & rhs) const545 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 iconStateToSubPropertyFlag(QIcon::Mode mode,QIcon::State state)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 subPropertyFlagToIconModeState(unsigned flag)585 static inline QPair<QIcon::Mode, QIcon::State> subPropertyFlagToIconModeState(unsigned flag) 586 { 587 switch (flag) { 588 case NormalOnIconMask: 589 return qMakePair(QIcon::Normal, QIcon::On); 590 case DisabledOffIconMask: 591 return qMakePair(QIcon::Disabled, QIcon::Off); 592 case DisabledOnIconMask: 593 return qMakePair(QIcon::Disabled, QIcon::On); 594 case ActiveOffIconMask: 595 return qMakePair(QIcon::Active, QIcon::Off); 596 case ActiveOnIconMask: 597 return qMakePair(QIcon::Active, QIcon::On); 598 case SelectedOffIconMask: 599 return qMakePair(QIcon::Selected, QIcon::Off); 600 case SelectedOnIconMask: 601 return qMakePair(QIcon::Selected, QIcon::On); 602 case NormalOffIconMask: 603 default: 604 break; 605 } 606 return qMakePair(QIcon::Normal, QIcon::Off); 607 } 608 mask() const609 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(it.key().first, it.key().second); 614 if (!m_data->m_theme.isEmpty()) 615 flags |= ThemeIconMask; 616 return flags; 617 } 618 compare(const PropertySheetIconValue & other) const619 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(state.first, state.second) == other.pixmap(state.first, state.second)) 627 diffMask &= ~flag; 628 } 629 } 630 if ((diffMask & ThemeIconMask) && theme() == other.theme()) 631 diffMask &= ~ThemeIconMask; 632 return diffMask; 633 } 634 themed() const635 PropertySheetIconValue PropertySheetIconValue::themed() const 636 { 637 PropertySheetIconValue rc(*this); 638 rc.m_data->m_paths.clear(); 639 return rc; 640 } 641 unthemed() const642 PropertySheetIconValue PropertySheetIconValue::unthemed() const 643 { 644 PropertySheetIconValue rc(*this); 645 rc.m_data->m_theme.clear(); 646 return rc; 647 } 648 assign(const PropertySheetIconValue & other,uint mask)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(state.first, state.second, other.pixmap(state.first, state.second)); 656 } 657 } 658 if (mask & ThemeIconMask) 659 setTheme(other.theme()); 660 } 661 paths() const662 const PropertySheetIconValue::ModeStateToPixmapMap &PropertySheetIconValue::paths() const 663 { 664 return m_data->m_paths; 665 } 666 operator <<(QDebug d,const PropertySheetIconValue & p)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(), 16); 677 return d; 678 } 679 createTextPropertyCommand(const QString & propertyName,const QString & text,QObject * object,QDesignerFormWindowInterface * fw)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, text); 689 return cmd; 690 } 691 preferredEditAction(QDesignerFormEditorInterface * core,QWidget * managedWidget)692 QDESIGNER_SHARED_EXPORT QAction *preferredEditAction(QDesignerFormEditorInterface *core, QWidget *managedWidget) 693 { 694 QAction *action = nullptr; 695 if (const QDesignerTaskMenuExtension *taskMenu = qt_extension<QDesignerTaskMenuExtension*>(core->extensionManager(), 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 core->extensionManager()->extension(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 runUIC(const QString & fileName,UicLanguage language,QByteArray & ba,QString & errorMessage)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(binary, arguments); 733 if (!uic.waitForStarted()) { 734 errorMessage = QApplication::translate("Designer", "Unable to launch %1: %2"). 735 arg(QDir::toNativeSeparators(binary), uic.errorString()); 736 return false; 737 } 738 if (!uic.waitForFinished()) { 739 errorMessage = QApplication::translate("Designer", "%1 timed out.").arg(binary); 740 return false; 741 } 742 if (uic.exitCode()) { 743 errorMessage = QString::fromLatin1(uic.readAllStandardError()); 744 return false; 745 } 746 ba = uic.readAllStandardOutput(); 747 return true; 748 } 749 qtify(const QString & name)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(1).isUpper()) { 758 const QChar first = qname.at(0); 759 if (first == QLatin1Char('Q') || first == QLatin1Char('K')) 760 qname.remove(0, 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 UpdateBlocker(QWidget * w)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 ~UpdateBlocker()779 UpdateBlocker::~UpdateBlocker() 780 { 781 if (m_enabled) 782 m_widget->setUpdatesEnabled(true); 783 } 784 785 } // namespace qdesigner_internal 786 787 QT_END_NAMESPACE 788