forked from qt-creator/qt-creator
QuickDesigner.navigator: Display all QGraphicsObject-type node
properties The navigator now displays all properties whose type is a sub class of QGraphicsObject, except for those properties inherited by Qt/Item. The contents of the default property are displayed as direct children of the model node's tree node. Reparenting into and from the displayed properties is supported. original author: Joerg Schummer
This commit is contained in:
@@ -31,14 +31,21 @@
|
|||||||
|
|
||||||
#include <nodeabstractproperty.h>
|
#include <nodeabstractproperty.h>
|
||||||
#include <nodelistproperty.h>
|
#include <nodelistproperty.h>
|
||||||
|
#include <nodeproperty.h>
|
||||||
|
#include <metainfo.h>
|
||||||
|
#include <propertymetainfo.h>
|
||||||
|
#include <qgraphicswidget.h>
|
||||||
#include <abstractview.h>
|
#include <abstractview.h>
|
||||||
#include <invalididexception.h>
|
#include <invalididexception.h>
|
||||||
|
|
||||||
#include <QMimeData>
|
#include <QMimeData>
|
||||||
#include <QMessageBox>
|
#include <QMessageBox>
|
||||||
|
#include <QApplication>
|
||||||
|
|
||||||
namespace QmlDesigner {
|
namespace QmlDesigner {
|
||||||
|
|
||||||
|
const int NavigatorTreeModel::NavigatorRole = Qt::UserRole;
|
||||||
|
|
||||||
NavigatorTreeModel::NavigatorTreeModel(QObject *parent)
|
NavigatorTreeModel::NavigatorTreeModel(QObject *parent)
|
||||||
: QStandardItemModel(parent),
|
: QStandardItemModel(parent),
|
||||||
m_blockItemChangedSignal(false)
|
m_blockItemChangedSignal(false)
|
||||||
@@ -90,7 +97,7 @@ QMimeData *NavigatorTreeModel::mimeData(const QModelIndexList &indexList) const
|
|||||||
continue;
|
continue;
|
||||||
|
|
||||||
rowAlreadyUsedSet.insert(idIndex);
|
rowAlreadyUsedSet.insert(idIndex);
|
||||||
stream << idIndex.data(Qt::UserRole).toUInt();
|
stream << idIndex.data(NavigatorRole).toUInt();
|
||||||
}
|
}
|
||||||
|
|
||||||
mimeData->setData("application/vnd.modelnode.list", encodedData);
|
mimeData->setData("application/vnd.modelnode.list", encodedData);
|
||||||
@@ -98,21 +105,11 @@ QMimeData *NavigatorTreeModel::mimeData(const QModelIndexList &indexList) const
|
|||||||
return mimeData;
|
return mimeData;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool isAnchestorInList(const ModelNode &node, const QList<ModelNode> &nodeList)
|
|
||||||
{
|
|
||||||
foreach (const ModelNode &nodeInList, nodeList) {
|
|
||||||
if (nodeInList.isAncestorOf(node))
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool NavigatorTreeModel::dropMimeData(const QMimeData *data,
|
bool NavigatorTreeModel::dropMimeData(const QMimeData *data,
|
||||||
Qt::DropAction action,
|
Qt::DropAction action,
|
||||||
int row,
|
int row,
|
||||||
int column,
|
int column,
|
||||||
const QModelIndex &parentIndex)
|
const QModelIndex &dropIndex)
|
||||||
{
|
{
|
||||||
if (action == Qt::IgnoreAction)
|
if (action == Qt::IgnoreAction)
|
||||||
return true;
|
return true;
|
||||||
@@ -122,59 +119,57 @@ bool NavigatorTreeModel::dropMimeData(const QMimeData *data,
|
|||||||
return false;
|
return false;
|
||||||
if (column > 1)
|
if (column > 1)
|
||||||
return false;
|
return false;
|
||||||
if (parentIndex.model() != this)
|
if (dropIndex.model() != this)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
QModelIndex parentIndex, parentItemIndex;
|
||||||
|
QString parentPropertyName;
|
||||||
|
int targetIndex;
|
||||||
|
|
||||||
QModelIndex parentIdIndex = parentIndex;
|
parentIndex = dropIndex.sibling(dropIndex.row(), 0);
|
||||||
parentIdIndex = parentIdIndex.sibling(parentIdIndex.row(), 0);
|
targetIndex = (row > -1)? row : rowCount(parentIndex);
|
||||||
|
|
||||||
Q_ASSERT(parentIdIndex.isValid());
|
if (this->data(parentIndex, NavigatorRole).isValid()) {
|
||||||
|
parentItemIndex = parentIndex;
|
||||||
int targetIndex = 0;
|
ModelNode parentNode = nodeForIndex(parentItemIndex);
|
||||||
if (row > -1) {
|
if (!parentNode.metaInfo().hasDefaultProperty())
|
||||||
targetIndex = row;
|
return false;
|
||||||
} else {
|
targetIndex -= visibleProperties(parentNode).count();
|
||||||
targetIndex = rowCount(parentIdIndex);
|
parentPropertyName = parentNode.metaInfo().defaultProperty();
|
||||||
}
|
}
|
||||||
|
else {
|
||||||
|
parentItemIndex = parentIndex.parent();
|
||||||
|
parentPropertyName = parentIndex.data(Qt::DisplayRole).toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Disallow dropping items between properties, which are listed first.
|
||||||
|
if (targetIndex < 0)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
Q_ASSERT(parentItemIndex.isValid());
|
||||||
|
|
||||||
QByteArray encodedData = data->data("application/vnd.modelnode.list");
|
QByteArray encodedData = data->data("application/vnd.modelnode.list");
|
||||||
QDataStream stream(&encodedData, QIODevice::ReadOnly);
|
QDataStream stream(&encodedData, QIODevice::ReadOnly);
|
||||||
|
|
||||||
ModelNode parentNode(nodeForIndex(parentIdIndex));
|
|
||||||
|
|
||||||
QList<ModelNode> nodeList;
|
QList<ModelNode> nodeList;
|
||||||
|
|
||||||
while (!stream.atEnd()) {
|
while (!stream.atEnd()) {
|
||||||
uint nodeHash;
|
uint nodeHash;
|
||||||
stream >> nodeHash;
|
stream >> nodeHash;
|
||||||
ModelNode node(nodeForHash(nodeHash));
|
if (containsNodeHash(nodeHash)) {
|
||||||
if (!node.isValid() || (parentNode == node) || node.isAncestorOf(parentNode))
|
ModelNode node(nodeForHash(nodeHash));
|
||||||
continue;
|
nodeList.append(node);
|
||||||
nodeList.append(node);
|
|
||||||
}
|
|
||||||
|
|
||||||
RewriterTransaction transaction = m_view->beginRewriterTransaction();
|
|
||||||
foreach (const ModelNode &node, nodeList) {
|
|
||||||
if (!isAnchestorInList(node, nodeList)) {
|
|
||||||
if (node.parentProperty().parentModelNode() != parentNode) {
|
|
||||||
if (node != parentNode) {
|
|
||||||
reparentModelNode(parentNode, node);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (node.parentProperty().isNodeListProperty()) {
|
|
||||||
int index = node.parentProperty().toNodeListProperty().toModelNodeList().indexOf(node);
|
|
||||||
if (index < targetIndex) { // item is first removed from oldIndex, then inserted at new index
|
|
||||||
--targetIndex;
|
|
||||||
}
|
|
||||||
if (index != targetIndex) {
|
|
||||||
node.parentProperty().toNodeListProperty().slide(index, targetIndex);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ModelNode parentNode(nodeForIndex(parentItemIndex));
|
||||||
|
NodeAbstractProperty parentProperty = parentNode.nodeAbstractProperty(parentPropertyName);
|
||||||
|
|
||||||
|
if (parentProperty.isNodeProperty() &&
|
||||||
|
nodeList.count() > 1) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
moveNodesInteractive(parentProperty, nodeList, targetIndex);
|
||||||
propagateInvisible(parentNode, isNodeInvisible(parentNode));
|
propagateInvisible(parentNode, isNodeInvisible(parentNode));
|
||||||
|
|
||||||
return false; // don't let the view do drag&drop on its own
|
return false; // don't let the view do drag&drop on its own
|
||||||
@@ -192,7 +187,7 @@ NavigatorTreeModel::ItemRow NavigatorTreeModel::createItemRow(const ModelNode &n
|
|||||||
idItem->setDragEnabled(true);
|
idItem->setDragEnabled(true);
|
||||||
idItem->setDropEnabled(dropEnabled);
|
idItem->setDropEnabled(dropEnabled);
|
||||||
idItem->setEditable(true);
|
idItem->setEditable(true);
|
||||||
idItem->setData(hash, Qt::UserRole);
|
idItem->setData(hash, NavigatorRole);
|
||||||
|
|
||||||
# ifdef _LOCK_ITEMS_
|
# ifdef _LOCK_ITEMS_
|
||||||
QStandardItem *lockItem = new QStandardItem;
|
QStandardItem *lockItem = new QStandardItem;
|
||||||
@@ -200,28 +195,40 @@ NavigatorTreeModel::ItemRow NavigatorTreeModel::createItemRow(const ModelNode &n
|
|||||||
lockItem->setDropEnabled(dropEnabled);
|
lockItem->setDropEnabled(dropEnabled);
|
||||||
lockItem->setEditable(false);
|
lockItem->setEditable(false);
|
||||||
lockItem->setCheckable(true);
|
lockItem->setCheckable(true);
|
||||||
lockItem->setData(hash, Qt::UserRole);
|
lockItem->setData(hash, NavigatorRole);
|
||||||
# endif
|
# endif
|
||||||
|
|
||||||
QStandardItem *visibilityItem = new QStandardItem;
|
QStandardItem *visibilityItem = new QStandardItem;
|
||||||
visibilityItem->setDropEnabled(dropEnabled);
|
visibilityItem->setDropEnabled(dropEnabled);
|
||||||
visibilityItem->setCheckable(true);
|
visibilityItem->setCheckable(true);
|
||||||
visibilityItem->setEditable(false);
|
visibilityItem->setEditable(false);
|
||||||
visibilityItem->setData(hash, Qt::UserRole);
|
visibilityItem->setData(hash, NavigatorRole);
|
||||||
if (node.isRootNode()) {
|
if (node.isRootNode()) {
|
||||||
visibilityItem->setCheckable(false);
|
visibilityItem->setCheckable(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
# ifdef _LOCK_ITEMS_
|
QMap<QString, QStandardItem *> propertyItems;
|
||||||
return ItemRow(idItem, lockItem, visibilityItem);
|
foreach (QString propertyName, visibleProperties(node)) {
|
||||||
# else
|
QStandardItem *propertyItem = new QStandardItem;
|
||||||
return ItemRow(idItem, visibilityItem);
|
propertyItem->setSelectable(false);
|
||||||
# endif
|
propertyItem->setDragEnabled(false);
|
||||||
|
propertyItem->setDropEnabled(dropEnabled);
|
||||||
|
propertyItem->setEditable(false);
|
||||||
|
propertyItem->setData(propertyName, Qt::DisplayRole);
|
||||||
|
propertyItems.insert(propertyName, propertyItem);
|
||||||
|
idItem->appendRow(propertyItem);
|
||||||
|
}
|
||||||
|
|
||||||
|
# ifdef _LOCK_ITEMS_
|
||||||
|
return ItemRow(idItem, lockItem, visibilityItem, propertyItems);
|
||||||
|
# else
|
||||||
|
return ItemRow(idItem, visibilityItem, propertyItems);
|
||||||
|
# endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void NavigatorTreeModel::updateItemRow(const ModelNode &node, ItemRow items)
|
void NavigatorTreeModel::updateItemRow(const ModelNode &node, ItemRow items)
|
||||||
{
|
{
|
||||||
bool blockSignal = blockItemChangedSignal(true);
|
bool blockSignal = blockItemChangedSignal(true);
|
||||||
|
|
||||||
items.idItem->setText(node.id());
|
items.idItem->setText(node.id());
|
||||||
items.visibilityItem->setCheckState(node.auxiliaryData("invisible").toBool() ? Qt::Unchecked : Qt::Checked);
|
items.visibilityItem->setCheckState(node.auxiliaryData("invisible").toBool() ? Qt::Unchecked : Qt::Checked);
|
||||||
@@ -243,20 +250,34 @@ void NavigatorTreeModel::updateItemRow(const ModelNode &node)
|
|||||||
/**
|
/**
|
||||||
Updates the sibling position of the item, depending on the position in the model.
|
Updates the sibling position of the item, depending on the position in the model.
|
||||||
*/
|
*/
|
||||||
void NavigatorTreeModel::updateItemRowOrder(const ModelNode &node)
|
void NavigatorTreeModel::updateItemRowOrder(const NodeListProperty &listProperty, const ModelNode &node, int oldIndex)
|
||||||
{
|
{
|
||||||
|
Q_UNUSED(oldIndex);
|
||||||
|
|
||||||
if (!containsNode(node))
|
if (!containsNode(node))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
ItemRow itemRow = itemRowForNode(node);
|
ItemRow itemRow = itemRowForNode(node);
|
||||||
int currentRow = itemRow.idItem->row();
|
int currentRow = itemRow.idItem->row();
|
||||||
int newRow = currentRow;
|
int newRow = listProperty.toModelNodeList().indexOf(node);
|
||||||
if (node.parentProperty().parentModelNode().isValid())
|
|
||||||
newRow = modelNodeChildren(node.parentProperty().parentModelNode()).indexOf(node);
|
|
||||||
Q_ASSERT(newRow >= 0);
|
Q_ASSERT(newRow >= 0);
|
||||||
|
|
||||||
|
QStandardItem *parentIdItem = 0;
|
||||||
|
if (containsNode(listProperty.parentModelNode())) {
|
||||||
|
ItemRow parentRow = itemRowForNode(listProperty.parentModelNode());
|
||||||
|
parentIdItem = parentRow.propertyItems.value(listProperty.name());
|
||||||
|
if (!parentIdItem) {
|
||||||
|
parentIdItem = parentRow.idItem;
|
||||||
|
newRow += visibleProperties(listProperty.parentModelNode()).count();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
parentIdItem = itemRow.idItem->parent();
|
||||||
|
}
|
||||||
|
Q_ASSERT(parentIdItem);
|
||||||
|
|
||||||
if (currentRow != newRow) {
|
if (currentRow != newRow) {
|
||||||
QStandardItem *parentIdItem = itemRow.idItem->parent();
|
|
||||||
QList<QStandardItem*> items = parentIdItem->takeRow(currentRow);
|
QList<QStandardItem*> items = parentIdItem->takeRow(currentRow);
|
||||||
parentIdItem->insertRow(newRow, items);
|
parentIdItem->insertRow(newRow, items);
|
||||||
}
|
}
|
||||||
@@ -266,8 +287,10 @@ void NavigatorTreeModel::handleChangedItem(QStandardItem *item)
|
|||||||
{
|
{
|
||||||
if (m_blockItemChangedSignal)
|
if (m_blockItemChangedSignal)
|
||||||
return;
|
return;
|
||||||
|
if (!data(item->index(), NavigatorRole).isValid())
|
||||||
|
return;
|
||||||
|
|
||||||
uint nodeHash = item->data(Qt::UserRole).toUInt();
|
uint nodeHash = item->data(NavigatorRole).toUInt();
|
||||||
Q_ASSERT(nodeHash && containsNodeHash(nodeHash));
|
Q_ASSERT(nodeHash && containsNodeHash(nodeHash));
|
||||||
ModelNode node = nodeForHash(nodeHash);
|
ModelNode node = nodeForHash(nodeHash);
|
||||||
|
|
||||||
@@ -323,7 +346,12 @@ NavigatorTreeModel::ItemRow NavigatorTreeModel::itemRowForNode(const ModelNode &
|
|||||||
void NavigatorTreeModel::setView(AbstractView *view)
|
void NavigatorTreeModel::setView(AbstractView *view)
|
||||||
{
|
{
|
||||||
m_view = view;
|
m_view = view;
|
||||||
addSubTree(view->rootModelNode());
|
m_hiddenProperties.clear();
|
||||||
|
if (view) {
|
||||||
|
ModelNode sampleItemNode(m_view->createModelNode("Qt/Item", 4, 7));
|
||||||
|
m_hiddenProperties << visibleProperties(sampleItemNode);
|
||||||
|
addSubTree(view->rootModelNode());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void NavigatorTreeModel::clearView()
|
void NavigatorTreeModel::clearView()
|
||||||
@@ -346,7 +374,7 @@ QModelIndex NavigatorTreeModel::indexForNode(const ModelNode &node) const
|
|||||||
ModelNode NavigatorTreeModel::nodeForIndex(const QModelIndex &index) const
|
ModelNode NavigatorTreeModel::nodeForIndex(const QModelIndex &index) const
|
||||||
{
|
{
|
||||||
Q_ASSERT(index.isValid());
|
Q_ASSERT(index.isValid());
|
||||||
uint hash = index.data(Qt::UserRole).toUInt();
|
uint hash = index.data(NavigatorRole).toUInt();
|
||||||
Q_ASSERT(hash);
|
Q_ASSERT(hash);
|
||||||
Q_ASSERT(containsNodeHash(hash));
|
Q_ASSERT(containsNodeHash(hash));
|
||||||
return nodeForHash(hash);
|
return nodeForHash(hash);
|
||||||
@@ -380,6 +408,8 @@ void NavigatorTreeModel::addSubTree(const ModelNode &node)
|
|||||||
Q_ASSERT(node.isValid());
|
Q_ASSERT(node.isValid());
|
||||||
Q_ASSERT(!containsNodeHash(qHash(node)));
|
Q_ASSERT(!containsNodeHash(qHash(node)));
|
||||||
|
|
||||||
|
//updateItemRow(node, newRow);
|
||||||
|
|
||||||
// only add items that are in the modelNodeChildren list (that means, visible in the editor)
|
// only add items that are in the modelNodeChildren list (that means, visible in the editor)
|
||||||
if (!node.isRootNode()
|
if (!node.isRootNode()
|
||||||
&& !modelNodeChildren(node.parentProperty().parentModelNode()).contains(node)) {
|
&& !modelNodeChildren(node.parentProperty().parentModelNode()).contains(node)) {
|
||||||
@@ -397,9 +427,16 @@ void NavigatorTreeModel::addSubTree(const ModelNode &node)
|
|||||||
|
|
||||||
// We assume that the node is always added to the _end_ of the property list.
|
// We assume that the node is always added to the _end_ of the property list.
|
||||||
if (node.hasParentProperty()) {
|
if (node.hasParentProperty()) {
|
||||||
ItemRow parentRow = itemRowForNode(node.parentProperty().parentModelNode());
|
AbstractProperty property(node.parentProperty());
|
||||||
if (parentRow.idItem)
|
ItemRow parentRow = itemRowForNode(property.parentModelNode());
|
||||||
parentRow.idItem->appendRow(newRow.toList());
|
QStandardItem *parentItem = parentRow.propertyItems.value(property.name());
|
||||||
|
if (!parentItem) {
|
||||||
|
// Child nodes in the default property are added directly under the
|
||||||
|
// parent.
|
||||||
|
parentItem = parentRow.idItem;
|
||||||
|
}
|
||||||
|
if (parentItem)
|
||||||
|
parentItem->appendRow(newRow.toList());
|
||||||
} else {
|
} else {
|
||||||
appendRow(newRow.toList());
|
appendRow(newRow.toList());
|
||||||
}
|
}
|
||||||
@@ -431,26 +468,111 @@ void NavigatorTreeModel::removeSubTree(const ModelNode &node)
|
|||||||
m_nodeItemHash.remove(node);
|
m_nodeItemHash.remove(node);
|
||||||
}
|
}
|
||||||
|
|
||||||
void NavigatorTreeModel::reparentModelNode(const ModelNode &parentNode, const ModelNode &node)
|
void NavigatorTreeModel::moveNodesInteractive(NodeAbstractProperty parentProperty, const QList<ModelNode> &modelNodes, int targetIndex)
|
||||||
{
|
{
|
||||||
parentNode.nodeListProperty("data").reparentHere(node);
|
QString propertyQmlType = qmlTypeInQtContainer(parentProperty.metaInfo().type());
|
||||||
|
|
||||||
|
RewriterTransaction transaction = m_view->beginRewriterTransaction();
|
||||||
|
foreach (const ModelNode &node, modelNodes) {
|
||||||
|
if (!node.isValid())
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (node != parentProperty.parentModelNode() &&
|
||||||
|
!node.isAncestorOf(parentProperty.parentModelNode()) &&
|
||||||
|
node.metaInfo().isSubclassOf(propertyQmlType, -1, -1)) {
|
||||||
|
|
||||||
|
if (node.parentProperty() != parentProperty) {
|
||||||
|
|
||||||
|
if (parentProperty.isNodeProperty()) {
|
||||||
|
ModelNode propertyNode = parentProperty.toNodeProperty().modelNode();
|
||||||
|
// Destruction of ancestors is not allowed
|
||||||
|
if (propertyNode.isAncestorOf(node)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (propertyNode.isValid()) {
|
||||||
|
QApplication::setOverrideCursor(Qt::ArrowCursor);
|
||||||
|
if (QMessageBox::warning(0, tr("Warning"), tr("Reparenting the component %1 here will cause the component %2 to be deleted. Do you want to proceed?").arg(node.id(), propertyNode.id()), QMessageBox::Ok | QMessageBox::Cancel) == QMessageBox::Cancel) {
|
||||||
|
QApplication::restoreOverrideCursor();
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
QApplication::restoreOverrideCursor();
|
||||||
|
propertyNode.destroy();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
parentProperty.reparentHere(node);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (parentProperty.isNodeListProperty()) {
|
||||||
|
int index = parentProperty.toNodeListProperty().toModelNodeList().indexOf(node);
|
||||||
|
if (index < targetIndex) { // item is first removed from oldIndex, then inserted at new index
|
||||||
|
--targetIndex;
|
||||||
|
}
|
||||||
|
if (index != targetIndex) {
|
||||||
|
parentProperty.toNodeListProperty().slide(index, targetIndex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
QList<ModelNode> NavigatorTreeModel::modelNodeChildren(const ModelNode &parentNode)
|
QList<ModelNode> NavigatorTreeModel::modelNodeChildren(const ModelNode &parentNode)
|
||||||
{
|
{
|
||||||
QList<ModelNode> children;
|
QList<ModelNode> children;
|
||||||
|
QStringList properties;
|
||||||
|
|
||||||
if (parentNode.hasProperty("children")) {
|
if (parentNode.metaInfo().hasDefaultProperty())
|
||||||
children.append(parentNode.nodeListProperty("children").toModelNodeList());
|
properties << parentNode.metaInfo().defaultProperty();
|
||||||
}
|
|
||||||
|
|
||||||
if (parentNode.hasProperty("data")) {
|
properties << visibleProperties(parentNode);
|
||||||
children.append(parentNode.nodeListProperty("data").toModelNodeList());
|
|
||||||
|
foreach (QString propertyName, properties) {
|
||||||
|
AbstractProperty property(parentNode.property(propertyName));
|
||||||
|
if (property.isNodeProperty())
|
||||||
|
children << property.toNodeProperty().modelNode();
|
||||||
|
else if (property.isNodeListProperty())
|
||||||
|
children << property.toNodeListProperty().toModelNodeList();
|
||||||
}
|
}
|
||||||
|
|
||||||
return children;
|
return children;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QString NavigatorTreeModel::qmlTypeInQtContainer(const QString &qtContainerType) const
|
||||||
|
{
|
||||||
|
QString typeName(qtContainerType);
|
||||||
|
if (typeName.startsWith("QDeclarativeListProperty<") &&
|
||||||
|
typeName.endsWith(">")) {
|
||||||
|
typeName.remove(0, 25);
|
||||||
|
typeName.chop(1);
|
||||||
|
}
|
||||||
|
if (typeName.endsWith('*'))
|
||||||
|
typeName.chop(1);
|
||||||
|
|
||||||
|
return m_view->model()->metaInfo().fromQtTypes(typeName);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
QStringList NavigatorTreeModel::visibleProperties(const ModelNode &node) const
|
||||||
|
{
|
||||||
|
QStringList propertyList;
|
||||||
|
|
||||||
|
foreach (PropertyMetaInfo propertyMetaInfo, node.metaInfo().properties().values()) {
|
||||||
|
if (!m_hiddenProperties.contains(propertyMetaInfo.name()) &&
|
||||||
|
propertyMetaInfo.name() != node.metaInfo().defaultProperty() &&
|
||||||
|
propertyMetaInfo.isReadable() &&
|
||||||
|
propertyMetaInfo.isWriteable()) {
|
||||||
|
|
||||||
|
QString qmlType = qmlTypeInQtContainer(propertyMetaInfo.type());
|
||||||
|
if (node.metaInfo().metaInfo().hasNodeMetaInfo(qmlType) &&
|
||||||
|
node.metaInfo().metaInfo().nodeMetaInfo(qmlType).isSubclassOf("QGraphicsObject", -1, -1)) {
|
||||||
|
propertyList << propertyMetaInfo.name();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return propertyList;
|
||||||
|
}
|
||||||
|
|
||||||
// along the lines of QObject::blockSignals
|
// along the lines of QObject::blockSignals
|
||||||
bool NavigatorTreeModel::blockItemChangedSignal(bool block)
|
bool NavigatorTreeModel::blockItemChangedSignal(bool block)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -50,8 +50,8 @@ class NavigatorTreeModel : public QStandardItemModel
|
|||||||
struct ItemRow {
|
struct ItemRow {
|
||||||
ItemRow()
|
ItemRow()
|
||||||
: idItem(0), lockItem(0), visibilityItem(0) {}
|
: idItem(0), lockItem(0), visibilityItem(0) {}
|
||||||
ItemRow(QStandardItem *id, QStandardItem *lock, QStandardItem *visibility)
|
ItemRow(QStandardItem *id, QStandardItem *lock, QStandardItem *visibility, const PropertyItemMap &properties)
|
||||||
: idItem(id), lockItem(lock), visibilityItem(visibility) {}
|
: idItem(id), lockItem(lock), visibilityItem(visibility), propertyItems(properties) {}
|
||||||
|
|
||||||
QList<QStandardItem*> toList() const {
|
QList<QStandardItem*> toList() const {
|
||||||
return QList<QStandardItem*>() << idItem << lockItem << visibilityItem;
|
return QList<QStandardItem*>() << idItem << lockItem << visibilityItem;
|
||||||
@@ -60,13 +60,14 @@ class NavigatorTreeModel : public QStandardItemModel
|
|||||||
QStandardItem *idItem;
|
QStandardItem *idItem;
|
||||||
QStandardItem *lockItem;
|
QStandardItem *lockItem;
|
||||||
QStandardItem *visibilityItem;
|
QStandardItem *visibilityItem;
|
||||||
|
QMap<QString, QStandardItem *> propertyItems;
|
||||||
};
|
};
|
||||||
#else
|
#else
|
||||||
struct ItemRow {
|
struct ItemRow {
|
||||||
ItemRow()
|
ItemRow()
|
||||||
: idItem(0), visibilityItem(0) {}
|
: idItem(0), visibilityItem(0) {}
|
||||||
ItemRow(QStandardItem *id, QStandardItem *visibility)
|
ItemRow(QStandardItem *id, QStandardItem *visibility, const QMap<QString, QStandardItem *> &properties)
|
||||||
: idItem(id), visibilityItem(visibility) {}
|
: idItem(id), visibilityItem(visibility), propertyItems(properties) {}
|
||||||
|
|
||||||
QList<QStandardItem*> toList() const {
|
QList<QStandardItem*> toList() const {
|
||||||
return QList<QStandardItem*>() << idItem << visibilityItem;
|
return QList<QStandardItem*>() << idItem << visibilityItem;
|
||||||
@@ -74,9 +75,12 @@ class NavigatorTreeModel : public QStandardItemModel
|
|||||||
|
|
||||||
QStandardItem *idItem;
|
QStandardItem *idItem;
|
||||||
QStandardItem *visibilityItem;
|
QStandardItem *visibilityItem;
|
||||||
|
QMap<QString, QStandardItem *> propertyItems;
|
||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
static const int NavigatorRole;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
NavigatorTreeModel(QObject *parent = 0);
|
NavigatorTreeModel(QObject *parent = 0);
|
||||||
~NavigatorTreeModel();
|
~NavigatorTreeModel();
|
||||||
@@ -105,7 +109,7 @@ public:
|
|||||||
void addSubTree(const ModelNode &node);
|
void addSubTree(const ModelNode &node);
|
||||||
void removeSubTree(const ModelNode &node);
|
void removeSubTree(const ModelNode &node);
|
||||||
void updateItemRow(const ModelNode &node);
|
void updateItemRow(const ModelNode &node);
|
||||||
void updateItemRowOrder(const ModelNode &node);
|
void updateItemRowOrder(const NodeListProperty &listProperty, const ModelNode &movedNode, int oldIndex);
|
||||||
|
|
||||||
void setId(const QModelIndex &index, const QString &id);
|
void setId(const QModelIndex &index, const QString &id);
|
||||||
void setVisible(const QModelIndex &index, bool visible);
|
void setVisible(const QModelIndex &index, bool visible);
|
||||||
@@ -123,9 +127,13 @@ private:
|
|||||||
ItemRow createItemRow(const ModelNode &node);
|
ItemRow createItemRow(const ModelNode &node);
|
||||||
void updateItemRow(const ModelNode &node, ItemRow row);
|
void updateItemRow(const ModelNode &node, ItemRow row);
|
||||||
|
|
||||||
void reparentModelNode(const ModelNode &parentNode, const ModelNode &node);
|
void moveNodesInteractive(NodeAbstractProperty parentProperty, const QList<ModelNode> &modelNodes, int targetIndex);
|
||||||
|
|
||||||
QList<ModelNode> modelNodeChildren(const ModelNode &parentNode);
|
QList<ModelNode> modelNodeChildren(const ModelNode &parentNode);
|
||||||
|
|
||||||
|
QString qmlTypeInQtContainer(const QString &qtContainerType) const;
|
||||||
|
QStringList visibleProperties(const ModelNode &node) const;
|
||||||
|
|
||||||
bool blockItemChangedSignal(bool block);
|
bool blockItemChangedSignal(bool block);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@@ -134,6 +142,8 @@ private:
|
|||||||
QWeakPointer<AbstractView> m_view;
|
QWeakPointer<AbstractView> m_view;
|
||||||
|
|
||||||
bool m_blockItemChangedSignal;
|
bool m_blockItemChangedSignal;
|
||||||
|
|
||||||
|
QStringList m_hiddenProperties;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace QmlDesigner
|
} // namespace QmlDesigner
|
||||||
|
|||||||
@@ -127,12 +127,19 @@ QSize IconCheckboxItemDelegate::sizeHint(const QStyleOptionViewItem &option,
|
|||||||
{
|
{
|
||||||
Q_UNUSED(option);
|
Q_UNUSED(option);
|
||||||
Q_UNUSED(index);
|
Q_UNUSED(index);
|
||||||
return QSize(15,20);
|
|
||||||
|
if (!index.data(Qt::UserRole).isValid())
|
||||||
|
return QSize();
|
||||||
|
|
||||||
|
return QSize(15, 20);
|
||||||
}
|
}
|
||||||
|
|
||||||
void IconCheckboxItemDelegate::paint(QPainter *painter,
|
void IconCheckboxItemDelegate::paint(QPainter *painter,
|
||||||
const QStyleOptionViewItem &option, const QModelIndex &index) const
|
const QStyleOptionViewItem &option, const QModelIndex &index) const
|
||||||
{
|
{
|
||||||
|
if (!index.data(Qt::UserRole).isValid())
|
||||||
|
return;
|
||||||
|
|
||||||
painter->save();
|
painter->save();
|
||||||
if (option.state & QStyle::State_Selected)
|
if (option.state & QStyle::State_Selected)
|
||||||
drawSelectionBackground(painter, option);
|
drawSelectionBackground(painter, option);
|
||||||
@@ -152,70 +159,84 @@ void IconCheckboxItemDelegate::paint(QPainter *painter,
|
|||||||
painter->restore();
|
painter->restore();
|
||||||
}
|
}
|
||||||
|
|
||||||
void IdItemDelegate::paint(QPainter *painter,
|
void NameItemDelegate::paint(QPainter *painter,
|
||||||
const QStyleOptionViewItem &option, const QModelIndex &index) const
|
const QStyleOptionViewItem &option, const QModelIndex &index) const
|
||||||
{
|
{
|
||||||
if (option.state & QStyle::State_Selected)
|
if (option.state & QStyle::State_Selected)
|
||||||
drawSelectionBackground(painter, option);
|
drawSelectionBackground(painter, option);
|
||||||
|
|
||||||
|
QString displayString;
|
||||||
|
QPoint displayStringOffset;
|
||||||
|
|
||||||
painter->save();
|
painter->save();
|
||||||
|
|
||||||
if (m_TreeModel->isNodeInvisible( index ))
|
if (index.data(Qt::UserRole).isValid()) {
|
||||||
painter->setOpacity(0.5);
|
|
||||||
|
|
||||||
ModelNode node = m_TreeModel->nodeForIndex(index);
|
int pixmapSide = 16;
|
||||||
|
|
||||||
QIcon icon;
|
if (m_TreeModel->isNodeInvisible( index ))
|
||||||
if (node.metaInfo().isValid()) {
|
painter->setOpacity(0.5);
|
||||||
icon=node.metaInfo().icon();
|
|
||||||
if (icon.isNull())
|
ModelNode node = m_TreeModel->nodeForIndex(index);
|
||||||
{
|
|
||||||
// if node has no own icon, search for it in the itemlibrary
|
QIcon icon;
|
||||||
const NodeMetaInfo typeInfo = node.metaInfo();
|
if (node.metaInfo().isValid()) {
|
||||||
const ItemLibraryInfo *libraryInfo = node.metaInfo().metaInfo().itemLibraryInfo();
|
icon=node.metaInfo().icon();
|
||||||
QList <ItemLibraryEntry> infoList = libraryInfo->entriesForType(typeInfo.typeName(),
|
if (icon.isNull())
|
||||||
typeInfo.majorVersion(),
|
{
|
||||||
typeInfo.minorVersion());
|
// if node has no own icon, search for it in the itemlibrary
|
||||||
foreach (const ItemLibraryEntry &entry, infoList) {
|
const NodeMetaInfo typeInfo = node.metaInfo();
|
||||||
if (!icon.isNull()) {
|
const ItemLibraryInfo *libraryInfo = node.metaInfo().metaInfo().itemLibraryInfo();
|
||||||
icon = entry.icon();
|
QList <ItemLibraryEntry> infoList = libraryInfo->entriesForType(typeInfo.typeName(),
|
||||||
break;
|
typeInfo.majorVersion(),
|
||||||
|
typeInfo.minorVersion());
|
||||||
|
foreach (const ItemLibraryEntry &entry, infoList) {
|
||||||
|
if (!icon.isNull()) {
|
||||||
|
icon = entry.icon();
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// if the library was also empty, use the default icon
|
// if the library was also empty, use the default icon
|
||||||
if (icon.isNull())
|
if (icon.isNull())
|
||||||
icon = QIcon(QLatin1String(":/ItemLibrary/images/item-default-icon.png"));
|
icon = QIcon(QLatin1String(":/ItemLibrary/images/item-default-icon.png"));
|
||||||
|
|
||||||
// If no icon is present, leave an empty space of 24 pixels anyway
|
// If no icon is present, leave an empty space of 24 pixels anyway
|
||||||
int pixmapSide = 16;
|
QPixmap pixmap = icon.pixmap(pixmapSide, pixmapSide);
|
||||||
QPixmap pixmap = icon.pixmap(pixmapSide, pixmapSide);
|
painter->drawPixmap(option.rect.x()+1,option.rect.y()+2,pixmap);
|
||||||
painter->drawPixmap(option.rect.x()+1,option.rect.y()+2,pixmap);
|
|
||||||
|
|
||||||
QString myString = node.id();
|
displayString = node.id();
|
||||||
if (myString.isEmpty())
|
if (displayString.isEmpty())
|
||||||
myString = node.simplifiedTypeName();
|
displayString = node.simplifiedTypeName();
|
||||||
|
|
||||||
// Check text length does not exceed available space
|
// Check text length does not exceed available space
|
||||||
int extraSpace=12+pixmapSide;
|
int extraSpace=12+pixmapSide;
|
||||||
QFontMetrics fm(option.font);
|
QFontMetrics fm(option.font);
|
||||||
myString = fm.elidedText(myString,Qt::ElideMiddle,option.rect.width()-extraSpace);
|
displayString = fm.elidedText(displayString,Qt::ElideMiddle,option.rect.width()-extraSpace);
|
||||||
|
displayStringOffset = QPoint(5+pixmapSide,-5);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
displayString = index.data(Qt::DisplayRole).toString();
|
||||||
|
displayStringOffset = QPoint(0, -2);
|
||||||
|
}
|
||||||
|
|
||||||
painter->drawText(option.rect.bottomLeft()+QPoint(5+pixmapSide,-5),myString);
|
painter->drawText(option.rect.bottomLeft()+displayStringOffset,displayString);
|
||||||
|
|
||||||
painter->restore();
|
painter->restore();
|
||||||
}
|
}
|
||||||
|
|
||||||
QWidget *IdItemDelegate::createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const
|
QWidget *NameItemDelegate::createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const
|
||||||
{
|
{
|
||||||
Q_UNUSED(option);
|
Q_UNUSED(option);
|
||||||
Q_UNUSED(index);
|
if (!index.data(Qt::UserRole).isValid())
|
||||||
|
return 0;
|
||||||
|
|
||||||
return new QLineEdit(parent);
|
return new QLineEdit(parent);
|
||||||
}
|
}
|
||||||
|
|
||||||
void IdItemDelegate::setEditorData(QWidget *editor, const QModelIndex &index) const
|
void NameItemDelegate::setEditorData(QWidget *editor, const QModelIndex &index) const
|
||||||
{
|
{
|
||||||
ModelNode node = m_TreeModel->nodeForIndex(index);
|
ModelNode node = m_TreeModel->nodeForIndex(index);
|
||||||
QString value = node.id();
|
QString value = node.id();
|
||||||
@@ -224,7 +245,7 @@ void IdItemDelegate::setEditorData(QWidget *editor, const QModelIndex &index) co
|
|||||||
lineEdit->setText(value);
|
lineEdit->setText(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
void IdItemDelegate::setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const
|
void NameItemDelegate::setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const
|
||||||
{
|
{
|
||||||
Q_UNUSED(model);
|
Q_UNUSED(model);
|
||||||
QLineEdit *lineEdit = static_cast<QLineEdit*>(editor);
|
QLineEdit *lineEdit = static_cast<QLineEdit*>(editor);
|
||||||
@@ -232,7 +253,7 @@ void IdItemDelegate::setModelData(QWidget *editor, QAbstractItemModel *model, co
|
|||||||
lineEdit->clearFocus();
|
lineEdit->clearFocus();
|
||||||
}
|
}
|
||||||
|
|
||||||
void IdItemDelegate::updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option, const QModelIndex &index) const
|
void NameItemDelegate::updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option, const QModelIndex &index) const
|
||||||
{
|
{
|
||||||
Q_UNUSED(index);
|
Q_UNUSED(index);
|
||||||
QLineEdit *lineEdit = static_cast<QLineEdit*>(editor);
|
QLineEdit *lineEdit = static_cast<QLineEdit*>(editor);
|
||||||
|
|||||||
@@ -70,10 +70,10 @@ class IconCheckboxItemDelegate : public QStyledItemDelegate
|
|||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class IdItemDelegate : public QStyledItemDelegate
|
class NameItemDelegate : public QStyledItemDelegate
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
explicit IdItemDelegate(QObject *parent=0, NavigatorTreeModel *treeModel=NULL) : QStyledItemDelegate(parent),m_TreeModel(treeModel) {}
|
explicit NameItemDelegate(QObject *parent=0, NavigatorTreeModel *treeModel=NULL) : QStyledItemDelegate(parent),m_TreeModel(treeModel) {}
|
||||||
|
|
||||||
void paint(QPainter *painter,
|
void paint(QPainter *painter,
|
||||||
const QStyleOptionViewItem &option, const QModelIndex &index) const;
|
const QStyleOptionViewItem &option, const QModelIndex &index) const;
|
||||||
|
|||||||
@@ -49,7 +49,7 @@ NavigatorView::NavigatorView(QObject* parent) :
|
|||||||
connect(treeWidget()->selectionModel(), SIGNAL(selectionChanged(QItemSelection,QItemSelection)), this, SLOT(changeSelection(QItemSelection,QItemSelection)));
|
connect(treeWidget()->selectionModel(), SIGNAL(selectionChanged(QItemSelection,QItemSelection)), this, SLOT(changeSelection(QItemSelection,QItemSelection)));
|
||||||
treeWidget()->setIndentation(treeWidget()->indentation() * 0.5);
|
treeWidget()->setIndentation(treeWidget()->indentation() * 0.5);
|
||||||
|
|
||||||
IdItemDelegate *idDelegate = new IdItemDelegate(this,m_treeModel.data());
|
NameItemDelegate *idDelegate = new NameItemDelegate(this,m_treeModel.data());
|
||||||
IconCheckboxItemDelegate *showDelegate = new IconCheckboxItemDelegate(this,":/qmldesigner/images/eye_open.png",
|
IconCheckboxItemDelegate *showDelegate = new IconCheckboxItemDelegate(this,":/qmldesigner/images/eye_open.png",
|
||||||
":/qmldesigner/images/placeholder.png",m_treeModel.data());
|
":/qmldesigner/images/placeholder.png",m_treeModel.data());
|
||||||
|
|
||||||
@@ -191,10 +191,10 @@ void NavigatorView::scriptFunctionsChanged(const ModelNode &/*node*/, const QStr
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void NavigatorView::nodeOrderChanged(const NodeListProperty &/*listProperty*/, const ModelNode &node, int /*oldIndex*/)
|
void NavigatorView::nodeOrderChanged(const NodeListProperty &listProperty, const ModelNode &node, int oldIndex)
|
||||||
{
|
{
|
||||||
if (m_treeModel->isInTree(node))
|
if (m_treeModel->isInTree(node))
|
||||||
m_treeModel->updateItemRowOrder(node);
|
m_treeModel->updateItemRowOrder(listProperty, node, oldIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
void NavigatorView::changeSelection(const QItemSelection & /*newSelection*/, const QItemSelection &/*deselected*/)
|
void NavigatorView::changeSelection(const QItemSelection & /*newSelection*/, const QItemSelection &/*deselected*/)
|
||||||
@@ -203,7 +203,8 @@ void NavigatorView::changeSelection(const QItemSelection & /*newSelection*/, con
|
|||||||
return;
|
return;
|
||||||
QSet<ModelNode> nodeSet;
|
QSet<ModelNode> nodeSet;
|
||||||
foreach (const QModelIndex &index, treeWidget()->selectionModel()->selectedIndexes()) {
|
foreach (const QModelIndex &index, treeWidget()->selectionModel()->selectedIndexes()) {
|
||||||
nodeSet.insert(m_treeModel->nodeForIndex(index));
|
if (m_treeModel->data(index, Qt::UserRole).isValid())
|
||||||
|
nodeSet.insert(m_treeModel->nodeForIndex(index));
|
||||||
}
|
}
|
||||||
|
|
||||||
bool blocked = blockSelectionChangedSignal(true);
|
bool blocked = blockSelectionChangedSignal(true);
|
||||||
|
|||||||
Reference in New Issue
Block a user