Update locking state from external views and cleanup

Improve treeview styling related to locking/pinning
    Use font icons.
    Show implicitly locked nodes by darkening text and icon.
    Show implicitly locked curves by darkening the text.
    Show unlocked/unpined icons only when hovering the mouse above the item.
It is now possible to lock/pin multiple curves by locking/pinning the node items.
Load unselected curves into the graphicsview when pinning them.
Rename namespace DesignTools to QmlDesigner.
Remove unused function from the timeline module.
Get rid of a memory leak.

Change-Id: I2c9c0a9e1ffe79520c4869178a11cc5825d04bbe
Reviewed-by: Henning Gründl <henning.gruendl@qt.io>
Reviewed-by: Thomas Hartmann <thomas.hartmann@qt.io>
This commit is contained in:
Knud Dollereder
2020-10-26 15:26:17 +01:00
parent ed678000a1
commit 8ca3b557da
50 changed files with 777 additions and 456 deletions

View File

@@ -33,7 +33,7 @@
#include <sstream>
namespace DesignTools {
namespace QmlDesigner {
AnimationCurve::AnimationCurve()
: m_fromData(false)
@@ -395,4 +395,4 @@ void AnimationCurve::analyze()
}
}
} // End namespace DesignTools.
} // End namespace QmlDesigner.

View File

@@ -33,7 +33,7 @@
QT_FORWARD_DECLARE_CLASS(QEasingCurve);
QT_FORWARD_DECLARE_CLASS(QPainterPath);
namespace DesignTools {
namespace QmlDesigner {
class CurveSegment;
@@ -100,4 +100,4 @@ private:
std::vector<Keyframe> m_frames;
};
} // End namespace DesignTools.
} // End namespace QmlDesigner.

View File

@@ -35,7 +35,7 @@
#include <QSplitter>
#include <QVBoxLayout>
namespace DesignTools {
namespace QmlDesigner {
CurveEditor::CurveEditor(CurveEditorModel *model, QWidget *parent)
: QWidget(parent)
@@ -52,10 +52,9 @@ CurveEditor::CurveEditor(CurveEditorModel *model, QWidget *parent)
box->addWidget(splitter);
setLayout(box);
connect(m_tree, &TreeView::treeItemLocked, model, &CurveEditorModel::curveChanged);
connect(m_tree, &TreeView::treeItemPinned, model, &CurveEditorModel::curveChanged);
connect(m_tree, &TreeView::treeItemLocked, model, &CurveEditorModel::setLocked);
connect(m_tree, &TreeView::treeItemPinned, model, &CurveEditorModel::setPinned);
connect(m_tree, &TreeView::treeItemLocked, m_view, &GraphicsView::setLocked);
connect(m_tree->selectionModel(),
&SelectionModel::curvesSelected,
m_view,
@@ -180,4 +179,4 @@ QToolBar *CurveEditor::createToolBar(CurveEditorModel *model)
return bar;
}
} // End namespace DesignTools.
} // End namespace QmlDesigner.

View File

@@ -28,7 +28,7 @@
#include <QToolBar>
#include <QWidget>
namespace DesignTools {
namespace QmlDesigner {
class CurveEditorModel;
class GraphicsView;
@@ -57,4 +57,4 @@ private:
GraphicsView *m_view;
};
} // End namespace DesignTools.
} // End namespace QmlDesigner.

View File

