QIcon VariantPropertyManager::valueIcon(const QtProperty *property) const { if (mValues.contains(property)) { QVariant value = mValues[property].value; QString filePath; int typeId = propertyType(property); if (typeId == filePathTypeId()) filePath = value.value<FilePath>().absolutePath; if (typeId == tilesetParametersTypeId()) { if (TilesetDocument *tilesetDocument = value.value<TilesetDocument*>()) filePath = tilesetDocument->tileset()->imageSource(); } // TODO: This assumes the file path is an image reference. It should be // replaced with a more generic icon. if (filePath.isEmpty() || !QFile::exists(filePath)) return QIcon::fromTheme(QLatin1String("image-missing"), mImageMissingIcon); else return mIconProvider.icon(QFileInfo(filePath)); } return QtVariantPropertyManager::valueIcon(property); }
Properties VariantToMapConverter::toProperties(const QVariant &propertiesVariant, const QVariant &propertyTypesVariant) const { const QVariantMap propertiesMap = propertiesVariant.toMap(); const QVariantMap propertyTypesMap = propertyTypesVariant.toMap(); Properties properties; QVariantMap::const_iterator it = propertiesMap.constBegin(); QVariantMap::const_iterator it_end = propertiesMap.constEnd(); for (; it != it_end; ++it) { int type = nameToType(propertyTypesMap.value(it.key()).toString()); if (type == QVariant::Invalid) type = QVariant::String; QVariant value = it.value(); if (type == filePathTypeId()) value = resolvePath(mMapDir, value); value = fromExportValue(value, type); properties[it.key()] = value; } return properties; }
QString VariantPropertyManager::valueText(const QtProperty *property) const { if (mValues.contains(property)) { QVariant value = mValues[property].value; int typeId = propertyType(property); if (typeId == filePathTypeId()) { FilePath filePath = value.value<FilePath>(); QString path = filePath.absolutePath; if (path.endsWith(QLatin1Char('/'))) path.chop(1); return QFileInfo(path).fileName(); } if (typeId == tilesetParametersTypeId()) { if (TilesetDocument *tilesetDocument = value.value<TilesetDocument*>()) return QFileInfo(tilesetDocument->tileset()->imageSource()).fileName(); } return value.toString(); } auto stringAttributesIt = mStringAttributes.find(property); if (stringAttributesIt != mStringAttributes.end()) { if ((*stringAttributesIt).multiline) return escapeNewlines(value(property).toString()); } return QtVariantPropertyManager::valueText(property); }
int VariantPropertyManager::valueType(int propertyType) const { if (propertyType == filePathTypeId()) return QVariant::String; if (propertyType == tilesetParametersTypeId()) return qMetaTypeId<TilesetDocument*>(); return QtVariantPropertyManager::valueType(propertyType); }
bool VariantPropertyManager::isPropertyTypeSupported(int propertyType) const { if (propertyType == filePathTypeId()) return true; if (propertyType == tilesetParametersTypeId()) return true; return QtVariantPropertyManager::isPropertyTypeSupported(propertyType); }
QStringList VariantPropertyManager::attributes(int propertyType) const { if (propertyType == filePathTypeId()) { return QStringList { QStringLiteral("filter") }; } return QtVariantPropertyManager::attributes(propertyType); }
int VariantPropertyManager::attributeType(int propertyType, const QString &attribute) const { if (propertyType == filePathTypeId()) { if (attribute == QLatin1String("filter")) return QVariant::String; return 0; } return QtVariantPropertyManager::attributeType(propertyType, attribute); }
void VariantPropertyManager::initializeProperty(QtProperty *property) { const int type = propertyType(property); if (type == filePathTypeId()) mValues[property] = Data(); else if (type == tilesetParametersTypeId()) mValues[property] = Data(); else if (type == QVariant::String) mStringAttributes[property] = StringAttributes(); QtVariantPropertyManager::initializeProperty(property); }
QWidget *VariantEditorFactory::createEditor(QtVariantPropertyManager *manager, QtProperty *property, QWidget *parent) { const int type = manager->propertyType(property); if (type == filePathTypeId()) { FileEdit *editor = new FileEdit(parent); FilePath filePath = manager->value(property).value<FilePath>(); editor->setFilePath(filePath.absolutePath); editor->setFilter(manager->attributeValue(property, QLatin1String("filter")).toString()); mCreatedFileEdits[property].append(editor); mFileEditToProperty[editor] = property; connect(editor, &FileEdit::filePathChanged, this, &VariantEditorFactory::fileEditFilePathChanged); connect(editor, SIGNAL(destroyed(QObject *)), this, SLOT(slotEditorDestroyed(QObject *))); return editor; }
QWidget *VariantEditorFactory::createEditor(QtVariantPropertyManager *manager, QtProperty *property, QWidget *parent) { const int type = manager->propertyType(property); if (type == filePathTypeId()) { FileEdit *editor = new FileEdit(parent); FilePath filePath = manager->value(property).value<FilePath>(); editor->setFileUrl(filePath.url); editor->setFilter(manager->attributeValue(property, QLatin1String("filter")).toString()); mCreatedFileEdits[property].append(editor); mFileEditToProperty[editor] = property; connect(editor, &FileEdit::fileUrlChanged, this, &VariantEditorFactory::fileEditFileUrlChanged); connect(editor, &QObject::destroyed, this, &VariantEditorFactory::slotEditorDestroyed); return editor; } if (type == VariantPropertyManager::tilesetParametersTypeId()) { auto editor = new TilesetParametersEdit(parent); editor->setTilesetDocument(manager->value(property).value<TilesetDocument*>()); mCreatedTilesetEdits[property].append(editor); mTilesetEditToProperty[editor] = property; connect(editor, &QObject::destroyed, this, &VariantEditorFactory::slotEditorDestroyed); return editor; } if (type == QVariant::String) { bool multiline = manager->attributeValue(property, QLatin1String("multiline")).toBool(); if (multiline) { auto editor = new TextPropertyEdit(parent); editor->setText(manager->value(property).toString()); mCreatedTextPropertyEdits[property].append(editor); mTextPropertyEditToProperty[editor] = property; connect(editor, &TextPropertyEdit::textChanged, this, &VariantEditorFactory::textPropertyEditTextChanged); connect(editor, &QObject::destroyed, this, &VariantEditorFactory::slotEditorDestroyed); return editor; } } QWidget *editor = QtVariantEditorFactory::createEditor(manager, property, parent); if (type == QVariant::String) { // Add support for "suggestions" attribute that adds a QCompleter to the QLineEdit QVariant suggestions = manager->attributeValue(property, QLatin1String("suggestions")); if (!suggestions.toStringList().isEmpty()) { if (QLineEdit *lineEdit = qobject_cast<QLineEdit*>(editor)) { QCompleter *completer = new QCompleter(suggestions.toStringList(), lineEdit); completer->setCaseSensitivity(Qt::CaseInsensitive); lineEdit->setCompleter(completer); } } } if (type == QVariant::Color) { // Allow resetting a color property to the invalid color ResetWidget *resetWidget = new ResetWidget(property, editor, parent); connect(resetWidget, &ResetWidget::resetProperty, this, &VariantEditorFactory::resetProperty); editor = resetWidget; } return editor; }
void PropertiesDock::showContextMenu(const QPoint& pos) { const Object *object = mDocument->currentObject(); if (!object) return; const QList<QtBrowserItem *> items = mPropertyBrowser->selectedItems(); const bool customPropertiesSelected = !items.isEmpty() && mPropertyBrowser->allCustomPropertyItems(items); bool currentObjectHasAllProperties = true; QStringList propertyNames; for (QtBrowserItem *item : items) { const QString propertyName = item->property()->propertyName(); propertyNames.append(propertyName); if (!object->hasProperty(propertyName)) currentObjectHasAllProperties = false; } QMenu contextMenu(mPropertyBrowser); QAction *cutAction = contextMenu.addAction(tr("Cu&t")); QAction *copyAction = contextMenu.addAction(tr("&Copy")); QAction *pasteAction = contextMenu.addAction(tr("&Paste")); contextMenu.addSeparator(); QMenu *convertMenu = contextMenu.addMenu(tr("Convert To")); QAction *renameAction = contextMenu.addAction(tr("Rename...")); QAction *removeAction = contextMenu.addAction(tr("Remove")); cutAction->setShortcuts(QKeySequence::Cut); cutAction->setIcon(QIcon(QLatin1String(":/images/16x16/edit-cut.png"))); cutAction->setEnabled(customPropertiesSelected && currentObjectHasAllProperties); copyAction->setShortcuts(QKeySequence::Copy); copyAction->setIcon(QIcon(QLatin1String(":/images/16x16/edit-copy.png"))); copyAction->setEnabled(customPropertiesSelected && currentObjectHasAllProperties); pasteAction->setShortcuts(QKeySequence::Paste); pasteAction->setIcon(QIcon(QLatin1String(":/images/16x16/edit-paste.png"))); pasteAction->setEnabled(ClipboardManager::instance()->hasProperties()); renameAction->setEnabled(mActionRenameProperty->isEnabled()); renameAction->setIcon(mActionRenameProperty->icon()); removeAction->setEnabled(mActionRemoveProperty->isEnabled()); removeAction->setShortcuts(mActionRemoveProperty->shortcuts()); removeAction->setIcon(mActionRemoveProperty->icon()); Utils::setThemeIcon(cutAction, "edit-cut"); Utils::setThemeIcon(copyAction, "edit-copy"); Utils::setThemeIcon(pasteAction, "edit-paste"); Utils::setThemeIcon(removeAction, "remove"); if (customPropertiesSelected) { const int convertTo[] = { QVariant::Bool, QVariant::Color, QVariant::Double, filePathTypeId(), QVariant::Int, QVariant::String }; for (int toType : convertTo) { bool someDifferentType = false; bool allCanConvert = true; for (const QString &propertyName : propertyNames) { QVariant propertyValue = object->property(propertyName); if (propertyValue.userType() != toType) someDifferentType = true; if (!propertyValue.convert(toType)) { allCanConvert = false; break; } } if (someDifferentType && allCanConvert) { QAction *action = convertMenu->addAction(typeToName(toType)); action->setData(toType); } } } convertMenu->setEnabled(!convertMenu->actions().isEmpty()); connect(cutAction, &QAction::triggered, this, &PropertiesDock::cutProperties); connect(copyAction, &QAction::triggered, this, &PropertiesDock::copyProperties); connect(pasteAction, &QAction::triggered, this, &PropertiesDock::pasteProperties); connect(renameAction, &QAction::triggered, this, &PropertiesDock::renameProperty); connect(removeAction, &QAction::triggered, this, &PropertiesDock::removeProperties); const QPoint globalPos = mPropertyBrowser->mapToGlobal(pos); const QAction *selectedItem = contextMenu.exec(globalPos); if (selectedItem && selectedItem->parentWidget() == convertMenu) { QUndoStack *undoStack = mDocument->undoStack(); undoStack->beginMacro(tr("Convert Property/Properties", nullptr, items.size())); for (const QString &propertyName : propertyNames) { QVariant propertyValue = object->property(propertyName); int toType = selectedItem->data().toInt(); propertyValue.convert(toType); undoStack->push(new SetProperty(mDocument, mDocument->currentObjects(), propertyName, propertyValue)); } undoStack->endMacro(); } }