forked from qt-creator/qt-creator
QmlDesigner: Implement new asset drags
Drag image to existing image/texture type - Update source property. Drag image containing multiple frames - Create AnimatedImage. Drag sound - Create new SoundEffect or update an existing one. Drag shader - Create new Shader or update an existing one. Drag font - Create new Text or update font on an existing one. Fixes: QDS-3389 Change-Id: I62cf964bbba7772ecbf6f1c6fadb0f9e41a86206 Reviewed-by: Mahmoud Badri <mahmoud.badri@qt.io> Reviewed-by: Thomas Hartmann <thomas.hartmann@qt.io>
This commit is contained in:
@@ -234,8 +234,9 @@ void AbstractFormEditorTool::dropEvent(const QList<QGraphicsItem*> &/*itemList*/
|
|||||||
|
|
||||||
void AbstractFormEditorTool::dragEnterEvent(const QList<QGraphicsItem*> &itemList, QGraphicsSceneDragDropEvent *event)
|
void AbstractFormEditorTool::dragEnterEvent(const QList<QGraphicsItem*> &itemList, QGraphicsSceneDragDropEvent *event)
|
||||||
{
|
{
|
||||||
if (event->mimeData()->hasFormat(QLatin1String("application/vnd.bauhaus.itemlibraryinfo")) ||
|
if (event->mimeData()->hasFormat(QLatin1String("application/vnd.bauhaus.itemlibraryinfo"))
|
||||||
event->mimeData()->hasFormat(QLatin1String("application/vnd.bauhaus.libraryresource"))) {
|
|| event->mimeData()->hasFormat(QLatin1String("application/vnd.bauhaus.libraryresource.image"))
|
||||||
|
|| event->mimeData()->hasFormat(QLatin1String("application/vnd.bauhaus.libraryresource.font"))) {
|
||||||
event->accept();
|
event->accept();
|
||||||
view()->changeToDragTool();
|
view()->changeToDragTool();
|
||||||
view()->currentTool()->dragEnterEvent(itemList, event);
|
view()->currentTool()->dragEnterEvent(itemList, event);
|
||||||
|
@@ -136,6 +136,26 @@ void DragTool::createQmlItemNodeFromImage(const QString &imageName,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void DragTool::createQmlItemNodeFromFont(const QString &fontFamily,
|
||||||
|
const QmlItemNode &parentNode,
|
||||||
|
const QPointF &scenePos)
|
||||||
|
{
|
||||||
|
if (parentNode.isValid()) {
|
||||||
|
MetaInfo metaInfo = MetaInfo::global();
|
||||||
|
|
||||||
|
FormEditorItem *parentItem = scene()->itemForQmlItemNode(parentNode);
|
||||||
|
QPointF positonInItemSpace = parentItem->qmlItemNode().instanceSceneContentItemTransform()
|
||||||
|
.inverted().map(scenePos);
|
||||||
|
|
||||||
|
m_dragNode = QmlItemNode::createQmlItemNodeFromFont(view(), fontFamily, positonInItemSpace,
|
||||||
|
parentNode);
|
||||||
|
|
||||||
|
QList<QmlItemNode> nodeList;
|
||||||
|
nodeList.append(m_dragNode);
|
||||||
|
m_selectionIndicator.setItems(scene()->itemsForQmlItemNodes(nodeList));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
FormEditorItem *DragTool::targetContainerOrRootItem(const QList<QGraphicsItem *> &itemList, FormEditorItem *currentItem)
|
FormEditorItem *DragTool::targetContainerOrRootItem(const QList<QGraphicsItem *> &itemList, FormEditorItem *currentItem)
|
||||||
{
|
{
|
||||||
FormEditorItem *formEditorItem = containerFormEditorItem(itemList, {currentItem});
|
FormEditorItem *formEditorItem = containerFormEditorItem(itemList, {currentItem});
|
||||||
@@ -208,25 +228,29 @@ static bool canBeDropped(const QMimeData *mimeData)
|
|||||||
return NodeHints::fromItemLibraryEntry(itemLibraryEntryFromMimeData(mimeData)).canBeDroppedInFormEditor();
|
return NodeHints::fromItemLibraryEntry(itemLibraryEntryFromMimeData(mimeData)).canBeDroppedInFormEditor();
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool canHandleMimeData(const QMimeData *mimeData)
|
|
||||||
{
|
|
||||||
return mimeData->hasFormat(QStringLiteral("application/vnd.bauhaus.itemlibraryinfo"))
|
|
||||||
|| mimeData->hasFormat(QStringLiteral("application/vnd.bauhaus.libraryresource"));
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool dragAndDropPossible(const QMimeData *mimeData)
|
|
||||||
{
|
|
||||||
return canHandleMimeData(mimeData) && canBeDropped(mimeData);
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool hasItemLibraryInfo(const QMimeData *mimeData)
|
static bool hasItemLibraryInfo(const QMimeData *mimeData)
|
||||||
{
|
{
|
||||||
return mimeData->hasFormat(QStringLiteral("application/vnd.bauhaus.itemlibraryinfo"));
|
return mimeData->hasFormat(QStringLiteral("application/vnd.bauhaus.itemlibraryinfo"));
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool hasLibraryResources(const QMimeData *mimeData)
|
static bool hasImageResource(const QMimeData *mimeData)
|
||||||
{
|
{
|
||||||
return mimeData->hasFormat(QStringLiteral("application/vnd.bauhaus.libraryresource"));
|
return mimeData->hasFormat(QStringLiteral("application/vnd.bauhaus.libraryresource.image"));
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool hasFontResource(const QMimeData *mimeData)
|
||||||
|
{
|
||||||
|
return mimeData->hasFormat(QStringLiteral("application/vnd.bauhaus.libraryresource.font"));
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool canHandleMimeData(const QMimeData *mimeData)
|
||||||
|
{
|
||||||
|
return hasItemLibraryInfo(mimeData) || hasImageResource(mimeData) || hasFontResource(mimeData);
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool dragAndDropPossible(const QMimeData *mimeData)
|
||||||
|
{
|
||||||
|
return canHandleMimeData(mimeData) && canBeDropped(mimeData);
|
||||||
}
|
}
|
||||||
|
|
||||||
void DragTool::dropEvent(const QList<QGraphicsItem *> &/*itemList*/, QGraphicsSceneDragDropEvent *event)
|
void DragTool::dropEvent(const QList<QGraphicsItem *> &/*itemList*/, QGraphicsSceneDragDropEvent *event)
|
||||||
@@ -290,11 +314,16 @@ void DragTool::dragLeaveEvent(const QList<QGraphicsItem *> &/*itemList*/, QGraph
|
|||||||
view()->changeToSelectionTool();
|
view()->changeToSelectionTool();
|
||||||
}
|
}
|
||||||
|
|
||||||
static QString libraryResourceImageName(const QMimeData *mimeData)
|
static QString libraryResourceFile(const QMimeData *mimeData)
|
||||||
{
|
{
|
||||||
return QString::fromUtf8((mimeData->data(QStringLiteral("application/vnd.bauhaus.libraryresource"))));
|
return QString::fromUtf8((mimeData->data(QStringLiteral("application/vnd.bauhaus.libraryresource"))));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static QString libraryResourceFont(const QMimeData *mimeData)
|
||||||
|
{
|
||||||
|
return QString::fromUtf8((mimeData->data(QStringLiteral("application/vnd.bauhaus.libraryresource.font"))));
|
||||||
|
}
|
||||||
|
|
||||||
void DragTool::createDragNode(const QMimeData *mimeData, const QPointF &scenePosition, const QList<QGraphicsItem *> &itemList)
|
void DragTool::createDragNode(const QMimeData *mimeData, const QPointF &scenePosition, const QList<QGraphicsItem *> &itemList)
|
||||||
{
|
{
|
||||||
if (!m_dragNode.hasModelNode()) {
|
if (!m_dragNode.hasModelNode()) {
|
||||||
@@ -306,8 +335,10 @@ void DragTool::createDragNode(const QMimeData *mimeData, const QPointF &scenePos
|
|||||||
|
|
||||||
if (hasItemLibraryInfo(mimeData))
|
if (hasItemLibraryInfo(mimeData))
|
||||||
createQmlItemNode(itemLibraryEntryFromMimeData(mimeData), targetContainerQmlItemNode, scenePosition);
|
createQmlItemNode(itemLibraryEntryFromMimeData(mimeData), targetContainerQmlItemNode, scenePosition);
|
||||||
else if (hasLibraryResources(mimeData))
|
else if (hasImageResource(mimeData))
|
||||||
createQmlItemNodeFromImage(libraryResourceImageName(mimeData), targetContainerQmlItemNode, scenePosition);
|
createQmlItemNodeFromImage(libraryResourceFile(mimeData), targetContainerQmlItemNode, scenePosition);
|
||||||
|
else if (hasFontResource(mimeData))
|
||||||
|
createQmlItemNodeFromFont(libraryResourceFont(mimeData), targetContainerQmlItemNode, scenePosition);
|
||||||
|
|
||||||
m_blockMove = true;
|
m_blockMove = true;
|
||||||
m_startPoint = scenePosition;
|
m_startPoint = scenePosition;
|
||||||
|
@@ -81,6 +81,7 @@ protected:
|
|||||||
void abort();
|
void abort();
|
||||||
void createQmlItemNode(const ItemLibraryEntry &itemLibraryEntry, const QmlItemNode &parentNode, const QPointF &scenePos);
|
void createQmlItemNode(const ItemLibraryEntry &itemLibraryEntry, const QmlItemNode &parentNode, const QPointF &scenePos);
|
||||||
void createQmlItemNodeFromImage(const QString &imageName, const QmlItemNode &parentNode, const QPointF &scenePos);
|
void createQmlItemNodeFromImage(const QString &imageName, const QmlItemNode &parentNode, const QPointF &scenePos);
|
||||||
|
void createQmlItemNodeFromFont(const QString &fontFamily, const QmlItemNode &parentNode, const QPointF &scenePos);
|
||||||
FormEditorItem *targetContainerOrRootItem(const QList<QGraphicsItem*> &itemList, FormEditorItem *urrentItem = nullptr);
|
FormEditorItem *targetContainerOrRootItem(const QList<QGraphicsItem*> &itemList, FormEditorItem *urrentItem = nullptr);
|
||||||
void begin(QPointF scenePos);
|
void begin(QPointF scenePos);
|
||||||
void end();
|
void end();
|
||||||
|
@@ -53,6 +53,12 @@ static const QStringList &supportedImageSuffixes()
|
|||||||
return retList;
|
return retList;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static const QStringList &supportedFragmentShaderSuffixes()
|
||||||
|
{
|
||||||
|
static const QStringList retList {"frag", "glsl", "glslf", "fsh"};
|
||||||
|
return retList;
|
||||||
|
}
|
||||||
|
|
||||||
static const QStringList &supportedShaderSuffixes()
|
static const QStringList &supportedShaderSuffixes()
|
||||||
{
|
{
|
||||||
static const QStringList retList {"frag", "vert",
|
static const QStringList retList {"frag", "vert",
|
||||||
@@ -131,6 +137,14 @@ static QPixmap generateFontImage(const QFileInfo &info, const QSize &size)
|
|||||||
return fontImageCache[key];
|
return fontImageCache[key];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QString fontFamily(const QFileInfo &info)
|
||||||
|
{
|
||||||
|
QRawFont font(info.absoluteFilePath(), 10);
|
||||||
|
if (font.isValid())
|
||||||
|
return font.familyName();
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
class ItemLibraryFileIconProvider : public QFileIconProvider
|
class ItemLibraryFileIconProvider : public QFileIconProvider
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@@ -147,7 +161,7 @@ public:
|
|||||||
|
|
||||||
if (supportedImageSuffixes().contains(suffix))
|
if (supportedImageSuffixes().contains(suffix))
|
||||||
pixmap.load(info.absoluteFilePath());
|
pixmap.load(info.absoluteFilePath());
|
||||||
else if (supportedFontSuffixes().contains(suffix))
|
else if (supportedFontSuffixes().contains(suffix))
|
||||||
pixmap = generateFontImage(info, iconSize);
|
pixmap = generateFontImage(info, iconSize);
|
||||||
|
|
||||||
if (pixmap.isNull())
|
if (pixmap.isNull())
|
||||||
@@ -162,8 +176,8 @@ public:
|
|||||||
return icon;
|
return icon;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Generated icon sizes should match ItemLibraryResourceView icon sizes
|
// Generated icon sizes should match ItemLibraryResourceView needed icon sizes
|
||||||
QList<QSize> iconSizes = {{192, 192}, {96, 96}, {48, 48}, {32, 32}};
|
QList<QSize> iconSizes = {{192, 192}, {128, 128}, {96, 96}, {48, 48}, {32, 32}};
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -274,6 +288,29 @@ void CustomFileSystemModel::setSearchFilter(const QString &nameFilterList)
|
|||||||
setRootPath(m_fileSystemModel->rootPath());
|
setRootPath(m_fileSystemModel->rootPath());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QPair<QString, QByteArray> CustomFileSystemModel::resourceTypeAndData(const QModelIndex &index) const
|
||||||
|
{
|
||||||
|
QFileInfo fi = fileInfo(index);
|
||||||
|
QString suffix = fi.suffix();
|
||||||
|
if (!suffix.isEmpty()) {
|
||||||
|
if (supportedImageSuffixes().contains(suffix)) {
|
||||||
|
// Data: Image format (suffix)
|
||||||
|
return {"application/vnd.bauhaus.libraryresource.image", suffix.toUtf8()};
|
||||||
|
} else if (supportedFontSuffixes().contains(suffix)) {
|
||||||
|
// Data: Font family name
|
||||||
|
return {"application/vnd.bauhaus.libraryresource.font", fontFamily(fi).toUtf8()};
|
||||||
|
} else if (supportedShaderSuffixes().contains(suffix)) {
|
||||||
|
// Data: shader type, frament (f) or vertex (v)
|
||||||
|
return {"application/vnd.bauhaus.libraryresource.shader",
|
||||||
|
supportedFragmentShaderSuffixes().contains(suffix) ? "f" : "v"};
|
||||||
|
} else if (supportedAudioSuffixes().contains(suffix)) {
|
||||||
|
// No extra data for sounds
|
||||||
|
return {"application/vnd.bauhaus.libraryresource.sound", {}};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
void CustomFileSystemModel::appendIfNotFiltered(const QString &file)
|
void CustomFileSystemModel::appendIfNotFiltered(const QString &file)
|
||||||
{
|
{
|
||||||
if (filterMetaIcons(file))
|
if (filterMetaIcons(file))
|
||||||
|
@@ -27,6 +27,7 @@
|
|||||||
|
|
||||||
#include <QAbstractTableModel>
|
#include <QAbstractTableModel>
|
||||||
#include <QDir>
|
#include <QDir>
|
||||||
|
#include <QPair>
|
||||||
|
|
||||||
QT_BEGIN_NAMESPACE
|
QT_BEGIN_NAMESPACE
|
||||||
class QFileIconProvider;
|
class QFileIconProvider;
|
||||||
@@ -60,6 +61,8 @@ public:
|
|||||||
Qt::ItemFlags flags(const QModelIndex &index) const override;
|
Qt::ItemFlags flags(const QModelIndex &index) const override;
|
||||||
void setSearchFilter(const QString &nameFilterList);
|
void setSearchFilter(const QString &nameFilterList);
|
||||||
|
|
||||||
|
QPair<QString, QByteArray> resourceTypeAndData(const QModelIndex &index) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QModelIndex updatePath(const QString &newPath);
|
QModelIndex updatePath(const QString &newPath);
|
||||||
QModelIndex fileSystemModelIndex(const QModelIndex &index) const;
|
QModelIndex fileSystemModelIndex(const QModelIndex &index) const;
|
||||||
|
@@ -108,23 +108,32 @@ void ItemLibraryResourceView::startDrag(Qt::DropActions /* supportedActions */)
|
|||||||
{
|
{
|
||||||
if (debug)
|
if (debug)
|
||||||
qDebug() << Q_FUNC_INFO;
|
qDebug() << Q_FUNC_INFO;
|
||||||
QMimeData *mimeData = model()->mimeData(selectedIndexes());
|
|
||||||
|
|
||||||
if (!mimeData)
|
const auto indexes = selectedIndexes();
|
||||||
|
if (indexes.isEmpty())
|
||||||
|
return;
|
||||||
|
|
||||||
|
const QModelIndex &index = indexes.constFirst();
|
||||||
|
if (!index.isValid())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
auto fileSystemModel = qobject_cast<CustomFileSystemModel*>(model());
|
auto fileSystemModel = qobject_cast<CustomFileSystemModel*>(model());
|
||||||
Q_ASSERT(fileSystemModel);
|
Q_ASSERT(fileSystemModel);
|
||||||
QFileInfo fileInfo = fileSystemModel->fileInfo(selectedIndexes().constFirst());
|
QPair<QString, QByteArray> typeAndData = fileSystemModel->resourceTypeAndData(index);
|
||||||
QPixmap pixmap(fileInfo.absoluteFilePath());
|
|
||||||
if (!pixmap.isNull()) {
|
if (typeAndData.first.isEmpty())
|
||||||
auto drag = new QDrag(this);
|
return;
|
||||||
drag->setPixmap(QIcon(pixmap).pixmap(128, 128));
|
|
||||||
auto mimeData = new QMimeData;
|
QFileInfo fileInfo = fileSystemModel->fileInfo(index);
|
||||||
mimeData->setData(QLatin1String("application/vnd.bauhaus.libraryresource"), fileInfo.absoluteFilePath().toUtf8());
|
|
||||||
drag->setMimeData(mimeData);
|
auto drag = new QDrag(this);
|
||||||
drag->exec();
|
drag->setPixmap(fileSystemModel->fileIcon(index).pixmap(128, 128));
|
||||||
}
|
QMimeData *mimeData = new QMimeData;
|
||||||
|
mimeData->setData(QLatin1String("application/vnd.bauhaus.libraryresource"),
|
||||||
|
fileInfo.absoluteFilePath().toUtf8());
|
||||||
|
mimeData->setData(typeAndData.first, typeAndData.second);
|
||||||
|
drag->setMimeData(mimeData);
|
||||||
|
drag->exec();
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace QmlDesigner
|
} // namespace QmlDesigner
|
||||||
|
@@ -41,6 +41,7 @@
|
|||||||
#include <rewritingexception.h>
|
#include <rewritingexception.h>
|
||||||
#include <qmlitemnode.h>
|
#include <qmlitemnode.h>
|
||||||
#include <designeractionmanager.h>
|
#include <designeractionmanager.h>
|
||||||
|
#include <import.h>
|
||||||
|
|
||||||
#include <coreplugin/icore.h>
|
#include <coreplugin/icore.h>
|
||||||
|
|
||||||
@@ -498,8 +499,14 @@ bool NavigatorTreeModel::dropMimeData(const QMimeData *mimeData,
|
|||||||
if (dropModelIndex.model() == this) {
|
if (dropModelIndex.model() == this) {
|
||||||
if (mimeData->hasFormat("application/vnd.bauhaus.itemlibraryinfo")) {
|
if (mimeData->hasFormat("application/vnd.bauhaus.itemlibraryinfo")) {
|
||||||
handleItemLibraryItemDrop(mimeData, rowNumber, dropModelIndex);
|
handleItemLibraryItemDrop(mimeData, rowNumber, dropModelIndex);
|
||||||
} else if (mimeData->hasFormat("application/vnd.bauhaus.libraryresource")) {
|
} else if (mimeData->hasFormat("application/vnd.bauhaus.libraryresource.image")) {
|
||||||
handleItemLibraryImageDrop(mimeData, rowNumber, dropModelIndex);
|
handleItemLibraryImageDrop(mimeData, rowNumber, dropModelIndex);
|
||||||
|
} else if (mimeData->hasFormat("application/vnd.bauhaus.libraryresource.font")) {
|
||||||
|
handleItemLibraryFontDrop(mimeData, rowNumber, dropModelIndex);
|
||||||
|
} else if (mimeData->hasFormat("application/vnd.bauhaus.libraryresource.shader")) {
|
||||||
|
handleItemLibraryShaderDrop(mimeData, rowNumber, dropModelIndex);
|
||||||
|
} else if (mimeData->hasFormat("application/vnd.bauhaus.libraryresource.sound")) {
|
||||||
|
handleItemLibrarySoundDrop(mimeData, rowNumber, dropModelIndex);
|
||||||
} else if (mimeData->hasFormat("application/vnd.modelnode.list")) {
|
} else if (mimeData->hasFormat("application/vnd.modelnode.list")) {
|
||||||
handleInternalDrop(mimeData, rowNumber, dropModelIndex);
|
handleInternalDrop(mimeData, rowNumber, dropModelIndex);
|
||||||
}
|
}
|
||||||
@@ -772,8 +779,10 @@ void NavigatorTreeModel::handleItemLibraryImageDrop(const QMimeData *mimeData, i
|
|||||||
targetNode.bindingProperty("texture").setExpression(newModelNode.validId());
|
targetNode.bindingProperty("texture").setExpression(newModelNode.validId());
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
} else if (targetNode.isSubclassOf("QtQuick3D.Texture")) {
|
} else if (targetNode.isSubclassOf("QtQuick3D.Texture")
|
||||||
// if dropping an image on a texture, set the texture source
|
|| targetNode.isSubclassOf("QtQuick.Image")
|
||||||
|
|| targetNode.isSubclassOf("QtQuick.BorderImage")) {
|
||||||
|
// if dropping an image on an existing texture or image, set the source
|
||||||
targetNode.variantProperty("source").setValue(imagePath);
|
targetNode.variantProperty("source").setValue(imagePath);
|
||||||
} else {
|
} else {
|
||||||
m_view->executeInTransaction("NavigatorTreeModel::handleItemLibraryImageDrop", [&] {
|
m_view->executeInTransaction("NavigatorTreeModel::handleItemLibraryImageDrop", [&] {
|
||||||
@@ -793,6 +802,162 @@ void NavigatorTreeModel::handleItemLibraryImageDrop(const QMimeData *mimeData, i
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void NavigatorTreeModel::handleItemLibraryFontDrop(const QMimeData *mimeData, int rowNumber,
|
||||||
|
const QModelIndex &dropModelIndex)
|
||||||
|
{
|
||||||
|
QTC_ASSERT(m_view, return);
|
||||||
|
const QModelIndex rowModelIndex = dropModelIndex.sibling(dropModelIndex.row(), 0);
|
||||||
|
int targetRowNumber = rowNumber;
|
||||||
|
NodeAbstractProperty targetProperty;
|
||||||
|
|
||||||
|
bool foundTarget = findTargetProperty(rowModelIndex, this, &targetProperty, &targetRowNumber);
|
||||||
|
if (foundTarget) {
|
||||||
|
ModelNode targetNode(modelNodeForIndex(rowModelIndex));
|
||||||
|
|
||||||
|
const QString fontFamily = QString::fromUtf8(
|
||||||
|
mimeData->data("application/vnd.bauhaus.libraryresource.font"));
|
||||||
|
|
||||||
|
ModelNode newModelNode;
|
||||||
|
|
||||||
|
m_view->executeInTransaction("NavigatorTreeModel::handleItemLibraryFontDrop", [&] {
|
||||||
|
if (targetNode.isSubclassOf("QtQuick.Text")) {
|
||||||
|
// if dropping into an existing Text, update font
|
||||||
|
targetNode.variantProperty("font.family").setValue(fontFamily);
|
||||||
|
} else {
|
||||||
|
// create a Text node
|
||||||
|
QmlItemNode newItemNode = QmlItemNode::createQmlItemNodeFromFont(
|
||||||
|
m_view, fontFamily, QPointF(), targetProperty, false);
|
||||||
|
if (NodeHints::fromModelNode(targetProperty.parentModelNode()).canBeContainerFor(newItemNode.modelNode()))
|
||||||
|
newModelNode = newItemNode.modelNode();
|
||||||
|
else
|
||||||
|
newItemNode.destroy();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
if (newModelNode.isValid()) {
|
||||||
|
moveNodesInteractive(targetProperty, {newModelNode}, targetRowNumber);
|
||||||
|
m_view->setSelectedModelNode(newModelNode);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void NavigatorTreeModel::handleItemLibraryShaderDrop(const QMimeData *mimeData, int rowNumber,
|
||||||
|
const QModelIndex &dropModelIndex)
|
||||||
|
{
|
||||||
|
QTC_ASSERT(m_view, return);
|
||||||
|
Import import = Import::createLibraryImport(QStringLiteral("QtQuick3D"));
|
||||||
|
if (!m_view->model()->hasImport(import, true, true))
|
||||||
|
return;
|
||||||
|
|
||||||
|
const QModelIndex rowModelIndex = dropModelIndex.sibling(dropModelIndex.row(), 0);
|
||||||
|
int targetRowNumber = rowNumber;
|
||||||
|
NodeAbstractProperty targetProperty;
|
||||||
|
|
||||||
|
bool foundTarget = findTargetProperty(rowModelIndex, this, &targetProperty, &targetRowNumber);
|
||||||
|
if (foundTarget) {
|
||||||
|
ModelNode targetNode(modelNodeForIndex(rowModelIndex));
|
||||||
|
ModelNode newModelNode;
|
||||||
|
|
||||||
|
const QString shaderSource = QString::fromUtf8(mimeData->data("application/vnd.bauhaus.libraryresource"));
|
||||||
|
const bool fragShader = mimeData->data("application/vnd.bauhaus.libraryresource.shader").startsWith('f');
|
||||||
|
const QString relPath = DocumentManager::currentFilePath().toFileInfo().dir().relativeFilePath(shaderSource);
|
||||||
|
|
||||||
|
m_view->executeInTransaction("NavigatorTreeModel::handleItemLibraryShaderDrop", [&] {
|
||||||
|
if (targetNode.isSubclassOf("QtQuick3D.Shader")) {
|
||||||
|
// if dropping into an existing Shader, update
|
||||||
|
if (fragShader)
|
||||||
|
targetNode.variantProperty("stage").setEnumeration("Shader.Fragment");
|
||||||
|
else
|
||||||
|
targetNode.variantProperty("stage").setEnumeration("Shader.Vertex");
|
||||||
|
targetNode.variantProperty("shader").setValue(relPath);
|
||||||
|
} else {
|
||||||
|
// create a new Shader
|
||||||
|
ItemLibraryEntry itemLibraryEntry;
|
||||||
|
itemLibraryEntry.setName("Shader");
|
||||||
|
itemLibraryEntry.setType("QtQuick3D.Shader", 1, 0);
|
||||||
|
|
||||||
|
// set shader properties
|
||||||
|
PropertyName prop = "shader";
|
||||||
|
QString type = "QByteArray";
|
||||||
|
QVariant val = relPath;
|
||||||
|
itemLibraryEntry.addProperty(prop, type, val);
|
||||||
|
prop = "stage";
|
||||||
|
type = "enum";
|
||||||
|
val = fragShader ? "Shader.Fragment" : "Shader.Vertex";
|
||||||
|
itemLibraryEntry.addProperty(prop, type, val);
|
||||||
|
|
||||||
|
// create a texture
|
||||||
|
newModelNode = QmlItemNode::createQmlObjectNode(m_view, itemLibraryEntry, {},
|
||||||
|
targetProperty, false);
|
||||||
|
|
||||||
|
// Rename the node based on shader source
|
||||||
|
QFileInfo fi(relPath);
|
||||||
|
newModelNode.setIdWithoutRefactoring(m_view->generateNewId(fi.baseName(),
|
||||||
|
"shader"));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
if (newModelNode.isValid()) {
|
||||||
|
moveNodesInteractive(targetProperty, {newModelNode}, targetRowNumber);
|
||||||
|
m_view->setSelectedModelNode(newModelNode);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void NavigatorTreeModel::handleItemLibrarySoundDrop(const QMimeData *mimeData, int rowNumber,
|
||||||
|
const QModelIndex &dropModelIndex)
|
||||||
|
{
|
||||||
|
QTC_ASSERT(m_view, return);
|
||||||
|
Import import = Import::createLibraryImport(QStringLiteral("QtMultimedia"));
|
||||||
|
if (!m_view->model()->hasImport(import, true, true))
|
||||||
|
return;
|
||||||
|
|
||||||
|
const QModelIndex rowModelIndex = dropModelIndex.sibling(dropModelIndex.row(), 0);
|
||||||
|
int targetRowNumber = rowNumber;
|
||||||
|
NodeAbstractProperty targetProperty;
|
||||||
|
|
||||||
|
bool foundTarget = findTargetProperty(rowModelIndex, this, &targetProperty, &targetRowNumber);
|
||||||
|
if (foundTarget) {
|
||||||
|
ModelNode targetNode(modelNodeForIndex(rowModelIndex));
|
||||||
|
ModelNode newModelNode;
|
||||||
|
|
||||||
|
const QString soundSource = QString::fromUtf8(mimeData->data("application/vnd.bauhaus.libraryresource"));
|
||||||
|
const QString relPath = DocumentManager::currentFilePath().toFileInfo().dir().relativeFilePath(soundSource);
|
||||||
|
|
||||||
|
m_view->executeInTransaction("NavigatorTreeModel::handleItemLibrarySoundDrop", [&] {
|
||||||
|
if (targetNode.isSubclassOf("QtMultimedia.SoundEffect")) {
|
||||||
|
// if dropping into on an existing SoundEffect, update
|
||||||
|
targetNode.variantProperty("source").setValue(relPath);
|
||||||
|
} else {
|
||||||
|
// create a new SoundEffect
|
||||||
|
ItemLibraryEntry itemLibraryEntry;
|
||||||
|
itemLibraryEntry.setName("SoundEffect");
|
||||||
|
itemLibraryEntry.setType("QtMultimedia.SoundEffect", 1, 0);
|
||||||
|
|
||||||
|
// set shader properties
|
||||||
|
PropertyName prop = "source";
|
||||||
|
QString type = "QUrl";
|
||||||
|
QVariant val = relPath;
|
||||||
|
itemLibraryEntry.addProperty(prop, type, val);
|
||||||
|
|
||||||
|
// create a texture
|
||||||
|
newModelNode = QmlItemNode::createQmlObjectNode(m_view, itemLibraryEntry, {},
|
||||||
|
targetProperty, false);
|
||||||
|
|
||||||
|
// Rename the node based on source
|
||||||
|
QFileInfo fi(relPath);
|
||||||
|
newModelNode.setIdWithoutRefactoring(m_view->generateNewId(fi.baseName(),
|
||||||
|
"soundEffect"));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
if (newModelNode.isValid()) {
|
||||||
|
moveNodesInteractive(targetProperty, {newModelNode}, targetRowNumber);
|
||||||
|
m_view->setSelectedModelNode(newModelNode);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
TypeName propertyType(const NodeAbstractProperty &property)
|
TypeName propertyType(const NodeAbstractProperty &property)
|
||||||
{
|
{
|
||||||
return property.parentModelNode().metaInfo().propertyTypeName(property.name());
|
return property.parentModelNode().metaInfo().propertyTypeName(property.name());
|
||||||
|
@@ -115,6 +115,9 @@ private:
|
|||||||
void handleInternalDrop(const QMimeData *mimeData, int rowNumber, const QModelIndex &dropModelIndex);
|
void handleInternalDrop(const QMimeData *mimeData, int rowNumber, const QModelIndex &dropModelIndex);
|
||||||
void handleItemLibraryItemDrop(const QMimeData *mimeData, int rowNumber, const QModelIndex &dropModelIndex);
|
void handleItemLibraryItemDrop(const QMimeData *mimeData, int rowNumber, const QModelIndex &dropModelIndex);
|
||||||
void handleItemLibraryImageDrop(const QMimeData *mimeData, int rowNumber, const QModelIndex &dropModelIndex);
|
void handleItemLibraryImageDrop(const QMimeData *mimeData, int rowNumber, const QModelIndex &dropModelIndex);
|
||||||
|
void handleItemLibraryFontDrop(const QMimeData *mimeData, int rowNumber, const QModelIndex &dropModelIndex);
|
||||||
|
void handleItemLibraryShaderDrop(const QMimeData *mimeData, int rowNumber, const QModelIndex &dropModelIndex);
|
||||||
|
void handleItemLibrarySoundDrop(const QMimeData *mimeData, int rowNumber, const QModelIndex &dropModelIndex);
|
||||||
QList<QPersistentModelIndex> nodesToPersistentIndex(const QList<ModelNode> &modelNodes);
|
QList<QPersistentModelIndex> nodesToPersistentIndex(const QList<ModelNode> &modelNodes);
|
||||||
|
|
||||||
QPointer<NavigatorView> m_view;
|
QPointer<NavigatorView> m_view;
|
||||||
|
@@ -69,6 +69,17 @@ public:
|
|||||||
NodeAbstractProperty parentproperty,
|
NodeAbstractProperty parentproperty,
|
||||||
bool executeInTransaction = true);
|
bool executeInTransaction = true);
|
||||||
|
|
||||||
|
static QmlItemNode createQmlItemNodeFromFont(AbstractView *view,
|
||||||
|
const QString &fontFamily,
|
||||||
|
const QPointF &position,
|
||||||
|
QmlItemNode parentQmlItemNode,
|
||||||
|
bool executeInTransaction = true);
|
||||||
|
static QmlItemNode createQmlItemNodeFromFont(AbstractView *view,
|
||||||
|
const QString &fontFamily,
|
||||||
|
const QPointF &position,
|
||||||
|
NodeAbstractProperty parentproperty,
|
||||||
|
bool executeInTransaction = true);
|
||||||
|
|
||||||
QList<QmlItemNode> children() const;
|
QList<QmlItemNode> children() const;
|
||||||
QList<QmlObjectNode> resources() const;
|
QList<QmlObjectNode> resources() const;
|
||||||
QList<QmlObjectNode> allDirectSubNodes() const;
|
QList<QmlObjectNode> allDirectSubNodes() const;
|
||||||
|
@@ -43,6 +43,7 @@
|
|||||||
#include <QPlainTextEdit>
|
#include <QPlainTextEdit>
|
||||||
#include <QFileInfo>
|
#include <QFileInfo>
|
||||||
#include <QDir>
|
#include <QDir>
|
||||||
|
#include <QImageReader>
|
||||||
|
|
||||||
#include <utils/qtcassert.h>
|
#include <utils/qtcassert.h>
|
||||||
|
|
||||||
@@ -106,7 +107,12 @@ QmlItemNode QmlItemNode::createQmlItemNodeFromImage(AbstractView *view, const QS
|
|||||||
propertyPairList.append({PropertyName("source"), QVariant(relativeImageName)});
|
propertyPairList.append({PropertyName("source"), QVariant(relativeImageName)});
|
||||||
}
|
}
|
||||||
|
|
||||||
newQmlItemNode = QmlItemNode(view->createModelNode("QtQuick.Image", metaInfo.majorVersion(), metaInfo.minorVersion(), propertyPairList));
|
TypeName type("QtQuick.Image");
|
||||||
|
QImageReader reader(imageName);
|
||||||
|
if (reader.supportsAnimation())
|
||||||
|
type = "QtQuick.AnimatedImage";
|
||||||
|
|
||||||
|
newQmlItemNode = QmlItemNode(view->createModelNode(type, metaInfo.majorVersion(), metaInfo.minorVersion(), propertyPairList));
|
||||||
parentproperty.reparentHere(newQmlItemNode);
|
parentproperty.reparentHere(newQmlItemNode);
|
||||||
|
|
||||||
QFileInfo fi(relativeImageName);
|
QFileInfo fi(relativeImageName);
|
||||||
@@ -125,6 +131,54 @@ QmlItemNode QmlItemNode::createQmlItemNodeFromImage(AbstractView *view, const QS
|
|||||||
return newQmlItemNode;
|
return newQmlItemNode;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QmlItemNode QmlItemNode::createQmlItemNodeFromFont(AbstractView *view,
|
||||||
|
const QString &fontFamily,
|
||||||
|
const QPointF &position,
|
||||||
|
QmlItemNode parentQmlItemNode,
|
||||||
|
bool executeInTransaction)
|
||||||
|
{
|
||||||
|
if (!parentQmlItemNode.isValid())
|
||||||
|
parentQmlItemNode = QmlItemNode(view->rootModelNode());
|
||||||
|
|
||||||
|
NodeAbstractProperty parentProperty = parentQmlItemNode.defaultNodeAbstractProperty();
|
||||||
|
|
||||||
|
return QmlItemNode::createQmlItemNodeFromFont(view, fontFamily, position,
|
||||||
|
parentProperty, executeInTransaction);
|
||||||
|
}
|
||||||
|
|
||||||
|
QmlItemNode QmlItemNode::createQmlItemNodeFromFont(AbstractView *view,
|
||||||
|
const QString &fontFamily,
|
||||||
|
const QPointF &position,
|
||||||
|
NodeAbstractProperty parentproperty,
|
||||||
|
bool executeInTransaction)
|
||||||
|
{
|
||||||
|
QmlItemNode newQmlItemNode;
|
||||||
|
|
||||||
|
auto doCreateQmlItemNodeFromFont = [=, &newQmlItemNode, &parentproperty]() {
|
||||||
|
NodeMetaInfo metaInfo = view->model()->metaInfo("QtQuick.Text");
|
||||||
|
QList<QPair<PropertyName, QVariant>> propertyPairList;
|
||||||
|
propertyPairList.append({PropertyName("x"), QVariant(qRound(position.x()))});
|
||||||
|
propertyPairList.append({PropertyName("y"), QVariant(qRound(position.y()))});
|
||||||
|
propertyPairList.append({PropertyName("font.family"), QVariant(fontFamily)});
|
||||||
|
propertyPairList.append({PropertyName("text"), QVariant(fontFamily)});
|
||||||
|
|
||||||
|
newQmlItemNode = QmlItemNode(view->createModelNode("QtQuick.Text", metaInfo.majorVersion(),
|
||||||
|
metaInfo.minorVersion(), propertyPairList));
|
||||||
|
parentproperty.reparentHere(newQmlItemNode);
|
||||||
|
|
||||||
|
newQmlItemNode.setId(view->generateNewId("text", "text"));
|
||||||
|
|
||||||
|
Q_ASSERT(newQmlItemNode.isValid());
|
||||||
|
};
|
||||||
|
|
||||||
|
if (executeInTransaction)
|
||||||
|
view->executeInTransaction("QmlItemNode::createQmlItemNodeFromImage", doCreateQmlItemNodeFromFont);
|
||||||
|
else
|
||||||
|
doCreateQmlItemNodeFromFont();
|
||||||
|
|
||||||
|
return newQmlItemNode;
|
||||||
|
}
|
||||||
|
|
||||||
bool QmlItemNode::isValid() const
|
bool QmlItemNode::isValid() const
|
||||||
{
|
{
|
||||||
return isValidQmlItemNode(modelNode());
|
return isValidQmlItemNode(modelNode());
|
||||||
|
Reference in New Issue
Block a user