Commit 562d0c5f authored by Marco Bubke's avatar Marco Bubke

QmlDesigner: Refactor states editor

Reviewed-By: Thomas Hartmann
parent fabf76d2
......@@ -151,7 +151,7 @@ void ComponentView::nodeRemoved(const ModelNode & /*removedNode*/, const NodeAbs
// }
// }
//}
void ComponentView::nodeAboutToBeReparented(const ModelNode &/*node*/, const NodeAbstractProperty &/*newPropertyParent*/, const NodeAbstractProperty &/*oldPropertyParent*/, AbstractView::PropertyChangeFlags /*propertyChange*/) {}
void ComponentView::nodeReparented(const ModelNode &/*node*/, const NodeAbstractProperty &/*newPropertyParent*/, const NodeAbstractProperty &/*oldPropertyParent*/, AbstractView::PropertyChangeFlags /*propertyChange*/) {}
void ComponentView::nodeIdChanged(const ModelNode& /*node*/, const QString& /*newId*/, const QString& /*oldId*/) {}
void ComponentView::propertiesAboutToBeRemoved(const QList<AbstractProperty>& /*propertyList*/) {}
......
......@@ -59,6 +59,7 @@ public:
void nodeCreated(const ModelNode &createdNode);
void nodeAboutToBeRemoved(const ModelNode &removedNode);
void nodeRemoved(const ModelNode &removedNode, const NodeAbstractProperty &parentProperty, PropertyChangeFlags propertyChange);
void nodeAboutToBeReparented(const ModelNode &node, const NodeAbstractProperty &newPropertyParent, const NodeAbstractProperty &oldPropertyParent, AbstractView::PropertyChangeFlags propertyChange);
void nodeReparented(const ModelNode &node, const NodeAbstractProperty &newPropertyParent, const NodeAbstractProperty &oldPropertyParent, AbstractView::PropertyChangeFlags propertyChange);
void nodeIdChanged(const ModelNode& node, const QString& newId, const QString& oldId);
void propertiesAboutToBeRemoved(const QList<AbstractProperty>& propertyList);
......
......@@ -37,7 +37,7 @@
#include <allpropertiesbox.h>
#include <itemlibrary.h>
#include <navigatorview.h>
#include <stateseditorwidget.h>
#include <stateseditorview.h>
#include <formeditorview.h>
#include <formeditorwidget.h>
#include <basetexteditmodifier.h>
......@@ -87,7 +87,7 @@ public:
QWeakPointer<ItemLibrary> itemLibrary;
QWeakPointer<NavigatorView> navigator;
QWeakPointer<AllPropertiesBox> allPropertiesBox;
QWeakPointer<StatesEditorWidget> statesEditorWidget;
QWeakPointer<StatesEditorView> statesEditorView;
QWeakPointer<QStackedWidget> stackedWidget;
QWeakPointer<NodeInstanceView> nodeInstanceView;
......@@ -205,9 +205,9 @@ void DesignDocumentController::setAllPropertiesBox(AllPropertiesBox* allProperti
m_d->allPropertiesBox = allPropertiesBox;
}
void DesignDocumentController::setStatesEditorWidget(StatesEditorWidget* statesEditorWidget)
void DesignDocumentController::setStatesEditorView(StatesEditorView* statesEditorView)
{
m_d->statesEditorWidget = statesEditorWidget;
m_d->statesEditorView = statesEditorView;
}
void DesignDocumentController::setFormEditorView(FormEditorView *formEditorView)
......@@ -375,7 +375,7 @@ void DesignDocumentController::loadCurrentModel()
m_d->stackedWidget->addWidget(m_d->textEdit.data());
// Will call setCurrentState (formEditorView etc has to be constructed first)
m_d->statesEditorWidget->setup(m_d->model.data());
m_d->model->attachView(m_d->statesEditorView.data());
m_d->allPropertiesBox->setModel(m_d->model.data());
......
......@@ -54,7 +54,7 @@ class RewriterView;
class ItemLibrary;
class NavigatorView;
class AllPropertiesBox;
class StatesEditorWidget;
class StatesEditorView;
class FormEditorView;
class DesignDocumentController: public QObject
......@@ -92,7 +92,7 @@ public:
void setItemLibrary(ItemLibrary* itemLibrary);
void setNavigator(NavigatorView* navigatorView);
void setAllPropertiesBox(AllPropertiesBox* allPropertiesBox);
void setStatesEditorWidget(StatesEditorWidget* statesEditorWidget);
void setStatesEditorView(StatesEditorView* statesEditorView);
void setFormEditorView(FormEditorView *formEditorView);
void setNodeInstanceView(NodeInstanceView *nodeInstanceView);
......
......@@ -43,6 +43,7 @@ namespace QmlDesigner {
void DesignDocumentControllerView::nodeCreated(const ModelNode & /*createdNode*/) {};
void DesignDocumentControllerView::nodeAboutToBeRemoved(const ModelNode & /*removedNode*/) {};
void DesignDocumentControllerView::nodeRemoved(const ModelNode & /*removedNode*/, const NodeAbstractProperty & /*parentProperty*/, AbstractView::PropertyChangeFlags /*propertyChange*/) {};
void DesignDocumentControllerView::nodeAboutToBeReparented(const ModelNode & /*node*/, const NodeAbstractProperty & /*newPropertyParent*/, const NodeAbstractProperty & /*oldPropertyParent*/, AbstractView::PropertyChangeFlags /*propertyChange*/) {};
void DesignDocumentControllerView::nodeReparented(const ModelNode & /*node*/, const NodeAbstractProperty & /*newPropertyParent*/, const NodeAbstractProperty & /*oldPropertyParent*/, AbstractView::PropertyChangeFlags /*propertyChange*/) {};
void DesignDocumentControllerView::nodeIdChanged(const ModelNode& /*node*/, const QString& /*newId*/, const QString& /*oldId*/) {};
void DesignDocumentControllerView::propertiesAboutToBeRemoved(const QList<AbstractProperty>& /*propertyList*/) {};
......
......@@ -45,6 +45,7 @@ public:
virtual void nodeCreated(const ModelNode &createdNode);
virtual void nodeAboutToBeRemoved(const ModelNode &removedNode);
virtual void nodeRemoved(const ModelNode &removedNode, const NodeAbstractProperty &parentProperty, PropertyChangeFlags propertyChange);
virtual void nodeAboutToBeReparented(const ModelNode &node, const NodeAbstractProperty &newPropertyParent, const NodeAbstractProperty &oldPropertyParent, AbstractView::PropertyChangeFlags propertyChange);
virtual void nodeReparented(const ModelNode &node, const NodeAbstractProperty &newPropertyParent, const NodeAbstractProperty &oldPropertyParent, AbstractView::PropertyChangeFlags propertyChange);
virtual void nodeIdChanged(const ModelNode& node, const QString& newId, const QString& oldId);
virtual void propertiesAboutToBeRemoved(const QList<AbstractProperty>& propertyList);
......
......@@ -130,6 +130,10 @@ void NavigatorView::nodeAboutToBeRemoved(const ModelNode &removedNode)
m_treeModel->removeSubTree(removedNode);
}
void NavigatorView::nodeAboutToBeReparented(const ModelNode &/*node*/, const NodeAbstractProperty &/*newPropertyParent*/, const NodeAbstractProperty &/*oldPropertyParent*/, AbstractView::PropertyChangeFlags /*propertyChange*/)
{
}
void NavigatorView::nodeReparented(const ModelNode &node, const NodeAbstractProperty & /*newPropertyParent*/, const NodeAbstractProperty & /*oldPropertyParent*/, AbstractView::PropertyChangeFlags /*propertyChange*/)
{
bool blocked = blockSelectionChangedSignal(true);
......
......@@ -69,9 +69,9 @@ public:
void bindingPropertiesChanged(const QList<BindingProperty> &propertyList, PropertyChangeFlags propertyChange);
void nodeAboutToBeRemoved(const ModelNode &removedNode);
void nodeReparented(const ModelNode &node, const ModelNode &oldParent, const ModelNode &newParent);
void nodeOrderChanged(const NodeListProperty &listProperty, const ModelNode &movedNode, int oldIndex);
void nodeAboutToBeReparented(const ModelNode &node, const NodeAbstractProperty &newPropertyParent, const NodeAbstractProperty &oldPropertyParent, AbstractView::PropertyChangeFlags propertyChange);
void nodeReparented(const ModelNode &node, const NodeAbstractProperty &newPropertyParent, const NodeAbstractProperty &oldPropertyParent, AbstractView::PropertyChangeFlags propertyChange);
void rootNodeTypeChanged(const QString &type, int majorVersion, int minorVersion);
void nodeIdChanged(const ModelNode& node, const QString& newId, const QString& oldId);
......
......@@ -33,107 +33,143 @@
#include <QtCore/QDebug>
#include <QMessageBox>
#include <nodelistproperty.h>
#include <modelnode.h>
#include <variantproperty.h>
enum {
debug = false
};
namespace QmlDesigner {
namespace Internal {
StatesEditorModel::StatesEditorModel(QObject *parent) :
QAbstractListModel(parent),
m_updateCounter(0)
StatesEditorModel::StatesEditorModel(StatesEditorView *view)
: QAbstractListModel(view),
m_statesEditorView(view),
m_updateCounter(0)
{
QHash<int, QByteArray> roleNames;
roleNames.insert(StateNameRole, "stateName");
roleNames.insert(StateImageSourceRole, "stateImageSource");
roleNames.insert(NodeId, "nodeId");
setRoleNames(roleNames);
}
int StatesEditorModel::count() const
{
return m_stateNames.count();
return rowCount();
}
QModelIndex StatesEditorModel::index(int row, int column, const QModelIndex &parent) const
{
if (m_statesEditorView.isNull())
return QModelIndex();
int internalId = 0;
if (row > 0)
internalId = m_statesEditorView->rootModelNode().nodeListProperty("states").at(row - 1).internalId();
return hasIndex(row, column, parent) ? createIndex(row, column, internalId) : QModelIndex();
}
int StatesEditorModel::rowCount(const QModelIndex &parent) const
{
if (parent.isValid())
if (parent.isValid() || m_statesEditorView.isNull() || !m_statesEditorView->model())
return 0;
return m_stateNames.count();
if (!m_statesEditorView->rootModelNode().hasNodeListProperty("states"))
return 1;
return m_statesEditorView->rootModelNode().nodeListProperty("states").count() + 1;
}
void StatesEditorModel::reset()
{
QAbstractListModel::reset();
}
QVariant StatesEditorModel::data(const QModelIndex &index, int role) const
{
if (index.parent().isValid() || index.column() != 0)
if (index.parent().isValid() || index.column() != 0 || m_statesEditorView.isNull() || !m_statesEditorView->hasModelNodeForInternalId(index.internalId()))
return QVariant();
QVariant result;
ModelNode stateNode;
if (index.internalId() > 0)
stateNode = m_statesEditorView->modelNodeForInternalId(index.internalId());
switch (role) {
case StateNameRole: {
if (index.row()==0)
result = QString(tr("base state", "Implicit default state"));
else
result = m_stateNames.at(index.row());
break;
}
case StateImageSourceRole: {
if (!m_statesView.isNull())
return QString("image://qmldesigner_stateseditor/%1-%2").arg(index.row()).arg(m_updateCounter);
break;
if (index.row() == 0) {
return QString(tr("base state", "Implicit default state"));
} else {
if (stateNode.hasVariantProperty("name")) {
return stateNode.variantProperty("name").value();
} else {
return QVariant();
}
}
}
case StateImageSourceRole: return QString("image://qmldesigner_stateseditor/%1").arg(index.internalId());
case NodeId : return index.internalId();
}
return result;
return QVariant();
}
void StatesEditorModel::insertState(int i, const QString &name)
void StatesEditorModel::insertState(int stateIndex)
{
beginInsertRows(QModelIndex(), i, i);
if (stateIndex >= 0) {
m_stateNames.insert(i, name);
const int index = stateIndex + 1;
beginInsertRows(QModelIndex(), index, index);
endInsertRows();
endInsertRows();
emit dataChanged(createIndex(i, 0), createIndex(i, 0));
emit countChanged();
emit dataChanged(createIndex(index, 0), createIndex(index, 0));
emit countChanged();
}
}
void StatesEditorModel::removeState(int i)
void StatesEditorModel::updateState(int stateIndex)
{
beginRemoveRows(QModelIndex(), i, i);
if (stateIndex >= 0) {
const int index = stateIndex + 1;
m_stateNames.removeAt(i);
endRemoveRows();
emit dataChanged(createIndex(i, 0), createIndex(i, 0));
emit countChanged();
emit dataChanged(createIndex(index, 0), createIndex(index, 0));
}
}
void StatesEditorModel::renameState(int i, const QString &newName)
void StatesEditorModel::removeState(int stateIndex)
{
Q_ASSERT(i > 0 && i < m_stateNames.count());
if (m_stateNames[i] != newName) {
if (m_stateNames.contains(newName) || newName.isEmpty()) {
QMessageBox::warning(0, tr("Invalid state name"),
newName.isEmpty() ?
tr("The empty string as a name is reserved for the base state.") :
tr("Name already used in another state"));
} else {
m_stateNames.replace(i, newName);
m_statesView->renameState(i,newName);
emit dataChanged(createIndex(i, 0), createIndex(i, 0));
}
if (stateIndex >= 0) {
const int index = stateIndex + 1;
beginRemoveRows(QModelIndex(), index, index);
endRemoveRows();
emit dataChanged(createIndex(index, 0), createIndex(index, 0));
emit countChanged();
}
}
void StatesEditorModel::setStatesEditorView(StatesEditorView *statesView)
{
m_statesView = statesView;
void StatesEditorModel::renameState(int nodeId, const QString &newName)
{
if (newName.isEmpty() ||! m_statesEditorView->validStateName(newName)) {
QMessageBox::warning(0, tr("Invalid state name"),
newName.isEmpty() ?
tr("The empty string as a name is reserved for the base state.") :
tr("Name already used in another state"));
} else {
m_statesEditorView->renameState(nodeId, newName);
}
}
void StatesEditorModel::emitChangedToState(int n)
......@@ -141,5 +177,4 @@ void StatesEditorModel::emitChangedToState(int n)
emit changedToState(n);
}
} // namespace Internal
} // namespace QmlDesigner
......@@ -33,11 +33,10 @@
#include <QAbstractListModel>
#include <QWeakPointer>
#include <stateseditorview.h>
namespace QmlDesigner {
namespace Internal {
class StatesEditorView;
class StatesEditorModel : public QAbstractListModel
{
......@@ -48,32 +47,34 @@ class StatesEditorModel : public QAbstractListModel
enum {
StateNameRole = Qt::DisplayRole,
StateImageSourceRole = Qt::UserRole,
NodeId
};
public:
StatesEditorModel(QObject *parent);
StatesEditorModel(StatesEditorView *view);
int count() const;
QModelIndex index(int row, int column = 0, const QModelIndex &parent = QModelIndex()) const;
int rowCount(const QModelIndex &parent = QModelIndex()) const;
QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const;
void insertState(int i, const QString &name);
void removeState(int i);
Q_INVOKABLE void renameState(int i, const QString &newName);
void setStatesEditorView(StatesEditorView *statesView);
void insertState(int stateIndex);
void removeState(int stateIndex);
void updateState(int stateIndex);
Q_INVOKABLE void renameState(int nodeId, const QString &newName);
void emitChangedToState(int n);
void reset();
signals:
void countChanged();
void changedToState(int n);
private:
QList<QString> m_stateNames;
QWeakPointer<StatesEditorView> m_statesView;
QWeakPointer<StatesEditorView> m_statesEditorView;
int m_updateCounter;
};
} // namespace Itnernal
} // namespace QmlDesigner
#endif // STATESEDITORMODEL_H
......@@ -34,24 +34,18 @@
namespace QmlDesigner {
namespace Internal {
class StatesEditorModel;
class StatesEditorWidget;
class StatesEditorView : public QmlModelView {
Q_OBJECT
public:
explicit StatesEditorView(StatesEditorModel *model, QObject *parent = 0);
explicit StatesEditorView(QObject *parent = 0);
void setCurrentState(int index);
void createState(const QString &name);
void removeState(int index);
void renameState(int index,const QString &newName);
void duplicateCurrentState(int index);
QmlItemNode stateRootNode() { return m_stateRootNode; }
bool isAttachedToModel() const { return m_attachedToModel; }
void renameState(int nodeId,const QString &newName);
bool validStateName(const QString &name) const;
void nodeInstancePropertyChanged(const ModelNode &node, const QString &propertyName);
......@@ -62,9 +56,12 @@ public:
void variantPropertiesChanged(const QList<VariantProperty>& propertyList, PropertyChangeFlags propertyChange);
void nodeAboutToBeRemoved(const ModelNode &removedNode);
void nodeRemoved(const ModelNode &removedNode, const NodeAbstractProperty &parentProperty, PropertyChangeFlags propertyChange);
void nodeAboutToBeReparented(const ModelNode &node, const NodeAbstractProperty &newPropertyParent, const NodeAbstractProperty &oldPropertyParent, AbstractView::PropertyChangeFlags propertyChange);
void nodeReparented(const ModelNode &node, const NodeAbstractProperty &newPropertyParent, const NodeAbstractProperty &oldPropertyParent, AbstractView::PropertyChangeFlags propertyChange);
void nodeOrderChanged(const NodeListProperty &listProperty, const ModelNode &movedNode, int oldIndex);
// QmlModelView
void stateChanged(const QmlModelState &newQmlModelState, const QmlModelState &oldQmlModelState);
void transformChanged(const QmlObjectNode &qmlObjectNode, const QString &propertyName);
......@@ -77,23 +74,24 @@ public:
void bindingPropertiesChanged(const QList<BindingProperty> &propertyList, PropertyChangeFlags propertyChange);
void selectedNodesChanged(const QList<ModelNode> &selectedNodeList, const QList<ModelNode> &lastSelectedNodeList);
private:
void insertModelState(int i, const QmlModelState &state);
void removeModelState(const QmlModelState &state);
void clearModelStates();
int modelStateIndex(const QmlModelState &state);
StatesEditorWidget *widget();
public slots:
void synchonizeCurrentStateFromWidget();
void createNewState();
void removeState(int nodeId);
QList<QmlModelState> m_modelStates;
StatesEditorModel *m_editorModel;
QmlItemNode m_stateRootNode;
private:
void resetModel();
void addState();
void duplicateCurrentState();
QmlModelState m_oldRewriterAmendState;
bool m_attachedToModel;
bool m_settingSilentState;
private:
QWeakPointer<StatesEditorModel> m_statesEditorModel;
QWeakPointer<StatesEditorWidget> m_statesEditorWidget;
int m_lastIndex;
};
} // namespace Internal
} // namespace QmlDesigner
#endif // STATESEDITORVIEW_H
......@@ -55,139 +55,58 @@ enum {
namespace QmlDesigner {
namespace Internal {
class StatesEditorWidgetPrivate : QObject
{
Q_OBJECT
private:
StatesEditorWidgetPrivate(StatesEditorWidget *q);
int currentIndex() const;
void setCurrentIndex(int i);
bool validStateName(const QString &name) const;
private slots:
void currentStateChanged();
void addState();
void removeState(int);
void duplicateCurrentState();
private:
StatesEditorWidget *m_q;
QWeakPointer<Model> model;
QWeakPointer<QDeclarativeView> listView;
QWeakPointer<Internal::StatesEditorModel> statesEditorModel;
QWeakPointer<Internal::StatesEditorView> statesEditorView;
friend class QmlDesigner::StatesEditorWidget;
};
StatesEditorWidgetPrivate::StatesEditorWidgetPrivate(StatesEditorWidget *q) :
QObject(q),
m_q(q)
int StatesEditorWidget::currentStateInternalId() const
{
}
Q_ASSERT(m_declarativeView->rootObject());
Q_ASSERT(m_declarativeView->rootObject()->property("currentStateInternalId").isValid());
int StatesEditorWidgetPrivate::currentIndex() const
{
Q_ASSERT(listView->rootObject());
Q_ASSERT(listView->rootObject()->property("currentStateIndex").isValid());
return listView->rootObject()->property("currentStateIndex").toInt();
}
void StatesEditorWidgetPrivate::setCurrentIndex(int i)
{
listView->rootObject()->setProperty("currentStateIndex", i);
return m_declarativeView->rootObject()->property("currentStateInternalId").toInt();
}
bool StatesEditorWidgetPrivate::validStateName(const QString &name) const
void StatesEditorWidget::setCurrentStateInternalId(int internalId)
{
if (name == tr("base state"))
return false;
QList<QmlModelState> modelStates = statesEditorView->stateRootNode().states().allStates();
foreach (const QmlModelState &state, modelStates) {
if (state.name() == name)
return false;
}
return true;
m_declarativeView->rootObject()->setProperty("currentStateInternalId", internalId);
}
void StatesEditorWidgetPrivate::currentStateChanged()
StatesEditorWidget::StatesEditorWidget(StatesEditorView *statesEditorView, StatesEditorModel *statesEditorModel):
QWidget()
{
if (statesEditorView->isAttachedToModel())
statesEditorView->setCurrentState(currentIndex());
}
void StatesEditorWidgetPrivate::addState()
{
// can happen when root node is e.g. a ListModel
if (!statesEditorView->stateRootNode().isValid())
return;
QStringList modelStateNames = statesEditorView->stateRootNode().states().names();
QString newStateName;
int index = 1;
while (1) {
newStateName = tr("State%1", "Default name for newly created states").arg(index++);
if (!modelStateNames.contains(newStateName))
break;
}
statesEditorView->createState(newStateName);
}
m_declarativeView = new QDeclarativeView(this);
void StatesEditorWidgetPrivate::removeState(int i)
{
statesEditorView->removeState(i);
}
void StatesEditorWidgetPrivate::duplicateCurrentState()
{
statesEditorView->duplicateCurrentState(currentIndex());
}
} // namespace Internal
m_declarativeView->engine()->addImageProvider(
QLatin1String("qmldesigner_stateseditor"), new Internal::StatesEditorImageProvider);
StatesEditorWidget::StatesEditorWidget(QWidget *parent):
QWidget(parent),
m_d(new Internal::StatesEditorWidgetPrivate(this))
{
m_d->statesEditorModel = new Internal::StatesEditorModel(this);
m_d->listView = new QDeclarativeView(this);
m_d->listView->setAcceptDrops(false);
m_declarativeView->setAcceptDrops(false);
QVBoxLayout *layout = new QVBoxLayout(this);
layout->setMargin(0);
layout->setSpacing(0);
layout->addWidget(m_d->listView.data());
layout->addWidget(m_declarativeView.data());