Commit 5c0b8462 authored by Thomas Hartmann's avatar Thomas Hartmann
Browse files

QmlDesigner.propertyEditor: add GradientLine widget for gradient editing

parent f871b964
......@@ -40,6 +40,9 @@
#include <nodelistproperty.h>
#include <variantproperty.h>
#include <qmlobjectnode.h>
#include <qmlitemnode.h>
#include <QGradient>
#include <metainfo.h>
namespace QmlDesigner {
......@@ -47,6 +50,7 @@ namespace QmlDesigner {
qmlRegisterType<QmlDesigner::ColorButton>("Bauhaus",1,0,"ColorButton");
qmlRegisterType<QmlDesigner::HueControl>("Bauhaus",1,0,"HueControl");
qmlRegisterType<QmlDesigner::ColorBox>("Bauhaus",1,0,"ColorBox");
qmlRegisterType<QmlDesigner::GradientLine>("Bauhaus",1,0,"GradientLine");
}
void ColorButton::paintEvent(QPaintEvent *event)
......@@ -65,7 +69,17 @@ namespace QmlDesigner {
else
p.setBrush(Qt::transparent);
p.setPen(Qt::black);
p.drawRect(r);
if (!m_noColor) {
p.drawRect(r);
} else {
p.fillRect(r, Qt::white);
p.fillRect(0, 0, width() /2, height() /2, QColor(Qt::gray));
p.fillRect(width() /2, height() /2, width() /2, height() /2, QColor(Qt::gray));
p.setBrush(Qt::transparent);
p.drawRect(r);
}
QVector<QPointF> points;
if (isChecked()) {
......@@ -198,4 +212,265 @@ namespace QmlDesigner {
p.drawRect(QRect(0, 0, width() - 1, height() -1).adjusted(4, 4, -4, -4));
}
void GradientLine::setItemNode(const QVariant &itemNode)
{
if (!itemNode.value<ModelNode>().isValid() || !QmlItemNode(itemNode.value<ModelNode>()).hasNodeParent())
return;
m_itemNode = itemNode.value<ModelNode>();
setup();
emit itemNodeChanged();
}
static inline QColor invertColor(const QColor color)
{
QColor c = color.toHsv();
c.setHsv(c.hue(), c.saturation(), 255 - c.value());
return c;
}
void GradientLine::setupGradient()
{
ModelNode modelNode = m_itemNode.modelNode();
m_colorList.clear();
m_stops.clear();
if (modelNode.hasProperty(m_gradientName)) { //gradient exists
ModelNode gradientNode = modelNode.nodeProperty(m_gradientName).modelNode();
QList<ModelNode> stopList = gradientNode.nodeListProperty("stops").toModelNodeList();
foreach (const ModelNode &stopNode, stopList) {
QmlObjectNode stopObjectNode = stopNode;
if (stopObjectNode.isValid()) {
m_stops << stopObjectNode.instanceValue("position").toReal();
m_colorList << stopObjectNode.instanceValue("color").value<QColor>();
}
}
} else {
m_colorList << m_activeColor << QColor(Qt::black);
m_stops << 0 << 1;
}
updateGradient();
}
bool GradientLine::event(QEvent *event)
{
if (event->type() == QEvent::ShortcutOverride)
if (static_cast<QKeyEvent*>(event)->matches(QKeySequence::Delete)) {
event->accept();
return true;
}
return QWidget::event(event);
}
void GradientLine::keyPressEvent(QKeyEvent * event)
{
if (event->matches(QKeySequence::Delete)) {
if ((currentColorIndex()) != 0 && (currentColorIndex() < m_stops.size() - 1)) {
m_dragActive = false;
m_stops.removeAt(currentColorIndex());
m_colorList.removeAt(currentColorIndex());
updateGradient();
setCurrentIndex(0);
//delete item
}
} else {
QWidget::keyPressEvent(event);
}
}
void GradientLine::paintEvent(QPaintEvent *event)
{
QWidget::paintEvent(event);
QPainter p(this);
QPen pen(Qt::black);
pen.setWidth(1);
p.setPen(pen);
QLinearGradient linearGradient(QPointF(2, 0), QPointF(width() -2, 0));
for (int i =0; i < m_stops.size(); i++)
linearGradient.setColorAt(m_stops.at(i), m_colorList.at(i));
p.setBrush(linearGradient);
p.drawRoundedRect(8, 30, width() - 16, height() - 32, 5, 5);
for (int i =0; i < m_colorList.size(); i++) {
int localYOffset = 0;
QColor arrowColor(Qt::black);
if (i == currentColorIndex()) {
localYOffset = m_yOffset;
arrowColor = QColor("#cdcdcd");
}
p.setPen(arrowColor);
if (i == 0 || i == (m_colorList.size() - 1))
localYOffset = 0;
int pos = qreal((width() - 20)) * m_stops.at(i) + 10;
p.setBrush(arrowColor);
QVector<QPointF> points;
points.append(QPointF(pos, 28 + localYOffset)); //triangle
points.append(QPointF(pos - 4, 22 + localYOffset));
points.append(QPointF(pos + 4, 22 + localYOffset));
p.drawPolygon(points);
if (i == currentColorIndex())
p.fillRect(pos - 6, 9 + localYOffset, 13, 13, invertColor(m_colorList.at(i)));
p.fillRect(pos - 4, 11 + localYOffset, 9, 9, m_colorList.at(i));
}
}
void GradientLine::mousePressEvent(QMouseEvent *event)
{
if (event->button() == Qt::LeftButton) {
int xPos = event->pos().x();
int yPos = event->pos().y();
int draggedIndex = -1;
m_create = false;
m_dragActive = false;
if ((yPos > 10) && (yPos < 30))
for (int i =0; i < m_stops.size(); i++) {
int pos = qreal((width() - 20)) * m_stops.at(i) + 10;
if (((xPos + 5) > pos) && ((xPos - 5) < pos)) {
draggedIndex = i;
m_dragActive = true;
m_dragStart = event->pos();
setCurrentIndex(draggedIndex);
update();
}
}
if (draggedIndex == -1)
m_create = true;
}
setFocus(Qt::MouseFocusReason);
event->accept();
//QWidget::mousePressEvent(event);
}
void GradientLine::mouseReleaseEvent(QMouseEvent *event)
{
if (event->button() == Qt::LeftButton) {
if (m_dragActive == false && m_create) {
qreal stopPos = qreal(event->pos().x() - 10) / qreal((width() - 20));
int index = -1;
for (int i =0; i < m_stops.size() - 1; i++) {
if ((stopPos > m_stops.at(i)) && (index == -1))
index = i +1;
}
if (index != -1 && m_itemNode.isInBaseState()) { //creating of items only in base state
m_stops.insert(index, stopPos);
m_colorList.insert(index, QColor(Qt::white));
setCurrentIndex(index);
updateGradient();
}
}
}
m_dragActive = false;
m_yOffset = 0;
update();
updateGradient();
event->accept();
//QWidget::mouseReleaseEvent(event);
}
void GradientLine::mouseMoveEvent(QMouseEvent *event)
{
if (m_dragActive) {
int xDistance = event->pos().x() - m_dragStart.x();
qreal distance = qreal(xDistance) / qreal((width() - 20));
qreal newStop = m_stops.at(currentColorIndex()) + distance;
if ((newStop >=0) && (newStop <= 1))
m_stops[currentColorIndex()] = newStop;
m_yOffset += event->pos().y() - m_dragStart.y();
if (m_yOffset > 0 || !m_itemNode.isInBaseState()) { //deleting only in base state
m_yOffset = 0;
} else if ((m_yOffset < - 12) && (currentColorIndex()) != 0 && (currentColorIndex() < m_stops.size() - 1)) {
m_yOffset = 0;
m_dragActive = false;
m_stops.removeAt(currentColorIndex());
m_colorList.removeAt(currentColorIndex());
updateGradient();
setCurrentIndex(0);
//delete item
}
int xPos = event->pos().x();
int pos = qreal((width() - 20)) * m_stops.at(currentColorIndex()) + 10;
if (!(((xPos + 5) > pos) && ((xPos - 5) < pos))) { //still on top of the item?
m_dragActive = false; //abort drag
m_yOffset = 0;
}
m_dragStart = event->pos();
update();
}
QWidget::mouseMoveEvent(event);
}
void GradientLine::setup()
{
}
static inline QColor normalizeColor(const QColor &color)
{
QColor newColor = QColor(color.name());
newColor.setAlpha(color.alpha());
return newColor;
}
static inline qreal roundReal(qreal real)
{
int i = real * 100;
return qreal(i) / 100;
}
void GradientLine::updateGradient()
{
if (!active())
return;
RewriterTransaction transaction;
if (!m_itemNode.isValid())
return;
if (!m_itemNode.modelNode().metaInfo().hasProperty(m_gradientName))
return;
ModelNode modelNode = m_itemNode.modelNode();
if (m_itemNode.isInBaseState()) {
if (modelNode.hasProperty(m_gradientName))
modelNode.removeProperty(m_gradientName);
ModelNode gradientNode = modelNode.view()->createModelNode("Qt/Gradient", 4, 6);
for (int i = 0;i < m_stops.size(); i++) {
ModelNode gradientStopNode = modelNode.view()->createModelNode("Qt/GradientStop", 4, 6);
gradientStopNode.variantProperty("position") = roundReal(m_stops.at(i));
gradientStopNode.variantProperty("color") = normalizeColor(m_colorList.at(i));
gradientNode.nodeListProperty("stops").reparentHere(gradientStopNode);
}
modelNode.nodeProperty(m_gradientName).reparentHere(gradientNode);
} else { //state
if (!modelNode.hasProperty(m_gradientName)) {
qWarning(" GradientLine::updateGradient: no gradient in state");
return;
}
ModelNode gradientNode = modelNode.nodeProperty(m_gradientName).modelNode();
QList<ModelNode> stopList = gradientNode.nodeListProperty("stops").toModelNodeList();
for (int i = 0;i < m_stops.size(); i++) {
QmlObjectNode stopObjectNode = stopList.at(i);
stopObjectNode.setVariantProperty("position", roundReal(m_stops.at(i)));
stopObjectNode.setVariantProperty("color", normalizeColor(m_colorList.at(i)));
}
}
}
}
......@@ -38,6 +38,7 @@
#include <modelnode.h>
#include <qdeclarative.h>
#include <propertyeditorvalue.h>
#include <qmlitemnode.h>
QT_BEGIN_NAMESPACE
class QtColorButton;
......@@ -51,10 +52,12 @@ class ColorButton : public QToolButton {
Q_OBJECT
Q_PROPERTY(QString color READ color WRITE setColor NOTIFY colorChanged)
Q_PROPERTY(bool noColor READ noColor WRITE setNoColor)
public:
ColorButton(QWidget *parent = 0) : QToolButton (parent), m_colorString("#ffffff")
ColorButton(QWidget *parent = 0) : QToolButton (parent), m_colorString("#ffffff"), m_noColor(false)
{
}
......@@ -73,6 +76,9 @@ public:
return m_colorString;
}
bool noColor() const { return m_noColor; }
void setNoColor(bool f) { m_noColor = f; update(); }
signals:
void colorChanged();
......@@ -80,6 +86,7 @@ protected:
void paintEvent(QPaintEvent *event);
private:
QString m_colorString;
bool m_noColor;
};
inline QString properName(const QColor &color)
......@@ -342,10 +349,106 @@ private:
QPixmap m_cache;
};
class GradientLine : public QWidget {
Q_OBJECT
Q_PROPERTY(QColor activeColor READ activeColor WRITE setActiveColor NOTIFY activeColorChanged)
Q_PROPERTY(QVariant itemNode READ itemNode WRITE setItemNode NOTIFY itemNodeChanged)
Q_PROPERTY(QString gradientName READ gradientName WRITE setGradientName NOTIFY gradientNameChanged)
Q_PROPERTY(bool active READ active WRITE setActive)
public:
GradientLine(QWidget *parent = 0) : QWidget(parent), m_gradientName("gradient"), m_activeColor(Qt::black), m_dragActive(false), m_yOffset(0), m_create(false), m_active(false)
{
setSizePolicy(QSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed));
setFocusPolicy(Qt::StrongFocus);
setFixedHeight(50);
setMinimumWidth(160);
resize(160, 50);
m_colorList << m_activeColor << QColor(Qt::white);
m_stops << 0 << 1;
updateGradient();
setCurrentIndex(0);
}
QVariant itemNode() const { return QVariant::fromValue(m_itemNode.modelNode()); }
void setItemNode(const QVariant &itemNode);
QString gradientName() const { return m_gradientName; }
void setGradientName(const QString &newName)
{
if (newName == m_gradientName)
return;
m_gradientName = newName;
setup();
emit gradientNameChanged();
}
QColor activeColor() const { return m_activeColor; }
void setActiveColor(const QColor &newColor)
{
if (newColor.name() == m_activeColor.name() && newColor.alpha() == m_activeColor.alpha())
return;
m_activeColor = newColor;
m_colorList.removeAt(currentColorIndex());
m_colorList.insert(currentColorIndex(), m_activeColor);
updateGradient();
update();
}
bool active() const { return m_active; }
void setActive(bool a) { m_active = a; }
public slots:
void setupGradient();
signals:
void activeColorChanged();
void itemNodeChanged();
void gradientNameChanged();
protected:
bool GradientLine::event(QEvent *event);
void keyPressEvent(QKeyEvent * event);
void paintEvent(QPaintEvent *event);
void mousePressEvent(QMouseEvent *);
void mouseReleaseEvent(QMouseEvent *);
void mouseMoveEvent(QMouseEvent *);
private:
void setup();
void updateGradient();
int currentColorIndex() const { return m_colorIndex; }
void setCurrentIndex(int i)
{
if (i == m_colorIndex)
return;
m_colorIndex = i;
setActiveColor(m_colorList.at(i));
emit activeColorChanged();
update();
}
QColor m_activeColor;
QmlItemNode m_itemNode;
QString m_gradientName;
QList<QColor> m_colorList;
QList<qreal> m_stops;
int m_colorIndex;
bool m_dragActive;
QPoint m_dragStart;
int m_yOffset;
bool m_create;
bool m_active;
};
class ColorWidget {
public:
static void registerDeclarativeTypes();
};
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment