1 /**************************************************************************** 2 ** 3 ** Copyright (C) 2015 The Qt Company Ltd. 4 ** Contact: http://www.qt.io/licensing/ 5 ** 6 ** This file is part of the Qt Designer of the Qt Toolkit. 7 ** 8 ** $QT_BEGIN_LICENSE:LGPL$ 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 http://www.qt.io/terms-conditions. For further 15 ** information use the contact form at http://www.qt.io/contact-us. 16 ** 17 ** GNU Lesser General Public License Usage 18 ** Alternatively, this file may be used under the terms of the GNU Lesser 19 ** General Public License version 2.1 or version 3 as published by the Free 20 ** Software Foundation and appearing in the file LICENSE.LGPLv21 and 21 ** LICENSE.LGPLv3 included in the packaging of this file. Please review the 22 ** following information to ensure the GNU Lesser General Public License 23 ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and 24 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. 25 ** 26 ** As a special exception, The Qt Company gives you certain additional 27 ** rights. These rights are described in The Qt Company LGPL Exception 28 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. 29 ** 30 ** GNU General Public License Usage 31 ** Alternatively, this file may be used under the terms of the GNU 32 ** General Public License version 3.0 as published by the Free Software 33 ** Foundation and appearing in the file LICENSE.GPL included in the 34 ** packaging of this file. Please review the following information to 35 ** ensure the GNU General Public License version 3.0 requirements will be 36 ** met: http://www.gnu.org/copyleft/gpl.html. 37 ** 38 ** $QT_END_LICENSE$ 39 ** 40 ****************************************************************************/ 41 42 #include "qdesigner_utils_p.h" 43 #include "qdesigner_propertycommand_p.h" 44 #include "abstractformbuilder.h" 45 #include "formwindowbase_p.h" 46 47 #include <QtDesigner/QDesignerFormEditorInterface> 48 #include <QtDesigner/QDesignerFormWindowInterface> 49 #include <QtDesigner/QDesignerIconCacheInterface> 50 #include <QtDesigner/QDesignerResourceBrowserInterface> 51 #include <QtDesigner/QDesignerLanguageExtension> 52 #include <QtDesigner/QDesignerTaskMenuExtension> 53 #include <QtDesigner/QExtensionManager> 54 55 #include <QtCore/QDir> 56 #include <QtCore/QProcess> 57 #include <QtCore/QLibraryInfo> 58 #include <QtCore/QDebug> 59 #include <QtCore/QQueue> 60 #include <QtCore/QSharedData> 61 62 #include <QtGui/QApplication> 63 #include <QtGui/QIcon> 64 #include <QtGui/QPixmap> 65 #include <QtGui/QListWidget> 66 #include <QtGui/QTreeWidget> 67 #include <QtGui/QTableWidget> 68 #include <QtGui/QComboBox> 69 70 QT_BEGIN_NAMESPACE 71 72 namespace qdesigner_internal 73 { designerWarning(const QString & message)74 QDESIGNER_SHARED_EXPORT void designerWarning(const QString &message) 75 { 76 qWarning("Designer: %s", qPrintable(message)); 77 } 78 reloadTreeItem(DesignerIconCache * iconCache,QTreeWidgetItem * item)79 void reloadTreeItem(DesignerIconCache *iconCache, QTreeWidgetItem *item) 80 { 81 if (!item) 82 return; 83 84 for (int c = 0; c < item->columnCount(); c++) { 85 const QVariant v = item->data(c, Qt::DecorationPropertyRole); 86 if (v.canConvert<PropertySheetIconValue>()) 87 item->setIcon(c, iconCache->icon(qvariant_cast<PropertySheetIconValue>(v))); 88 } 89 } 90 reloadListItem(DesignerIconCache * iconCache,QListWidgetItem * item)91 void reloadListItem(DesignerIconCache *iconCache, QListWidgetItem *item) 92 { 93 if (!item) 94 return; 95 96 const QVariant v = item->data(Qt::DecorationPropertyRole); 97 if (v.canConvert<PropertySheetIconValue>()) 98 item->setIcon(iconCache->icon(qvariant_cast<PropertySheetIconValue>(v))); 99 } 100 reloadTableItem(DesignerIconCache * iconCache,QTableWidgetItem * item)101 void reloadTableItem(DesignerIconCache *iconCache, QTableWidgetItem *item) 102 { 103 if (!item) 104 return; 105 106 const QVariant v = item->data(Qt::DecorationPropertyRole); 107 if (v.canConvert<PropertySheetIconValue>()) 108 item->setIcon(iconCache->icon(qvariant_cast<PropertySheetIconValue>(v))); 109 } 110 reloadIconResources(DesignerIconCache * iconCache,QObject * object)111 void reloadIconResources(DesignerIconCache *iconCache, QObject *object) 112 { 113 if (QListWidget *listWidget = qobject_cast<QListWidget *>(object)) { 114 for (int i = 0; i < listWidget->count(); i++) 115 reloadListItem(iconCache, listWidget->item(i)); 116 } else if (QComboBox *comboBox = qobject_cast<QComboBox *>(object)) { 117 for (int i = 0; i < comboBox->count(); i++) { 118 const QVariant v = comboBox->itemData(i, Qt::DecorationPropertyRole); 119 if (v.canConvert<PropertySheetIconValue>()) { 120 QIcon icon = iconCache->icon(qvariant_cast<PropertySheetIconValue>(v)); 121 comboBox->setItemIcon(i, icon); 122 comboBox->setItemData(i, icon); 123 } 124 } 125 } else if (QTreeWidget *treeWidget = qobject_cast<QTreeWidget *>(object)) { 126 reloadTreeItem(iconCache, treeWidget->headerItem()); 127 QQueue<QTreeWidgetItem *> itemsQueue; 128 for (int i = 0; i < treeWidget->topLevelItemCount(); i++) 129 itemsQueue.enqueue(treeWidget->topLevelItem(i)); 130 while (!itemsQueue.isEmpty()) { 131 QTreeWidgetItem *item = itemsQueue.dequeue(); 132 for (int i = 0; i < item->childCount(); i++) 133 itemsQueue.enqueue(item->child(i)); 134 reloadTreeItem(iconCache, item); 135 } 136 } else if (QTableWidget *tableWidget = qobject_cast<QTableWidget *>(object)) { 137 const int columnCount = tableWidget->columnCount(); 138 const int rowCount = tableWidget->rowCount(); 139 for (int c = 0; c < columnCount; c++) 140 reloadTableItem(iconCache, tableWidget->horizontalHeaderItem(c)); 141 for (int r = 0; r < rowCount; r++) 142 reloadTableItem(iconCache, tableWidget->verticalHeaderItem(r)); 143 for (int c = 0; c < columnCount; c++) 144 for (int r = 0; r < rowCount; r++) 145 reloadTableItem(iconCache, tableWidget->item(r, c)); 146 } 147 } 148 149 // ------------- DesignerMetaEnum DesignerMetaEnum(const QString & name,const QString & scope,const QString & separator)150 DesignerMetaEnum::DesignerMetaEnum(const QString &name, const QString &scope, const QString &separator) : 151 MetaEnum<int>(name, scope, separator) 152 { 153 } 154 155 toString(int value,SerializationMode sm,bool * ok) const156 QString DesignerMetaEnum::toString(int value, SerializationMode sm, bool *ok) const 157 { 158 // find value 159 bool valueOk; 160 const QString item = valueToKey(value, &valueOk); 161 if (ok) 162 *ok = valueOk; 163 164 if (!valueOk || sm == NameOnly) 165 return item; 166 167 QString qualifiedItem; 168 appendQualifiedName(item, qualifiedItem); 169 return qualifiedItem; 170 } 171 messageToStringFailed(int value) const172 QString DesignerMetaEnum::messageToStringFailed(int value) const 173 { 174 return QCoreApplication::translate("DesignerMetaEnum", "%1 is not a valid enumeration value of '%2'.").arg(value).arg(name()); 175 } 176 messageParseFailed(const QString & s) const177 QString DesignerMetaEnum::messageParseFailed(const QString &s) const 178 { 179 return QCoreApplication::translate("DesignerMetaEnum", "'%1' could not be converted to an enumeration value of type '%2'.").arg(s).arg(name()); 180 } 181 // -------------- DesignerMetaFlags DesignerMetaFlags(const QString & name,const QString & scope,const QString & separator)182 DesignerMetaFlags::DesignerMetaFlags(const QString &name, const QString &scope, const QString &separator) : 183 MetaEnum<uint>(name, scope, separator) 184 { 185 } 186 flags(int ivalue) const187 QStringList DesignerMetaFlags::flags(int ivalue) const 188 { 189 typedef MetaEnum<uint>::KeyToValueMap::const_iterator KeyToValueMapIterator; 190 QStringList rc; 191 const uint v = static_cast<uint>(ivalue); 192 const KeyToValueMapIterator cend = keyToValueMap().constEnd(); 193 for (KeyToValueMapIterator it = keyToValueMap().constBegin();it != cend; ++it ) { 194 const uint itemValue = it.value(); 195 // Check for equality first as flag values can be 0 or -1, too. Takes preference over a bitwise flag 196 if (v == itemValue) { 197 rc.clear(); 198 rc.push_back(it.key()); 199 return rc; 200 } 201 // Do not add 0-flags (None-flags) 202 if (itemValue) 203 if ((v & itemValue) == itemValue) 204 rc.push_back(it.key()); 205 } 206 return rc; 207 } 208 209 toString(int value,SerializationMode sm) const210 QString DesignerMetaFlags::toString(int value, SerializationMode sm) const 211 { 212 const QStringList flagIds = flags(value); 213 if (flagIds.empty()) 214 return QString(); 215 216 const QChar delimiter = QLatin1Char('|'); 217 QString rc; 218 const QStringList::const_iterator cend = flagIds.constEnd(); 219 for (QStringList::const_iterator it = flagIds.constBegin(); it != cend; ++it) { 220 if (!rc.isEmpty()) 221 rc += delimiter ; 222 if (sm == FullyQualified) 223 appendQualifiedName(*it, rc); 224 else 225 rc += *it; 226 } 227 return rc; 228 } 229 230 parseFlags(const QString & s,bool * ok) const231 int DesignerMetaFlags::parseFlags(const QString &s, bool *ok) const 232 { 233 if (s.isEmpty()) { 234 if (ok) 235 *ok = true; 236 return 0; 237 } 238 uint flags = 0; 239 bool valueOk = true; 240 QStringList keys = s.split(QString(QLatin1Char('|'))); 241 const QStringList::iterator cend = keys.end(); 242 for (QStringList::iterator it = keys.begin(); it != cend; ++it) { 243 const uint flagValue = keyToValue(*it, &valueOk); 244 if (!valueOk) { 245 flags = 0; 246 break; 247 } 248 flags |= flagValue; 249 } 250 if (ok) 251 *ok = valueOk; 252 return static_cast<int>(flags); 253 } 254 messageParseFailed(const QString & s) const255 QString DesignerMetaFlags::messageParseFailed(const QString &s) const 256 { 257 return QCoreApplication::translate("DesignerMetaFlags", "'%1' could not be converted to a flag value of type '%2'.").arg(s).arg(name()); 258 } 259 260 // ---------- PropertySheetEnumValue 261 PropertySheetEnumValue(int v,const DesignerMetaEnum & me)262 PropertySheetEnumValue::PropertySheetEnumValue(int v, const DesignerMetaEnum &me) : 263 value(v), 264 metaEnum(me) 265 { 266 } PropertySheetEnumValue()267 PropertySheetEnumValue::PropertySheetEnumValue() : 268 value(0) 269 { 270 } 271 272 // ---------------- PropertySheetFlagValue PropertySheetFlagValue(int v,const DesignerMetaFlags & mf)273 PropertySheetFlagValue::PropertySheetFlagValue(int v, const DesignerMetaFlags &mf) : 274 value(v), 275 metaFlags(mf) 276 { 277 } 278 PropertySheetFlagValue()279 PropertySheetFlagValue::PropertySheetFlagValue() : 280 value(0) 281 { 282 } 283 284 // ---------------- PropertySheetPixmapValue PropertySheetPixmapValue(const QString & path)285 PropertySheetPixmapValue::PropertySheetPixmapValue(const QString &path) : m_path(path) 286 { 287 } 288 PropertySheetPixmapValue()289 PropertySheetPixmapValue::PropertySheetPixmapValue() 290 { 291 } 292 getPixmapSource(QDesignerFormEditorInterface * core,const QString & path)293 PropertySheetPixmapValue::PixmapSource PropertySheetPixmapValue::getPixmapSource(QDesignerFormEditorInterface *core, const QString & path) 294 { 295 if (const QDesignerLanguageExtension *lang = qt_extension<QDesignerLanguageExtension *>(core->extensionManager(), core)) 296 return lang->isLanguageResource(path) ? LanguageResourcePixmap : FilePixmap; 297 return path.startsWith(QLatin1Char(':')) ? ResourcePixmap : FilePixmap; 298 } 299 compare(const PropertySheetPixmapValue & other) const300 int PropertySheetPixmapValue::compare(const PropertySheetPixmapValue &other) const 301 { 302 return m_path.compare(other.m_path); 303 } 304 path() const305 QString PropertySheetPixmapValue::path() const 306 { 307 return m_path; 308 } 309 setPath(const QString & path)310 void PropertySheetPixmapValue::setPath(const QString &path) 311 { 312 if (m_path == path) 313 return; 314 m_path = path; 315 } 316 317 // ---------- PropertySheetIconValue 318 319 class PropertySheetIconValueData : public QSharedData { 320 public: 321 PropertySheetIconValue::ModeStateToPixmapMap m_paths; 322 QString m_theme; 323 }; 324 PropertySheetIconValue(const PropertySheetPixmapValue & pixmap)325 PropertySheetIconValue::PropertySheetIconValue(const PropertySheetPixmapValue &pixmap) : 326 m_data(new PropertySheetIconValueData) 327 { 328 setPixmap(QIcon::Normal, QIcon::Off, pixmap); 329 } 330 PropertySheetIconValue()331 PropertySheetIconValue::PropertySheetIconValue() : 332 m_data(new PropertySheetIconValueData) 333 { 334 } 335 ~PropertySheetIconValue()336 PropertySheetIconValue::~PropertySheetIconValue() 337 { 338 } 339 PropertySheetIconValue(const PropertySheetIconValue & rhs)340 PropertySheetIconValue::PropertySheetIconValue(const PropertySheetIconValue &rhs) : 341 m_data(rhs.m_data) 342 { 343 } 344 operator =(const PropertySheetIconValue & rhs)345 PropertySheetIconValue &PropertySheetIconValue::operator=(const PropertySheetIconValue &rhs) 346 { 347 if (this != &rhs) 348 m_data.operator=(rhs.m_data); 349 return *this; 350 } 351 equals(const PropertySheetIconValue & rhs) const352 bool PropertySheetIconValue::equals(const PropertySheetIconValue &rhs) const 353 { 354 return m_data->m_theme == rhs.m_data->m_theme && m_data->m_paths == rhs.m_data->m_paths; 355 } 356 operator <(const PropertySheetIconValue & other) const357 bool PropertySheetIconValue::operator<(const PropertySheetIconValue &other) const 358 { 359 if (const int themeCmp = m_data->m_theme.compare(other.m_data->m_theme)) 360 return themeCmp < 0; 361 QMapIterator<ModeStateKey, PropertySheetPixmapValue> itThis(m_data->m_paths); 362 QMapIterator<ModeStateKey, PropertySheetPixmapValue> itOther(other.m_data->m_paths); 363 while (itThis.hasNext() && itOther.hasNext()) { 364 const ModeStateKey thisPair = itThis.next().key(); 365 const ModeStateKey otherPair = itOther.next().key(); 366 if (thisPair < otherPair) 367 return true; 368 else if (otherPair < thisPair) 369 return false; 370 const int crc = itThis.value().compare(itOther.value()); 371 if (crc < 0) 372 return true; 373 if (crc > 0) 374 return false; 375 } 376 if (itOther.hasNext()) 377 return true; 378 return false; 379 } 380 isEmpty() const381 bool PropertySheetIconValue::isEmpty() const 382 { 383 return m_data->m_theme.isEmpty() && m_data->m_paths.isEmpty(); 384 } 385 theme() const386 QString PropertySheetIconValue::theme() const 387 { 388 return m_data->m_theme; 389 } 390 setTheme(const QString & t)391 void PropertySheetIconValue::setTheme(const QString &t) 392 { 393 m_data->m_theme = t; 394 } 395 pixmap(QIcon::Mode mode,QIcon::State state) const396 PropertySheetPixmapValue PropertySheetIconValue::pixmap(QIcon::Mode mode, QIcon::State state) const 397 { 398 const ModeStateKey pair = qMakePair(mode, state); 399 return m_data->m_paths.value(pair); 400 } 401 setPixmap(QIcon::Mode mode,QIcon::State state,const PropertySheetPixmapValue & pixmap)402 void PropertySheetIconValue::setPixmap(QIcon::Mode mode, QIcon::State state, const PropertySheetPixmapValue &pixmap) 403 { 404 const ModeStateKey pair = qMakePair(mode, state); 405 if (pixmap.path().isEmpty()) 406 m_data->m_paths.remove(pair); 407 else 408 m_data->m_paths.insert(pair, pixmap); 409 } 410 pixmap(const PropertySheetPixmapValue & value) const411 QPixmap DesignerPixmapCache::pixmap(const PropertySheetPixmapValue &value) const 412 { 413 QMap<PropertySheetPixmapValue, QPixmap>::const_iterator it = m_cache.constFind(value); 414 if (it != m_cache.constEnd()) 415 return it.value(); 416 417 QPixmap pix = QPixmap(value.path()); 418 m_cache.insert(value, pix); 419 return pix; 420 } 421 clear()422 void DesignerPixmapCache::clear() 423 { 424 m_cache.clear(); 425 } 426 DesignerPixmapCache(QObject * parent)427 DesignerPixmapCache::DesignerPixmapCache(QObject *parent) 428 : QObject(parent) 429 { 430 } 431 icon(const PropertySheetIconValue & value) const432 QIcon DesignerIconCache::icon(const PropertySheetIconValue &value) const 433 { 434 typedef PropertySheetIconValue::ModeStateToPixmapMap::const_iterator ModeStateToPixmapMapConstIt; 435 436 QMap<PropertySheetIconValue, QIcon>::const_iterator it = m_cache.constFind(value); 437 if (it != m_cache.constEnd()) 438 return it.value(); 439 440 // Match on the theme first if it is available. 441 if (!value.theme().isEmpty()) { 442 const QString theme = value.theme(); 443 if (QIcon::hasThemeIcon(theme)) { 444 const QIcon themeIcon = QIcon::fromTheme(theme); 445 m_cache.insert(value, themeIcon); 446 return themeIcon; 447 } 448 } 449 450 QIcon icon; 451 const PropertySheetIconValue::ModeStateToPixmapMap &paths = value.paths(); 452 const ModeStateToPixmapMapConstIt cend = paths.constEnd(); 453 for (ModeStateToPixmapMapConstIt it = paths.constBegin(); it != cend; ++it) { 454 const QPair<QIcon::Mode, QIcon::State> pair = it.key(); 455 icon.addFile(it.value().path(), QSize(), pair.first, pair.second); 456 } 457 m_cache.insert(value, icon); 458 return icon; 459 } 460 clear()461 void DesignerIconCache::clear() 462 { 463 m_cache.clear(); 464 } 465 DesignerIconCache(DesignerPixmapCache * pixmapCache,QObject * parent)466 DesignerIconCache::DesignerIconCache(DesignerPixmapCache *pixmapCache, QObject *parent) 467 : QObject(parent), 468 m_pixmapCache(pixmapCache) 469 { 470 471 } 472 PropertySheetStringValue(const QString & value,bool translatable,const QString & disambiguation,const QString & comment)473 PropertySheetStringValue::PropertySheetStringValue(const QString &value, 474 bool translatable, const QString &disambiguation, const QString &comment) 475 : m_value(value), m_translatable(translatable), m_disambiguation(disambiguation), m_comment(comment) 476 { } 477 value() const478 QString PropertySheetStringValue::value() const 479 { 480 return m_value; 481 } 482 setValue(const QString & value)483 void PropertySheetStringValue::setValue(const QString &value) 484 { 485 m_value = value; 486 } 487 translatable() const488 bool PropertySheetStringValue::translatable() const 489 { 490 return m_translatable; 491 } 492 setTranslatable(bool translatable)493 void PropertySheetStringValue::setTranslatable(bool translatable) 494 { 495 m_translatable = translatable; 496 } 497 disambiguation() const498 QString PropertySheetStringValue::disambiguation() const 499 { 500 return m_disambiguation; 501 } 502 setDisambiguation(const QString & disambiguation)503 void PropertySheetStringValue::setDisambiguation(const QString &disambiguation) 504 { 505 m_disambiguation = disambiguation; 506 } 507 comment() const508 QString PropertySheetStringValue::comment() const 509 { 510 return m_comment; 511 } 512 setComment(const QString & comment)513 void PropertySheetStringValue::setComment(const QString &comment) 514 { 515 m_comment = comment; 516 } 517 equals(const PropertySheetStringValue & rhs) const518 bool PropertySheetStringValue::equals(const PropertySheetStringValue &rhs) const 519 { 520 return (m_value == rhs.m_value) && (m_translatable == rhs.m_translatable) 521 && (m_disambiguation == rhs.m_disambiguation) && (m_comment == rhs.m_comment); 522 } 523 PropertySheetKeySequenceValue(const QKeySequence & value,bool translatable,const QString & disambiguation,const QString & comment)524 PropertySheetKeySequenceValue::PropertySheetKeySequenceValue(const QKeySequence &value, 525 bool translatable, const QString &disambiguation, const QString &comment) 526 : m_value(value), 527 m_standardKey(QKeySequence::UnknownKey), 528 m_translatable(translatable), 529 m_disambiguation(disambiguation), 530 m_comment(comment) 531 { } 532 PropertySheetKeySequenceValue(const QKeySequence::StandardKey & standardKey,bool translatable,const QString & disambiguation,const QString & comment)533 PropertySheetKeySequenceValue::PropertySheetKeySequenceValue(const QKeySequence::StandardKey &standardKey, 534 bool translatable, const QString &disambiguation, const QString &comment) 535 : m_value(QKeySequence(standardKey)), 536 m_standardKey(standardKey), 537 m_translatable(translatable), 538 m_disambiguation(disambiguation), 539 m_comment(comment) 540 { } 541 value() const542 QKeySequence PropertySheetKeySequenceValue::value() const 543 { 544 return m_value; 545 } 546 setValue(const QKeySequence & value)547 void PropertySheetKeySequenceValue::setValue(const QKeySequence &value) 548 { 549 m_value = value; 550 m_standardKey = QKeySequence::UnknownKey; 551 } 552 standardKey() const553 QKeySequence::StandardKey PropertySheetKeySequenceValue::standardKey() const 554 { 555 return m_standardKey; 556 } 557 setStandardKey(const QKeySequence::StandardKey & standardKey)558 void PropertySheetKeySequenceValue::setStandardKey(const QKeySequence::StandardKey &standardKey) 559 { 560 m_value = QKeySequence(standardKey); 561 m_standardKey = standardKey; 562 } 563 isStandardKey() const564 bool PropertySheetKeySequenceValue::isStandardKey() const 565 { 566 return m_standardKey != QKeySequence::UnknownKey; 567 } 568 comment() const569 QString PropertySheetKeySequenceValue::comment() const 570 { 571 return m_comment; 572 } 573 setComment(const QString & comment)574 void PropertySheetKeySequenceValue::setComment(const QString &comment) 575 { 576 m_comment = comment; 577 } 578 disambiguation() const579 QString PropertySheetKeySequenceValue::disambiguation() const 580 { 581 return m_disambiguation; 582 } 583 setDisambiguation(const QString & disambiguation)584 void PropertySheetKeySequenceValue::setDisambiguation(const QString &disambiguation) 585 { 586 m_disambiguation = disambiguation; 587 } 588 translatable() const589 bool PropertySheetKeySequenceValue::translatable() const 590 { 591 return m_translatable; 592 } 593 setTranslatable(bool translatable)594 void PropertySheetKeySequenceValue::setTranslatable(bool translatable) 595 { 596 m_translatable = translatable; 597 } 598 equals(const PropertySheetKeySequenceValue & rhs) const599 bool PropertySheetKeySequenceValue::equals(const PropertySheetKeySequenceValue &rhs) const 600 { 601 return (m_value == rhs.m_value) && (m_standardKey == rhs.m_standardKey) 602 && (m_translatable == rhs.m_translatable) && (m_disambiguation == rhs.m_disambiguation) && (m_comment == rhs.m_comment); 603 } 604 605 606 /* IconSubPropertyMask: Assign each icon sub-property (pixmaps for the 607 * various states/modes and the theme) a flag bit (see QFont) so that they 608 * can be handled individually when assigning property values to 609 * multiselections in the set-property-commands (that is, do not clobber 610 * other subproperties when assigning just one). 611 * Provide back-and-forth mapping functions for the icon states. */ 612 613 enum IconSubPropertyMask { 614 NormalOffIconMask = 0x01, 615 NormalOnIconMask = 0x02, 616 DisabledOffIconMask = 0x04, 617 DisabledOnIconMask = 0x08, 618 ActiveOffIconMask = 0x10, 619 ActiveOnIconMask = 0x20, 620 SelectedOffIconMask = 0x40, 621 SelectedOnIconMask = 0x80, 622 ThemeIconMask = 0x10000 623 }; 624 iconStateToSubPropertyFlag(QIcon::Mode mode,QIcon::State state)625 static inline uint iconStateToSubPropertyFlag(QIcon::Mode mode, QIcon::State state) 626 { 627 switch (mode) { 628 case QIcon::Disabled: 629 return state == QIcon::On ? DisabledOnIconMask : DisabledOffIconMask; 630 case QIcon::Active: 631 return state == QIcon::On ? ActiveOnIconMask : ActiveOffIconMask; 632 case QIcon::Selected: 633 return state == QIcon::On ? SelectedOnIconMask : SelectedOffIconMask; 634 case QIcon::Normal: 635 break; 636 } 637 return state == QIcon::On ? NormalOnIconMask : NormalOffIconMask; 638 } 639 subPropertyFlagToIconModeState(unsigned flag)640 static inline QPair<QIcon::Mode, QIcon::State> subPropertyFlagToIconModeState(unsigned flag) 641 { 642 switch (flag) { 643 case NormalOnIconMask: 644 return qMakePair(QIcon::Normal, QIcon::On); 645 case DisabledOffIconMask: 646 return qMakePair(QIcon::Disabled, QIcon::Off); 647 case DisabledOnIconMask: 648 return qMakePair(QIcon::Disabled, QIcon::On); 649 case ActiveOffIconMask: 650 return qMakePair(QIcon::Active, QIcon::Off); 651 case ActiveOnIconMask: 652 return qMakePair(QIcon::Active, QIcon::On); 653 case SelectedOffIconMask: 654 return qMakePair(QIcon::Selected, QIcon::Off); 655 case SelectedOnIconMask: 656 return qMakePair(QIcon::Selected, QIcon::On); 657 case NormalOffIconMask: 658 default: 659 break; 660 } 661 return qMakePair(QIcon::Normal, QIcon::Off); 662 } 663 mask() const664 uint PropertySheetIconValue::mask() const 665 { 666 typedef ModeStateToPixmapMap::const_iterator ModeStateToPixmapMapConstIt; 667 668 uint flags = 0; 669 const ModeStateToPixmapMapConstIt cend = m_data->m_paths.constEnd(); 670 for (ModeStateToPixmapMapConstIt it = m_data->m_paths.constBegin(); it != cend; ++it) 671 flags |= iconStateToSubPropertyFlag(it.key().first, it.key().second); 672 if (!m_data->m_theme.isEmpty()) 673 flags |= ThemeIconMask; 674 return flags; 675 } 676 compare(const PropertySheetIconValue & other) const677 uint PropertySheetIconValue::compare(const PropertySheetIconValue &other) const 678 { 679 uint diffMask = mask() | other.mask(); 680 for (int i = 0; i < 8; i++) { 681 const uint flag = 1 << i; 682 if (diffMask & flag) { // if state is set in both icons, compare the values 683 const QPair<QIcon::Mode, QIcon::State> state = subPropertyFlagToIconModeState(flag); 684 if (pixmap(state.first, state.second) == other.pixmap(state.first, state.second)) 685 diffMask &= ~flag; 686 } 687 } 688 if ((diffMask & ThemeIconMask) && theme() == other.theme()) 689 diffMask &= ~ThemeIconMask; 690 return diffMask; 691 } 692 themed() const693 PropertySheetIconValue PropertySheetIconValue::themed() const 694 { 695 PropertySheetIconValue rc(*this); 696 rc.m_data->m_paths.clear(); 697 return rc; 698 } 699 unthemed() const700 PropertySheetIconValue PropertySheetIconValue::unthemed() const 701 { 702 PropertySheetIconValue rc(*this); 703 rc.m_data->m_theme.clear(); 704 return rc; 705 } 706 assign(const PropertySheetIconValue & other,uint mask)707 void PropertySheetIconValue::assign(const PropertySheetIconValue &other, uint mask) 708 { 709 for (int i = 0; i < 8; i++) { 710 uint flag = 1 << i; 711 if (mask & flag) { 712 const ModeStateKey state = subPropertyFlagToIconModeState(flag); 713 setPixmap(state.first, state.second, other.pixmap(state.first, state.second)); 714 } 715 } 716 if (mask & ThemeIconMask) 717 setTheme(other.theme()); 718 } 719 paths() const720 const PropertySheetIconValue::ModeStateToPixmapMap &PropertySheetIconValue::paths() const 721 { 722 return m_data->m_paths; 723 } 724 operator <<(QDebug d,const PropertySheetIconValue & p)725 QDESIGNER_SHARED_EXPORT QDebug operator<<(QDebug d, const PropertySheetIconValue &p) 726 { 727 typedef PropertySheetIconValue::ModeStateToPixmapMap::const_iterator ModeStateToPixmapMapConstIt; 728 729 QDebug nospace = d.nospace(); 730 nospace << "PropertySheetIconValue theme='" << p.theme() << "' "; 731 732 const PropertySheetIconValue::ModeStateToPixmapMap &paths = p.paths(); 733 const ModeStateToPixmapMapConstIt cend = paths.constEnd(); 734 for (ModeStateToPixmapMapConstIt it = paths.constBegin(); it != cend; ++it) 735 nospace << " mode=" << it.key().first << ",state=" << it.key().second 736 << ",'" << it.value().path() << '\''; 737 nospace << " mask=0x" << QString::number(p.mask(), 16); 738 return d; 739 } 740 createTextPropertyCommand(const QString & propertyName,const QString & text,QObject * object,QDesignerFormWindowInterface * fw)741 QDESIGNER_SHARED_EXPORT QDesignerFormWindowCommand *createTextPropertyCommand(const QString &propertyName, const QString &text, QObject *object, QDesignerFormWindowInterface *fw) 742 { 743 if (text.isEmpty()) { 744 ResetPropertyCommand *cmd = new ResetPropertyCommand(fw); 745 cmd->init(object, propertyName); 746 return cmd; 747 } 748 SetPropertyCommand *cmd = new SetPropertyCommand(fw); 749 cmd->init(object, propertyName, text); 750 return cmd; 751 } 752 preferredEditAction(QDesignerFormEditorInterface * core,QWidget * managedWidget)753 QDESIGNER_SHARED_EXPORT QAction *preferredEditAction(QDesignerFormEditorInterface *core, QWidget *managedWidget) 754 { 755 QAction *action = 0; 756 if (const QDesignerTaskMenuExtension *taskMenu = qt_extension<QDesignerTaskMenuExtension*>(core->extensionManager(), managedWidget)) { 757 action = taskMenu->preferredEditAction(); 758 if (!action) { 759 const QList<QAction *> actions = taskMenu->taskActions(); 760 if (!actions.isEmpty()) 761 action = actions.first(); 762 } 763 } 764 if (!action) { 765 if (const QDesignerTaskMenuExtension *taskMenu = qobject_cast<QDesignerTaskMenuExtension *>( 766 core->extensionManager()->extension(managedWidget, QLatin1String("QDesignerInternalTaskMenuExtension")))) { 767 action = taskMenu->preferredEditAction(); 768 if (!action) { 769 const QList<QAction *> actions = taskMenu->taskActions(); 770 if (!actions.isEmpty()) 771 action = actions.first(); 772 } 773 } 774 } 775 return action; 776 } 777 runUIC(const QString & fileName,UIC_Mode mode,QByteArray & ba,QString & errorMessage)778 QDESIGNER_SHARED_EXPORT bool runUIC(const QString &fileName, UIC_Mode mode, QByteArray& ba, QString &errorMessage) 779 { 780 QStringList argv; 781 QString binary = QLibraryInfo::location(QLibraryInfo::BinariesPath); 782 binary += QDir::separator(); 783 switch (mode) { 784 case UIC_GenerateCode: 785 binary += QLatin1String("uic"); 786 break; 787 case UIC_ConvertV3: 788 binary += QLatin1String("uic3"); 789 argv += QLatin1String("-convert"); 790 break; 791 } 792 argv += fileName; 793 QProcess uic; 794 uic.start(binary, argv); 795 if (!uic.waitForStarted()) { 796 errorMessage = QApplication::translate("Designer", "Unable to launch %1.").arg(binary); 797 return false; 798 } 799 if (!uic.waitForFinished()) { 800 errorMessage = QApplication::translate("Designer", "%1 timed out.").arg(binary); 801 return false; 802 } 803 if (uic.exitCode()) { 804 errorMessage = QString::fromAscii(uic.readAllStandardError()); 805 return false; 806 } 807 ba = uic.readAllStandardOutput(); 808 return true; 809 } 810 qtify(const QString & name)811 QDESIGNER_SHARED_EXPORT QString qtify(const QString &name) 812 { 813 QString qname = name; 814 815 Q_ASSERT(qname.isEmpty() == false); 816 817 818 if (qname.count() > 1 && qname.at(1).isUpper()) { 819 const QChar first = qname.at(0); 820 if (first == QLatin1Char('Q') || first == QLatin1Char('K')) 821 qname.remove(0, 1); 822 } 823 824 const int len = qname.count(); 825 for (int i = 0; i < len && qname.at(i).isUpper(); i++) 826 qname[i] = qname.at(i).toLower(); 827 828 return qname; 829 } 830 831 // --------------- UpdateBlocker UpdateBlocker(QWidget * w)832 UpdateBlocker::UpdateBlocker(QWidget *w) : 833 m_widget(w), 834 m_enabled(w->updatesEnabled() && w->isVisible()) 835 { 836 if (m_enabled) 837 m_widget->setUpdatesEnabled(false); 838 } 839 ~UpdateBlocker()840 UpdateBlocker::~UpdateBlocker() 841 { 842 if (m_enabled) 843 m_widget->setUpdatesEnabled(true); 844 } 845 846 } // namespace qdesigner_internal 847 848 QT_END_NAMESPACE 849