void WidgetDataBase::grabDefaultPropertyValues() { const int itemCount = count(); for (int i = 0; i < itemCount; ++i) { QDesignerWidgetDataBaseItemInterface *dbItem = item(i); const QList<QVariant> default_prop_values = defaultPropertyValues(dbItem->name()); dbItem->setDefaultPropertyValues(default_prop_values); } }
void QSimpleResource::addCustomWidgetsToWidgetDatabase(const QDesignerFormEditorInterface *core, QList<DomCustomWidget*>& custom_widget_list) { QDesignerWidgetDataBaseInterface *db = core->widgetDataBase(); for (int i=0; i < custom_widget_list.size(); ) { bool classInserted = false; DomCustomWidget *custom_widget = custom_widget_list[i]; const QString customClassName = custom_widget->elementClass(); const QString base_class = custom_widget->elementExtends(); QString includeFile; IncludeType includeType = IncludeLocal; if (const DomHeader *header = custom_widget->elementHeader()) { includeFile = header->text(); if (header->hasAttributeLocation() && header->attributeLocation() == QStringLiteral("global")) includeType = IncludeGlobal; } const bool domIsContainer = custom_widget->elementContainer(); // Append a new item if (base_class.isEmpty()) { WidgetDataBaseItem *item = new WidgetDataBaseItem(customClassName); item->setPromoted(false); item->setGroup(QCoreApplication::translate("Designer", "Custom Widgets")); item->setIncludeFile(buildIncludeFile(includeFile, includeType)); item->setContainer(domIsContainer); item->setCustom(true); addFakeMethodsToWidgetDataBase(custom_widget, item); db->append(item); custom_widget_list.removeAt(i); classInserted = true; } else { // Create a new entry cloned from base class. Note that this will ignore existing // classes, eg, plugin custom widgets. QDesignerWidgetDataBaseItemInterface *item = appendDerived(db, customClassName, QCoreApplication::translate("Designer", "Promoted Widgets"), base_class, buildIncludeFile(includeFile, includeType), true,true); // Ok, base class found. if (item) { // Hack to accommodate for old UI-files in which "container" is not set properly: // Apply "container" from DOM only if true (else, eg classes from QFrame might not accept // dropping child widgets on them as container=false). This also allows for // QWidget-derived stacked pages. if (domIsContainer) item->setContainer(domIsContainer); addFakeMethodsToWidgetDataBase(custom_widget, static_cast<WidgetDataBaseItem*>(item)); custom_widget_list.removeAt(i); classInserted = true; } } // Skip failed item. if (!classInserted) i++; } }
void QDesignerPromotionDialog::slotRemove() { unsigned flags; QDesignerWidgetDataBaseItemInterface *dbItem = databaseItemAt(m_treeView->selectionModel()->selection(), flags); if (!dbItem || (flags & Referenced)) return; QString errorMessage; if (m_promotion->removePromotedClass(dbItem->name(), &errorMessage)) { slotUpdateFromWidgetDatabase(); } else { displayError(errorMessage); } }
QDESIGNER_SHARED_EXPORT WidgetDataBaseItemList promotionCandidates(const QDesignerWidgetDataBaseInterface *db, const QString &baseClassName) { WidgetDataBaseItemList rc; // find existing promoted widgets deriving from base. const int count = db->count(); for (int i = 0; i < count; ++i) { QDesignerWidgetDataBaseItemInterface *item = db->item(i); if (item->isPromoted() && item->extends() == baseClassName) { rc.push_back(item); } } return rc; }
QDesignerWidgetDataBaseItemInterface *QDesignerPromotionDialog::databaseItemAt(const QItemSelection &selected, unsigned &flags) const { flags = 0; const QModelIndexList indexes = selected.indexes(); if (indexes.empty()) return 0; bool referenced; QDesignerWidgetDataBaseItemInterface *dbItem = m_model->databaseItemAt(indexes.front(), &referenced); if (dbItem) { if (referenced) flags |= Referenced; // In choose mode, can we promote to the class? if (m_mode == ModeEditChooseClass && dbItem && dbItem->isPromoted() && dbItem->extends() == m_promotableWidgetClassName) flags |= CanPromote; } return dbItem; }
void WidgetDataBase::grabStandardWidgetBoxIcons() { // At this point, grab the default icons for the non-custom widgets from // the widget box. They will show up in the object inspector. if (const QDesignerWidgetBox *wb = qobject_cast<const QDesignerWidgetBox *>(m_core->widgetBox())) { const QString qWidgetClass = QLatin1String("QWidget"); const int itemCount = count(); for (int i = 0; i < itemCount; ++i) { QDesignerWidgetDataBaseItemInterface *dbItem = item(i); if (!dbItem->isCustom() && dbItem->icon().isNull()) { // Careful not to catch the layout icons when looking for // QWidget const QString name = dbItem->name(); if (name == qWidgetClass) { dbItem->setIcon(wb->iconForWidget(name, QLatin1String("Containers"))); } else { dbItem->setIcon(wb->iconForWidget(name)); } } } } }
QDESIGNER_SHARED_EXPORT QDesignerWidgetDataBaseItemInterface * appendDerived(QDesignerWidgetDataBaseInterface *db, const QString &className, const QString &group, const QString &baseClassName, const QString &includeFile, bool promoted, bool custom) { if (debugWidgetDataBase) qDebug() << "appendDerived " << className << " derived from " << baseClassName; // Check. if (className.isEmpty() || baseClassName.isEmpty()) { qWarning("** WARNING %s called with an empty class names: '%s' extends '%s'.", Q_FUNC_INFO, className.toUtf8().constData(), baseClassName.toUtf8().constData()); return 0; } // Check whether item already exists. QDesignerWidgetDataBaseItemInterface *derivedItem = 0; const int existingIndex = db->indexOfClassName(className); if ( existingIndex != -1) derivedItem = db->item(existingIndex); if (derivedItem) { // Check the existing item for base class mismatch. This will likely // happen when loading a file written by an instance with missing plugins. // In that case, just warn and ignore the file properties. // // An empty base class indicates that it is not known (for example, for custom plugins). // In this case, the widget DB is later updated once the widget is created // by DOM (by querying the metaobject). Suppress the warning. const QString existingBaseClass = derivedItem->extends(); if (existingBaseClass.isEmpty() || baseClassName == existingBaseClass) return derivedItem; // Warn about mismatches designerWarning(QCoreApplication::translate("WidgetDataBase", "The file contains a custom widget '%1' whose base class (%2)" " differs from the current entry in the widget database (%3)." " The widget database is left unchanged."). arg(className, baseClassName, existingBaseClass)); return derivedItem; } // Create this item, inheriting its base properties const int baseIndex = db->indexOfClassName(baseClassName); if (baseIndex == -1) { if (debugWidgetDataBase) qDebug() << "appendDerived failed due to missing base class"; return 0; } const QDesignerWidgetDataBaseItemInterface *baseItem = db->item(baseIndex); derivedItem = WidgetDataBaseItem::clone(baseItem); // Sort of hack: If base class is QWidget, we most likely // do not want to inherit the container attribute. static const QString qWidgetName = QLatin1String("QWidget"); if (baseItem->name() == qWidgetName) derivedItem->setContainer(false); // set new props derivedItem->setName(className); derivedItem->setGroup(group); derivedItem->setCustom(custom); derivedItem->setPromoted(promoted); derivedItem->setExtends(baseClassName); derivedItem->setIncludeFile(includeFile); db->append(derivedItem); return derivedItem; }
void WidgetDataBase::loadPlugins() { typedef QMap<QString, int> NameIndexMap; typedef QList<QDesignerWidgetDataBaseItemInterface*> ItemList; typedef QMap<QString, QDesignerWidgetDataBaseItemInterface*> NameItemMap; typedef QSet<QString> NameSet; // 1) create a map of existing custom classes NameIndexMap existingCustomClasses; NameSet nonCustomClasses; const int count = m_items.size(); for (int i = 0; i < count; i++) { const QDesignerWidgetDataBaseItemInterface* item = m_items[i]; if (item->isCustom() && !item->isPromoted()) existingCustomClasses.insert(item->name(), i); else nonCustomClasses.insert(item->name()); } // 2) create a list plugins ItemList pluginList; const QDesignerPluginManager *pm = m_core->pluginManager(); foreach(QDesignerCustomWidgetInterface* c, pm->registeredCustomWidgets()) pluginList += createCustomWidgetItem(c, pm->customWidgetData(c)); // 3) replace custom classes or add new ones, remove them from existingCustomClasses, // leaving behind deleted items unsigned replacedPlugins = 0; unsigned addedPlugins = 0; unsigned removedPlugins = 0; if (!pluginList.empty()) { ItemList::const_iterator cend = pluginList.constEnd(); for (ItemList::const_iterator it = pluginList.constBegin();it != cend; ++it ) { QDesignerWidgetDataBaseItemInterface* pluginItem = *it; const QString pluginName = pluginItem->name(); NameIndexMap::iterator existingIt = existingCustomClasses.find(pluginName); if (existingIt == existingCustomClasses.end()) { // Add new class. if (nonCustomClasses.contains(pluginName)) { designerWarning(tr("A custom widget plugin whose class name (%1) matches that of an existing class has been found.").arg(pluginName)); } else { append(pluginItem); addedPlugins++; } } else { // replace existing info const int existingIndex = existingIt.value(); delete m_items[existingIndex]; m_items[existingIndex] = pluginItem; existingCustomClasses.erase(existingIt); replacedPlugins++; } } } // 4) remove classes that have not been matched. The stored indexes become invalid while deleting. if (!existingCustomClasses.empty()) { NameIndexMap::const_iterator cend = existingCustomClasses.constEnd(); for (NameIndexMap::const_iterator it = existingCustomClasses.constBegin();it != cend; ++it ) { const int index = indexOfClassName(it.key()); if (index != -1) { remove(index); removedPlugins++; } } } if (debugWidgetDataBase) qDebug() << "WidgetDataBase::loadPlugins(): " << addedPlugins << " added, " << replacedPlugins << " replaced, " << removedPlugins << "deleted."; }