forked from qt-creator/qt-creator
QmlDesigner: Show and edit texture name instead of ID in MaterialBrowser
Task-number: QDS-13024 Change-Id: I7cb223caf1577942fc273004f0e08df5569c2af0 Reviewed-by: Mahmoud Badri <mahmoud.badri@qt.io> Reviewed-by: Miikka Heikkinen <miikka.heikkinen@qt.io>
This commit is contained in:
@@ -23,7 +23,7 @@ TextInput {
|
||||
selectedTextColor: StudioTheme.Values.themeTextSelectedTextColor
|
||||
|
||||
// allow only alphanumeric characters, underscores, no space at start, and 1 space between words
|
||||
validator: RegExpValidator { regExp: /^(\w+\s)*\w+$/ }
|
||||
validator: RegularExpressionValidator { regularExpression: /^(\w+\s)*\w+$/ }
|
||||
|
||||
signal renamed(string newName)
|
||||
signal clicked()
|
||||
|
@@ -16,7 +16,7 @@ Item {
|
||||
signal showContextMenu()
|
||||
|
||||
function forceFinishEditing() {
|
||||
txtId.commitRename()
|
||||
txtName.commitRename()
|
||||
}
|
||||
|
||||
MouseArea {
|
||||
@@ -76,16 +76,14 @@ Item {
|
||||
}
|
||||
|
||||
MaterialBrowserItemName {
|
||||
id: txtId
|
||||
id: txtName
|
||||
|
||||
text: textureId
|
||||
text: textureName
|
||||
width: img.width
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
|
||||
validator: RegularExpressionValidator { regularExpression: /(^$|^[a-z_]\w*$)/ }
|
||||
|
||||
onRenamed: (newId) => {
|
||||
MaterialBrowserBackend.materialBrowserTexturesModel.setTextureId(index, newId);
|
||||
onRenamed: (newName) => {
|
||||
MaterialBrowserBackend.materialBrowserTexturesModel.setTextureName(index, newName);
|
||||
mouseArea.forceActiveFocus()
|
||||
}
|
||||
|
||||
|
@@ -34,30 +34,30 @@ QVariant MaterialBrowserTexturesModel::data(const QModelIndex &index, int role)
|
||||
QTC_ASSERT(index.isValid() && index.row() < m_textureList.size(), return {});
|
||||
QTC_ASSERT(roleNames().contains(role), return {});
|
||||
|
||||
if (role == RoleTexSource) {
|
||||
switch (role) {
|
||||
case RoleTexVisible:
|
||||
return isVisible(index.row());
|
||||
case RoleTexHasDynamicProps:
|
||||
return !m_textureList.at(index.row()).dynamicProperties().isEmpty();
|
||||
case RoleTexInternalId:
|
||||
return m_textureList.at(index.row()).internalId();
|
||||
case RoleTexName:
|
||||
return m_textureList.at(index.row()).variantProperty("objectName").value();
|
||||
case RoleTexSource: {
|
||||
QString source = QmlObjectNode(m_textureList.at(index.row())).modelValue("source").toString();
|
||||
if (source.isEmpty())
|
||||
return {};
|
||||
if (Utils::FilePath::fromString(source).isAbsolutePath())
|
||||
return QVariant(source);
|
||||
return QVariant(QmlDesignerPlugin::instance()->documentManager().currentDesignDocument()
|
||||
->fileName().absolutePath().pathAppended(source).cleanPath().toString());
|
||||
}
|
||||
|
||||
if (role == RoleTexVisible)
|
||||
return isVisible(index.row());
|
||||
|
||||
if (role == RoleTexHasDynamicProps)
|
||||
return !m_textureList.at(index.row()).dynamicProperties().isEmpty();
|
||||
|
||||
if (role == RoleTexInternalId)
|
||||
return m_textureList.at(index.row()).internalId();
|
||||
|
||||
if (role == RoleTexId) {
|
||||
return m_textureList.at(index.row()).id();
|
||||
}
|
||||
|
||||
if (role == RoleTexToolTip) {
|
||||
return QVariant(QmlDesignerPlugin::instance()
|
||||
->documentManager()
|
||||
.currentDesignDocument()
|
||||
->fileName()
|
||||
.absolutePath()
|
||||
.pathAppended(source)
|
||||
.toFSPathString());
|
||||
};
|
||||
case RoleTexToolTip: {
|
||||
QString source = data(index, RoleTexSource).toString(); // absolute path
|
||||
if (source.isEmpty())
|
||||
return tr("Texture has no source image.");
|
||||
@@ -68,12 +68,14 @@ QVariant MaterialBrowserTexturesModel::data(const QModelIndex &index, int role)
|
||||
if (info.isEmpty())
|
||||
return tr("Texture has no data.");
|
||||
|
||||
QString textName = data(index, RoleTexName).toString();
|
||||
QString sourceRelative = QmlObjectNode(texNode).modelValue("source").toString();
|
||||
return QLatin1String("%1\n%2\n%3").arg(texNode.id(), sourceRelative, info);
|
||||
}
|
||||
|
||||
return QLatin1String("%1 (%2)\n%3\n%4").arg(textName, texNode.id(), sourceRelative, info);
|
||||
};
|
||||
default:
|
||||
return {};
|
||||
}
|
||||
}
|
||||
|
||||
bool MaterialBrowserTexturesModel::isVisible(int idx) const
|
||||
{
|
||||
@@ -94,10 +96,10 @@ QHash<int, QByteArray> MaterialBrowserTexturesModel::roleNames() const
|
||||
static const QHash<int, QByteArray> roles{
|
||||
{RoleTexHasDynamicProps, "hasDynamicProperties"},
|
||||
{RoleTexInternalId, "textureInternalId"},
|
||||
{RoleTexId, "textureId"},
|
||||
{RoleTexName, "textureName"},
|
||||
{RoleTexSource, "textureSource"},
|
||||
{RoleTexToolTip, "textureToolTip"},
|
||||
{RoleTexVisible, "textureVisible"}
|
||||
{RoleTexVisible, "textureVisible"},
|
||||
};
|
||||
return roles;
|
||||
}
|
||||
@@ -210,7 +212,14 @@ void MaterialBrowserTexturesModel::updateTextureId(const ModelNode &texture)
|
||||
{
|
||||
int idx = textureIndex(texture);
|
||||
if (idx != -1)
|
||||
emit dataChanged(index(idx, 0), index(idx, 0), {RoleTexId, RoleTexSource, RoleTexToolTip});
|
||||
emit dataChanged(index(idx, 0), index(idx, 0), {RoleTexToolTip});
|
||||
}
|
||||
|
||||
void MaterialBrowserTexturesModel::updateTextureName(const ModelNode &texture)
|
||||
{
|
||||
int idx = textureIndex(texture);
|
||||
if (idx != -1)
|
||||
emit dataChanged(index(idx, 0), index(idx, 0), {RoleTexName, RoleTexToolTip});
|
||||
}
|
||||
|
||||
void MaterialBrowserTexturesModel::updateAllTexturesSources()
|
||||
@@ -311,7 +320,7 @@ void MaterialBrowserTexturesModel::deleteTexture(int idx)
|
||||
}
|
||||
}
|
||||
|
||||
void MaterialBrowserTexturesModel::setTextureId(int idx, const QString &newId)
|
||||
void MaterialBrowserTexturesModel::setTextureName(int idx, const QString &newName)
|
||||
{
|
||||
if (!isValidIndex(idx))
|
||||
return;
|
||||
@@ -320,14 +329,17 @@ void MaterialBrowserTexturesModel::setTextureId(int idx, const QString &newId)
|
||||
if (!node.isValid())
|
||||
return;
|
||||
|
||||
if (node.id() != newId) {
|
||||
QString nodeId;
|
||||
if (!newId.isEmpty()) {
|
||||
const auto model = m_view->model();
|
||||
VariantProperty objectNameProperty = node.variantProperty("objectName");
|
||||
QString oldName = objectNameProperty.value().toString();
|
||||
|
||||
if (oldName != newName) {
|
||||
const Model *model = m_view->model();
|
||||
QTC_ASSERT(model, return);
|
||||
nodeId = model->generateNewId(newId);
|
||||
}
|
||||
node.setIdWithRefactoring(nodeId);
|
||||
|
||||
m_view->executeInTransaction(__FUNCTION__, [&] {
|
||||
node.setIdWithRefactoring(model->generateNewId(newName, "texture"));
|
||||
objectNameProperty.setValue(newName);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -39,6 +39,7 @@ public:
|
||||
void updateSelectedTexture();
|
||||
void updateTextureSource(const ModelNode &texture);
|
||||
void updateTextureId(const ModelNode &texture);
|
||||
void updateTextureName(const ModelNode &texture);
|
||||
void updateAllTexturesSources();
|
||||
int textureIndex(const ModelNode &texture) const;
|
||||
ModelNode textureAt(int idx) const;
|
||||
@@ -58,7 +59,7 @@ public:
|
||||
Q_INVOKABLE void addNewTexture();
|
||||
Q_INVOKABLE void duplicateTexture(int idx);
|
||||
Q_INVOKABLE void deleteTexture(int idx);
|
||||
Q_INVOKABLE void setTextureId(int idx, const QString &newId);
|
||||
Q_INVOKABLE void setTextureName(int idx, const QString &newName);
|
||||
Q_INVOKABLE void applyToSelectedMaterial(qint64 internalId);
|
||||
Q_INVOKABLE void applyToSelectedModel(qint64 internalId);
|
||||
Q_INVOKABLE void openTextureEditor();
|
||||
@@ -97,7 +98,7 @@ private:
|
||||
enum {
|
||||
RoleTexHasDynamicProps = Qt::UserRole + 1,
|
||||
RoleTexInternalId,
|
||||
RoleTexId,
|
||||
RoleTexName,
|
||||
RoleTexSource,
|
||||
RoleTexToolTip,
|
||||
RoleTexVisible
|
||||
|
@@ -290,11 +290,15 @@ void MaterialBrowserView::updatePropertyList(const QList<T> &propertyList)
|
||||
m_widget->materialBrowserModel()->updateMaterialName(node);
|
||||
else
|
||||
m_previewRequests << node;
|
||||
} else if (property.name() == "source") {
|
||||
} else if (isTexture(node)) {
|
||||
QmlObjectNode selectedTex = m_widget->materialBrowserTexturesModel()->selectedTexture();
|
||||
if (isTexture(node))
|
||||
if (property.name() == "source")
|
||||
m_widget->materialBrowserTexturesModel()->updateTextureSource(node);
|
||||
else if (selectedTex.propertyChangeForCurrentState() == node)
|
||||
else if (property.name() == "objectName")
|
||||
m_widget->materialBrowserTexturesModel()->updateTextureName(node);
|
||||
} else {
|
||||
QmlObjectNode selectedTex = m_widget->materialBrowserTexturesModel()->selectedTexture();
|
||||
if (property.name() == "source" && selectedTex.propertyChangeForCurrentState() == node)
|
||||
m_widget->materialBrowserTexturesModel()->updateTextureSource(selectedTex);
|
||||
}
|
||||
}
|
||||
|
@@ -48,6 +48,43 @@
|
||||
#include <QTimer>
|
||||
#include <QColorDialog>
|
||||
|
||||
using namespace Qt::StringLiterals;
|
||||
|
||||
namespace {
|
||||
|
||||
QString nameFromId(const QString &id, const QString &defaultName)
|
||||
{
|
||||
if (id.isEmpty())
|
||||
return defaultName;
|
||||
|
||||
QString newName = id;
|
||||
static const QRegularExpression sideUnderscores{R"((?:^_+)|(?:_+$))"};
|
||||
static const QRegularExpression underscores{R"((?:_+))"};
|
||||
static const QRegularExpression camelCases{R"((?:[A-Z](?=[a-z]))|(?:(?<=[a-z])[A-Z]))"};
|
||||
|
||||
newName.remove(sideUnderscores);
|
||||
|
||||
// Insert underscore to camel case edges
|
||||
QRegularExpressionMatchIterator caseMatch = camelCases.globalMatch(newName);
|
||||
QStack<int> camelCaseIndexes;
|
||||
while (caseMatch.hasNext())
|
||||
camelCaseIndexes.push(caseMatch.next().capturedStart());
|
||||
while (!camelCaseIndexes.isEmpty())
|
||||
newName.insert(camelCaseIndexes.pop(), '_');
|
||||
|
||||
// Replace underscored joints with space
|
||||
newName.replace(underscores, " ");
|
||||
newName = newName.trimmed();
|
||||
|
||||
if (newName.isEmpty())
|
||||
return defaultName;
|
||||
|
||||
newName[0] = newName[0].toUpper();
|
||||
return newName;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
namespace QmlDesigner {
|
||||
|
||||
TextureEditorView::TextureEditorView(AsynchronousImageCache &imageCache,
|
||||
@@ -389,6 +426,8 @@ void TextureEditorView::handleToolBarAction(int action)
|
||||
metaInfo.minorVersion());
|
||||
#endif
|
||||
newTextureNode.ensureIdExists();
|
||||
VariantProperty textureName = newTextureNode.variantProperty("objectName");
|
||||
textureName.setValue(nameFromId(newTextureNode.id(), "Texture"_L1));
|
||||
matLib.defaultNodeListProperty().reparentHere(newTextureNode);
|
||||
});
|
||||
break;
|
||||
|
Reference in New Issue
Block a user