@@ -25,6 +25,7 @@
#include "curveeditormodel.h"
#include "curveeditorstyle.h"
#include "detail/treeview.h"
#include "treeitem.h"
#include "detail/graphicsview.h"
@@ -34,10 +35,11 @@
#include "qmltimeline.h"
#include <bindingproperty.h>
#include <nodeabstractproperty.h>
#include <theme.h>
#include <variantproperty.h>
namespace DesignTools {
namespace QmlDesigner {
CurveEditorModel::CurveEditorModel(QObject *parent)
: TreeModel(parent)
@@ -57,10 +59,10 @@ double CurveEditorModel::maximumTime() const
return m_maxTime;
}
DesignTools::CurveEditorStyle CurveEditorModel::style() const
CurveEditorStyle CurveEditorModel::style() const
{
// Pseudo auto generated. See: CurveEditorStyleDialog
DesignTools::CurveEditorStyle out;
CurveEditorStyle out;
out.backgroundBrush = QBrush(QColor(21, 21, 21));
out.backgroundAlternateBrush = QBrush(QColor(32, 32, 32));
out.fontColor = QColor(255, 255, 255);
@@ -98,9 +100,9 @@ void CurveEditorModel::setTimeline(const QmlDesigner::QmlTimeline &timeline)
{
m_minTime = timeline.startKeyframe();
m_maxTime = timeline.endKeyframe();
std::vector<DesignTools::TreeItem *> items;
std::vector<TreeItem *> items;
for (auto &&target : timeline.allTargets()) {
if (DesignTools::TreeItem *item = createTopLevelItem(timeline, target))
if (TreeItem *item = createTopLevelItem(timeline, target))
items.push_back(item);
}
@@ -135,6 +137,32 @@ void CurveEditorModel::setCurve(unsigned int id, const AnimationCurve &curve)
}
}
void CurveEditorModel::setLocked(TreeItem *item, bool val)
{
item->setLocked(val);
if (auto *gview = graphicsView())
gview->setLocked(item);
if (auto *tview = treeView())
tview->viewport()->update();
emit curveChanged(item);
}
void CurveEditorModel::setPinned(TreeItem *item, bool val)
{
item->setPinned(val);
if (auto *gview = graphicsView())
gview->setPinned(item);
if (auto *tview = treeView())
tview->viewport()->update();
emit curveChanged(item);
}
bool contains(const std::vector<TreeItem::Path> &selection, const TreeItem::Path &path)
{
for (auto &&sel : selection)
@@ -176,38 +204,57 @@ void CurveEditorModel::reset(const std::vector<TreeItem *> &items)
sm->selectPaths(sel);
}
DesignTools::ValueType typeFrom(const QmlDesigner::QmlTimelineKeyframeGroup &group)
PropertyTreeItem::ValueType typeFrom(const QmlDesigner::QmlTimelineKeyframeGroup &group)
{
if (group.valueType() == QmlDesigner::TypeName("double")
|| group.valueType() == QmlDesigner::TypeName("real")
|| group.valueType() == QmlDesigner::TypeName("float"))
return DesignTools::ValueType::Double;
return PropertyTreeItem::ValueType::Double;
if (group.valueType() == QmlDesigner::TypeName("boolean")
|| group.valueType() == QmlDesigner::TypeName("bool"))
return DesignTools::ValueType::Bool;
return PropertyTreeItem::ValueType::Bool;
if (group.valueType() == QmlDesigner::TypeName("integer")
|| group.valueType() == QmlDesigner::TypeName("int"))
return DesignTools::ValueType::Integer;
return PropertyTreeItem::ValueType::Integer;
// Ignoring: QColor / HAlignment / VAlignment
return DesignTools::ValueType::Undefined;
return PropertyTreeItem::ValueType::Undefined;
}
DesignTools::TreeItem *CurveEditorModel::createTopLevelItem(const QmlDesigner::QmlTimeline &timeline,
const QmlDesigner::ModelNode &node)
std::vector<QString> parentIds(const QmlDesigner::ModelNode &node)
{
std::vector<QString> out;
QmlDesigner::ModelNode parent = node.parentProperty().parentModelNode();
while (parent.isValid()) {
out.push_back(parent.id());
if (parent.hasParentProperty())
parent = parent.parentProperty().parentModelNode();
else
break;
}
return out;
}
TreeItem *CurveEditorModel::createTopLevelItem(const QmlDesigner::QmlTimeline &timeline,
const QmlDesigner::ModelNode &node)
{
if (!node.isValid())
return nullptr;
auto *nodeItem = new DesignTools::NodeTreeItem(node.id(), QIcon(":/ICON_INSTANCE"));
auto *nodeItem = new NodeTreeItem(node.id(), node.typeIcon(), parentIds(node));
if (node.hasAuxiliaryData("locked"))
nodeItem->setLocked(true);
for (auto &&grp : timeline.keyframeGroupsForTarget(node)) {
if (grp.isValid()) {
DesignTools::AnimationCurve curve = createAnimationCurve(grp);
AnimationCurve curve = createAnimationCurve(grp);
if (curve.isValid()) {
QString name = QString::fromUtf8(grp.propertyName());
auto propertyItem = new DesignTools::PropertyTreeItem(name, curve, typeFrom(grp));
auto propertyItem = new PropertyTreeItem(name, curve, typeFrom(grp));
QmlDesigner::ModelNode target = grp.modelNode();
if (target.hasAuxiliaryData("locked"))
@@ -229,25 +276,24 @@ DesignTools::TreeItem *CurveEditorModel::createTopLevelItem(const QmlDesigner::Q
return nodeItem;
}
DesignTools::AnimationCurve CurveEditorModel::createAnimationCurve(
const QmlDesigner::QmlTimelineKeyframeGroup &group)
AnimationCurve CurveEditorModel::createAnimationCurve(const QmlDesigner::QmlTimelineKeyframeGroup &group)
{
switch (typeFrom(group)) {
case DesignTools::ValueType::Bool:
case PropertyTreeItem::ValueType::Bool:
return createDoubleCurve(group);
case DesignTools::ValueType::Integer:
case PropertyTreeItem::ValueType::Integer:
return createDoubleCurve(group);
case DesignTools::ValueType::Double:
case PropertyTreeItem::ValueType::Double:
return createDoubleCurve(group);
default:
return DesignTools::AnimationCurve();
return AnimationCurve();
}
}
std::vector<DesignTools::Keyframe> createKeyframes(QList<QmlDesigner::ModelNode> nodes)
std::vector<Keyframe> createKeyframes(QList<QmlDesigner::ModelNode> nodes)
{
auto byTime = [](const auto &a, const auto &b) {
return a.variantProperty("frame").value().toDouble()
@@ -255,7 +301,7 @@ std::vector<DesignTools::Keyframe> createKeyframes(QList<QmlDesigner::ModelNode>
};
std::sort(nodes.begin(), nodes.end(), byTime);
std::vector<DesignTools::Keyframe> frames;
std::vector<Keyframe> frames;
for (auto &&node : nodes) {
QVariant timeVariant = node.variantProperty("frame").value();
QVariant valueVariant = node.variantProperty("value").value();
@@ -264,7 +310,7 @@ std::vector<DesignTools::Keyframe> createKeyframes(QList<QmlDesigner::ModelNode>
QPointF position(timeVariant.toDouble(), valueVariant.toDouble());
auto keyframe = DesignTools::Keyframe(position);
auto keyframe = Keyframe(position);
if (node.hasBindingProperty("easing.bezierCurve")) {
QmlDesigner::EasingCurve ecurve;
@@ -276,15 +322,15 @@ std::vector<DesignTools::Keyframe> createKeyframes(QList<QmlDesigner::ModelNode>
return frames;
}
std::vector<DesignTools::Keyframe> resolveSmallCurves(const std::vector<DesignTools::Keyframe> &frames)
std::vector<Keyframe> resolveSmallCurves(const std::vector<Keyframe> &frames)
{
std::vector<DesignTools::Keyframe> out;
std::vector<Keyframe> out;
for (auto &&frame : frames) {
if (frame.hasData() && !out.empty()) {
QEasingCurve curve = frame.data().toEasingCurve();
// One-segment-curve: Since (0,0) is implicit => 3
if (curve.toCubicSpline().count() == 3) {
DesignTools::Keyframe &previous = out.back();
Keyframe &previous = out.back();
#if 0
// Do not resolve when two adjacent keyframes have the same value.
if (qFuzzyCompare(previous.position().y(), frame.position().y())) {
@@ -292,7 +338,7 @@ std::vector<DesignTools::Keyframe> resolveSmallCurves(const std::vector<DesignTo
continue;
}
#endif
DesignTools::AnimationCurve acurve(curve, previous.position(), frame.position());
AnimationCurve acurve(curve, previous.position(), frame.position());
previous.setRightHandle(acurve.keyframeAt(0).rightHandle());
out.push_back(acurve.keyframeAt(1));
continue;
@@ -303,10 +349,9 @@ std::vector<DesignTools::Keyframe> resolveSmallCurves(const std::vector<DesignTo
return out;
}
DesignTools::AnimationCurve CurveEditorModel::createDoubleCurve(
const QmlDesigner::QmlTimelineKeyframeGroup &group)
AnimationCurve CurveEditorModel::createDoubleCurve(const QmlDesigner::QmlTimelineKeyframeGroup &group)
{
std::vector<DesignTools::Keyframe> keyframes = createKeyframes(group.keyframePositions());
std::vector<Keyframe> keyframes = createKeyframes(group.keyframePositions());
keyframes = resolveSmallCurves(keyframes);
QString str;
@@ -321,7 +366,7 @@ DesignTools::AnimationCurve CurveEditorModel::createDoubleCurve(
}
}
return DesignTools::AnimationCurve(keyframes);
return AnimationCurve(keyframes);
}
} // End namespace DesignTools.
} // End namespace QmlDesigner.

View File

@@ -35,7 +35,7 @@ QT_BEGIN_NAMESPACE
class QPointF;
QT_END_NAMESPACE
namespace DesignTools {
namespace QmlDesigner {
struct CurveEditorStyle;
@@ -54,7 +54,7 @@ signals:
void commitEndFrame(int frame);
void curveChanged(PropertyTreeItem *item);
void curveChanged(TreeItem *item);
public:
CurveEditorModel(QObject *parent = nullptr);
@@ -65,7 +65,7 @@ public:
double maximumTime() const;
DesignTools::CurveEditorStyle style() const;
CurveEditorStyle style() const;
public:
void setTimeline(const QmlDesigner::QmlTimeline &timeline);
@@ -78,19 +78,23 @@ public:
void setCurve(unsigned int id, const AnimationCurve &curve);
void setLocked(TreeItem *item, bool val);
void setPinned(TreeItem *item, bool val);
void reset(const std::vector<TreeItem *> &items);
private:
DesignTools::TreeItem *createTopLevelItem(const QmlDesigner::QmlTimeline &timeline,
const QmlDesigner::ModelNode &node);
TreeItem *createTopLevelItem(const QmlDesigner::QmlTimeline &timeline,
const QmlDesigner::ModelNode &node);
DesignTools::AnimationCurve createAnimationCurve(const QmlDesigner::QmlTimelineKeyframeGroup &group);
AnimationCurve createAnimationCurve(const QmlDesigner::QmlTimelineKeyframeGroup &group);
DesignTools::AnimationCurve createDoubleCurve(const QmlDesigner::QmlTimelineKeyframeGroup &group);
AnimationCurve createDoubleCurve(const QmlDesigner::QmlTimelineKeyframeGroup &group);
double m_minTime = 0.;
double m_maxTime = 0.;
};
} // End namespace DesignTools.
} // End namespace QmlDesigner.

View File

@@ -27,7 +27,9 @@
#include "detail/shortcut.h"
#include <theme.h>
#include <utils/hostosinfo.h>
#include <utils/stylehelper.h>
#include <QBitmap>
#include <QBrush>
@@ -38,15 +40,30 @@
#include <cmath>
namespace DesignTools {
namespace QmlDesigner {
struct TreeItemStyleOption
{
double margins;
QIcon pinnedIcon = QIcon(":/curveeditor/images/treeview_pin.png");
QIcon unpinnedIcon = QIcon(":/curveeditor/images/treeview_unpin.png");
QIcon lockedIcon = QIcon(":/curveeditor/images/treeview_lock.png");
QIcon unlockedIcon = QIcon(":/curveeditor/images/treeview_unlock.png");
QIcon pinnedIcon = iconFromFont(QmlDesigner::Theme::Icon::pin);
QIcon unpinnedIcon = iconFromFont(QmlDesigner::Theme::Icon::unpin);
QIcon implicitlyPinnedIcon = iconFromFont(QmlDesigner::Theme::Icon::pin, Qt::gray);
QIcon lockedIcon = iconFromFont(QmlDesigner::Theme::Icon::lockOn);
QIcon unlockedIcon = iconFromFont(QmlDesigner::Theme::Icon::lockOff);
QIcon implicitlyLockedIcon = iconFromFont(QmlDesigner::Theme::Icon::lockOn, Qt::gray);
static QIcon iconFromFont(QmlDesigner::Theme::Icon type, const QColor &color = Qt::white)
{
const QString fontName = "qtds_propertyIconFont.ttf";
static const int fontSize = 28;
static const int iconSize = 28;
return Utils::StyleHelper::getIconFromIconFont(fontName,
QmlDesigner::Theme::getIconUnicode(type),
fontSize,
iconSize,
color);
}
};
struct HandleItemStyleOption
@@ -122,15 +139,15 @@ struct CurveEditorStyle
QColor iconColor = QColor(128, 128, 128);
QColor iconHoverColor = QColor(170, 170, 170);
QColor gridColor = QColor(128, 128, 128);
double canvasMargin = 5.0;
int canvasMargin = 5;
int zoomInWidth = 100;
int zoomInHeight = 100;
double timeAxisHeight = 40.0;
int timeAxisHeight = 40;
double timeOffsetLeft = 10.0;
double timeOffsetRight = 10.0;
QColor rangeBarColor = QColor(128, 128, 128);
QColor rangeBarCapsColor = QColor(50, 50, 255);
double valueAxisWidth = 60.0;
int valueAxisWidth = 60;
double valueOffsetTop = 10.0;
double valueOffsetBottom = 10.0;
double labelDensityY = 2.0;
@@ -151,4 +168,4 @@ inline QPixmap pixmapFromIcon(const QIcon &icon, const QSize &size, const QColor
return mask;
}
} // End namespace DesignTools.
} // End namespace QmlDesigner.

View File

@@ -27,6 +27,7 @@
#include "curveeditor.h"
#include "curveeditormodel.h"
#include "curvesegment.h"
#include "treeitem.h"
#include <bindingproperty.h>
#include <easingcurve.h>
@@ -42,29 +43,14 @@ namespace QmlDesigner {
CurveEditorView::CurveEditorView(QObject *parent)
: AbstractView(parent)
, m_block(false)
, m_model(new DesignTools::CurveEditorModel())
, m_editor(new DesignTools::CurveEditor(m_model))
, m_model(new CurveEditorModel())
, m_editor(new CurveEditor(m_model))
{
Q_UNUSED(parent);
connect(m_model,
&DesignTools::CurveEditorModel::commitCurrentFrame,
this,
&CurveEditorView::commitCurrentFrame);
connect(m_model,
&DesignTools::CurveEditorModel::commitStartFrame,
this,
&CurveEditorView::commitStartFrame);
connect(m_model,
&DesignTools::CurveEditorModel::commitEndFrame,
this,
&CurveEditorView::commitEndFrame);
connect(m_model,
&DesignTools::CurveEditorModel::curveChanged,
this,
&CurveEditorView::commitKeyframes);
connect(m_model, &CurveEditorModel::commitCurrentFrame, this, &CurveEditorView::commitCurrentFrame);
connect(m_model, &CurveEditorModel::commitStartFrame, this, &CurveEditorView::commitStartFrame);
connect(m_model, &CurveEditorModel::commitEndFrame, this, &CurveEditorView::commitEndFrame);
connect(m_model, &CurveEditorModel::curveChanged, this, &CurveEditorView::commitKeyframes);
}
CurveEditorView::~CurveEditorView() {}
@@ -134,6 +120,18 @@ void CurveEditorView::nodeReparented(const ModelNode &node,
updateKeyframes();
}
void CurveEditorView::auxiliaryDataChanged(const ModelNode &node,
const PropertyName &name,
const QVariant &data)
{
if (name == "locked") {
if (auto *item = m_model->find(node.id())) {
QSignalBlocker blocker(m_model);
m_model->setLocked(item, data.toBool());
}
}
}
void CurveEditorView::instancePropertyChanged(const QList<QPair<ModelNode, PropertyName>> &propertyList)
{
Q_UNUSED(propertyList);
@@ -261,9 +259,9 @@ void CurveEditorView::updateEndFrame(const ModelNode &node)
m_model->setMaximumTime(static_cast<int>(std::round(timeline.endKeyframe())));
}
ModelNode getTargetNode1(DesignTools::PropertyTreeItem *item, const QmlTimeline &timeline)
ModelNode getTargetNode(PropertyTreeItem *item, const QmlTimeline &timeline)
{
if (const DesignTools::NodeTreeItem *nodeItem = item->parentNodeTreeItem()) {
if (const NodeTreeItem *nodeItem = item->parentNodeTreeItem()) {
QString targetId = nodeItem->name();
if (timeline.isValid()) {
for (auto &&target : timeline.allTargets()) {
@@ -275,17 +273,16 @@ ModelNode getTargetNode1(DesignTools::PropertyTreeItem *item, const QmlTimeline
return ModelNode();
}
QmlTimelineKeyframeGroup timelineKeyframeGroup1(QmlTimeline &timeline,
DesignTools::PropertyTreeItem *item)
QmlTimelineKeyframeGroup timelineKeyframeGroup(QmlTimeline &timeline, PropertyTreeItem *item)
{
ModelNode node = getTargetNode1(item, timeline);
ModelNode node = getTargetNode(item, timeline);
if (node.isValid())
return timeline.keyframeGroup(node, item->name().toLatin1());
return QmlTimelineKeyframeGroup();
}
void attachEasingCurve1(double frame, const QEasingCurve &curve, const QmlTimelineKeyframeGroup &group)
void attachEasingCurve(const QmlTimelineKeyframeGroup &group, double frame, const QEasingCurve &curve)
{
ModelNode frameNode = group.keyframe(frame);
if (frameNode.isValid()) {
@@ -294,61 +291,73 @@ void attachEasingCurve1(double frame, const QEasingCurve &curve, const QmlTimeli
}
}
void CurveEditorView::commitKeyframes(DesignTools::PropertyTreeItem *item)
void commitAuxiliaryData(ModelNode &node, TreeItem *item)
{
QmlTimeline currentTimeline = activeTimeline();
QmlTimelineKeyframeGroup group = timelineKeyframeGroup1(currentTimeline, item);
if (node.isValid()) {
if (item->locked())
node.setAuxiliaryData("locked", true);
else
node.removeAuxiliaryData("locked");
if (group.isValid()) {
ModelNode groupNode = group.modelNode();
if (item->pinned())
node.setAuxiliaryData("pinned", true);
else
node.removeAuxiliaryData("pinned");
if (groupNode.isValid()) {
if (item->locked())
groupNode.setAuxiliaryData("locked", true);
if (auto *pitem = item->asPropertyItem()) {
if (pitem->hasUnified())
node.setAuxiliaryData("unified", pitem->unifyString());
else
groupNode.removeAuxiliaryData("locked");
if (item->pinned())
groupNode.setAuxiliaryData("pinned", true);
else
groupNode.removeAuxiliaryData("pinned");
if (item->hasUnified())
groupNode.setAuxiliaryData("unified", item->unifyString());
else
groupNode.removeAuxiliaryData("unified");
node.removeAuxiliaryData("unified");
}
}
}
auto replaceKeyframes = [&group, item, this]() {
m_block = true;
for (auto frame : group.keyframes())
frame.destroy();
void CurveEditorView::commitKeyframes(TreeItem *item)
{
if (auto *nitem = item->asNodeItem()) {
ModelNode node = modelNodeForId(nitem->name());
commitAuxiliaryData(node, item);
DesignTools::Keyframe previous;
for (auto &&frame : item->curve().keyframes()) {
QPointF pos = frame.position();
group.setValue(QVariant(pos.y()), pos.x());
} else if (auto *pitem = item->asPropertyItem()) {
QmlTimeline currentTimeline = activeTimeline();
QmlTimelineKeyframeGroup group = timelineKeyframeGroup(currentTimeline, pitem);
if (previous.isValid()) {
if (frame.interpolation() == DesignTools::Keyframe::Interpolation::Bezier) {
DesignTools::CurveSegment segment(previous, frame);
if (segment.isValid())
attachEasingCurve1(pos.x(), segment.easingCurve(), group);
} else if (frame.interpolation() == DesignTools::Keyframe::Interpolation::Easing) {
QVariant data = frame.data();
if (data.type() == static_cast<int>(QMetaType::QEasingCurve))
attachEasingCurve1(pos.x(), data.value<QEasingCurve>(), group);
} else if (frame.interpolation() == DesignTools::Keyframe::Interpolation::Step) {
// Warning: Keyframe::Interpolation::Step not yet implemented
if (group.isValid()) {
ModelNode groupNode = group.modelNode();
commitAuxiliaryData(groupNode, item);
auto replaceKeyframes = [&group, pitem, this]() {
m_block = true;
for (auto frame : group.keyframes())
frame.destroy();
Keyframe previous;
for (auto &&frame : pitem->curve().keyframes()) {
QPointF pos = frame.position();
group.setValue(QVariant(pos.y()), pos.x());
if (previous.isValid()) {
if (frame.interpolation() == Keyframe::Interpolation::Bezier) {
CurveSegment segment(previous, frame);
if (segment.isValid())
attachEasingCurve(group, pos.x(), segment.easingCurve());
} else if (frame.interpolation() == Keyframe::Interpolation::Easing) {
QVariant data = frame.data();
if (data.type() == static_cast<int>(QMetaType::QEasingCurve))
attachEasingCurve(group, pos.x(), data.value<QEasingCurve>());
} else if (frame.interpolation() == Keyframe::Interpolation::Step) {
// Warning: Keyframe::Interpolation::Step not yet implemented
}
}
previous = frame;
}
m_block = false;
};
previous = frame;
}
m_block = false;
};
executeInTransaction("CurveEditor::commitKeyframes", replaceKeyframes);
executeInTransaction("CurveEditor::commitKeyframes", replaceKeyframes);
}
}
}

View File

@@ -59,6 +59,10 @@ public:
const NodeAbstractProperty &oldPropertyParent,
PropertyChangeFlags propertyChange) override;
void auxiliaryDataChanged(const ModelNode &node,
const PropertyName &name,
const QVariant &data) override;
void instancePropertyChanged(const QList<QPair<ModelNode, PropertyName>> &propertyList) override;
void variantPropertiesChanged(const QList<VariantProperty> &propertyList,
@@ -77,15 +81,15 @@ private:
void updateStartFrame(const ModelNode &node);
void updateEndFrame(const ModelNode &node);
void commitKeyframes(DesignTools::PropertyTreeItem *item);
void commitKeyframes(TreeItem *item);
void commitCurrentFrame(int frame);
void commitStartFrame(int frame);
void commitEndFrame(int frame);
private:
bool m_block;
DesignTools::CurveEditorModel *m_model;
DesignTools::CurveEditor *m_editor;
CurveEditorModel *m_model;
CurveEditor *m_editor;
};
} // namespace QmlDesigner

View File

@@ -33,7 +33,7 @@
#include <assert.h>
namespace DesignTools {
namespace QmlDesigner {
class CubicPolynomial
{
@@ -566,4 +566,4 @@ void CurveSegment::setInterpolation(const Keyframe::Interpolation &interpol)
}
}
} // End namespace DesignTools.
} // End namespace QmlDesigner.

View File

@@ -36,7 +36,7 @@ class QEasingCurve;
class QPainterPath;
QT_END_NAMESPACE
namespace DesignTools {
namespace QmlDesigner {
class CurveSegment
{
@@ -97,4 +97,4 @@ private:
Keyframe m_right;
};
} // End namespace DesignTools.
} // End namespace QmlDesigner.

View File

@@ -29,7 +29,7 @@
#include <cmath>
#include <limits>
namespace DesignTools {
namespace QmlDesigner {
// The following is based on: "An Extension of Wilkinson's Algorithm for Positioning Tick Labels on Axes"
// by Justin Talbot, Sharon Lin and Pat Hanrahan.
@@ -210,4 +210,4 @@ Axis Axis::compute(double dmin, double dmax, double height, double pt)
return result;
}
} // End namespace DesignTools.
} // End namespace QmlDesigner.

View File

@@ -28,7 +28,7 @@
#include <QToolBar>
#include <QWidget>
namespace DesignTools {
namespace QmlDesigner {
struct Axis
{
@@ -39,4 +39,4 @@ struct Axis
double lstep;
};
} // End namespace DesignTools.
} // End namespace QmlDesigner.

View File

@@ -30,7 +30,9 @@
#include <QPainter>
#include <QToolTip>
namespace DesignTools {
namespace QmlDesigner {
namespace StyleEditor {
ColorControl::ColorControl()
: QWidget(nullptr)
@@ -98,4 +100,6 @@ void ColorControl::mousePressEvent(QMouseEvent *event)
event->accept();
}
} // End namespace DesignTools.
} // End namespace StyleEditor.
} // End namespace QmlDesigner.

View File

@@ -27,7 +27,9 @@
#include <QWidget>
namespace DesignTools {
namespace QmlDesigner {
namespace StyleEditor {
class ColorControl : public QWidget
{
@@ -60,4 +62,6 @@ private:
QColor m_color;
};
} // End namespace DesignTools.
} // End namespace StyleEditor.
} // End namespace QmlDesigner.

View File

@@ -33,7 +33,7 @@
#include <QSpinBox>
#include <QVBoxLayout>
namespace DesignTools {
namespace QmlDesigner {
QHBoxLayout *createRow(const QString &title, QWidget *widget)
{
@@ -50,35 +50,35 @@ QHBoxLayout *createRow(const QString &title, QWidget *widget)
CurveEditorStyleDialog::CurveEditorStyleDialog(CurveEditorStyle &style, QWidget *parent)
: QDialog(parent)
, m_printButton(new QPushButton("Print"))
, m_background(new ColorControl(style.backgroundBrush.color()))
, m_backgroundAlternate(new ColorControl(style.backgroundAlternateBrush.color()))
, m_fontColor(new ColorControl(style.fontColor))
, m_gridColor(new ColorControl(style.gridColor))
, m_background(new StyleEditor::ColorControl(style.backgroundBrush.color()))
, m_backgroundAlternate(new StyleEditor::ColorControl(style.backgroundAlternateBrush.color()))
, m_fontColor(new StyleEditor::ColorControl(style.fontColor))
, m_gridColor(new StyleEditor::ColorControl(style.gridColor))
, m_canvasMargin(new QDoubleSpinBox())
, m_zoomInWidth(new QSpinBox())
, m_zoomInHeight(new QSpinBox())
, m_timeAxisHeight(new QDoubleSpinBox())
, m_timeOffsetLeft(new QDoubleSpinBox())
, m_timeOffsetRight(new QDoubleSpinBox())
, m_rangeBarColor(new ColorControl(style.rangeBarCapsColor))
, m_rangeBarCapsColor(new ColorControl(style.rangeBarCapsColor))
, m_rangeBarColor(new StyleEditor::ColorControl(style.rangeBarCapsColor))
, m_rangeBarCapsColor(new StyleEditor::ColorControl(style.rangeBarCapsColor))
, m_valueAxisWidth(new QDoubleSpinBox())
, m_valueOffsetTop(new QDoubleSpinBox())
, m_valueOffsetBottom(new QDoubleSpinBox())
, m_handleSize(new QDoubleSpinBox())
, m_handleLineWidth(new QDoubleSpinBox())
, m_handleColor(new ColorControl(style.handleStyle.color))
, m_handleSelectionColor(new ColorControl(style.handleStyle.selectionColor))
, m_handleColor(new StyleEditor::ColorControl(style.handleStyle.color))
, m_handleSelectionColor(new StyleEditor::ColorControl(style.handleStyle.selectionColor))
, m_keyframeSize(new QDoubleSpinBox())
, m_keyframeColor(new ColorControl(style.keyframeStyle.color))
, m_keyframeSelectionColor(new ColorControl(style.keyframeStyle.selectionColor))
, m_keyframeColor(new StyleEditor::ColorControl(style.keyframeStyle.color))
, m_keyframeSelectionColor(new StyleEditor::ColorControl(style.keyframeStyle.selectionColor))
, m_curveWidth(new QDoubleSpinBox())
, m_curveColor(new ColorControl(style.curveStyle.color))
, m_curveSelectionColor(new ColorControl(style.curveStyle.selectionColor))
, m_curveColor(new StyleEditor::ColorControl(style.curveStyle.color))
, m_curveSelectionColor(new StyleEditor::ColorControl(style.curveStyle.selectionColor))
, m_treeMargins(new QDoubleSpinBox())
, m_playheadWidth(new QDoubleSpinBox())
, m_playheadRadius(new QDoubleSpinBox())
, m_playheadColor(new ColorControl(style.playhead.color))
, m_playheadColor(new StyleEditor::ColorControl(style.playhead.color))
{
setWindowFlag(Qt::Tool, true);
@@ -111,35 +111,35 @@ CurveEditorStyleDialog::CurveEditorStyleDialog(CurveEditorStyle &style, QWidget
auto intSignal = static_cast<void (QSpinBox::*)(int)>(&QSpinBox::valueChanged);
auto doubleSignal = static_cast<void (QDoubleSpinBox::*)(double)>(&QDoubleSpinBox::valueChanged);
connect(m_background, &ColorControl::valueChanged, colorChanged);
connect(m_backgroundAlternate, &ColorControl::valueChanged, colorChanged);
connect(m_fontColor, &ColorControl::valueChanged, colorChanged);
connect(m_gridColor, &ColorControl::valueChanged, colorChanged);
connect(m_background, &StyleEditor::ColorControl::valueChanged, colorChanged);
connect(m_backgroundAlternate, &StyleEditor::ColorControl::valueChanged, colorChanged);
connect(m_fontColor, &StyleEditor::ColorControl::valueChanged, colorChanged);
connect(m_gridColor, &StyleEditor::ColorControl::valueChanged, colorChanged);
connect(m_canvasMargin, doubleSignal, doubleChanged);
connect(m_zoomInWidth, intSignal, intChanged);
connect(m_zoomInHeight, intSignal, intChanged);
connect(m_timeAxisHeight, doubleSignal, doubleChanged);
connect(m_timeOffsetLeft, doubleSignal, doubleChanged);
connect(m_timeOffsetRight, doubleSignal, doubleChanged);
connect(m_rangeBarColor, &ColorControl::valueChanged, colorChanged);
connect(m_rangeBarCapsColor, &ColorControl::valueChanged, colorChanged);
connect(m_rangeBarColor, &StyleEditor::ColorControl::valueChanged, colorChanged);
connect(m_rangeBarCapsColor, &StyleEditor::ColorControl::valueChanged, colorChanged);
connect(m_valueAxisWidth, doubleSignal, doubleChanged);
connect(m_valueOffsetTop, doubleSignal, doubleChanged);
connect(m_valueOffsetBottom, doubleSignal, doubleChanged);
connect(m_handleSize, doubleSignal, doubleChanged);
connect(m_handleLineWidth, doubleSignal, doubleChanged);
connect(m_handleColor, &ColorControl::valueChanged, colorChanged);
connect(m_handleSelectionColor, &ColorControl::valueChanged, colorChanged);
connect(m_handleColor, &StyleEditor::ColorControl::valueChanged, colorChanged);
connect(m_handleSelectionColor, &StyleEditor::ColorControl::valueChanged, colorChanged);
connect(m_keyframeSize, doubleSignal, doubleChanged);
connect(m_keyframeColor, &ColorControl::valueChanged, colorChanged);
connect(m_keyframeSelectionColor, &ColorControl::valueChanged, colorChanged);
connect(m_keyframeColor, &StyleEditor::ColorControl::valueChanged, colorChanged);
connect(m_keyframeSelectionColor, &StyleEditor::ColorControl::valueChanged, colorChanged);
connect(m_curveWidth, doubleSignal, doubleChanged);
connect(m_curveColor, &ColorControl::valueChanged, colorChanged);
connect(m_curveSelectionColor, &ColorControl::valueChanged, colorChanged);
connect(m_curveColor, &StyleEditor::ColorControl::valueChanged, colorChanged);
connect(m_curveSelectionColor, &StyleEditor::ColorControl::valueChanged, colorChanged);
connect(m_treeMargins, doubleSignal, doubleChanged);
connect(m_playheadWidth, doubleSignal, doubleChanged);
connect(m_playheadRadius, doubleSignal, doubleChanged);
connect(m_playheadColor, &ColorControl::valueChanged, colorChanged);
connect(m_playheadColor, &StyleEditor::ColorControl::valueChanged, colorChanged);
auto *box = new QVBoxLayout;
box->addLayout(createRow("Background Color", m_background));
@@ -266,4 +266,4 @@ void CurveEditorStyleDialog::printStyle()
qDebug() << "";
}
} // End namespace DesignTools.
} // End namespace QmlDesigner.

View File

@@ -34,9 +34,11 @@ class QSpinBox;
class QDoubleSpinBox;
QT_END_NAMESPACE
namespace DesignTools {
namespace QmlDesigner {
namespace StyleEditor {
class ColorControl;
}
struct CurveEditorStyle;
@@ -60,13 +62,13 @@ private:
private:
QPushButton *m_printButton;
ColorControl *m_background;
StyleEditor::ColorControl *m_background;
ColorControl *m_backgroundAlternate;
StyleEditor::ColorControl *m_backgroundAlternate;
ColorControl *m_fontColor;
StyleEditor::ColorControl *m_fontColor;
ColorControl *m_gridColor;
StyleEditor::ColorControl *m_gridColor;
QDoubleSpinBox *m_canvasMargin;
@@ -80,9 +82,9 @@ private:
QDoubleSpinBox *m_timeOffsetRight;
ColorControl *m_rangeBarColor;
StyleEditor::ColorControl *m_rangeBarColor;
ColorControl *m_rangeBarCapsColor;
StyleEditor::ColorControl *m_rangeBarCapsColor;
QDoubleSpinBox *m_valueAxisWidth;
@@ -95,23 +97,23 @@ private:
QDoubleSpinBox *m_handleLineWidth;
ColorControl *m_handleColor;
StyleEditor::ColorControl *m_handleColor;
ColorControl *m_handleSelectionColor;
StyleEditor::ColorControl *m_handleSelectionColor;
// KeyframeItem
QDoubleSpinBox *m_keyframeSize;
ColorControl *m_keyframeColor;
StyleEditor::ColorControl *m_keyframeColor;
ColorControl *m_keyframeSelectionColor;
StyleEditor::ColorControl *m_keyframeSelectionColor;
// CurveItem
QDoubleSpinBox *m_curveWidth;
ColorControl *m_curveColor;
StyleEditor::ColorControl *m_curveColor;
ColorControl *m_curveSelectionColor;
StyleEditor::ColorControl *m_curveSelectionColor;
// TreeItem
QDoubleSpinBox *m_treeMargins;
@@ -121,7 +123,7 @@ private:
QDoubleSpinBox *m_playheadRadius;
ColorControl *m_playheadColor;
StyleEditor::ColorControl *m_playheadColor;
};
} // End namespace DesignTools.
} // End namespace QmlDesigner.

View File

@@ -35,13 +35,13 @@
#include <cmath>
#include <sstream>
namespace DesignTools {
namespace QmlDesigner {
CurveItem::CurveItem(QGraphicsItem *parent)
: CurveEditorItem(parent)
, m_id(0)
, m_style()
, m_type(ValueType::Undefined)
, m_type(PropertyTreeItem::ValueType::Undefined)
, m_component(PropertyTreeItem::Component::Generic)
, m_transform()
, m_keyframes()
@@ -52,7 +52,7 @@ CurveItem::CurveItem(unsigned int id, const AnimationCurve &curve, QGraphicsItem
: CurveEditorItem(parent)
, m_id(id)
, m_style()
, m_type(ValueType::Undefined)
, m_type(PropertyTreeItem::ValueType::Undefined)
, m_component(PropertyTreeItem::Component::Generic)
, m_transform()
, m_keyframes()
@@ -225,7 +225,7 @@ unsigned int CurveItem::id() const
return m_id;
}
ValueType CurveItem::valueType() const
PropertyTreeItem::ValueType CurveItem::valueType() const
{
return m_type;
}
@@ -385,7 +385,7 @@ void CurveItem::setHandleVisibility(bool visible)
frame->setHandleVisibility(visible);
}
void CurveItem::setValueType(ValueType type)
void CurveItem::setValueType(PropertyTreeItem::ValueType type)
{
m_type = type;
}
@@ -508,4 +508,4 @@ void CurveItem::emitCurveChanged()
update();
}
} // End namespace DesignTools.
} // End namespace QmlDesigner.

View File

@@ -35,7 +35,7 @@
#include <string>
#include <QGraphicsObject>
namespace DesignTools {
namespace QmlDesigner {
class AnimationCurve;
class KeyframeItem;
@@ -89,7 +89,7 @@ public:
unsigned int id() const;
ValueType valueType() const;
PropertyTreeItem::ValueType valueType() const;
PropertyTreeItem::Component component() const;
@@ -113,7 +113,7 @@ public:
void setHandleVisibility(bool visible);
void setValueType(ValueType type);
void setValueType(PropertyTreeItem::ValueType type);
void setComponent(PropertyTreeItem::Component comp);
@@ -140,7 +140,7 @@ private:
CurveItemStyleOption m_style;
ValueType m_type;
PropertyTreeItem::ValueType m_type;
PropertyTreeItem::Component m_component;
@@ -151,4 +151,4 @@ private:
bool m_itemDirty;
};
} // End namespace DesignTools.
} // End namespace QmlDesigner.

View File

@@ -33,7 +33,7 @@
#include <cmath>
namespace DesignTools {
namespace QmlDesigner {
GraphicsScene::GraphicsScene(QObject *parent)
: QGraphicsScene(parent)
@@ -236,9 +236,34 @@ void GraphicsScene::doNotMoveItems(bool val)
m_doNotMoveItems = val;
}
void GraphicsScene::removeCurveItem(unsigned int id)
{
CurveItem *tmp = nullptr;
for (auto *curve : m_curves) {
if (curve->id() == id) {
removeItem(curve);
tmp = curve;
break;
}
}
if (tmp) {
Q_UNUSED(m_curves.removeOne(tmp));
delete tmp;
}
m_dirty = true;
}
void GraphicsScene::addCurveItem(CurveItem *item)
{
m_dirty = true;
for (auto *curve : m_curves) {
if (curve->id() == item->id()) {
delete item;
return;
}
}
item->setDirty(false);
item->connect(this);
addItem(item);
@@ -249,6 +274,8 @@ void GraphicsScene::addCurveItem(CurveItem *item)
m_curves.push_back(item);
resetZValues();
m_dirty = true;
}
void GraphicsScene::moveToBottom(CurveItem *item)
@@ -449,4 +476,4 @@ void GraphicsScene::resetZValues()
}
}
} // End namespace DesignTools.
} // End namespace QmlDesigner.

View File

@@ -29,7 +29,7 @@
#include <QGraphicsScene>
namespace DesignTools {
namespace QmlDesigner {
class AnimationCurve;
class CurveItem;
@@ -95,6 +95,8 @@ public:
void doNotMoveItems(bool tmp);
void removeCurveItem(unsigned int id);
void addCurveItem(CurveItem *item);
void moveToBottom(CurveItem *item);
@@ -140,4 +142,4 @@ private:
bool m_doNotMoveItems;
};
} // End namespace DesignTools.
} // End namespace QmlDesigner.

View File

@@ -40,7 +40,7 @@
#include <iomanip>
#include <sstream>
namespace DesignTools {
namespace QmlDesigner {
GraphicsView::GraphicsView(CurveEditorModel *model, QWidget *parent)
: QGraphicsView(parent)
@@ -75,18 +75,15 @@ GraphicsView::GraphicsView(CurveEditorModel *model, QWidget *parent)
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);
update();
QmlDesigner::Navigation2dFilter *filter = new QmlDesigner::Navigation2dFilter(this);
auto zoomChanged = &QmlDesigner::Navigation2dFilter::zoomChanged;
connect(filter, zoomChanged, [this](double scale, const QPointF &pos) {
applyZoom(m_zoomX + scale, m_zoomY, mapToGlobal(pos.toPoint()));
});
installEventFilter(filter);
applyZoom(m_zoomX, m_zoomY);
update();
}
GraphicsView::~GraphicsView()
@@ -189,19 +186,62 @@ void GraphicsView::setStyle(const CurveEditorStyle &style)
viewport()->update();
}
void GraphicsView::setLocked(PropertyTreeItem *item)
void GraphicsView::setLocked(TreeItem *item)
{
if (CurveItem *curve = m_scene->findCurve(item->id())) {
if (item->locked()) {
curve->setLocked(true);
m_scene->moveToBottom(curve);
} else {
curve->setLocked(false);
m_scene->moveToTop(curve);
if (item->asNodeItem()) {
for (auto *ci : item->children())
setLocked(ci);
} else if (item->asPropertyItem()) {
if (CurveItem *curve = m_scene->findCurve(item->id())) {
if (item->locked() || item->implicitlyLocked()) {
curve->setLocked(true);
m_scene->moveToBottom(curve);
} else {
curve->setLocked(false);
m_scene->moveToTop(curve);
}
}
}
}
void GraphicsView::setPinned(TreeItem *item)
{
auto pin = [this](PropertyTreeItem *pitem, bool pinned) {
if (pinned) {
if (CurveItem *curve = m_scene->findCurve(pitem->id()))
curve->setPinned(pinned);
else if (CurveItem *citem = TreeModel::curveItem(pitem))
m_scene->addCurveItem(citem);
} else if (!pinned) {
if (!m_model->isSelected(pitem) && !pitem->pinned())
m_scene->removeCurveItem(pitem->id());
else if (CurveItem *curve = m_scene->findCurve(pitem->id()))
curve->setPinned(pinned);
}
};
if (auto *pitem = item->asPropertyItem()) {
pin(pitem, pitem->pinned() || pitem->implicitlyPinned());
} else if (auto *nitem = item->asNodeItem()) {
bool pinned = nitem->pinned();
if (!pinned && m_model->isSelected(nitem)) {
for (auto *i : nitem->children()) {
if (CurveItem *curve = m_scene->findCurve(i->id()))
curve->setPinned(pinned);
}
return;
}
for (auto *i : nitem->children()) {
if (auto *pitem = i->asPropertyItem())
pin(pitem, pinned);
}
}
applyZoom(m_zoomX, m_zoomY);
viewport()->update();
}
void GraphicsView::setZoomX(double zoom, const QPoint &pivot)
{
applyZoom(zoom, m_zoomY, pivot);
@@ -228,8 +268,8 @@ void GraphicsView::scrollContent(double x, double y)
{
QScrollBar *hs = horizontalScrollBar();
QScrollBar *vs = verticalScrollBar();
hs->setValue(hs->value() + x);
vs->setValue(vs->value() + y);
hs->setValue(hs->value() + static_cast<int>(x));
vs->setValue(vs->value() + static_cast<int>(y));
}
void GraphicsView::reset(const std::vector<CurveItem *> &items)
@@ -242,15 +282,19 @@ void GraphicsView::reset(const std::vector<CurveItem *> &items)
viewport()->update();
}
void GraphicsView::updateSelection(const std::vector<CurveItem *> &items)
void GraphicsView::updateSelection()
{
std::vector<CurveItem *> preservedItems = m_scene->takePinnedItems();
for (auto *curve : items) {
std::vector<CurveItem *> deleteItems;
for (auto *curve : m_model->selectedCurves()) {
auto finder = [curve](CurveItem *item) { return curve->id() == item->id(); };
auto iter = std::find_if(preservedItems.begin(), preservedItems.end(), finder);
if (iter == preservedItems.end())
preservedItems.push_back(curve);
else
deleteItems.push_back(curve);
}
freeClear(deleteItems);
reset(preservedItems);
}
@@ -304,7 +348,8 @@ void GraphicsView::mousePressEvent(QMouseEvent *event)
QPointF pos = mapToScene(event->pos());
if (timeScaleRect().contains(pos)) {
m_dragging = true;
setCurrentFrame(std::round(mapXtoTime(pos.x())));
double t = mapXtoTime(static_cast<int>(pos.x()));
setCurrentFrame(roundToInt(t));
m_playhead.setMoving(true);
event->accept();
return;
@@ -398,19 +443,18 @@ void GraphicsView::drawForeground(QPainter *painter, const QRectF &rect)
void GraphicsView::drawBackground(QPainter *painter, const QRectF &rect)
{
painter->fillRect(rect, m_style.backgroundBrush);
painter->fillRect(scene()->sceneRect(), m_style.backgroundAlternateBrush);
drawGrid(painter, rect);
drawGrid(painter);
}
int GraphicsView::mapTimeToX(double time) const
{
return std::round(time * scaleX(m_transform));
return roundToInt(time * scaleX(m_transform));
}
int GraphicsView::mapValueToY(double y) const
{
return std::round(y * scaleY(m_transform));
return roundToInt(y * scaleY(m_transform));
}
double GraphicsView::mapXtoTime(int x) const
@@ -430,7 +474,7 @@ QPointF GraphicsView::globalToScene(const QPoint &point) const
QPointF GraphicsView::globalToRaster(const QPoint &point) const
{
QPointF scene = globalToScene(point);
QPoint scene = globalToScene(point).toPoint();
return QPointF(mapXtoTime(scene.x()), mapYtoValue(scene.y()));
}
@@ -480,7 +524,7 @@ void GraphicsView::applyZoom(double x, double y, const QPoint &pivot)
m_scene->doNotMoveItems(false);
}
void GraphicsView::drawGrid(QPainter *painter, const QRectF &rect)
void GraphicsView::drawGrid(QPainter *painter)
{
QRectF gridRect = scene()->sceneRect();
@@ -488,12 +532,16 @@ void GraphicsView::drawGrid(QPainter *painter, const QRectF &rect)
return;
auto drawVerticalLine = [painter, gridRect](double position) {
painter->drawLine(position, gridRect.top(), position, gridRect.bottom());
QPointF p1(position, gridRect.top());
QPointF p2(position, gridRect.bottom());
painter->drawLine(p1, p2);
};
painter->save();
painter->setPen(m_style.gridColor);
painter->fillRect(gridRect, m_style.backgroundAlternateBrush);
double timeIncrement = timeLabelInterval(painter, m_model->maximumTime());
for (double i = minimumTime(); i <= maximumTime(); i += timeIncrement)
drawVerticalLine(mapTimeToX(i));
@@ -635,7 +683,7 @@ double GraphicsView::timeLabelInterval(QPainter *painter, double maxTime)
double tickDistance = mapTimeToX(deltaTime);
while (true) {
if (tickDistance == 0 && deltaTime >= maxTime)
if (qFuzzyCompare(tickDistance, 0.) && deltaTime >= maxTime)
return maxTime;
if (tickDistance > minTextSpacing)
@@ -658,12 +706,12 @@ QRectF GraphicsView::rangeMinHandle(const QRectF &rect)
QRectF labelRect = fontMetrics().boundingRect(QString("0"));
labelRect.moveCenter(rect.center());
qreal top = rect.bottom() - 2;
qreal bottom = labelRect.bottom() + 2;
QSize size(10, top - bottom);
qreal top = rect.bottom() - 2.;
qreal bottom = labelRect.bottom() + 2.;
QSize size(10, roundToInt(top - bottom));
int leftHandleLeft = mapTimeToX(m_model->minimumTime()) - size.width();
return QRectF(QPointF(leftHandleLeft, bottom), size);
int handle = mapTimeToX(m_model->minimumTime()) - size.width();
return QRectF(QPointF(handle, bottom), size);
}
QRectF GraphicsView::rangeMaxHandle(const QRectF &rect)
@@ -671,10 +719,13 @@ QRectF GraphicsView::rangeMaxHandle(const QRectF &rect)
QRectF labelRect = fontMetrics().boundingRect(QString("0"));
labelRect.moveCenter(rect.center());
qreal bottom = rect.bottom() - 2;
qreal top = labelRect.bottom() + 2;
qreal bottom = rect.bottom() - 2.;
qreal top = labelRect.bottom() + 2.;
return QRectF(QPointF(mapTimeToX(m_model->maximumTime()), bottom), QSize(10, top - bottom));
QSize size(10, roundToInt(top - bottom));
int handle = mapTimeToX(m_model->maximumTime());
return QRectF(QPointF(handle, bottom), size);
}
} // End namespace DesignTools.
} // End namespace QmlDesigner.

View File

@@ -33,12 +33,12 @@
#include <QGraphicsView>
namespace DesignTools {
namespace QmlDesigner {
class CurveItem;
class CurveEditorModel;
class Playhead;
class PropertyTreeItem;
class TreeItem;
class GraphicsView : public QGraphicsView
{
@@ -92,7 +92,9 @@ public:
QRectF defaultRasterRect() const;
void setLocked(PropertyTreeItem *item);
void setLocked(TreeItem *item);
void setPinned(TreeItem *item);
void setStyle(const CurveEditorStyle &style);
@@ -106,7 +108,7 @@ public:
void reset(const std::vector<CurveItem *> &items);
void updateSelection(const std::vector<CurveItem *> &items);
void updateSelection();
void setInterpolation(Keyframe::Interpolation interpol);
@@ -134,7 +136,7 @@ protected:
private:
void applyZoom(double x, double y, const QPoint &pivot = QPoint());
void drawGrid(QPainter *painter, const QRectF &rect);
void drawGrid(QPainter *painter);
#if 0
void drawExtremaX(QPainter *painter, const QRectF &rect);
@@ -176,4 +178,4 @@ private:
CurveEditorStyleDialog m_dialog;
};
} // End namespace DesignTools.
} // End namespace QmlDesigner.

View File

@@ -31,7 +31,7 @@
#include <QPainter>
namespace DesignTools {
namespace QmlDesigner {
struct HandleGeometry
{
@@ -196,4 +196,4 @@ QVariant HandleItem::itemChange(QGraphicsItem::GraphicsItemChange change, const
return QGraphicsItem::itemChange(change, value);
}
} // End namespace DesignTools.
} // End namespace QmlDesigner.

View File

@@ -28,7 +28,7 @@
#include "curveeditorstyle.h"
#include "selectableitem.h"
namespace DesignTools {
namespace QmlDesigner {
class KeyframeItem;
class CurveSegment;
@@ -77,4 +77,4 @@ private:
QPointF m_validPos;
};
} // End namespace DesignTools.
} // End namespace QmlDesigner.

View File

@@ -31,7 +31,7 @@
#include <cmath>
namespace DesignTools {
namespace QmlDesigner {
KeyframeItem::KeyframeItem(QGraphicsItem *parent)
: SelectableItem(parent)
@@ -408,9 +408,9 @@ QVariant KeyframeItem::itemChange(QGraphicsItem::GraphicsItemChange change, cons
if (ok) {
position.setX(std::round(position.x()));
if (curveItem->valueType() == ValueType::Integer)
if (curveItem->valueType() == PropertyTreeItem::ValueType::Integer)
position.setY(std::round(position.y()));
else if (curveItem->valueType() == ValueType::Bool)
else if (curveItem->valueType() == PropertyTreeItem::ValueType::Bool)
position.setY(position.y() > 0.5 ? 1.0 : 0.0);
if (!legalLeft() || !legalRight()) {
@@ -463,4 +463,4 @@ void KeyframeItem::selectionCallback()
m_right->setSelected(selected());
}
} // End namespace DesignTools.
} // End namespace QmlDesigner.

View File

@@ -32,7 +32,7 @@
#include <QGraphicsObject>
namespace DesignTools {
namespace QmlDesigner {
class HandleItem;
@@ -134,4 +134,4 @@ private:
bool m_visibleOverride = true;
};
} // End namespace DesignTools.
} // End namespace QmlDesigner.

View File

@@ -34,7 +34,7 @@
#include <cmath>
namespace DesignTools {
namespace QmlDesigner {
constexpr double g_playheadMargin = 5.0;
@@ -149,6 +149,7 @@ void Playhead::mouseMoveOutOfBounds(GraphicsView *view)
void Playhead::mouseRelease(GraphicsView *view)
{
Q_UNUSED(view);
m_moving = false;
}
@@ -188,4 +189,4 @@ void Playhead::paint(QPainter *painter, GraphicsView *view) const
painter->restore();
}
} // End namespace DesignTools.
} // End namespace QmlDesigner.

View File

@@ -32,7 +32,7 @@ QT_BEGIN_NAMESPACE
class QPainter;
QT_END_NAMESPACE
namespace DesignTools {
namespace QmlDesigner {
class GraphicsView;
@@ -69,4 +69,4 @@ private:
QTimer m_timer;
};
} // End namespace DesignTools.
} // End namespace QmlDesigner.

View File

@@ -26,7 +26,7 @@
#include "selectableitem.h"
#include "keyframeitem.h"
namespace DesignTools {
namespace QmlDesigner {
CurveEditorItem::CurveEditorItem(QGraphicsItem *parent)
: QGraphicsObject(parent)
@@ -193,4 +193,4 @@ void SelectableItem::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
activationCallback();
}
} // End namespace DesignTools.
} // End namespace QmlDesigner.

View File

@@ -27,7 +27,7 @@
#include <QGraphicsObject>
namespace DesignTools {
namespace QmlDesigner {
class CurveEditorItem : public QGraphicsObject
{
@@ -58,13 +58,14 @@ enum ItemType {
ItemTypeCurve = QGraphicsItem::UserType + 3
};
enum class SelectionMode : unsigned int { Undefined, Clear, New, Add, Remove, Toggle };
class SelectableItem : public CurveEditorItem
{
Q_OBJECT
public:
enum class SelectionMode : unsigned int { Undefined, Clear, New, Add, Remove, Toggle };
SelectableItem(QGraphicsItem *parent = nullptr);
~SelectableItem() override;
@@ -102,4 +103,4 @@ private:
SelectionMode m_preSelected;
};
} // End namespace DesignTools.
} // End namespace QmlDesigner.

View File

@@ -27,7 +27,7 @@
#include "curveitem.h"
#include "treemodel.h"
namespace DesignTools {
namespace QmlDesigner {
SelectionModel::SelectionModel(QAbstractItemModel *model)
: QItemSelectionModel(model)
@@ -46,10 +46,19 @@ void SelectionModel::select(const QItemSelection &selection,
}
}
bool SelectionModel::isSelected(TreeItem *item) const
{
for (auto *i : selectedTreeItems())
if (i->id() == item->id())
return true;
return false;
}
std::vector<TreeItem::Path> SelectionModel::selectedPaths() const
{
std::vector<TreeItem::Path> out;
for (auto &&item : selectedTreeItems())
for (auto *item : selectedTreeItems())
out.push_back(item->path());
return out;
}
@@ -112,20 +121,11 @@ void SelectionModel::selectPaths(const std::vector<TreeItem::Path> &selection)
}
}
void SelectionModel::changeSelection(const QItemSelection &selected,
const QItemSelection &deselected)
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);
emit curvesSelected();
}
} // End namespace DesignTools.
} // End namespace QmlDesigner.

View File

@@ -30,7 +30,7 @@
#include <QItemSelectionModel>
namespace DesignTools {
namespace QmlDesigner {
class TreeItem;
class NodeTreeItem;
@@ -41,13 +41,14 @@ class SelectionModel : public QItemSelectionModel
Q_OBJECT
signals:
void curvesSelected(const std::vector<CurveItem *> &curves);
void curvesSelected();
public:
SelectionModel(QAbstractItemModel *model = nullptr);
void select(const QItemSelection &selection,
QItemSelectionModel::SelectionFlags command) override;
void select(const QItemSelection &selection, QItemSelectionModel::SelectionFlags command) override;
bool isSelected(TreeItem *item) const;
std::vector<TreeItem::Path> selectedPaths() const;
@@ -65,4 +66,4 @@ private:
void changeSelection(const QItemSelection &selected, const QItemSelection &deselected);
};
} // End namespace DesignTools.
} // End namespace QmlDesigner.

View File

@@ -36,7 +36,7 @@
#include <cmath>
namespace DesignTools {
namespace QmlDesigner {
Selector::Selector() {}
@@ -139,7 +139,7 @@ void Selector::mouseRelease(QMouseEvent *event, GraphicsScene *scene)
bool Selector::select(const SelectionTool &tool, const QPointF &pos, GraphicsScene *scene)
{
auto selectWidthTool = [this,
tool](SelectionMode mode, const QPointF &pos, GraphicsScene *scene) {
tool](SelectableItem::SelectionMode mode, const QPointF &pos, GraphicsScene *scene) {
switch (tool) {
case SelectionTool::Lasso:
return lassoSelection(mode, pos, scene);
@@ -152,19 +152,19 @@ bool Selector::select(const SelectionTool &tool, const QPointF &pos, GraphicsSce
if (m_shortcut == m_shortcuts.newSelection) {
clearSelection(scene);
return selectWidthTool(SelectionMode::New, pos, scene);
return selectWidthTool(SelectableItem::SelectionMode::New, pos, scene);
} else if (m_shortcut == m_shortcuts.addToSelection) {
return selectWidthTool(SelectionMode::Add, pos, scene);
return selectWidthTool(SelectableItem::SelectionMode::Add, pos, scene);
} else if (m_shortcut == m_shortcuts.removeFromSelection) {
return selectWidthTool(SelectionMode::Remove, pos, scene);
return selectWidthTool(SelectableItem::SelectionMode::Remove, pos, scene);
} else if (m_shortcut == m_shortcuts.toggleSelection) {
return selectWidthTool(SelectionMode::Toggle, pos, scene);
return selectWidthTool(SelectableItem::SelectionMode::Toggle, pos, scene);
}
return false;
}
bool Selector::pressSelection(SelectionMode mode, const QPointF &pos, GraphicsScene *scene)
bool Selector::pressSelection(SelectableItem::SelectionMode mode, const QPointF &pos, GraphicsScene *scene)
{
bool out = false;
const auto itemList = scene->items();
@@ -190,7 +190,7 @@ bool Selector::pressSelection(SelectionMode mode, const QPointF &pos, GraphicsSc
return out;
}
bool Selector::rectangleSelection(SelectionMode mode, const QPointF &pos, GraphicsScene *scene)
bool Selector::rectangleSelection(SelectableItem::SelectionMode mode, const QPointF &pos, GraphicsScene *scene)
{
bool out = false;
m_rect.setBottomRight(pos);
@@ -201,14 +201,14 @@ bool Selector::rectangleSelection(SelectionMode mode, const QPointF &pos, Graphi
keyframeItem->setPreselected(mode);
out = true;
} else {
keyframeItem->setPreselected(SelectionMode::Undefined);
keyframeItem->setPreselected(SelectableItem::SelectionMode::Undefined);
}
}
}
return out;
}
bool Selector::lassoSelection(SelectionMode mode, const QPointF &pos, GraphicsScene *scene)
bool Selector::lassoSelection(SelectableItem::SelectionMode mode, const QPointF &pos, GraphicsScene *scene)
{
bool out = false;
m_lasso.lineTo(pos);
@@ -219,7 +219,7 @@ bool Selector::lassoSelection(SelectionMode mode, const QPointF &pos, GraphicsSc
keyframeItem->setPreselected(mode);
out = true;
} else {
keyframeItem->setPreselected(SelectionMode::Undefined);
keyframeItem->setPreselected(SelectableItem::SelectionMode::Undefined);
}
}
}
@@ -231,7 +231,7 @@ void Selector::clearSelection(GraphicsScene *scene)
const auto itemList = scene->items();
for (auto *item : itemList) {
if (auto *frameItem = qgraphicsitem_cast<KeyframeItem *>(item)) {
frameItem->setPreselected(SelectionMode::Clear);
frameItem->setPreselected(SelectableItem::SelectionMode::Clear);
frameItem->applyPreselection();
frameItem->setActivated(false, HandleItem::Slot::Left);
frameItem->setActivated(false, HandleItem::Slot::Right);
@@ -248,4 +248,4 @@ void Selector::applyPreSelection(GraphicsScene *scene)
}
}
} // End namespace DesignTools.
} // End namespace QmlDesigner.

View File

@@ -28,14 +28,12 @@
#include "curveeditorstyle.h"
#include "selectableitem.h"
namespace DesignTools {
namespace QmlDesigner {
class GraphicsView;
class GraphicsScene;
class Playhead;
enum class SelectionTool { Undefined, Lasso, Rectangle };
class Selector
{
public:
@@ -50,13 +48,15 @@ public:
void mouseRelease(QMouseEvent *event, GraphicsScene *scene);
private:
enum class SelectionTool { Undefined, Lasso, Rectangle };
bool select(const SelectionTool &tool, const QPointF &pos, GraphicsScene *scene);
bool pressSelection(SelectionMode mode, const QPointF &pos, GraphicsScene *scene);
bool pressSelection(SelectableItem::SelectionMode mode, const QPointF &pos, GraphicsScene *scene);
bool rectangleSelection(SelectionMode mode, const QPointF &pos, GraphicsScene *scene);
bool rectangleSelection(SelectableItem::SelectionMode mode, const QPointF &pos, GraphicsScene *scene);
bool lassoSelection(SelectionMode mode, const QPointF &pos, GraphicsScene *scene);
bool lassoSelection(SelectableItem::SelectionMode mode, const QPointF &pos, GraphicsScene *scene);
void clearSelection(GraphicsScene *scene);
@@ -77,4 +77,4 @@ private:
QRectF m_rect;
};
} // End namespace DesignTools.
} // End namespace QmlDesigner.

View File

@@ -24,7 +24,7 @@
****************************************************************************/
#include "shortcut.h"
namespace DesignTools {
namespace QmlDesigner {
Shortcut::Shortcut()
: m_key()
@@ -78,4 +78,4 @@ bool Shortcut::operator==(const Shortcut &other) const
return m_key == other.m_key && m_buttons == other.m_buttons && m_modifiers == other.m_modifiers;
}
} // End namespace DesignTools.
} // End namespace QmlDesigner.

View File

@@ -27,7 +27,7 @@
#include <QMouseEvent>
namespace DesignTools {
namespace QmlDesigner {
class Shortcut
{
@@ -58,4 +58,4 @@ private:
Qt::KeyboardModifiers m_modifiers;
};
} // End namespace DesignTools.
} // End namespace QmlDesigner.

View File

@@ -24,13 +24,14 @@
****************************************************************************/
#include "treeitemdelegate.h"
#include "treeitem.h"
#include "treemodel.h"
#include <QApplication>
#include <QEvent>
#include <QMouseEvent>
#include <QPainter>
namespace DesignTools {
namespace QmlDesigner {
TreeItemDelegate::TreeItemDelegate(const CurveEditorStyle &style, QObject *parent)
: QStyledItemDelegate(parent)
@@ -50,56 +51,66 @@ QRect makeSquare(const QRect &rect)
return r;
}
QPixmap pixmapFromStyle(int column, const CurveEditorStyle &style, const QRect &rect, TreeItem *item, bool underMouse)
{
QColor color = underMouse ? style.iconHoverColor : style.iconColor;
if (column == 1) {
bool locked = item->locked();
if (underMouse)
locked = !locked;
if (locked)
return pixmapFromIcon(style.treeItemStyle.lockedIcon, rect.size(), color);
else
return pixmapFromIcon(style.treeItemStyle.unlockedIcon, rect.size(), color);
}
bool pinned = item->pinned();
if (underMouse)
pinned = !pinned;
if (pinned)
return pixmapFromIcon(style.treeItemStyle.pinnedIcon, rect.size(), color);
else
return pixmapFromIcon(style.treeItemStyle.unpinnedIcon, rect.size(), color);
}
void TreeItemDelegate::paint(QPainter *painter,
const QStyleOptionViewItem &option,
const QModelIndex &index) const
{
if (index.column() == 1 || index.column() == 2) {
QStyleOptionViewItem opt = option;
initStyleOption(&opt, index);
QStyleOptionViewItem opt = option;
initStyleOption(&opt, index);
auto *treeItem = static_cast<TreeItem *>(index.internalPointer());
QColor high = Theme::getColor(Theme::Color::QmlDesigner_HighlightColor);
opt.palette.setColor(QPalette::Active, QPalette::Highlight, high);
opt.palette.setColor(QPalette::Inactive, QPalette::Highlight, high);
QPoint mousePos = QCursor::pos();
mousePos = option.widget->mapFromGlobal(mousePos);
QStyle *style = opt.widget ? opt.widget->style() : QApplication::style();
style->drawPrimitive(QStyle::PE_PanelItemViewItem, &opt, painter, opt.widget);
QRect iconRect = makeSquare(option.rect);
bool underMouse = option.rect.contains(m_mousePos)
&& option.state & QStyle::State_MouseOver;
auto *treeItem = static_cast<TreeItem *>(index.internalPointer());
QStyle *style = opt.widget ? opt.widget->style() : QApplication::style();
style->drawPrimitive(QStyle::PE_PanelItemViewItem, &opt, painter, opt.widget);
bool textColumn = TreeModel::isTextColumn(index);
bool lockedColumn = TreeModel::isLockedColumn(index);
bool pinnedColumn = TreeModel::isPinnedColumn(index);
QPixmap pixmap = pixmapFromStyle(index.column(), m_style, iconRect, treeItem, underMouse);
painter->drawPixmap(iconRect, pixmap);
QPixmap pixmap;
QRect iconRect = makeSquare(option.rect);
if (lockedColumn) {
if (treeItem->locked()) {
pixmap = m_style.treeItemStyle.lockedIcon.pixmap(iconRect.size());
} else if (treeItem->asNodeItem() != nullptr && treeItem->implicitlyLocked()) {
pixmap = m_style.treeItemStyle.implicitlyLockedIcon.pixmap(iconRect.size());
} else if (option.state.testFlag(QStyle::State_MouseOver)) {
if (treeItem->implicitlyLocked()) {
pixmap = m_style.treeItemStyle.implicitlyLockedIcon.pixmap(iconRect.size());
} else {
pixmap = m_style.treeItemStyle.unlockedIcon.pixmap(iconRect.size());
}
}
} else if (pinnedColumn) {
if (treeItem->pinned()) {
pixmap = m_style.treeItemStyle.pinnedIcon.pixmap(iconRect.size());
} else if (treeItem->asNodeItem() != nullptr && treeItem->implicitlyPinned()) {
pixmap = m_style.treeItemStyle.implicitlyPinnedIcon.pixmap(iconRect.size());
} else if (option.state.testFlag(QStyle::State_MouseOver)) {
if (treeItem->implicitlyPinned()) {
pixmap = m_style.treeItemStyle.implicitlyPinnedIcon.pixmap(iconRect.size());
} else {
pixmap = m_style.treeItemStyle.unpinnedIcon.pixmap(iconRect.size());
}
}
} else {
QStyledItemDelegate::paint(painter, option, index);
if (textColumn && (treeItem->locked() || treeItem->implicitlyLocked())) {
QColor col = opt.palette.color(QPalette::Disabled, QPalette::Text).darker();
opt.palette.setColor(QPalette::Active, QPalette::Text, col);
opt.palette.setColor(QPalette::Inactive, QPalette::Text, col);
}
QStyledItemDelegate::paint(painter, opt, index);
}
if (!pixmap.isNull())
painter->drawPixmap(iconRect, pixmap);
}
void TreeItemDelegate::setStyle(const CurveEditorStyle &style)
@@ -118,4 +129,4 @@ bool TreeItemDelegate::editorEvent(QEvent *event,
return QStyledItemDelegate::editorEvent(event, model, option, index);
}
} // End namespace DesignTools.
} // End namespace QmlDesigner.

View File

@@ -29,7 +29,7 @@
#include <QStyledItemDelegate>
namespace DesignTools {
namespace QmlDesigner {
class TreeItemDelegate : public QStyledItemDelegate
{
@@ -60,4 +60,4 @@ private:
QPoint m_mousePos;
};
} // End namespace DesignTools.
} // End namespace QmlDesigner.

View File

@@ -31,7 +31,22 @@
#include <QIcon>
namespace DesignTools {
namespace QmlDesigner {
bool TreeModel::isTextColumn(const QModelIndex &index)
{
return index.column() == 0;
}
bool TreeModel::isLockedColumn(const QModelIndex &index)
{
return index.column() == 1;
}
bool TreeModel::isPinnedColumn(const QModelIndex &index)
{
return index.column() == 2;
}
TreeItem *TreeModel::treeItem(const QModelIndex &index)
{
@@ -71,8 +86,8 @@ CurveItem *TreeModel::curveItem(TreeItem *item)
auto *citem = new CurveItem(pti->id(), pti->curve());
citem->setValueType(pti->valueType());
citem->setComponent(pti->component());
citem->setLocked(pti->locked());
citem->setPinned(pti->pinned());
citem->setLocked(pti->locked() || item->implicitlyLocked());
citem->setPinned(pti->pinned() || item->implicitlyPinned());
return citem;
}
@@ -183,6 +198,11 @@ void TreeModel::setGraphicsView(GraphicsView *view)
m_view = view;
}
TreeView *TreeModel::treeView() const
{
return m_tree;
}
GraphicsView *TreeModel::graphicsView() const
{
return m_view;
@@ -208,6 +228,36 @@ QModelIndex TreeModel::findIdx(const QString &name, const QModelIndex &parent) c
return QModelIndex();
}
bool TreeModel::isSelected(TreeItem *item) const
{
if (auto *sm = selectionModel())
return sm->isSelected(item);
return false;
}
void addCurvesFromItem(TreeItem *item, std::vector<CurveItem *> &curves)
{
if (auto *pitem = item->asPropertyItem()) {
if (auto *curveItem = TreeModel::curveItem(pitem))
curves.push_back(curveItem);
} else if (auto *nitem = item->asNodeItem()) {
for (auto *child : nitem->children())
addCurvesFromItem(child, curves);
}
}
std::vector<CurveItem *> TreeModel::selectedCurves() const
{
std::vector<CurveItem *> curves;
const auto ids = selectionModel()->selectedIndexes();
for (auto &&index : ids) {
if (auto *treeItem = TreeModel::treeItem(index))
addCurvesFromItem(treeItem, curves);
}
return curves;
}
QModelIndex TreeModel::indexOf(const TreeItem::Path &path) const
{
QModelIndex parent;
@@ -238,4 +288,9 @@ TreeItem *TreeModel::find(unsigned int id)
return m_root->find(id);
}
} // End namespace DesignTools.
TreeItem *TreeModel::find(const QString &id)
{
return m_root->find(id);
}
} // End namespace QmlDesigner.

View File

@@ -31,13 +31,11 @@
#include <vector>
namespace DesignTools {
namespace QmlDesigner {
class GraphicsView;
class TreeView;
class TreeItem;
class CurveItem;
class PropertyTreeItem;
class SelectionModel;
class TreeModel : public QAbstractItemModel
@@ -45,6 +43,12 @@ class TreeModel : public QAbstractItemModel
Q_OBJECT
public:
static bool isTextColumn(const QModelIndex &index);
static bool isLockedColumn(const QModelIndex &index);
static bool isPinnedColumn(const QModelIndex &index);
static TreeItem *treeItem(const QModelIndex &index);
static NodeTreeItem *nodeItem(const QModelIndex &index);
@@ -73,13 +77,23 @@ public:
int columnCount(const QModelIndex &parent = QModelIndex()) const override;
bool isSelected(TreeItem *item) const;
std::vector<CurveItem *> selectedCurves() const;
QModelIndex indexOf(const TreeItem::Path &path) const;
TreeItem *find(unsigned int id);
TreeItem *find(const QString &id);
void setTreeView(TreeView *view);
void setGraphicsView(GraphicsView *view);
protected:
TreeView *treeView() const;
GraphicsView *graphicsView() const;
SelectionModel *selectionModel() const;
@@ -88,8 +102,6 @@ protected:
TreeItem *root();
TreeItem *find(unsigned int id);
QModelIndex findIdx(const QString &name, const QModelIndex &parent) const;
private:
@@ -100,4 +112,4 @@ private:
TreeItem *m_root;
};
} // End namespace DesignTools.
} // End namespace QmlDesigner.

View File

@@ -28,11 +28,12 @@
#include "selectionmodel.h"
#include "treeitem.h"
#include "treeitemdelegate.h"
#include "treemodel.h"
#include <QHeaderView>
#include <QMouseEvent>
namespace DesignTools {
namespace QmlDesigner {
TreeView::TreeView(CurveEditorModel *model, QWidget *parent)
: QTreeView(parent)
@@ -105,17 +106,12 @@ void TreeView::mousePressEvent(QMouseEvent *event)
QModelIndex index = indexAt(event->pos());
if (index.isValid()) {
auto *treeItem = static_cast<TreeItem *>(index.internalPointer());
if (index.column() == 1) {
treeItem->setLocked(!treeItem->locked());
if (auto *propertyItem = treeItem->asPropertyItem())
emit treeItemLocked(propertyItem);
} else if (index.column() == 2) {
treeItem->setPinned(!treeItem->pinned());
if (auto *propertyItem = treeItem->asPropertyItem())
emit treeItemPinned(propertyItem);
}
if (TreeModel::isLockedColumn(index))
emit treeItemLocked(treeItem, !treeItem->locked());
else if (TreeModel::isPinnedColumn(index))
emit treeItemPinned(treeItem, !treeItem->pinned());
}
QTreeView::mousePressEvent(event);
}
} // End namespace DesignTools.
} // End namespace QmlDesigner.

View File

@@ -30,7 +30,7 @@
#include <QTreeView>
namespace DesignTools {
namespace QmlDesigner {
class AnimationCurve;
class CurveEditorModel;
@@ -44,9 +44,9 @@ class TreeView : public QTreeView
signals:
void curvesSelected(const std::vector<CurveItem *> &curves);
void treeItemLocked(PropertyTreeItem *item);
void treeItemLocked(TreeItem *item, bool val);
void treeItemPinned(PropertyTreeItem *item);
void treeItemPinned(TreeItem *item, bool val);
public:
TreeView(CurveEditorModel *model, QWidget *parent = nullptr);
@@ -63,4 +63,4 @@ protected:
void mousePressEvent(QMouseEvent *event) override;
};
} // End namespace DesignTools.
} // End namespace QmlDesigner.

