Masterwork From Distant Lands
ActivePublic

Authored by dkazakov on Jan 26 2017, 7:23 AM.
diff --git a/libs/flake/KoSelection.cpp b/libs/flake/KoSelection.cpp
index 81f1ce4..8bb71ff 100644
--- a/libs/flake/KoSelection.cpp
+++ b/libs/flake/KoSelection.cpp
@@ -181,13 +181,24 @@ const QList<KoShape*> KoSelection::selectedShapes() const
return d->selectedShapes;
}
+#include <functional>
+
+template <class C>
+ void filterContainer1(C &container, std::function<bool(typename C::value_type)> keepIf) {
+
+ auto newEnd = std::remove_if(container.begin(), container.end(), std::unary_negate<decltype(keepIf)>(keepIf));
+ while (newEnd != container.end()) {
+ newEnd = container.erase(newEnd);
+ }
+}
+
const QList<KoShape *> KoSelection::selectedEditableShapes() const
{
Q_D(const KoSelection);
QList<KoShape*> shapes = selectedShapes();
- KritaUtils::filterContainer (shapes, [](KoShape *shape) {
+ filterContainer1 (shapes, [](KoShape *shape) {
return shape->isEditable();
});
diff --git a/libs/pigment/resources/KoStopGradient.cpp b/libs/pigment/resources/KoStopGradient.cpp
index d006769..37644b5 100644
--- a/libs/pigment/resources/KoStopGradient.cpp
+++ b/libs/pigment/resources/KoStopGradient.cpp
@@ -205,7 +205,7 @@ void KoStopGradient::colorAt(KoColor& dst, qreal t) const
}
}
-KoStopGradient * KoStopGradient::fromQGradient(QGradient * gradient)
+KoStopGradient * KoStopGradient::fromQGradient(const QGradient * gradient)
{
if (! gradient)
return 0;
@@ -216,21 +216,21 @@ KoStopGradient * KoStopGradient::fromQGradient(QGradient * gradient)
switch (gradient->type()) {
case QGradient::LinearGradient: {
- QLinearGradient * g = static_cast<QLinearGradient*>(gradient);
+ const QLinearGradient * g = static_cast<const QLinearGradient*>(gradient);
newGradient->m_start = g->start();
newGradient->m_stop = g->finalStop();
newGradient->m_focalPoint = g->start();
break;
}
case QGradient::RadialGradient: {
- QRadialGradient * g = static_cast<QRadialGradient*>(gradient);
+ const QRadialGradient * g = static_cast<const QRadialGradient*>(gradient);
newGradient->m_start = g->center();
newGradient->m_stop = g->center() + QPointF(g->radius(), 0);
newGradient->m_focalPoint = g->focalPoint();
break;
}
case QGradient::ConicalGradient: {
- QConicalGradient * g = static_cast<QConicalGradient*>(gradient);
+ const QConicalGradient * g = static_cast<const QConicalGradient*>(gradient);
qreal radian = g->angle() * M_PI / 180.0;
newGradient->m_start = g->center();
newGradient->m_stop = QPointF(100.0 * cos(radian), 100.0 * sin(radian));
@@ -639,6 +639,11 @@ QString KoStopGradient::defaultFileExtension() const
return QString(".svg");
}
+bool KoStopGradient::stopLessThan(const KoGradientStop &a, const KoGradientStop &b)
+{
+ return a.first - b.first < -0.001;
+}
+
bool KoStopGradient::saveToDevice(QIODevice *dev) const
{
QTextStream stream(dev);
diff --git a/libs/pigment/resources/KoStopGradient.h b/libs/pigment/resources/KoStopGradient.h
index 609235f..7b1b764 100644
--- a/libs/pigment/resources/KoStopGradient.h
+++ b/libs/pigment/resources/KoStopGradient.h
@@ -26,7 +26,6 @@
#include <resources/KoResource.h>
#include <kritapigment_export.h>
-
typedef QPair<qreal, KoColor> KoGradientStop;
/**
@@ -53,7 +52,7 @@ public:
void colorAt(KoColor&, qreal t) const;
/// Creates KoStopGradient from a QGradient
- static KoStopGradient * fromQGradient(QGradient * gradient);
+ static KoStopGradient * fromQGradient(const QGradient * gradient);
/// Sets the gradient stops
void setStops(QList<KoGradientStop> stops);
@@ -62,6 +61,8 @@ public:
/// reimplemented
QString defaultFileExtension() const;
+ static bool stopLessThan(const KoGradientStop &a, const KoGradientStop &b);
+
protected:
QList<KoGradientStop> m_stops;
diff --git a/libs/ui/KisNodeDelegate.cpp b/libs/ui/KisNodeDelegate.cpp
index 4f71bcd..42cfd32 100644
--- a/libs/ui/KisNodeDelegate.cpp
+++ b/libs/ui/KisNodeDelegate.cpp
@@ -66,7 +66,7 @@ public:
void KisNodeDelegate::slotOnCloseEditor()
{
- KisPart::currentInputManager()->slotFocusOnEnter(true);
+ KisPart::instance()->currentInputManager()->slotFocusOnEnter(true);
}
KisNodeDelegate::KisNodeDelegate(KisNodeView *view, QObject *parent)
@@ -733,7 +733,7 @@ bool KisNodeDelegate::editorEvent(QEvent *event, QAbstractItemModel *model, cons
QWidget *KisNodeDelegate::createEditor(QWidget *parent, const QStyleOptionViewItem&, const QModelIndex&) const
{
- KisPart::currentInputManager()->slotFocusOnEnter(false);
+ KisPart::instance()->currentInputManager()->slotFocusOnEnter(false);
d->edit = new QLineEdit(parent);
d->edit->installEventFilter(const_cast<KisNodeDelegate*>(this)); //hack?
return d->edit;
diff --git a/libs/ui/KisPart.cpp b/libs/ui/KisPart.cpp
index 7e5b904..5f2d9a2 100644
--- a/libs/ui/KisPart.cpp
+++ b/libs/ui/KisPart.cpp
@@ -476,6 +476,8 @@ void KisPart::startCustomDocument(KisDocument* doc)
KisInputManager* KisPart::currentInputManager()
{
- return instance()->currentMainwindow()->viewManager()->inputManager();
+ KisMainWindow *mw = currentMainwindow();
+ KisViewManager *manager = mw ? mw->viewManager() : 0;
+ return manager ? manager->inputManager() : 0;
}
diff --git a/libs/ui/KisPart.h b/libs/ui/KisPart.h
index b089168..5569a58 100644
--- a/libs/ui/KisPart.h
+++ b/libs/ui/KisPart.h
@@ -189,7 +189,7 @@ Q_SIGNALS:
public:
- static KisInputManager *currentInputManager();
+ KisInputManager *currentInputManager();
//------------------ View management ------------------
diff --git a/libs/ui/forms/wdgstopgradienteditor.ui b/libs/ui/forms/wdgstopgradienteditor.ui
index 5dc6ea2..8d3a05d 100644
--- a/libs/ui/forms/wdgstopgradienteditor.ui
+++ b/libs/ui/forms/wdgstopgradienteditor.ui
@@ -2,25 +2,11 @@
<ui version="4.0">
<class>KisWdgStopGradientEditor</class>
<widget class="QWidget" name="KisWdgStopGradientEditor">
- <property name="geometry">
- <rect>
- <x>0</x>
- <y>0</y>
- <width>500</width>
- <height>250</height>
- </rect>
- </property>
- <property name="minimumSize">
- <size>
- <width>500</width>
- <height>250</height>
- </size>
- </property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
- <widget class="QLabel" name="label">
+ <widget class="QLabel" name="lblName">
<property name="text">
<string>Name:</string>
</property>
@@ -52,21 +38,15 @@
</widget>
</item>
<item>
- <layout class="QGridLayout" name="gridLayout">
- <item row="0" column="0">
+ <layout class="QHBoxLayout" name="horizontalLayout_2">
+ <item>
<widget class="KisColorButton" name="colorButton">
<property name="sizePolicy">
- <sizepolicy hsizetype="MinimumExpanding" vsizetype="Preferred">
+ <sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
- <property name="minimumSize">
- <size>
- <width>0</width>
- <height>30</height>
- </size>
- </property>
<property name="font">
<font>
<family>Sans Serif</family>
@@ -83,15 +63,28 @@
</property>
</widget>
</item>
+ <item>
+ <widget class="KisDoubleSliderSpinBox" name="opacitySlider" native="true">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="MinimumExpanding" vsizetype="Preferred">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ </widget>
+ </item>
</layout>
</item>
- <item>
- <widget class="KisDoubleSliderSpinBox" name="opacitySlider" native="true"/>
- </item>
</layout>
</widget>
<customwidgets>
<customwidget>
+ <class>KisDoubleSliderSpinBox</class>
+ <extends>QWidget</extends>
+ <header location="global">kis_slider_spin_box.h</header>
+ <container>1</container>
+ </customwidget>
+ <customwidget>
<class>KisColorButton</class>
<extends>QPushButton</extends>
<header>kis_color_button.h</header>
@@ -102,12 +95,6 @@
<header>kis_stopgradient_slider_widget.h</header>
<container>1</container>
</customwidget>
- <customwidget>
- <class>KisDoubleSliderSpinBox</class>
- <extends>QWidget</extends>
- <header>kis_slider_spin_box.h</header>
- <container>1</container>
- </customwidget>
</customwidgets>
<resources/>
<connections/>
diff --git a/libs/ui/kis_stopgradient_editor.cpp b/libs/ui/kis_stopgradient_editor.cpp
index 9c33bf1..91b5dc5 100644
--- a/libs/ui/kis_stopgradient_editor.cpp
+++ b/libs/ui/kis_stopgradient_editor.cpp
@@ -27,34 +27,44 @@
#include "kis_debug.h"
-#include "widgets/kis_gradient_slider_widget.h"
#include <kis_icon_utils.h>
/****************************** KisStopGradientEditor ******************************/
-KisStopGradientEditor::KisStopGradientEditor(KoStopGradient* gradient, QWidget *parent, const char* name, const QString& caption)
- : QWidget(parent), m_gradient(gradient)
+KisStopGradientEditor::KisStopGradientEditor(QWidget *parent)
+ : QWidget(parent),
+ m_gradient(0)
{
- setObjectName(name);
setupUi(this);
- setWindowTitle(caption);
-
- connect(gradientSlider, SIGNAL(sigSelectedStop(int)), this, SLOT(stopChanged(int)));
- gradientSlider->setGradientResource(m_gradient);
- nameedit->setText(gradient->name());
+ connect(gradientSlider, SIGNAL(sigSelectedStop(int)), this, SLOT(stopChanged(int)));
connect(nameedit, SIGNAL(editingFinished()), this, SLOT(nameChanged()));
-
connect(colorButton, SIGNAL(changed(const KoColor&)), SLOT(colorChanged(const KoColor&)));
-
+
opacitySlider->setRange(0.0, 1.0, 2);
connect(opacitySlider, SIGNAL(valueChanged(qreal)), this, SLOT(opacityChanged(qreal)));
-
+
+
+
buttonReverse->setIcon(KisIconUtils::loadIcon("mirrorAxis-HorizontalMove"));
KisIconUtils::updateIcon(buttonReverse);
connect(buttonReverse, SIGNAL(pressed()), this, SLOT(reverse()));
-
- stopChanged(gradientSlider->selectedStop());
+
+
+ lblName->setVisible(false);
+ buttonReverse->setVisible(false);
+ nameedit->setVisible(false);
+
+ setGradient(0);
+}
+
+KisStopGradientEditor::KisStopGradientEditor(KoStopGradient* gradient, QWidget *parent, const char* name, const QString& caption)
+ : KisStopGradientEditor(parent)
+{
+ setObjectName(name);
+ setWindowTitle(caption);
+
+ setGradient(gradient);
}
void KisStopGradientEditor::activate()
@@ -62,6 +72,18 @@ void KisStopGradientEditor::activate()
paramChanged();
}
+void KisStopGradientEditor::setGradient(KoStopGradient *gradient)
+{
+ m_gradient = gradient;
+ setEnabled(m_gradient);
+
+ if (m_gradient) {
+ gradientSlider->setGradientResource(m_gradient);
+ nameedit->setText(gradient->name());
+ stopChanged(gradientSlider->selectedStop());
+ }
+}
+
void KisStopGradientEditor::stopChanged(int stop)
{
KoColor color = m_gradient->stops()[stop].second;
@@ -125,12 +147,11 @@ void KisStopGradientEditor::reverse()
{
QList<KoGradientStop> stops = m_gradient->stops();
QList<KoGradientStop> reversedStops;
- for(const KoGradientStop& stop : stops)
- {
+ for(const KoGradientStop& stop : stops) {
reversedStops.push_front(KoGradientStop(1 - stop.first, stop.second));
}
m_gradient->setStops(reversedStops);
- gradientSlider->setSeletectStop(stops.size()-1 -gradientSlider->selectedStop());
+ gradientSlider->setSeletectStop(stops.size() - 1 - gradientSlider->selectedStop());
paramChanged();
}
diff --git a/libs/ui/kis_stopgradient_editor.h b/libs/ui/kis_stopgradient_editor.h
index c3017ca..275ace6 100644
--- a/libs/ui/kis_stopgradient_editor.h
+++ b/libs/ui/kis_stopgradient_editor.h
@@ -20,17 +20,25 @@
#ifndef _KIS_STOPGRADIENT_EDITOR_H_
#define _KIS_STOPGRADIENT_EDITOR_H_
+#include "kritaui_export.h"
#include "ui_wdgstopgradienteditor.h"
class KoStopGradient;
-class KisStopGradientEditor : public QWidget, public Ui::KisWdgStopGradientEditor
+class KRITAUI_EXPORT KisStopGradientEditor : public QWidget, public Ui::KisWdgStopGradientEditor
{
Q_OBJECT
public:
+ KisStopGradientEditor(QWidget *parent);
KisStopGradientEditor(KoStopGradient* gradient, QWidget *parent, const char* name, const QString& caption);
void activate();
+
+ void setGradient(KoStopGradient* gradient);
+
+public Q_SLOTS:
+ void reverse();
+
private:
KoStopGradient* m_gradient;
private Q_SLOTS:
@@ -38,7 +46,7 @@ private Q_SLOTS:
void colorChanged(const KoColor& color);
void opacityChanged(qreal value);
void nameChanged();
- void reverse();
+
void paramChanged();
};
diff --git a/libs/ui/tests/CMakeLists.txt b/libs/ui/tests/CMakeLists.txt
index 828205e..7d110b2 100644
--- a/libs/ui/tests/CMakeLists.txt
+++ b/libs/ui/tests/CMakeLists.txt
@@ -20,6 +20,7 @@ ecm_add_tests(
kis_derived_resources_test.cpp
kis_brush_hud_properties_config_test.cpp
kis_shape_commands_test.cpp
+ kis_stop_gradient_editor_test.cpp
NAME_PREFIX "krita-ui-"
LINK_LIBRARIES kritaui Qt5::Test
)
diff --git a/libs/ui/tests/kis_stop_gradient_editor_test.cpp b/libs/ui/tests/kis_stop_gradient_editor_test.cpp
new file mode 100644
index 0000000..3e36583
--- /dev/null
+++ b/libs/ui/tests/kis_stop_gradient_editor_test.cpp
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2016 Dmitry Kazakov <dimula73@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#include "kis_stop_gradient_editor_test.h"
+
+#include <QTest>
+#include <QDialog>
+#include <QVBoxLayout>
+#include <QLinearGradient>
+
+#include "kis_debug.h"
+#include "kis_stopgradient_editor.h"
+
+
+void KisStopGradientEditorTest::test()
+{
+ QLinearGradient gradient;
+ QScopedPointer<KoStopGradient> koGradient(KoStopGradient::fromQGradient(&gradient));
+ QDialog dlg;
+
+ KisStopGradientEditor *widget = new KisStopGradientEditor(&dlg);
+ widget->setGradient(koGradient.data());
+
+ QVBoxLayout *layout = new QVBoxLayout(&dlg);
+ layout->setContentsMargins(0,0,0,0);
+
+ layout->addWidget(widget);
+ dlg.setLayout(layout);
+ dlg.setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum);
+
+ dlg.exec();
+ //qWarning() << "WARNING: showing of the dialogs in the unittest is disabled!";
+}
+
+QTEST_MAIN(KisStopGradientEditorTest)
diff --git a/libs/ui/tests/kis_stop_gradient_editor_test.h b/libs/ui/tests/kis_stop_gradient_editor_test.h
new file mode 100644
index 0000000..b3f2ba7
--- /dev/null
+++ b/libs/ui/tests/kis_stop_gradient_editor_test.h
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2016 Dmitry Kazakov <dimula73@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#ifndef __KIS_STOP_GRADIENT_EDITOR_TEST_H
+#define __KIS_STOP_GRADIENT_EDITOR_TEST_H
+
+#include <QtTest/QtTest>
+
+class KisStopGradientEditorTest : public QObject
+{
+ Q_OBJECT
+private Q_SLOTS:
+
+ void test();
+};
+
+#endif /* __KIS_STOP_GRADIENT_EDITOR_TEST_H */
diff --git a/libs/ui/widgets/kis_slider_spin_box.cpp b/libs/ui/widgets/kis_slider_spin_box.cpp
index 5c9fb9e..f2d8794 100644
--- a/libs/ui/widgets/kis_slider_spin_box.cpp
+++ b/libs/ui/widgets/kis_slider_spin_box.cpp
@@ -142,7 +142,11 @@ void KisAbstractSliderSpinBox::showEdit()
d->edit->show();
d->edit->setFocus(Qt::OtherFocusReason);
update();
- KisPart::currentInputManager()->slotFocusOnEnter(false);
+
+ KisInputManager *inputManager = KisPart::instance()->currentInputManager();
+ if (inputManager) {
+ inputManager->slotFocusOnEnter(false);
+ }
}
void KisAbstractSliderSpinBox::hideEdit()
@@ -150,7 +154,11 @@ void KisAbstractSliderSpinBox::hideEdit()
Q_D(KisAbstractSliderSpinBox);
d->edit->hide();
update();
- KisPart::currentInputManager()->slotFocusOnEnter(true);
+
+ KisInputManager *inputManager = KisPart::instance()->currentInputManager();
+ if (inputManager) {
+ inputManager->slotFocusOnEnter(true);
+ }
}
void KisAbstractSliderSpinBox::paintEvent(QPaintEvent* e)
diff --git a/libs/ui/widgets/kis_stopgradient_slider_widget.cpp b/libs/ui/widgets/kis_stopgradient_slider_widget.cpp
index 2fef835..9b2fc9d 100644
--- a/libs/ui/widgets/kis_stopgradient_slider_widget.cpp
+++ b/libs/ui/widgets/kis_stopgradient_slider_widget.cpp
@@ -23,21 +23,31 @@
#include <QMouseEvent>
#include <QPolygon>
#include <QPaintEvent>
+#include <QFontMetrics>
+
+#include "kis_global.h"
+#include "kis_debug.h"
#define MARGIN 10
-#define HANDLE_SIZE 20
KisStopGradientSliderWidget::KisStopGradientSliderWidget(QWidget *parent, Qt::WFlags f)
: QWidget(parent, f)
, m_selectedStop(0)
, m_drag(0)
+ , m_handleSize(13, 20)
{
- setMinimumHeight(30);
+ QLinearGradient defaultGradient;
+ m_defaultGradient.reset(KoStopGradient::fromQGradient(&defaultGradient));
+
+ setGradientResource(0);
+ setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred);
+
+ setMouseTracking(true);
}
void KisStopGradientSliderWidget::setGradientResource(KoStopGradient* gradient)
{
- m_gradient = gradient;
+ m_gradient = gradient ? gradient : m_defaultGradient.data();
emit sigSelectedStop(m_selectedStop);
}
@@ -48,9 +58,9 @@ void KisStopGradientSliderWidget::paintEvent(QPaintEvent* pe)
QPainter painter(this);
painter.fillRect(rect(), palette().background());
painter.setPen(Qt::black);
- painter.drawRect(MARGIN, MARGIN, width() - 2 * MARGIN, height() - 2 * MARGIN - HANDLE_SIZE);
+ painter.drawRect(MARGIN, MARGIN, width() - 2 * MARGIN, height() - 2 * MARGIN - m_handleSize.height());
if (m_gradient) {
- QImage image = m_gradient->generatePreview(width() - 2 * MARGIN - 2, height() - 2 * MARGIN - HANDLE_SIZE - 2);
+ QImage image = m_gradient->generatePreview(width() - 2 * MARGIN - 2, height() - 2 * MARGIN - m_handleSize.height() - 2);
QPixmap pixmap(image.width(), image.height());
if (!image.isNull()) {
painter.drawImage(MARGIN + 1, MARGIN + 1, image);
@@ -61,9 +71,9 @@ void KisStopGradientSliderWidget::paintEvent(QPaintEvent* pe)
int position;
for (int i = 0; i < handlePositions.count(); i++) {
position = qRound(handlePositions[i].first * (double)(width() - 2*MARGIN)) + MARGIN;
- triangle[0] = QPoint(position, height() - HANDLE_SIZE - MARGIN);
- triangle[1] = QPoint(position + (HANDLE_SIZE / 2 - 1), height() - MARGIN);
- triangle[2] = QPoint(position - (HANDLE_SIZE / 2 - 1), height() - MARGIN);
+ triangle[0] = QPoint(position, height() - m_handleSize.height() - MARGIN);
+ triangle[1] = QPoint(position + (m_handleSize.width() / 2 - 1), height() - MARGIN);
+ triangle[2] = QPoint(position - (m_handleSize.width() / 2 - 1), height() - MARGIN);
if(i != m_selectedStop)
painter.setPen(QPen(Qt::black, 2.0));
@@ -74,101 +84,189 @@ void KisStopGradientSliderWidget::paintEvent(QPaintEvent* pe)
painter.drawPolygon(triangle);
}
}
+
+ painter.setPen(Qt::NoPen);
+ painter.setOpacity(0.5);
+ painter.fillRect(sliderRect(), QColor(Qt::blue));
+ painter.fillRect(handlesStipeRect(), QColor(Qt::red));
+}
+
+int findNearestHandle(qreal t, const qreal tolerance, const QList<KoGradientStop> &stops)
+{
+ int result = -1;
+ qreal minDistance = tolerance;
+
+ for (int i = 0; i < stops.size(); i++) {
+ const KoGradientStop &stop = stops[i];
+
+ const qreal distance = qAbs(t - stop.first);
+ if (distance < minDistance) {
+ minDistance = distance;
+ result = i;
+ }
+ }
+
+ return result;
}
+
void KisStopGradientSliderWidget::mousePressEvent(QMouseEvent * e)
{
- if (e->x() < MARGIN || e->x() > width() - MARGIN) {
+ if (!allowedClickRegion(qRound(0.5 * m_handleSize.width())).contains(e->pos())) {
QWidget::mousePressEvent(e);
return;
}
- double t = (double)(e->x() - MARGIN) / (double)(width() - 2 * MARGIN);
- if(e->y() < height() - HANDLE_SIZE - MARGIN) {
- if(e->button() == Qt::LeftButton)
- insertStop(t);
- }
- else {
- QPolygon triangle(3);
- QList<KoGradientStop> stops = m_gradient->stops();
- int position;
- for (int i = 0; i < stops.count(); i++) {
- position = qRound(stops[i].first * (double)(width() - 2*MARGIN)) + MARGIN;
- triangle[0] = QPoint(position, height() - HANDLE_SIZE - MARGIN);
- triangle[1] = QPoint(position + (HANDLE_SIZE / 2 - 1), height() - MARGIN);
- triangle[2] = QPoint(position - (HANDLE_SIZE / 2 - 1), height() - MARGIN);
-
- if(triangle.containsPoint(e->pos(), Qt::WindingFill))
- {
- if(e->button() == Qt::LeftButton) {
- m_selectedStop = i;
- emit sigSelectedStop(m_selectedStop);
- if(m_selectedStop > 0 && m_selectedStop < stops.size()-1)
- m_drag = true;
- }
- else if (e->button() == Qt::RightButton && (i > 0 && i < stops.size()-1)) {
- QList<KoGradientStop> stops = m_gradient->stops();
- stops.removeAt(i);
- m_gradient->setStops(stops);
- if(m_selectedStop == i)
- m_selectedStop = i-1;
- else if (m_selectedStop > i)
- m_selectedStop--;
- }
- break;
- }
+ const QRect handlesRect = this->handlesStipeRect();
+ const qreal t = (qreal(e->x()) - handlesRect.x()) / handlesRect.width();
+ const QList<KoGradientStop> stops = m_gradient->stops();
+
+ const int clickedStop = findNearestHandle(t, 0.5 * m_handleSize.width() / handlesRect.width(), stops);
+
+ if (clickedStop >= 0) {
+ if (m_selectedStop != clickedStop) {
+ m_selectedStop = clickedStop;
+ emit sigSelectedStop(m_selectedStop);
}
+ m_drag = true;
+ } else {
+ insertStop(qBound(0.0, t, 1.0));
+ m_drag = true;
}
+
update();
+ updateCursor(e->pos());
}
void KisStopGradientSliderWidget::mouseReleaseEvent(QMouseEvent * e)
{
Q_UNUSED(e);
m_drag = false;
+ updateCursor(e->pos());
}
-void KisStopGradientSliderWidget::mouseMoveEvent(QMouseEvent * e)
+int getNewInsertPosition(const KoGradientStop &stop, const QList<KoGradientStop> &stops)
{
- if ((e->y() < MARGIN || e->y() > height() - MARGIN) || (e->x() < MARGIN || e->x() > width() - MARGIN)) {
- QWidget::mouseMoveEvent(e);
- return;
+ int result = 0;
+
+ for (int i = 0; i < stops.size(); i++) {
+ if (stop.first <= stops[i].first) break;
+
+ result = i + 1;
}
- double t = (double)(e->x() - MARGIN) / (double)(width() - 2 * MARGIN);
+ return result;
+}
+
+void KisStopGradientSliderWidget::mouseMoveEvent(QMouseEvent * e)
+{
+ updateCursor(e->pos());
+
if (m_drag) {
- QList<KoGradientStop> stops = m_gradient->stops();
+ const QRect handlesRect = this->handlesStipeRect();
+ double t = (qreal(e->x()) - handlesRect.x()) / handlesRect.width();
- KoGradientStop dragedStop = stops[m_selectedStop];
+ QList<KoGradientStop> stops = m_gradient->stops();
- t = qBound(stops[m_selectedStop-1].first, t, stops[m_selectedStop+1].first);
- dragedStop.first = t;
+ if (t < -0.1 || t > 1.1) {
+ if (stops.size() > 2 && m_selectedStop >= 0) {
+ m_removedStop = stops[m_selectedStop];
+ stops.removeAt(m_selectedStop);
+ m_selectedStop = -1;
+ }
+ } else {
+ if (m_selectedStop < 0) {
+ m_removedStop.first = qBound(0.0, t, 1.0);
+ const int newPos = getNewInsertPosition(m_removedStop, stops);
+ stops.insert(newPos, m_removedStop);
+ m_selectedStop = newPos;
+ } else {
+ KoGradientStop draggedStop = stops[m_selectedStop];
+ draggedStop.first = qBound(0.0, t, 1.0);
- stops.removeAt(m_selectedStop);
- stops.insert(m_selectedStop, dragedStop);
+ stops.removeAt(m_selectedStop);
+ const int newPos = getNewInsertPosition(draggedStop, stops);
+ stops.insert(newPos, draggedStop);
+ m_selectedStop = newPos;
+ }
+ }
m_gradient->setStops(stops);
+ update();
+
+ } else {
+ QWidget::mouseMoveEvent(e);
}
- update();
+
+}
+
+void KisStopGradientSliderWidget::updateCursor(const QPoint &pos)
+{
+ const bool isInAllowedRegion =
+ allowedClickRegion(qRound(0.5 * m_handleSize.width())).contains(pos);
+
+ QCursor currentCursor;
+
+ if (isInAllowedRegion) {
+ const QRect handlesRect = this->handlesStipeRect();
+ const qreal t = (qreal(pos.x()) - handlesRect.x()) / handlesRect.width();
+ const QList<KoGradientStop> stops = m_gradient->stops();
+
+ const int clickedStop = findNearestHandle(t, 0.5 * m_handleSize.width() / handlesRect.width(), stops);
+
+ if (clickedStop >= 0) {
+ currentCursor = m_drag ? Qt::ClosedHandCursor : Qt::OpenHandCursor;
+ }
+ }
+
+ if (currentCursor.shape() != Qt::ArrowCursor) {
+ setCursor(currentCursor);
+ } else {
+ unsetCursor();
+ }
}
void KisStopGradientSliderWidget::insertStop(double t)
{
- QList<KoGradientStop> stopPositions = m_gradient->stops();
- int i = 0;
- while(stopPositions[i].first < t)
- i++;
+ KIS_ASSERT_RECOVER(t >= 0 && t <= 1.0 ) {
+ t = qBound(0.0, t, 1.0);
+ }
+
+ QList<KoGradientStop> stops = m_gradient->stops();
KoColor color;
m_gradient->colorAt(color, t);
- stopPositions.insert(i, KoGradientStop(t, color));
- m_gradient->setStops(stopPositions);
- m_selectedStop = i;
+ const KoGradientStop stop(t, color);
+ const int newPos = getNewInsertPosition(stop, stops);
+
+ stops.insert(newPos, stop);
+ m_gradient->setStops(stops);
+
+ m_selectedStop = newPos;
emit sigSelectedStop(m_selectedStop);
}
+QRect KisStopGradientSliderWidget::sliderRect() const
+{
+ return kisGrowRect(QRect(QPoint(), size()), -MARGIN);
+}
+
+QRect KisStopGradientSliderWidget::handlesStipeRect() const
+{
+ const QRect rc = sliderRect();
+ return rc.adjusted(0, rc.height() - m_handleSize.height(), 0, 0);
+}
+
+QRegion KisStopGradientSliderWidget::allowedClickRegion(int tolerance) const
+{
+ QRegion result;
+ result += sliderRect();
+ result += handlesStipeRect().adjusted(-tolerance, 0, tolerance, 0);
+ return result;
+}
+
int KisStopGradientSliderWidget::selectedStop()
{
return m_selectedStop;
@@ -180,5 +278,19 @@ void KisStopGradientSliderWidget::setSeletectStop(int selected)
emit sigSelectedStop(m_selectedStop);
}
+QSize KisStopGradientSliderWidget::sizeHint() const
+{
+ QFontMetrics fm(font());
+ const int h = fm.height();
+ return QSize(10 * h, 8 * h);
+}
+
+QSize KisStopGradientSliderWidget::minimumSizeHint() const
+{
+ QFontMetrics fm(font());
+ const int h = fm.height();
+ return QSize(5 * h, 5 * h);
+}
+
diff --git a/libs/ui/widgets/kis_stopgradient_slider_widget.h b/libs/ui/widgets/kis_stopgradient_slider_widget.h
index d213295..637b40c 100644
--- a/libs/ui/widgets/kis_stopgradient_slider_widget.h
+++ b/libs/ui/widgets/kis_stopgradient_slider_widget.h
@@ -23,6 +23,7 @@
#include <QWidget>
#include <QMouseEvent>
#include <QPaintEvent>
+#include <QScopedPointer>
#include <resources/KoStopGradient.h>
@@ -41,6 +42,9 @@ public:
void setSeletectStop(int selected);
+ QSize sizeHint() const override;
+ QSize minimumSizeHint() const override;
+
Q_SIGNALS:
void sigSelectedStop(int stop);
@@ -54,10 +58,20 @@ private Q_SLOTS:
private:
void insertStop(double t);
+ QRect sliderRect() const;
+ QRect handlesStipeRect() const;
+ QRegion allowedClickRegion(int tolerance) const;
+
+ void updateCursor(const QPoint &pos);
+
private:
+ QScopedPointer<KoStopGradient> m_defaultGradient;
KoStopGradient* m_gradient;
int m_selectedStop;
+ KoGradientStop m_removedStop;
+ QList<KoGradientStop> m_unsortedStops;
bool m_drag;
+ QSize m_handleSize;
};
#endif
diff --git a/plugins/tools/defaulttool/defaulttool/KoFillConfigWidget.cpp b/plugins/tools/defaulttool/defaulttool/KoFillConfigWidget.cpp
index 1a0bbb0..d2db6e0 100644
--- a/plugins/tools/defaulttool/defaulttool/KoFillConfigWidget.cpp
+++ b/plugins/tools/defaulttool/defaulttool/KoFillConfigWidget.cpp
@@ -280,14 +280,26 @@ KoFillConfigWidget::KoFillConfigWidget(QWidget *parent)
slotUpdateFillTitle();
styleButtonPressed(d->group->checkedId());
-#if 0
// Gradient selector
KoResourceServerProvider *serverProvider = KoResourceServerProvider::instance();
- QSharedPointer<KoAbstractResourceServerAdapter> gradientResourceAdapter(new KoResourceServerAdapter<KoAbstractGradient>(serverProvider->gradientServer()));
- d->gradientAction = new KoResourcePopupAction(gradientResourceAdapter, d->colorButton);
- d->gradientAction->setToolTip(i18n("Change the filling gradient"));
- connect(d->gradientAction, SIGNAL(resourceSelected(QSharedPointer<KoShapeBackground> )), this, SLOT(gradientChanged(QSharedPointer<KoShapeBackground> )));
- connect(d->colorButton, SIGNAL(iconSizeChanged()), d->gradientAction, SLOT(updateIcon()));
+ QSharedPointer<KoAbstractResourceServerAdapter> gradientResourceAdapter(
+ new KoResourceServerAdapter<KoAbstractGradient>(serverProvider->gradientServer()));
+
+ d->gradientAction = new KoResourcePopupAction(gradientResourceAdapter,
+ d->ui->btnChoosePredefinedGradient);
+
+ d->gradientAction->setToolTip(i18n("Change filling gradient"));
+ d->ui->btnChoosePredefinedGradient->setDefaultAction(d->gradientAction);
+ d->ui->btnChoosePredefinedGradient->setPopupMode(QToolButton::InstantPopup);
+
+ connect(d->gradientAction, SIGNAL(resourceSelected(QSharedPointer<KoShapeBackground> )),
+ SLOT(gradientChanged(QSharedPointer<KoShapeBackground> )));
+ connect(d->ui->btnChoosePredefinedGradient, SIGNAL(iconSizeChanged()), d->gradientAction, SLOT(updateIcon()));
+
+ d->ui->btnSaveGradient->setIcon(KisIconUtils::loadIcon("document-save"));
+ connect(d->ui->btnSaveGradient, SIGNAL(clicked()), SLOT(slotSavePredefinedGradientClicked()));
+
+#if 0
// Pattern selector
QSharedPointer<KoAbstractResourceServerAdapter>patternResourceAdapter(new KoResourceServerAdapter<KoPattern>(serverProvider->patternServer()));
@@ -392,8 +404,16 @@ void KoFillConfigWidget::colorChanged()
canvasController->canvas()->addCommand(cmd);
}
+void KoFillConfigWidget::slotSavePredefinedGradientClicked()
+{
+ ENTER_FUNCTION();
+}
+
+
void KoFillConfigWidget::gradientChanged(QSharedPointer<KoShapeBackground> background)
{
+ ENTER_FUNCTION() << ppVar(background);
+
Q_UNUSED(background);
#if 0
diff --git a/plugins/tools/defaulttool/defaulttool/KoFillConfigWidget.h b/plugins/tools/defaulttool/defaulttool/KoFillConfigWidget.h
index c635269..30fbae7 100644
--- a/plugins/tools/defaulttool/defaulttool/KoFillConfigWidget.h
+++ b/plugins/tools/defaulttool/defaulttool/KoFillConfigWidget.h
@@ -71,6 +71,8 @@ private Q_SLOTS:
void slotCanvasResourceChanged(int key, const QVariant &value);
+ void slotSavePredefinedGradientClicked();
+
private:
/// update the widget with the KoShape background
void updateWidget(KoShape *shape);
diff --git a/plugins/tools/defaulttool/defaulttool/KoFillConfigWidget.ui b/plugins/tools/defaulttool/defaulttool/KoFillConfigWidget.ui
index 458c8b4..16904fd 100644
--- a/plugins/tools/defaulttool/defaulttool/KoFillConfigWidget.ui
+++ b/plugins/tools/defaulttool/defaulttool/KoFillConfigWidget.ui
@@ -6,14 +6,14 @@
<rect>
<x>0</x>
<y>0</y>
- <width>350</width>
- <height>137</height>
+ <width>779</width>
+ <height>697</height>
</rect>
</property>
<property name="windowTitle">
<string>Form</string>
</property>
- <layout class="QVBoxLayout" name="verticalLayout_2">
+ <layout class="QVBoxLayout" name="verticalLayout_3">
<item>
<layout class="QHBoxLayout" name="horizontalLayout">
<property name="spacing">
@@ -151,7 +151,7 @@
<item>
<widget class="QStackedWidget" name="stackWidget">
<property name="currentIndex">
- <number>0</number>
+ <number>2</number>
</property>
<widget class="QWidget" name="pageNone"/>
<widget class="QWidget" name="pageSolid">
@@ -210,7 +210,135 @@
</item>
</layout>
</widget>
- <widget class="QWidget" name="pageGradient"/>
+ <widget class="QWidget" name="pageGradient">
+ <layout class="QVBoxLayout" name="verticalLayout_2">
+ <item>
+ <layout class="QFormLayout" name="formLayout">
+ <item row="0" column="0">
+ <widget class="QLabel" name="label">
+ <property name="text">
+ <string>Type:</string>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="1">
+ <widget class="QComboBox" name="comboBox">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Expanding" vsizetype="Fixed">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <item>
+ <property name="text">
+ <string>Linear</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>Radial</string>
+ </property>
+ </item>
+ </widget>
+ </item>
+ <item row="1" column="0">
+ <widget class="QLabel" name="label_2">
+ <property name="text">
+ <string>Repeat:</string>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="1">
+ <widget class="QComboBox" name="comboBox_2">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Expanding" vsizetype="Fixed">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <item>
+ <property name="text">
+ <string>None</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>Reflect</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>Repeat</string>
+ </property>
+ </item>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ <item>
+ <layout class="QHBoxLayout" name="horizontalLayout_3">
+ <item>
+ <widget class="KoColorPopupButton" name="btnChoosePredefinedGradient">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Expanding" vsizetype="Fixed">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>...</string>
+ </property>
+ <property name="popupMode">
+ <enum>QToolButton::InstantPopup</enum>
+ </property>
+ <property name="autoRaise">
+ <bool>true</bool>
+ </property>
+ <property name="arrowType">
+ <enum>Qt::NoArrow</enum>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QToolButton" name="btnSaveGradient">
+ <property name="text">
+ <string>...</string>
+ </property>
+ <property name="checkable">
+ <bool>false</bool>
+ </property>
+ <property name="autoRaise">
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ <item>
+ <widget class="QCheckBox" name="chkEditGradient">
+ <property name="text">
+ <string>Edit gradient</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="KisStopGradientEditor" name="wdgGradientEditor" native="true"/>
+ </item>
+ <item>
+ <spacer name="verticalSpacer_3">
+ <property name="orientation">
+ <enum>Qt::Vertical</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>20</width>
+ <height>1</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ </layout>
+ </widget>
<widget class="QWidget" name="pagePattern"/>
</widget>
</item>
@@ -235,6 +363,12 @@
<extends>QToolButton</extends>
<header>KoColorPopupButton.h</header>
</customwidget>
+ <customwidget>
+ <class>KisStopGradientEditor</class>
+ <extends>QWidget</extends>
+ <header>kis_stopgradient_editor.h</header>
+ <container>1</container>
+ </customwidget>
</customwidgets>
<resources/>
<connections/>
dkazakov edited the content of this paste. (Show Details)Jan 26 2017, 7:23 AM
dkazakov changed the title of this paste from untitled to Masterwork From Distant Lands.
dkazakov updated the paste's language from autodetect to autodetect.