Move selection related code into SelectionModel

And fix a bug where the curves where missing in the graphicsview after opening the
AnimationCurveDialog a second time.

Change-Id: I4f13bd345afafaa0578a3be28be6326fa232dbe1
Reviewed-by: Mahmoud Badri <mahmoud.badri@qt.io>
Reviewed-by: Miikka Heikkinen <miikka.heikkinen@qt.io>
Reviewed-by: Thomas Hartmann <thomas.hartmann@qt.io>
This commit is contained in:
Knud Dollereder
2019-11-29 16:12:16 +01:00
parent fd39ea9ef9
commit 16bd822d1b
18 changed files with 286 additions and 77 deletions

View File

@@ -626,6 +626,7 @@ extend_qtc_plugin(QmlDesigner
detail/keyframeitem.cpp detail/keyframeitem.h
detail/playhead.cpp detail/playhead.h
detail/selectableitem.cpp detail/selectableitem.h
detail/selectionmodel.cpp detail/selectionmodel.h
detail/selector.cpp detail/selector.h
detail/shortcut.cpp detail/shortcut.h
detail/treeitemdelegate.cpp detail/treeitemdelegate.h

View File

@@ -52,7 +52,7 @@ CurveEditor::CurveEditor(CurveEditorModel *model, QWidget *parent)
box->addWidget(splitter);
setLayout(box);
connect(m_tree, &TreeView::curvesSelected, m_view, &GraphicsView::reset);
connect(m_tree->selectionModel(), &SelectionModel::curvesSelected, m_view, &GraphicsView::reset);
}
void CurveEditor::zoomX(double zoom)
@@ -67,7 +67,7 @@ void CurveEditor::zoomY(double zoom)
void CurveEditor::clearCanvas()
{
m_view->reset(m_tree->selection());
m_view->reset({});
}
QToolBar *CurveEditor::createToolBar()

View File

@@ -14,6 +14,7 @@ HEADERS += \
$$PWD/detail/keyframeitem.h \
$$PWD/detail/playhead.h \
$$PWD/detail/selectableitem.h \
$$PWD/detail/selectionmodel.h \
$$PWD/detail/selector.h \
$$PWD/detail/shortcut.h \
$$PWD/detail/treeitemdelegate.h \
@@ -36,6 +37,7 @@ SOURCES += \
$$PWD/detail/keyframeitem.cpp \
$$PWD/detail/playhead.cpp \
$$PWD/detail/selectableitem.cpp \
$$PWD/detail/selectionmodel.cpp \
$$PWD/detail/selector.cpp \
$$PWD/detail/shortcut.cpp \
$$PWD/detail/treeitemdelegate.cpp \

View File

@@ -26,6 +26,7 @@
#include "curveeditormodel.h"
#include "treeitem.h"
#include "detail/graphicsview.h"
#include "detail/selectionmodel.h"
namespace DesignTools {
@@ -53,7 +54,9 @@ void CurveEditorModel::setCurve(unsigned int id, const AnimationCurve &curve)
void CurveEditorModel::reset(const std::vector<TreeItem *> &items)
{
std::vector<TreeItem::Path> sel = selection();
std::vector<TreeItem::Path> sel;
if (SelectionModel *sm = selectionModel())
sel = sm->selectedPaths();
beginResetModel();
@@ -67,7 +70,8 @@ void CurveEditorModel::reset(const std::vector<TreeItem *> &items)
endResetModel();
select(sel);
if (SelectionModel *sm = selectionModel())
sm->select(sel);
}
} // End namespace DesignTools.

View File