View File

@@ -29,7 +29,7 @@
#include <QRectF>
#include <QTransform>
namespace DesignTools {
namespace QmlDesigner {
double scaleX(const QTransform &transform)
{
@@ -92,4 +92,4 @@ QPalette singleColorPalette(const QColor &color)
return palette;
}
} // End namespace DesignTools.
} // End namespace QmlDesigner.

View File

@@ -26,6 +26,7 @@
#pragma once
#include <QtGlobal>
#include <cmath>
QT_BEGIN_NAMESPACE
class QColor;
@@ -37,7 +38,7 @@ QT_END_NAMESPACE
#include <vector>
namespace DesignTools {
namespace QmlDesigner {
double scaleX(const QTransform &transform);
@@ -58,7 +59,7 @@ inline void freeClear(T &vec)
}
template<typename TV, typename TC>
inline double clamp(const TV &val, const TC &lo, const TC &hi)
inline TV clamp(const TV &val, const TC &lo, const TC &hi)
{
return val < lo ? lo : (val > hi ? hi : val);
}
@@ -75,4 +76,10 @@ inline T reverseLerp(double blend, const T &a, const T &b)
return (blend - b) / (a - b);
}
} // End namespace DesignTools.
template<typename T>
inline int roundToInt(const T &val)
{
return static_cast<int>(std::round(val));
}
} // End namespace QmlDesigner.

