forked from qt-creator/qt-creator
Implement locking and pinning of animation-curves
Fixes: QDS-550 Fixes: QDS-551 Change-Id: I53a120a3753bb98fe729106b7e996f475fbda2f1 Reviewed-by: Thomas Hartmann <thomas.hartmann@qt.io>
This commit is contained in:
@@ -52,7 +52,11 @@ CurveEditor::CurveEditor(CurveEditorModel *model, QWidget *parent)
|
|||||||
box->addWidget(splitter);
|
box->addWidget(splitter);
|
||||||
setLayout(box);
|
setLayout(box);
|
||||||
|
|
||||||
|
connect(m_tree, &TreeView::treeItemLocked, m_view, &GraphicsView::setLocked);
|
||||||
connect(m_tree->selectionModel(), &SelectionModel::curvesSelected, m_view, &GraphicsView::reset);
|
connect(m_tree->selectionModel(), &SelectionModel::curvesSelected, m_view, &GraphicsView::reset);
|
||||||
|
|
||||||
|
connect(m_tree, &TreeView::treeItemLocked, model, &CurveEditorModel::curveChanged);
|
||||||
|
connect(m_tree, &TreeView::treeItemPinned, model, &CurveEditorModel::curveChanged);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CurveEditor::zoomX(double zoom)
|
void CurveEditor::zoomX(double zoom)
|
||||||
|
@@ -52,6 +52,15 @@ void CurveEditorModel::setCurve(unsigned int id, const AnimationCurve &curve)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool contains(const std::vector<TreeItem::Path> &selection, const TreeItem::Path &path)
|
||||||
|
{
|
||||||
|
for (auto &&sel : selection)
|
||||||
|
if (path == sel)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
void CurveEditorModel::reset(const std::vector<TreeItem *> &items)
|
void CurveEditorModel::reset(const std::vector<TreeItem *> &items)
|
||||||
{
|
{
|
||||||
std::vector<TreeItem::Path> sel;
|
std::vector<TreeItem::Path> sel;
|
||||||
@@ -63,13 +72,24 @@ void CurveEditorModel::reset(const std::vector<TreeItem *> &items)
|
|||||||
initialize();
|
initialize();
|
||||||
|
|
||||||
unsigned int counter = 0;
|
unsigned int counter = 0;
|
||||||
|
std::vector<CurveItem *> pinned;
|
||||||
|
|
||||||
for (auto *item : items) {
|
for (auto *item : items) {
|
||||||
item->setId(++counter);
|
item->setId(++counter);
|
||||||
root()->addChild(item);
|
root()->addChild(item);
|
||||||
|
if (auto *nti = item->asNodeItem()) {
|
||||||
|
for (auto *pti : nti->properties()) {
|
||||||
|
if (pti->pinned() && !contains(sel, pti->path()))
|
||||||
|
pinned.push_back(TreeModel::curveItem(pti));
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
endResetModel();
|
endResetModel();
|
||||||
|
|
||||||
|
if (!pinned.empty())
|
||||||
|
graphicsView()->reset(pinned);
|
||||||
|
|
||||||
if (SelectionModel *sm = selectionModel())
|
if (SelectionModel *sm = selectionModel())
|
||||||
sm->select(sel);
|
sm->select(sel);
|
||||||
}
|
}
|
||||||
|
@@ -46,6 +46,8 @@ CurveItem::CurveItem(QGraphicsItem *parent)
|
|||||||
, m_component(PropertyTreeItem::Component::Generic)
|
, m_component(PropertyTreeItem::Component::Generic)
|
||||||
, m_transform()
|
, m_transform()
|
||||||
, m_keyframes()
|
, m_keyframes()
|
||||||
|
, m_locked(false)
|
||||||
|
, m_pinned(false)
|
||||||
, m_underMouse(false)
|
, m_underMouse(false)
|
||||||
, m_itemDirty(false)
|
, m_itemDirty(false)
|
||||||
{}
|
{}
|
||||||
@@ -58,6 +60,8 @@ CurveItem::CurveItem(unsigned int id, const AnimationCurve &curve, QGraphicsItem
|
|||||||
, m_component(PropertyTreeItem::Component::Generic)
|
, m_component(PropertyTreeItem::Component::Generic)
|
||||||
, m_transform()
|
, m_transform()
|
||||||
, m_keyframes()
|
, m_keyframes()
|
||||||
|
, m_locked(false)
|
||||||
|
, m_pinned(false)
|
||||||
, m_underMouse(false)
|
, m_underMouse(false)
|
||||||
, m_itemDirty(false)
|
, m_itemDirty(false)
|
||||||
{
|
{
|
||||||
@@ -128,7 +132,9 @@ void CurveItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *, QWidg
|
|||||||
if (segment.interpolation() == Keyframe::Interpolation::Easing) {
|
if (segment.interpolation() == Keyframe::Interpolation::Easing) {
|
||||||
pen.setColor(m_style.easingCurveColor);
|
pen.setColor(m_style.easingCurveColor);
|
||||||
} else {
|
} else {
|
||||||
if (m_underMouse)
|
if (m_locked)
|
||||||
|
pen.setColor(Qt::black);
|
||||||
|
else if (m_underMouse)
|
||||||
pen.setColor(Qt::red);
|
pen.setColor(Qt::red);
|
||||||
else if (hasSelection())
|
else if (hasSelection())
|
||||||
pen.setColor(m_style.selectionColor);
|
pen.setColor(m_style.selectionColor);
|
||||||
@@ -147,6 +153,16 @@ bool CurveItem::isDirty() const
|
|||||||
return m_itemDirty;
|
return m_itemDirty;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool CurveItem::locked() const
|
||||||
|
{
|
||||||
|
return m_locked;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CurveItem::pinned() const
|
||||||
|
{
|
||||||
|
return m_pinned;
|
||||||
|
}
|
||||||
|
|
||||||
bool CurveItem::hasSelection() const
|
bool CurveItem::hasSelection() const
|
||||||
{
|
{
|
||||||
for (auto *frame : m_keyframes) {
|
for (auto *frame : m_keyframes) {
|
||||||
@@ -267,6 +283,20 @@ void CurveItem::restore()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CurveItem::setLocked(bool locked)
|
||||||
|
{
|
||||||
|
m_locked = locked;
|
||||||
|
for (auto frame : m_keyframes)
|
||||||
|
frame->setLocked(locked);
|
||||||
|
|
||||||
|
setHandleVisibility(!m_locked);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CurveItem::setPinned(bool pinned)
|
||||||
|
{
|
||||||
|
m_pinned = pinned;
|
||||||
|
}
|
||||||
|
|
||||||
void CurveItem::setDirty(bool dirty)
|
void CurveItem::setDirty(bool dirty)
|
||||||
{
|
{
|
||||||
m_itemDirty = dirty;
|
m_itemDirty = dirty;
|
||||||
@@ -294,6 +324,7 @@ void CurveItem::setCurve(const AnimationCurve &curve)
|
|||||||
|
|
||||||
for (auto frame : curve.keyframes()) {
|
for (auto frame : curve.keyframes()) {
|
||||||
auto *item = new KeyframeItem(frame, this);
|
auto *item = new KeyframeItem(frame, this);
|
||||||
|
item->setLocked(m_locked);
|
||||||
item->setComponentTransform(m_transform);
|
item->setComponentTransform(m_transform);
|
||||||
m_keyframes.push_back(item);
|
m_keyframes.push_back(item);
|
||||||
QObject::connect(item, &KeyframeItem::redrawCurve, this, &CurveItem::emitCurveChanged);
|
QObject::connect(item, &KeyframeItem::redrawCurve, this, &CurveItem::emitCurveChanged);
|
||||||
|
@@ -66,6 +66,10 @@ public:
|
|||||||
|
|
||||||
bool isDirty() const;
|
bool isDirty() const;
|
||||||
|
|
||||||
|
bool locked() const;
|
||||||
|
|
||||||
|
bool pinned() const;
|
||||||
|
|
||||||
bool isUnderMouse() const;
|
bool isUnderMouse() const;
|
||||||
|
|
||||||
bool hasSelection() const;
|
bool hasSelection() const;
|
||||||
@@ -84,6 +88,10 @@ public:
|
|||||||
|
|
||||||
void restore();
|
void restore();
|
||||||
|
|
||||||
|
void setLocked(bool locked);
|
||||||
|
|
||||||
|
void setPinned(bool pinned);
|
||||||
|
|
||||||
void setDirty(bool dirty);
|
void setDirty(bool dirty);
|
||||||
|
|
||||||
void setHandleVisibility(bool visible);
|
void setHandleVisibility(bool visible);
|
||||||
@@ -123,6 +131,10 @@ private:
|
|||||||
|
|
||||||
std::vector<KeyframeItem *> m_keyframes;
|
std::vector<KeyframeItem *> m_keyframes;
|
||||||
|
|
||||||
|
bool m_locked;
|
||||||
|
|
||||||
|
bool m_pinned;
|
||||||
|
|
||||||
bool m_underMouse;
|
bool m_underMouse;
|
||||||
|
|
||||||
bool m_itemDirty;
|
bool m_itemDirty;
|
||||||
|
@@ -121,6 +121,32 @@ void GraphicsScene::handleMoved(KeyframeItem *frame,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void GraphicsScene::setPinned(int id, bool pinned)
|
||||||
|
{
|
||||||
|
const auto itemList = items();
|
||||||
|
for (auto *item : itemList) {
|
||||||
|
if (auto *curveItem = qgraphicsitem_cast<CurveItem *>(item)) {
|
||||||
|
if (curveItem->id() == id)
|
||||||
|
curveItem->setPinned(pinned);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<CurveItem *> GraphicsScene::takePinnedItems()
|
||||||
|
{
|
||||||
|
std::vector<CurveItem *> out;
|
||||||
|
const auto itemList = items();
|
||||||
|
for (auto *item : itemList) {
|
||||||
|
if (auto *curveItem = qgraphicsitem_cast<CurveItem *>(item)) {
|
||||||
|
if (curveItem->pinned()) {
|
||||||
|
removeItem(curveItem);
|
||||||
|
out.push_back(curveItem);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
void GraphicsScene::mouseMoveEvent(QGraphicsSceneMouseEvent *mouseEvent)
|
void GraphicsScene::mouseMoveEvent(QGraphicsSceneMouseEvent *mouseEvent)
|
||||||
{
|
{
|
||||||
QGraphicsScene::mouseMoveEvent(mouseEvent);
|
QGraphicsScene::mouseMoveEvent(mouseEvent);
|
||||||
|
@@ -69,6 +69,10 @@ public:
|
|||||||
|
|
||||||
void handleMoved(KeyframeItem *frame, HandleSlot handle, double angle, double deltaLength);
|
void handleMoved(KeyframeItem *frame, HandleSlot handle, double angle, double deltaLength);
|
||||||
|
|
||||||
|
void setPinned(int id, bool pinned);
|
||||||
|
|
||||||
|
std::vector<CurveItem *> takePinnedItems();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void mouseMoveEvent(QGraphicsSceneMouseEvent *mouseEvent) override;
|
void mouseMoveEvent(QGraphicsSceneMouseEvent *mouseEvent) override;
|
||||||
|
|
||||||
|
@@ -26,6 +26,7 @@
|
|||||||
#include "graphicsview.h"
|
#include "graphicsview.h"
|
||||||
#include "curveeditormodel.h"
|
#include "curveeditormodel.h"
|
||||||
#include "curveitem.h"
|
#include "curveitem.h"
|
||||||
|
#include "treeitem.h"
|
||||||
#include "utils.h"
|
#include "utils.h"
|
||||||
|
|
||||||
#include <QAction>
|
#include <QAction>
|
||||||
@@ -69,6 +70,9 @@ GraphicsView::GraphicsView(CurveEditorModel *model, QWidget *parent)
|
|||||||
|
|
||||||
connect(&m_scene, &GraphicsScene::curveChanged, itemSlot);
|
connect(&m_scene, &GraphicsScene::curveChanged, itemSlot);
|
||||||
|
|
||||||
|
auto pinSlot = [this](PropertyTreeItem *pti) { m_scene.setPinned(pti->id(), pti->pinned()); };
|
||||||
|
connect(m_model, &CurveEditorModel::curveChanged, pinSlot);
|
||||||
|
|
||||||
applyZoom(m_zoomX, m_zoomY);
|
applyZoom(m_zoomX, m_zoomY);
|
||||||
update();
|
update();
|
||||||
}
|
}
|
||||||
@@ -185,6 +189,16 @@ void GraphicsView::setStyle(const CurveEditorStyle &style)
|
|||||||
viewport()->update();
|
viewport()->update();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void GraphicsView::setLocked(PropertyTreeItem *item)
|
||||||
|
{
|
||||||
|
const auto itemList = items();
|
||||||
|
for (auto *gitem : itemList) {
|
||||||
|
if (auto *citem = qgraphicsitem_cast<CurveItem *>(gitem))
|
||||||
|
if (item->id() == citem->id())
|
||||||
|
citem->setLocked(item->locked());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void GraphicsView::setZoomX(double zoom, const QPoint &pivot)
|
void GraphicsView::setZoomX(double zoom, const QPoint &pivot)
|
||||||
{
|
{
|
||||||
applyZoom(zoom, m_zoomY, pivot);
|
applyZoom(zoom, m_zoomY, pivot);
|
||||||
@@ -217,8 +231,22 @@ void GraphicsView::scrollContent(double x, double y)
|
|||||||
|
|
||||||
void GraphicsView::reset(const std::vector<CurveItem *> &items)
|
void GraphicsView::reset(const std::vector<CurveItem *> &items)
|
||||||
{
|
{
|
||||||
|
const std::vector<CurveItem *> pinnedItems = m_scene.takePinnedItems();
|
||||||
|
auto notPinned = [pinnedItems](CurveItem *item) {
|
||||||
|
for (auto *pinned : pinnedItems) {
|
||||||
|
if (pinned->id() == item->id())
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
|
||||||
m_scene.clear();
|
m_scene.clear();
|
||||||
for (auto *item : items)
|
for (auto *item : items) {
|
||||||
|
if (notPinned(item))
|
||||||
|
m_scene.addCurveItem(item);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (auto *item : pinnedItems)
|
||||||
m_scene.addCurveItem(item);
|
m_scene.addCurveItem(item);
|
||||||
|
|
||||||
applyZoom(m_zoomX, m_zoomY);
|
applyZoom(m_zoomX, m_zoomY);
|
||||||
|
@@ -38,6 +38,7 @@ namespace DesignTools {
|
|||||||
class CurveItem;
|
class CurveItem;
|
||||||
class CurveEditorModel;
|
class CurveEditorModel;
|
||||||
class Playhead;
|
class Playhead;
|
||||||
|
class PropertyTreeItem;
|
||||||
|
|
||||||
class GraphicsView : public QGraphicsView
|
class GraphicsView : public QGraphicsView
|
||||||
{
|
{
|
||||||
@@ -93,6 +94,8 @@ public:
|
|||||||
|
|
||||||
QRectF defaultRasterRect() const;
|
QRectF defaultRasterRect() const;
|
||||||
|
|
||||||
|
void setLocked(PropertyTreeItem *item);
|
||||||
|
|
||||||
void setStyle(const CurveEditorStyle &style);
|
void setStyle(const CurveEditorStyle &style);
|
||||||
|
|
||||||
void setZoomX(double zoom, const QPoint &pivot = QPoint());
|
void setZoomX(double zoom, const QPoint &pivot = QPoint());
|
||||||
|
@@ -76,6 +76,9 @@ QRectF HandleItem::boundingRect() const
|
|||||||
|
|
||||||
void HandleItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
|
void HandleItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
|
||||||
{
|
{
|
||||||
|
if (locked())
|
||||||
|
return;
|
||||||
|
|
||||||
Q_UNUSED(option)
|
Q_UNUSED(option)
|
||||||
Q_UNUSED(widget)
|
Q_UNUSED(widget)
|
||||||
|
|
||||||
|
@@ -69,12 +69,23 @@ void KeyframeItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *opti
|
|||||||
|
|
||||||
painter->save();
|
painter->save();
|
||||||
painter->setPen(pen);
|
painter->setPen(pen);
|
||||||
painter->setBrush(selected() ? Qt::red : m_style.color);
|
painter->setBrush(locked() ? Qt::black : (selected() ? Qt::red : m_style.color));
|
||||||
painter->drawEllipse(boundingRect());
|
painter->drawEllipse(boundingRect());
|
||||||
|
|
||||||
painter->restore();
|
painter->restore();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void KeyframeItem::setLocked(bool locked)
|
||||||
|
{
|
||||||
|
SelectableItem::setLocked(locked);
|
||||||
|
|
||||||
|
if (m_left)
|
||||||
|
m_left->setLocked(locked);
|
||||||
|
|
||||||
|
if (m_right)
|
||||||
|
m_right->setLocked(locked);
|
||||||
|
}
|
||||||
|
|
||||||
KeyframeItem::~KeyframeItem() {}
|
KeyframeItem::~KeyframeItem() {}
|
||||||
|
|
||||||
Keyframe KeyframeItem::keyframe() const
|
Keyframe KeyframeItem::keyframe() const
|
||||||
|
@@ -63,6 +63,8 @@ public:
|
|||||||
|
|
||||||
void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) override;
|
void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) override;
|
||||||
|
|
||||||
|
void setLocked(bool locked) override;
|
||||||
|
|
||||||
Keyframe keyframe() const;
|
Keyframe keyframe() const;
|
||||||
|
|
||||||
bool hasLeftHandle() const;
|
bool hasLeftHandle() const;
|
||||||
|
@@ -32,6 +32,7 @@ SelectableItem::SelectableItem(QGraphicsItem *parent)
|
|||||||
: QGraphicsObject(parent)
|
: QGraphicsObject(parent)
|
||||||
, m_active(false)
|
, m_active(false)
|
||||||
, m_selected(false)
|
, m_selected(false)
|
||||||
|
, m_locked(false)
|
||||||
, m_preSelected(SelectionMode::Undefined)
|
, m_preSelected(SelectionMode::Undefined)
|
||||||
{
|
{
|
||||||
setFlag(QGraphicsItem::ItemIsSelectable, false);
|
setFlag(QGraphicsItem::ItemIsSelectable, false);
|
||||||
@@ -43,6 +44,13 @@ SelectableItem::SelectableItem(QGraphicsItem *parent)
|
|||||||
|
|
||||||
SelectableItem::~SelectableItem() {}
|
SelectableItem::~SelectableItem() {}
|
||||||
|
|
||||||
|
void SelectableItem::setLocked(bool locked)
|
||||||
|
{
|
||||||
|
setPreselected(SelectionMode::Clear);
|
||||||
|
applyPreselection();
|
||||||
|
m_locked = locked;
|
||||||
|
}
|
||||||
|
|
||||||
bool SelectableItem::activated() const
|
bool SelectableItem::activated() const
|
||||||
{
|
{
|
||||||
return m_active;
|
return m_active;
|
||||||
@@ -68,6 +76,11 @@ bool SelectableItem::selected() const
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool SelectableItem::locked() const
|
||||||
|
{
|
||||||
|
return m_locked;
|
||||||
|
}
|
||||||
|
|
||||||
void SelectableItem::setActivated(bool active)
|
void SelectableItem::setActivated(bool active)
|
||||||
{
|
{
|
||||||
m_active = active;
|
m_active = active;
|
||||||
@@ -75,6 +88,9 @@ void SelectableItem::setActivated(bool active)
|
|||||||
|
|
||||||
void SelectableItem::setPreselected(SelectionMode mode)
|
void SelectableItem::setPreselected(SelectionMode mode)
|
||||||
{
|
{
|
||||||
|
if (m_locked)
|
||||||
|
return;
|
||||||
|
|
||||||
m_preSelected = mode;
|
m_preSelected = mode;
|
||||||
selectionCallback();
|
selectionCallback();
|
||||||
}
|
}
|
||||||
@@ -89,12 +105,18 @@ void SelectableItem::selectionCallback() {}
|
|||||||
|
|
||||||
void SelectableItem::mousePressEvent(QGraphicsSceneMouseEvent *event)
|
void SelectableItem::mousePressEvent(QGraphicsSceneMouseEvent *event)
|
||||||
{
|
{
|
||||||
|
if (m_locked)
|
||||||
|
return;
|
||||||
|
|
||||||
m_active = true;
|
m_active = true;
|
||||||
QGraphicsObject::mousePressEvent(event);
|
QGraphicsObject::mousePressEvent(event);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SelectableItem::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
|
void SelectableItem::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
|
||||||
{
|
{
|
||||||
|
if (m_locked)
|
||||||
|
return;
|
||||||
|
|
||||||
if (type() == KeyframeItem::Type && !selected())
|
if (type() == KeyframeItem::Type && !selected())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@@ -103,6 +125,9 @@ void SelectableItem::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
|
|||||||
|
|
||||||
void SelectableItem::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
|
void SelectableItem::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
|
||||||
{
|
{
|
||||||
|
if (m_locked)
|
||||||
|
return;
|
||||||
|
|
||||||
m_active = false;
|
m_active = false;
|
||||||
QGraphicsObject::mouseReleaseEvent(event);
|
QGraphicsObject::mouseReleaseEvent(event);
|
||||||
}
|
}
|
||||||
|
@@ -29,15 +29,13 @@
|
|||||||
|
|
||||||
namespace DesignTools {
|
namespace DesignTools {
|
||||||
|
|
||||||
enum ItemType
|
enum ItemType {
|
||||||
{
|
|
||||||
ItemTypeKeyframe = QGraphicsItem::UserType + 1,
|
ItemTypeKeyframe = QGraphicsItem::UserType + 1,
|
||||||
ItemTypeHandle = QGraphicsItem::UserType + 2,
|
ItemTypeHandle = QGraphicsItem::UserType + 2,
|
||||||
ItemTypeCurve = QGraphicsItem::UserType + 3
|
ItemTypeCurve = QGraphicsItem::UserType + 3
|
||||||
};
|
};
|
||||||
|
|
||||||
enum class SelectionMode : unsigned int
|
enum class SelectionMode : unsigned int {
|
||||||
{
|
|
||||||
Undefined,
|
Undefined,
|
||||||
Clear,
|
Clear,
|
||||||
New,
|
New,
|
||||||
@@ -55,10 +53,14 @@ public:
|
|||||||
|
|
||||||
~SelectableItem() override;
|
~SelectableItem() override;
|
||||||
|
|
||||||
|
virtual void setLocked(bool locked);
|
||||||
|
|
||||||
bool activated() const;
|
bool activated() const;
|
||||||
|
|
||||||
bool selected() const;
|
bool selected() const;
|
||||||
|
|
||||||
|
bool locked() const;
|
||||||
|
|
||||||
void setActivated(bool active);
|
void setActivated(bool active);
|
||||||
|
|
||||||
void setPreselected(SelectionMode mode);
|
void setPreselected(SelectionMode mode);
|
||||||
@@ -79,6 +81,8 @@ private:
|
|||||||
|
|
||||||
bool m_selected;
|
bool m_selected;
|
||||||
|
|
||||||
|
bool m_locked;
|
||||||
|
|
||||||
SelectionMode m_preSelected;
|
SelectionMode m_preSelected;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@@ -24,6 +24,7 @@
|
|||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
#include "selectionmodel.h"
|
#include "selectionmodel.h"
|
||||||
|
#include "curveitem.h"
|
||||||
#include "treemodel.h"
|
#include "treemodel.h"
|
||||||
|
|
||||||
namespace DesignTools {
|
namespace DesignTools {
|
||||||
@@ -34,6 +35,17 @@ SelectionModel::SelectionModel(QAbstractItemModel *model)
|
|||||||
connect(this, &QItemSelectionModel::selectionChanged, this, &SelectionModel::changeSelection);
|
connect(this, &QItemSelectionModel::selectionChanged, this, &SelectionModel::changeSelection);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SelectionModel::select(const QItemSelection &selection,
|
||||||
|
QItemSelectionModel::SelectionFlags command)
|
||||||
|
{
|
||||||
|
for (auto &&index : selection.indexes()) {
|
||||||
|
if (index.column() == 0) {
|
||||||
|
QItemSelectionModel::select(selection, command);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
std::vector<TreeItem::Path> SelectionModel::selectedPaths() const
|
std::vector<TreeItem::Path> SelectionModel::selectedPaths() const
|
||||||
{
|
{
|
||||||
std::vector<TreeItem::Path> out;
|
std::vector<TreeItem::Path> out;
|
||||||
@@ -90,9 +102,12 @@ void SelectionModel::select(const std::vector<TreeItem::Path> &selection)
|
|||||||
{
|
{
|
||||||
for (auto &&path : selection) {
|
for (auto &&path : selection) {
|
||||||
if (auto *treeModel = qobject_cast<TreeModel *>(model())) {
|
if (auto *treeModel = qobject_cast<TreeModel *>(model())) {
|
||||||
QModelIndex index = treeModel->indexOf(path);
|
QModelIndex left = treeModel->indexOf(path);
|
||||||
if (index.isValid())
|
QModelIndex right = left.siblingAtColumn(2);
|
||||||
QItemSelectionModel::select(index, QItemSelectionModel::Select);
|
if (left.isValid() && right.isValid()) {
|
||||||
|
auto is = QItemSelection(left, right);
|
||||||
|
QItemSelectionModel::select(is, QItemSelectionModel::Select);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -46,6 +46,9 @@ signals:
|
|||||||
public:
|
public:
|
||||||
SelectionModel(QAbstractItemModel *model = nullptr);
|
SelectionModel(QAbstractItemModel *model = nullptr);
|
||||||
|
|
||||||
|
void select(const QItemSelection &selection,
|
||||||
|
QItemSelectionModel::SelectionFlags command) override;
|
||||||
|
|
||||||
std::vector<TreeItem::Path> selectedPaths() const;
|
std::vector<TreeItem::Path> selectedPaths() const;
|
||||||
|
|
||||||
std::vector<CurveItem *> selectedCurveItems() const;
|
std::vector<CurveItem *> selectedCurveItems() const;
|
||||||
|
@@ -59,10 +59,20 @@ PropertyTreeItem *TreeModel::propertyItem(const QModelIndex &index)
|
|||||||
|
|
||||||
CurveItem *TreeModel::curveItem(const QModelIndex &index)
|
CurveItem *TreeModel::curveItem(const QModelIndex &index)
|
||||||
{
|
{
|
||||||
if (auto *pti = propertyItem(index)) {
|
if (auto *ti = treeItem(index))
|
||||||
|
return curveItem(ti);
|
||||||
|
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
CurveItem *TreeModel::curveItem(TreeItem *item)
|
||||||
|
{
|
||||||
|
if (auto *pti = item->asPropertyItem()) {
|
||||||
auto *citem = new CurveItem(pti->id(), pti->curve());
|
auto *citem = new CurveItem(pti->id(), pti->curve());
|
||||||
citem->setValueType(pti->valueType());
|
citem->setValueType(pti->valueType());
|
||||||
citem->setComponent(pti->component());
|
citem->setComponent(pti->component());
|
||||||
|
citem->setLocked(pti->locked());
|
||||||
|
citem->setPinned(pti->pinned());
|
||||||
return citem;
|
return citem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -53,6 +53,8 @@ public:
|
|||||||
|
|
||||||
static CurveItem *curveItem(const QModelIndex &index);
|
static CurveItem *curveItem(const QModelIndex &index);
|
||||||
|
|
||||||
|
static CurveItem *curveItem(TreeItem *item);
|
||||||
|
|
||||||
TreeModel(QObject *parent = nullptr);
|
TreeModel(QObject *parent = nullptr);
|
||||||
|
|
||||||
~TreeModel() override;
|
~TreeModel() override;
|
||||||
|
@@ -105,10 +105,15 @@ void TreeView::mousePressEvent(QMouseEvent *event)
|
|||||||
QModelIndex index = indexAt(event->pos());
|
QModelIndex index = indexAt(event->pos());
|
||||||
if (index.isValid()) {
|
if (index.isValid()) {
|
||||||
auto *treeItem = static_cast<TreeItem *>(index.internalPointer());
|
auto *treeItem = static_cast<TreeItem *>(index.internalPointer());
|
||||||
if (index.column() == 1)
|
if (index.column() == 1) {
|
||||||
treeItem->setLocked(!treeItem->locked());
|
treeItem->setLocked(!treeItem->locked());
|
||||||
else if (index.column() == 2)
|
if (auto *propertyItem = treeItem->asPropertyItem())
|
||||||
|
emit treeItemLocked(propertyItem);
|
||||||
|
} else if (index.column() == 2) {
|
||||||
treeItem->setPinned(!treeItem->pinned());
|
treeItem->setPinned(!treeItem->pinned());
|
||||||
|
if (auto *propertyItem = treeItem->asPropertyItem())
|
||||||
|
emit treeItemPinned(propertyItem);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
QTreeView::mousePressEvent(event);
|
QTreeView::mousePressEvent(event);
|
||||||
}
|
}
|
||||||
|
@@ -44,6 +44,10 @@ class TreeView : public QTreeView
|
|||||||
signals:
|
signals:
|
||||||
void curvesSelected(const std::vector<CurveItem *> &curves);
|
void curvesSelected(const std::vector<CurveItem *> &curves);
|
||||||
|
|
||||||
|
void treeItemLocked(PropertyTreeItem *item);
|
||||||
|
|
||||||
|
void treeItemPinned(PropertyTreeItem *item);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
TreeView(CurveEditorModel *model, QWidget *parent = nullptr);
|
TreeView(CurveEditorModel *model, QWidget *parent = nullptr);
|
||||||
|
|
||||||
@@ -57,9 +61,6 @@ protected:
|
|||||||
QSize sizeHint() const override;
|
QSize sizeHint() const override;
|
||||||
|
|
||||||
void mousePressEvent(QMouseEvent *event) override;
|
void mousePressEvent(QMouseEvent *event) override;
|
||||||
|
|
||||||
private:
|
|
||||||
void changeSelection(const QItemSelection &selected, const QItemSelection &deselected);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
} // End namespace DesignTools.
|
} // End namespace DesignTools.
|
||||||
|
@@ -246,6 +246,17 @@ QIcon NodeTreeItem::icon() const
|
|||||||
return m_icon;
|
return m_icon;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::vector<PropertyTreeItem *> NodeTreeItem::properties() const
|
||||||
|
{
|
||||||
|
std::vector<PropertyTreeItem *> out;
|
||||||
|
for (auto *child : m_children) {
|
||||||
|
if (auto *pti = child->asPropertyItem())
|
||||||
|
out.push_back(pti);
|
||||||
|
}
|
||||||
|
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
std::string toString(ValueType type)
|
std::string toString(ValueType type)
|
||||||
{
|
{
|
||||||
switch (type) {
|
switch (type) {
|
||||||
|
@@ -122,6 +122,8 @@ public:
|
|||||||
|
|
||||||
QIcon icon() const override;
|
QIcon icon() const override;
|
||||||
|
|
||||||
|
std::vector<PropertyTreeItem *> properties() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QIcon m_icon;
|
QIcon m_icon;
|
||||||
};
|
};
|
||||||
|
@@ -94,9 +94,10 @@ void AnimationCurveEditorModel::setTimeline(const QmlTimeline &timeline)
|
|||||||
m_maxTime = timeline.endKeyframe();
|
m_maxTime = timeline.endKeyframe();
|
||||||
|
|
||||||
std::vector<DesignTools::TreeItem *> items;
|
std::vector<DesignTools::TreeItem *> items;
|
||||||
for (auto &&target : timeline.allTargets())
|
for (auto &&target : timeline.allTargets()) {
|
||||||
if (DesignTools::TreeItem *item = createTopLevelItem(timeline, target))
|
if (DesignTools::TreeItem *item = createTopLevelItem(timeline, target))
|
||||||
items.push_back(item);
|
items.push_back(item);
|
||||||
|
}
|
||||||
|
|
||||||
reset(items);
|
reset(items);
|
||||||
}
|
}
|
||||||
@@ -113,8 +114,7 @@ void AnimationCurveEditorModel::setMaximumTime(double time)
|
|||||||
|
|
||||||
DesignTools::ValueType typeFrom(const QmlTimelineKeyframeGroup &group)
|
DesignTools::ValueType typeFrom(const QmlTimelineKeyframeGroup &group)
|
||||||
{
|
{
|
||||||
if (group.valueType() == TypeName("double")
|
if (group.valueType() == TypeName("double") || group.valueType() == TypeName("real")
|
||||||
|| group.valueType() == TypeName("real")
|
|
||||||
|| group.valueType() == TypeName("float"))
|
|| group.valueType() == TypeName("float"))
|
||||||
return DesignTools::ValueType::Double;
|
return DesignTools::ValueType::Double;
|
||||||
|
|
||||||
@@ -140,7 +140,16 @@ DesignTools::TreeItem *AnimationCurveEditorModel::createTopLevelItem(const QmlTi
|
|||||||
DesignTools::AnimationCurve curve = createAnimationCurve(grp);
|
DesignTools::AnimationCurve curve = createAnimationCurve(grp);
|
||||||
if (curve.isValid()) {
|
if (curve.isValid()) {
|
||||||
QString name = QString::fromUtf8(grp.propertyName());
|
QString name = QString::fromUtf8(grp.propertyName());
|
||||||
nodeItem->addChild(new DesignTools::PropertyTreeItem(name, curve, typeFrom(grp)));
|
auto propertyItem = new DesignTools::PropertyTreeItem(name, curve, typeFrom(grp));
|
||||||
|
|
||||||
|
ModelNode target = grp.modelNode();
|
||||||
|
if (target.hasAuxiliaryData("locked"))
|
||||||
|
propertyItem->setLocked(true);
|
||||||
|
|
||||||
|
if (target.hasAuxiliaryData("pinned"))
|
||||||
|
propertyItem->setPinned(true);
|
||||||
|
|
||||||
|
nodeItem->addChild(propertyItem);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -328,6 +328,20 @@ void TimelineWidget::updateAnimationCurve(DesignTools::PropertyTreeItem *item)
|
|||||||
QmlTimelineKeyframeGroup group = timelineKeyframeGroup(currentTimeline, item);
|
QmlTimelineKeyframeGroup group = timelineKeyframeGroup(currentTimeline, item);
|
||||||
|
|
||||||
if (group.isValid()) {
|
if (group.isValid()) {
|
||||||
|
ModelNode groupNode = group.modelNode();
|
||||||
|
|
||||||
|
if (groupNode.isValid()) {
|
||||||
|
if (item->locked())
|
||||||
|
groupNode.setAuxiliaryData("locked", true);
|
||||||
|
else
|
||||||
|
groupNode.removeAuxiliaryData("locked");
|
||||||
|
|
||||||
|
if (item->pinned())
|
||||||
|
groupNode.setAuxiliaryData("pinned", true);
|
||||||
|
else
|
||||||
|
groupNode.removeAuxiliaryData("pinned");
|
||||||
|
}
|
||||||
|
|
||||||
auto replaceKeyframes = [&group, item, this]() {
|
auto replaceKeyframes = [&group, item, this]() {
|
||||||
m_toolbar->setBlockReflection(true);
|
m_toolbar->setBlockReflection(true);
|
||||||
for (auto frame : group.keyframes())
|
for (auto frame : group.keyframes())
|
||||||
@@ -407,8 +421,8 @@ void TimelineWidget::init()
|
|||||||
QmlTimeline currentTimeline = m_timelineView->timelineForState(m_timelineView->currentState());
|
QmlTimeline currentTimeline = m_timelineView->timelineForState(m_timelineView->currentState());
|
||||||
if (currentTimeline.isValid()) {
|
if (currentTimeline.isValid()) {
|
||||||
setTimelineId(currentTimeline.modelNode().id());
|
setTimelineId(currentTimeline.modelNode().id());
|
||||||
m_statusBar->setText(tr(TimelineConstants::statusBarPlayheadFrame)
|
m_statusBar->setText(
|
||||||
.arg(getcurrentFrame(currentTimeline)));
|
tr(TimelineConstants::statusBarPlayheadFrame).arg(getcurrentFrame(currentTimeline)));
|
||||||
} else {
|
} else {
|
||||||
setTimelineId({});
|
setTimelineId({});
|
||||||
m_statusBar->clear();
|
m_statusBar->clear();
|
||||||
|
Reference in New Issue
Block a user