@@ -339,6 +339,8 @@ void CurveItem::setInterpolation(Keyframe::Interpolation interpolation)
void CurveItem::connect(GraphicsScene *scene)
{
QObject::connect(this, &CurveItem::curveChanged, scene, &GraphicsScene::curveChanged);
for (auto *frame : m_keyframes) {
QObject::connect(frame, &KeyframeItem::keyframeMoved, scene, &GraphicsScene::keyframeMoved);
QObject::connect(frame, &KeyframeItem::handleMoved, scene, &GraphicsScene::handleMoved);

View File

@@ -68,11 +68,8 @@ void GraphicsScene::addCurveItem(CurveItem *item)
{
m_dirty = true;
item->setDirty(false);
connect(item, &CurveItem::curveChanged, this, &GraphicsScene::curveChanged);
addItem(item);
item->connect(this);
addItem(item);
}
void GraphicsScene::setComponentTransform(const QTransform &transform)

View File

@@ -0,0 +1,116 @@
/****************************************************************************
**
** Copyright (C) 2019 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the Qt Design Tooling
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3 as published by the Free Software
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
**
****************************************************************************/
#include "selectionmodel.h"
#include "treemodel.h"
namespace DesignTools {
SelectionModel::SelectionModel(QAbstractItemModel *model)
: QItemSelectionModel(model)
{
connect(this, &QItemSelectionModel::selectionChanged, this, &SelectionModel::changeSelection);
}
std::vector<TreeItem::Path> SelectionModel::selectedPaths() const
{
std::vector<TreeItem::Path> out;
for (auto &&item : selectedTreeItems())
out.push_back(item->path());
return out;
}
std::vector<CurveItem *> SelectionModel::selectedCurveItems() const
{
std::vector<CurveItem *> items;
const auto rows = selectedRows(0);
for (auto &&index : rows) {
if (auto *curveItem = TreeModel::curveItem(index))
items.push_back(curveItem);
}
return items;
}
std::vector<TreeItem *> SelectionModel::selectedTreeItems() const
{
std::vector<TreeItem *> items;
const auto rows = selectedRows(0);
for (auto &&index : rows) {
if (auto *treeItem = TreeModel::treeItem(index))
items.push_back(treeItem);
}
return items;
}
std::vector<NodeTreeItem *> SelectionModel::selectedNodeItems() const
{
std::vector<NodeTreeItem *> items;
const auto rows = selectedRows(0);
for (auto &&index : rows) {
if (auto *ni = TreeModel::nodeItem(index))
items.push_back(ni);
}
return items;
}
std::vector<PropertyTreeItem *> SelectionModel::selectedPropertyItems() const
{
std::vector<PropertyTreeItem *> items;
const auto rows = selectedRows(0);
for (auto &&index : rows) {
if (auto *pi = TreeModel::propertyItem(index))
items.push_back(pi);
}
return items;
}
void SelectionModel::select(const std::vector<TreeItem::Path> &selection)
{
for (auto &&path : selection) {
if (auto *treeModel = qobject_cast<TreeModel *>(model())) {
QModelIndex index = treeModel->indexOf(path);
if (index.isValid())
QItemSelectionModel::select(index, QItemSelectionModel::Select);
}
}
}
void SelectionModel::changeSelection(const QItemSelection &selected,
const QItemSelection &deselected)
{
Q_UNUSED(selected)
Q_UNUSED(deselected)
std::vector<CurveItem *> curves;
const auto ids = selectedIndexes();
for (auto &&index : ids) {
if (auto *curveItem = TreeModel::curveItem(index))
curves.push_back(curveItem);
}
emit curvesSelected(curves);
}
} // End namespace DesignTools.

View File

@@ -0,0 +1,65 @@
/****************************************************************************
**
** Copyright (C) 2019 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the Qt Design Tooling
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3 as published by the Free Software
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
**
****************************************************************************/
#pragma once
#include "treeitem.h"
#include <QItemSelectionModel>
namespace DesignTools {
class CurveItem;
class TreeItem;
class NodeTreeItem;
class PropertyTreeItem;
class SelectionModel : public QItemSelectionModel
{
Q_OBJECT
signals:
void curvesSelected(const std::vector<CurveItem *> &curves);
public:
SelectionModel(QAbstractItemModel *model = nullptr);
std::vector<TreeItem::Path> selectedPaths() const;
std::vector<CurveItem *> selectedCurveItems() const;
std::vector<TreeItem *> selectedTreeItems() const;
std::vector<NodeTreeItem *> selectedNodeItems() const;
std::vector<PropertyTreeItem *> selectedPropertyItems() const;
void select(const std::vector<TreeItem::Path> &selection);
private:
void changeSelection(const QItemSelection &selected, const QItemSelection &deselected);
};
} // End namespace DesignTools.

View File

@@ -24,6 +24,7 @@
****************************************************************************/
#include "treemodel.h"
#include "curveitem.h"
#include "detail/graphicsview.h"
#include "treeitem.h"
#include "treeview.h"
@@ -32,6 +33,42 @@
namespace DesignTools {
TreeItem *TreeModel::treeItem(const QModelIndex &index)
{
if (index.isValid() && index.column() == 0)
return static_cast<TreeItem *>(index.internalPointer());
return nullptr;
}
NodeTreeItem *TreeModel::nodeItem(const QModelIndex &index)
{
if (auto *ti = treeItem(index))
return ti->asNodeItem();
return nullptr;
}
PropertyTreeItem *TreeModel::propertyItem(const QModelIndex &index)
{
if (auto *ti = treeItem(index))
return ti->asPropertyItem();
return nullptr;
}
CurveItem *TreeModel::curveItem(const QModelIndex &index)
{
if (auto *pti = propertyItem(index)) {
auto *citem = new CurveItem(pti->id(), pti->curve());
citem->setValueType(pti->valueType());
citem->setComponent(pti->component());
return citem;
}
return nullptr;
}
TreeModel::TreeModel(QObject *parent)
: QAbstractItemModel(parent)
, m_view(nullptr)
@@ -141,16 +178,11 @@ GraphicsView *TreeModel::graphicsView() const
return m_view;
}
std::vector<TreeItem::Path> TreeModel::selection() const
SelectionModel *TreeModel::selectionModel() const
{
std::vector<TreeItem::Path> out;
for (auto &&index : m_tree->selectionModel()->selectedIndexes()) {
if (index.column() == 0) {
TreeItem *item = static_cast<TreeItem *>(index.internalPointer());
out.push_back(item->path());
}
}
return out;
if (m_tree)
return m_tree->selectionModel();
return nullptr;
}
QModelIndex TreeModel::findIdx(const QString &name, const QModelIndex &parent) const
@@ -178,15 +210,6 @@ QModelIndex TreeModel::indexOf(const TreeItem::Path &path) const
return parent;
}
void TreeModel::select(const std::vector<TreeItem::Path> &selection)
{
for (auto &&sel : selection) {
QModelIndex idx = indexOf(sel);
if (idx.isValid())
m_tree->selectionModel()->select(idx, QItemSelectionModel::Select);
}
}
void TreeModel::initialize()
{
if (m_root)

View File

@@ -35,12 +35,24 @@ namespace DesignTools {
class GraphicsView;
class TreeView;
class TreeItem;
class CurveItem;
class PropertyTreeItem;
class SelectionModel;
class TreeModel : public QAbstractItemModel
{
Q_OBJECT
public:
static TreeItem *treeItem(const QModelIndex &index);
static NodeTreeItem *nodeItem(const QModelIndex &index);
static PropertyTreeItem *propertyItem(const QModelIndex &index);
static CurveItem *curveItem(const QModelIndex &index);
TreeModel(QObject *parent = nullptr);
~TreeModel() override;
@@ -59,6 +71,8 @@ public:
int columnCount(const QModelIndex &parent = QModelIndex()) const override;
QModelIndex indexOf(const TreeItem::Path &path) const;
void setTreeView(TreeView *view);
void setGraphicsView(GraphicsView *view);
@@ -66,9 +80,7 @@ public:
protected:
GraphicsView *graphicsView() const;
std::vector<TreeItem::Path> selection() const;
void select(const std::vector<TreeItem::Path> &selection);
SelectionModel *selectionModel() const;
void initialize();
@@ -78,8 +90,6 @@ protected:
QModelIndex findIdx(const QString &name, const QModelIndex &parent) const;
QModelIndex indexOf(const TreeItem::Path &path) const;
private:
GraphicsView *m_view;

View File

@@ -25,6 +25,7 @@
#include "treeview.h"
#include "curveeditormodel.h"
#include "curveitem.h"
#include "selectionmodel.h"
#include "treeitem.h"
#include "treeitemdelegate.h"
@@ -49,16 +50,12 @@ TreeView::TreeView(CurveEditorModel *model, QWidget *parent)
auto expandItems = [this]() { expandAll(); };
connect(model, &QAbstractItemModel::modelReset, expandItems);
auto *delegate = new TreeItemDelegate(model->style(), this);
setItemDelegate(delegate);
setItemDelegate(new TreeItemDelegate(model->style(), this));
setSelectionModel(new SelectionModel(model));
setSelectionBehavior(QAbstractItemView::SelectRows);
setSelectionMode(QAbstractItemView::ExtendedSelection);
connect(selectionModel(),
&QItemSelectionModel::selectionChanged,
this,
&TreeView::changeSelection);
setStyle(model->style());
header()->setSectionResizeMode(0, QHeaderView::Stretch);
@@ -70,6 +67,11 @@ TreeView::TreeView(CurveEditorModel *model, QWidget *parent)
header()->resizeSection(2, 20);
}
SelectionModel *TreeView::selectionModel() const
{
return qobject_cast<SelectionModel *>(QTreeView::selectionModel());
}
void TreeView::setStyle(const CurveEditorStyle &style)
{
QPalette pal = palette();
@@ -87,46 +89,12 @@ void TreeView::setStyle(const CurveEditorStyle &style)
delegate->setStyle(style);
}
std::vector<CurveItem *> TreeView::selection()
{
std::vector<DesignTools::CurveItem *> items;
for (auto &&index : selectionModel()->selectedRows(0)) {
if (index.isValid()) {
auto *treeItem = static_cast<TreeItem *>(index.internalPointer());
if (auto *propertyItem = treeItem->asPropertyItem())
items.push_back(new CurveItem(treeItem->id(), propertyItem->curve()));
}
}
return items;
}
void TreeView::changeCurve(unsigned int id, const AnimationCurve &curve)
{
if (auto *curveModel = qobject_cast<CurveEditorModel *>(model()))
curveModel->setCurve(id, curve);
}
void TreeView::changeSelection(const QItemSelection &selected, const QItemSelection &deselected)
{
Q_UNUSED(selected)
Q_UNUSED(deselected)
std::vector<CurveItem *> curves;
for (auto index : selectedIndexes()) {
if (index.isValid() && index.column() == 0) {
auto *treeItem = static_cast<TreeItem *>(index.internalPointer());
if (auto *propertyItem = treeItem->asPropertyItem()) {
auto *citem = new CurveItem(treeItem->id(), propertyItem->curve());
citem->setValueType(propertyItem->valueType());
citem->setComponent(propertyItem->component());
curves.push_back(citem);
}
}
}
emit curvesSelected(curves);
}
QSize TreeView::sizeHint() const
{
return QSize(170, 300);

View File

@@ -25,6 +25,8 @@
#pragma once
#include "selectionmodel.h"
#include <QTreeView>
namespace DesignTools {
@@ -45,12 +47,12 @@ signals:
public:
TreeView(CurveEditorModel *model, QWidget *parent = nullptr);
SelectionModel *selectionModel() const;
void changeCurve(unsigned int id, const AnimationCurve &curve);
void setStyle(const CurveEditorStyle &style);
std::vector<CurveItem *> selection();
protected:
QSize sizeHint() const override;

View File

@@ -246,6 +246,20 @@ QIcon NodeTreeItem::icon() const
return m_icon;
}
std::string toString(ValueType type)
{
switch (type) {
case ValueType::Bool:
return "Bool";
case ValueType::Integer:
return "Integer";
case ValueType::Double:
return "Double";
default:
return "Undefined";
}
}
PropertyTreeItem::PropertyTreeItem(const QString &name,
const AnimationCurve &curve,
const ValueType &type)

View File

@@ -133,6 +133,8 @@ enum class ValueType {
Double,
};
std::string toString(ValueType type);
class PropertyTreeItem : public TreeItem
{
public:

View File

@@ -56,8 +56,9 @@ void AnimationCurveDialog::setModel(DesignTools::CurveEditorModel *model)
setLayout(layout);
}
void AnimationCurveDialog::showEvent(QShowEvent *)
void AnimationCurveDialog::refresh()
{
if (m_editor)
m_editor->clearCanvas();
}

View File

@@ -42,8 +42,7 @@ public:
void setModel(DesignTools::CurveEditorModel *model);
protected:
void showEvent(QShowEvent *event) override;
void refresh();
private:
DesignTools::CurveEditor *m_editor;

View File

@@ -232,6 +232,7 @@ void TimelineToolBar::openAnimationCurveEditor()
timeline = tlv->timelineForState(tlv->currentState());
}
m_dialog.refresh();
m_curveModel->setTimeline(timeline);
m_dialog.show();
}

View File

@@ -691,6 +691,8 @@ Project {
"curveeditor/detail/playhead.h",
"curveeditor/detail/selectableitem.cpp",
"curveeditor/detail/selectableitem.h",
"curveeditor/detail/selectionmodel.cpp",
"curveeditor/detail/selectionmodel.h",
"curveeditor/detail/selector.cpp",
"curveeditor/detail/selector.h",
"curveeditor/detail/shortcut.cpp",