View File

@@ -27,7 +27,7 @@
#include <sstream>
namespace DesignTools {
namespace QmlDesigner {
Keyframe::Keyframe()
: m_interpolation(Interpolation::Undefined)
@@ -193,4 +193,4 @@ std::string toString(Keyframe::Interpolation interpol)
}
}
} // End namespace DesignTools.
} // End namespace QmlDesigner.

View File

@@ -28,7 +28,7 @@
#include <QPointF>
#include <QVariant>
namespace DesignTools {
namespace QmlDesigner {
class Keyframe
{
@@ -93,4 +93,4 @@ private:
std::string toString(Keyframe::Interpolation interpol);
} // End namespace DesignTools.
} // End namespace QmlDesigner.

View File

@@ -28,7 +28,7 @@
#include <QIcon>
#include <QVariant>
namespace DesignTools {
namespace QmlDesigner {
TreeItem::TreeItem(const QString &name)
: m_name(name)
@@ -123,9 +123,9 @@ bool TreeItem::compare(const std::vector<QString> &path) const
int TreeItem::row() const
{
if (m_parent) {
for (int i = 0, total = int(m_parent->m_children.size()); i < total; ++i) {
for (size_t i = 0, total = m_parent->m_children.size(); i < total; ++i) {
if (m_parent->m_children[i] == this)
return i;
return static_cast<int>(i);
}
}
@@ -147,6 +147,17 @@ int TreeItem::columnCount() const
return 3;
}
TreeItem *TreeItem::root() const
{
TreeItem *p = parent();
while (p) {
if (!p->parent())
return p;
p = p->parent();
}
return p;
}
TreeItem *TreeItem::parent() const
{
return m_parent;
@@ -154,10 +165,10 @@ TreeItem *TreeItem::parent() const
TreeItem *TreeItem::child(int row) const
{
if (row < 0 || row >= static_cast<int>(m_children.size()))
if (row < 0 || row >= rowCount())
return nullptr;
return m_children.at(row);
return m_children.at(static_cast<size_t>(row));
}
TreeItem *TreeItem::find(unsigned int id) const
@@ -173,6 +184,24 @@ TreeItem *TreeItem::find(unsigned int id) const
return nullptr;
}
TreeItem *TreeItem::find(const QString &id) const
{
for (auto *child : m_children) {
if (child->name() == id)
return child;
if (auto *childsChild = child->find(id))
return childsChild;
}
return nullptr;
}
std::vector<TreeItem *> TreeItem::children() const
{
return m_children;
}
QVariant TreeItem::data(int column) const
{
switch (column) {
@@ -205,6 +234,11 @@ QVariant TreeItem::headerData(int column) const
}
}
bool TreeItem::operator==(unsigned int id) const
{
return m_id == id;
}
void TreeItem::setId(unsigned int &id)
{
m_id = id;
@@ -229,9 +263,10 @@ void TreeItem::setPinned(bool pinned)
m_pinned = pinned;
}
NodeTreeItem::NodeTreeItem(const QString &name, const QIcon &icon)
NodeTreeItem::NodeTreeItem(const QString &name, const QIcon &icon, const std::vector<QString> &parentIds)
: TreeItem(name)
, m_icon(icon)
, m_parentIds(parentIds)
{
Q_UNUSED(icon)
}
@@ -241,6 +276,35 @@ NodeTreeItem *NodeTreeItem::asNodeItem()
return this;
}
bool NodeTreeItem::implicitlyLocked() const
{
TreeItem *r = root();
if (!r)
return false;
for (auto &&id : m_parentIds) {
if (TreeItem *item = r->find(id))
if (item->locked())
return true;
}
return false;
}
bool NodeTreeItem::implicitlyPinned() const
{
TreeItem *r = root();
if (!r)
return false;
for (auto &&id : m_parentIds) {
if (TreeItem *item = r->find(id))
if (item->pinned())
return true;
}
return false;
}
QIcon NodeTreeItem::icon() const
{
return m_icon;
@@ -257,20 +321,6 @@ std::vector<PropertyTreeItem *> NodeTreeItem::properties() const
return out;
}
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)
@@ -280,6 +330,22 @@ PropertyTreeItem::PropertyTreeItem(const QString &name,
, m_curve(curve)
{}
bool PropertyTreeItem::implicitlyLocked() const
{
if (auto *parentNode = parentNodeTreeItem())
return parentNode->locked() || parentNode->implicitlyLocked();
return false;
}
bool PropertyTreeItem::implicitlyPinned() const
{
if (auto *parentNode = parentNodeTreeItem())
return parentNode->pinned() || parentNode->implicitlyPinned();
return false;
}
PropertyTreeItem *PropertyTreeItem::asPropertyItem()
{
return this;
@@ -296,7 +362,7 @@ const NodeTreeItem *PropertyTreeItem::parentNodeTreeItem() const
return nullptr;
}
ValueType PropertyTreeItem::valueType() const
PropertyTreeItem::ValueType PropertyTreeItem::valueType() const
{
return m_type;
}
@@ -331,4 +397,18 @@ void PropertyTreeItem::setComponent(const Component &comp)
m_component = comp;
}
} // End namespace DesignTools.
std::string toString(PropertyTreeItem::ValueType type)
{
switch (type) {
case PropertyTreeItem::ValueType::Bool:
return "Bool";
case PropertyTreeItem::ValueType::Integer:
return "Integer";
case PropertyTreeItem::ValueType::Double:
return "Double";
default:
return "Undefined";
}
}
} // End namespace QmlDesigner.

View File

@@ -38,7 +38,7 @@ class QIcon;
class QVariant;
QT_END_NAMESPACE
namespace DesignTools {
namespace QmlDesigner {
class NodeTreeItem;
class PropertyTreeItem;
@@ -48,6 +48,10 @@ class TreeItem
public:
using Path = std::vector<QString>;
virtual bool implicitlyLocked() const { return false; }
virtual bool implicitlyPinned() const { return false; }
public:
TreeItem(const QString &name);
@@ -81,16 +85,24 @@ public:
int columnCount() const;
TreeItem *root() const;
TreeItem *parent() const;
TreeItem *child(int row) const;
TreeItem *find(unsigned int row) const;
TreeItem *find(unsigned int id) const;
TreeItem *find(const QString &id) const;
std::vector<TreeItem *> children() const;
QVariant data(int column) const;
QVariant headerData(int column) const;
bool operator==(unsigned int id) const;
void setId(unsigned int &id);
void addChild(TreeItem *child);
@@ -116,37 +128,45 @@ protected:
class NodeTreeItem : public TreeItem
{
public:
NodeTreeItem(const QString &name, const QIcon &icon);
NodeTreeItem(const QString &name, const QIcon &icon, const std::vector<QString> &parentIds);
NodeTreeItem *asNodeItem() override;
bool implicitlyLocked() const override;
bool implicitlyPinned() const override;
QIcon icon() const override;
std::vector<PropertyTreeItem *> properties() const;
private:
QIcon m_icon;
};
enum class ValueType {
Undefined,
Bool,
Integer,
Double,
std::vector<QString> m_parentIds;
};
std::string toString(ValueType type);
class PropertyTreeItem : public TreeItem
{
public:
enum class Component { Generic, R, G, B, A, X, Y, Z, W };
enum class ValueType {
Undefined,
Bool,
Integer,
Double,
};
public:
PropertyTreeItem(const QString &name, const AnimationCurve &curve, const ValueType &type);
PropertyTreeItem *asPropertyItem() override;
bool implicitlyLocked() const override;
bool implicitlyPinned() const override;
const NodeTreeItem *parentNodeTreeItem() const;
ValueType valueType() const;
@@ -173,4 +193,6 @@ private:
AnimationCurve m_curve;
};
} // End namespace DesignTools.
std::string toString(PropertyTreeItem::ValueType type);
} // End namespace QmlDesigner.

View File

@@ -347,41 +347,6 @@ void TimelineWidget::scroll(const TimelineUtils::Side &side)
m_scrollbar->setValue(m_scrollbar->value() + m_scrollbar->singleStep());
}
ModelNode getTargetNode(DesignTools::PropertyTreeItem *item, const QmlTimeline &timeline)
{
if (const DesignTools::NodeTreeItem *nodeItem = item->parentNodeTreeItem()) {
QString targetId = nodeItem->name();
if (timeline.isValid()) {
for (auto &&target : timeline.allTargets()) {
if (target.displayName() == targetId)
return target;
}
}
}
return ModelNode();
}
QmlTimelineKeyframeGroup timelineKeyframeGroup(QmlTimeline &timeline,
DesignTools::PropertyTreeItem *item)
{
ModelNode node = getTargetNode(item, timeline);
if (node.isValid())
return timeline.keyframeGroup(node, item->name().toLatin1());
return QmlTimelineKeyframeGroup();
}
void attachEasingCurve(double frame,
const QEasingCurve &curve,
const QmlTimelineKeyframeGroup &group)
{
ModelNode frameNode = group.keyframe(frame);
if (frameNode.isValid()) {
auto expression = EasingCurve(curve).toString();
frameNode.bindingProperty("easing.bezierCurve").setExpression(expression);
}
}
void TimelineWidget::selectionChanged()
{
if (graphicsScene()->hasSelection())