diff --git a/libs/ui/widgets/KoFillConfigWidget.ui b/libs/ui/widgets/KoFillConfigWidget.ui
index c765d01692..60c0e838ff 100644
--- a/libs/ui/widgets/KoFillConfigWidget.ui
+++ b/libs/ui/widgets/KoFillConfigWidget.ui
@@ -1,353 +1,371 @@
KoFillConfigWidget
0
0
314
- 257
+ 251
0
0
-
0
-
0
0
No fill
None
true
true
true
-
0
0
Solid color fill
Solid
true
true
-
0
0
Gradient fill
Gradient
true
true
-
0
0
Pattern fill
Pattern
true
true
-
Qt::Horizontal
QSizePolicy::Preferred
5
5
-
TypeText
-
Qt::Horizontal
10
5
-
-
Color:
-
-
...
true
true
-
-
Type:
-
0
0
+
+
+ 0
+ 30
+
+
-
Linear
-
Radial
-
Repeat:
-
0
0
+
+
+ 0
+ 30
+
+
-
None
-
Repeat
-
Reflect
-
-
Preset:
-
-
...
false
true
-
Qt::Horizontal
-
-
-
-
+
Qt::Vertical
20
40
KoColorPopupButton
QToolButton
KisStopGradientEditor
QWidget
kis_stopgradient_editor.h
1
diff --git a/libs/ui/widgets/KoStrokeConfigWidget.cpp b/libs/ui/widgets/KoStrokeConfigWidget.cpp
index 648023c72d..f5b90c02b5 100644
--- a/libs/ui/widgets/KoStrokeConfigWidget.cpp
+++ b/libs/ui/widgets/KoStrokeConfigWidget.cpp
@@ -1,783 +1,800 @@
/* This file is part of the KDE project
* Made by Tomislav Lukman (tomislav.lukman@ck.tel.hr)
* Copyright (C) 2002 Tomislav Lukman
* Copyright (C) 2002-2003 Rob Buis
* Copyright (C) 2005-2006 Tim Beaulen
* Copyright (C) 2005-2007 Thomas Zander
* Copyright (C) 2005-2006, 2011 Inge Wallin
* Copyright (C) 2005-2008 Jan Hambrecht
* Copyright (C) 2006 C. Boemann
* Copyright (C) 2006 Peter Simonsson
* Copyright (C) 2006 Laurent Montel
* Copyright (C) 2007,2011 Thorsten Zachmann
* Copyright (C) 2011 Jean-Nicolas Artaud
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library 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
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public License
* along with this library; see the file COPYING.LIB. If not, write to
* the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301, USA.
*/
// Own
#include "KoStrokeConfigWidget.h"
// Qt
#include
#include
#include
#include
#include
#include
#include
// KDE
#include
// Calligra
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include "ui_KoStrokeConfigWidget.h"
#include
#include
#include
#include "kis_canvas_resource_provider.h"
#include "kis_acyclic_signal_connector.h"
// Krita
#include "kis_double_parse_unit_spin_box.h"
class CapNJoinMenu : public QMenu
{
public:
CapNJoinMenu(QWidget *parent = 0);
QSize sizeHint() const override;
KisDoubleParseUnitSpinBox *miterLimit;
QButtonGroup *capGroup;
QButtonGroup *joinGroup;
};
CapNJoinMenu::CapNJoinMenu(QWidget *parent)
: QMenu(parent)
{
QGridLayout *mainLayout = new QGridLayout();
mainLayout->setMargin(2);
// The cap group
capGroup = new QButtonGroup(this);
capGroup->setExclusive(true);
QToolButton *button = 0;
button = new QToolButton(this);
button->setIcon(koIcon("stroke-cap-butt"));
button->setCheckable(true);
button->setToolTip(i18n("Butt cap"));
capGroup->addButton(button, Qt::FlatCap);
mainLayout->addWidget(button, 2, 0);
button = new QToolButton(this);
button->setIcon(koIcon("stroke-cap-round"));
button->setCheckable(true);
button->setToolTip(i18n("Round cap"));
capGroup->addButton(button, Qt::RoundCap);
mainLayout->addWidget(button, 2, 1);
button = new QToolButton(this);
button->setIcon(koIcon("stroke-cap-square"));
button->setCheckable(true);
button->setToolTip(i18n("Square cap"));
capGroup->addButton(button, Qt::SquareCap);
mainLayout->addWidget(button, 2, 2, Qt::AlignLeft);
// The join group
joinGroup = new QButtonGroup(this);
joinGroup->setExclusive(true);
button = new QToolButton(this);
button->setIcon(koIcon("stroke-join-miter"));
button->setCheckable(true);
button->setToolTip(i18n("Miter join"));
joinGroup->addButton(button, Qt::MiterJoin);
mainLayout->addWidget(button, 3, 0);
button = new QToolButton(this);
button->setIcon(koIcon("stroke-join-round"));
button->setCheckable(true);
button->setToolTip(i18n("Round join"));
joinGroup->addButton(button, Qt::RoundJoin);
mainLayout->addWidget(button, 3, 1);
button = new QToolButton(this);
button->setIcon(koIcon("stroke-join-bevel"));
button->setCheckable(true);
button->setToolTip(i18n("Bevel join"));
joinGroup->addButton(button, Qt::BevelJoin);
mainLayout->addWidget(button, 3, 2, Qt::AlignLeft);
// Miter limit
// set min/max/step and value in points, then set actual unit
miterLimit = new KisDoubleParseUnitSpinBox(this);
miterLimit->setMinMaxStep(0.0, 1000.0, 0.5);
miterLimit->setDecimals(2);
miterLimit->setUnit(KoUnit(KoUnit::Point));
miterLimit->setToolTip(i18n("Miter limit"));
mainLayout->addWidget(miterLimit, 4, 0, 1, 3);
mainLayout->setSizeConstraint(QLayout::SetMinAndMaxSize);
setLayout(mainLayout);
}
QSize CapNJoinMenu::sizeHint() const
{
return layout()->sizeHint();
}
class Q_DECL_HIDDEN KoStrokeConfigWidget::Private
{
public:
Private()
: canvas(0),
active(true),
allowLocalUnitManagement(true),
fillConfigWidget(0),
noSelectionTrackingMode(false)
{
}
KoLineStyleSelector *lineStyle;
KisDoubleParseUnitSpinBox *lineWidth;
KoMarkerSelector *startMarkerSelector;
KoMarkerSelector *midMarkerSelector;
KoMarkerSelector *endMarkerSelector;
CapNJoinMenu *capNJoinMenu;
QWidget *spacer;
KoCanvasBase *canvas;
bool active;
bool allowLocalUnitManagement;
KoFillConfigWidget *fillConfigWidget;
bool noSelectionTrackingMode;
KisAcyclicSignalConnector shapeChangedAcyclicConnector;
KisAcyclicSignalConnector resourceManagerAcyclicConnector;
std::vector deactivationLocks;
Ui_KoStrokeConfigWidget *ui;
};
KoStrokeConfigWidget::KoStrokeConfigWidget(KoCanvasBase *canvas, QWidget * parent)
: QWidget(parent)
, d(new Private())
{
// confure GUI
d->ui = new Ui_KoStrokeConfigWidget();
d->ui->setupUi(this);
setObjectName("Stroke widget");
{ // connect the canvas
d->shapeChangedAcyclicConnector.connectBackwardVoid(
canvas->selectedShapesProxy(), SIGNAL(selectionChanged()),
this, SLOT(selectionChanged()));
d->shapeChangedAcyclicConnector.connectBackwardVoid(
canvas->selectedShapesProxy(), SIGNAL(selectionContentChanged()),
this, SLOT(selectionChanged()));
d->resourceManagerAcyclicConnector.connectBackwardResourcePair(
canvas->resourceManager(), SIGNAL(canvasResourceChanged(int, const QVariant&)),
this, SLOT(canvasResourceChanged(int, const QVariant &)));
d->canvas = canvas;
}
{
d->fillConfigWidget = new KoFillConfigWidget(canvas, KoFlake::StrokeFill, this);
d->fillConfigWidget->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::MinimumExpanding);
d->ui->fillConfigWidgetLayout->addWidget(d->fillConfigWidget);
connect(d->fillConfigWidget, SIGNAL(sigFillChanged()), SIGNAL(sigStrokeChanged()));
}
d->ui->thicknessLabel->setAlignment(Qt::AlignRight | Qt::AlignVCenter);
d->ui->thicknessLabel->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
// set min/max/step and value in points, then set actual unit
d->ui->lineWidth->setMinMaxStep(0.0, 1000.0, 0.5);
d->ui->lineWidth->setDecimals(2);
d->ui->lineWidth->setUnit(KoUnit(KoUnit::Point));
d->ui->lineWidth->setToolTip(i18n("Set line width of actual selection"));
d->ui->capNJoinButton->setMinimumHeight(25);
d->capNJoinMenu = new CapNJoinMenu(this);
d->ui->capNJoinButton->setMenu(d->capNJoinMenu);
d->ui->capNJoinButton->setText("...");
d->ui->capNJoinButton->setPopupMode(QToolButton::InstantPopup);
{
// Line style
d->ui->strokeStyleLabel->setText(i18n("Line Style:"));
d->ui->strokeStyleLabel->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum);
d->ui->lineStyle->setToolTip(i18nc("@info:tooltip", "Line style"));
d->ui->lineStyle->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Minimum);
d->ui->lineStyle->setLineStyle(Qt::SolidLine, QVector());
}
{
QList emptyMarkers;
d->startMarkerSelector = new KoMarkerSelector(KoFlake::StartMarker, this);
d->startMarkerSelector->setToolTip(i18nc("@info:tooltip", "Start marker"));
d->startMarkerSelector->updateMarkers(emptyMarkers);
d->startMarkerSelector->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred );
d->ui->markerLayout->addWidget(d->startMarkerSelector);
d->midMarkerSelector = new KoMarkerSelector(KoFlake::MidMarker, this);
d->midMarkerSelector->setToolTip(i18nc("@info:tooltip", "Node marker"));
d->midMarkerSelector->updateMarkers(emptyMarkers);
d->midMarkerSelector->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred );
d->ui->markerLayout->addWidget(d->midMarkerSelector);
d->endMarkerSelector = new KoMarkerSelector(KoFlake::EndMarker, this);
d->endMarkerSelector->setToolTip(i18nc("@info:tooltip", "End marker"));
d->endMarkerSelector->updateMarkers(emptyMarkers);
d->endMarkerSelector->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred );
d->ui->markerLayout->addWidget(d->endMarkerSelector);
}
// Spacer
d->spacer = new QWidget();
d->spacer->setObjectName("SpecialSpacer");
d->ui->markerLayout->addWidget(d->spacer);
connect(d->ui->lineStyle, SIGNAL(currentIndexChanged(int)), this, SLOT(applyDashStyleChanges()));
connect(d->ui->lineWidth, SIGNAL(valueChangedPt(qreal)), this, SLOT(applyLineWidthChanges()));
connect(d->capNJoinMenu->capGroup, SIGNAL(buttonClicked(int)), this, SLOT(applyJoinCapChanges()));
connect(d->capNJoinMenu->joinGroup, SIGNAL(buttonClicked(int)), this, SLOT(applyJoinCapChanges()));
connect(d->capNJoinMenu->miterLimit, SIGNAL(valueChangedPt(qreal)), this, SLOT(applyJoinCapChanges()));
{ // Map the marker signals correclty
QSignalMapper *mapper = new QSignalMapper(this);
connect(mapper, SIGNAL(mapped(int)), SLOT(applyMarkerChanges(int)));
connect(d->startMarkerSelector, SIGNAL(currentIndexChanged(int)), mapper, SLOT(map()));
connect(d->midMarkerSelector, SIGNAL(currentIndexChanged(int)), mapper, SLOT(map()));
connect(d->endMarkerSelector, SIGNAL(currentIndexChanged(int)), mapper, SLOT(map()));
mapper->setMapping(d->startMarkerSelector, KoFlake::StartMarker);
mapper->setMapping(d->midMarkerSelector, KoFlake::MidMarker);
mapper->setMapping(d->endMarkerSelector, KoFlake::EndMarker);
}
KoDocumentResourceManager *resourceManager = canvas->shapeController()->resourceManager();
if (resourceManager) {
KoMarkerCollection *collection = resourceManager->resource(KoDocumentResourceManager::MarkerCollection).value();
if (collection) {
updateMarkers(collection->markers());
}
}
selectionChanged();
d->fillConfigWidget->activate();
deactivate();
}
KoStrokeConfigWidget::~KoStrokeConfigWidget()
{
delete d;
}
void KoStrokeConfigWidget::setNoSelectionTrackingMode(bool value)
{
d->fillConfigWidget->setNoSelectionTrackingMode(value);
d->noSelectionTrackingMode = value;
if (!d->noSelectionTrackingMode) {
selectionChanged();
}
}
// ----------------------------------------------------------------
// getters and setters
Qt::PenStyle KoStrokeConfigWidget::lineStyle() const
{
return d->ui->lineStyle->lineStyle();
}
QVector KoStrokeConfigWidget::lineDashes() const
{
return d->ui->lineStyle->lineDashes();
}
qreal KoStrokeConfigWidget::lineWidth() const
{
return d->ui->lineWidth->value();
}
qreal KoStrokeConfigWidget::miterLimit() const
{
return d->capNJoinMenu->miterLimit->value();
}
KoMarker *KoStrokeConfigWidget::startMarker() const
{
return d->startMarkerSelector->marker();
}
KoMarker *KoStrokeConfigWidget::endMarker() const
{
return d->endMarkerSelector->marker();
}
Qt::PenCapStyle KoStrokeConfigWidget::capStyle() const
{
return static_cast(d->capNJoinMenu->capGroup->checkedId());
}
Qt::PenJoinStyle KoStrokeConfigWidget::joinStyle() const
{
return static_cast(d->capNJoinMenu->joinGroup->checkedId());
}
KoShapeStrokeSP KoStrokeConfigWidget::createShapeStroke()
{
KoShapeStrokeSP stroke(d->fillConfigWidget->createShapeStroke());
stroke->setLineWidth(lineWidth());
stroke->setCapStyle(capStyle());
stroke->setJoinStyle(joinStyle());
stroke->setMiterLimit(miterLimit());
stroke->setLineStyle(lineStyle(), lineDashes());
return stroke;
}
// ----------------------------------------------------------------
// Other public functions
void KoStrokeConfigWidget::updateStyleControlsAvailability(bool enabled)
{
d->ui->lineWidth->setEnabled(enabled);
d->capNJoinMenu->setEnabled(enabled);
d->ui->lineStyle->setEnabled(enabled);
d->startMarkerSelector->setEnabled(enabled);
d->midMarkerSelector->setEnabled(enabled);
d->endMarkerSelector->setEnabled(enabled);
}
void KoStrokeConfigWidget::setUnit(const KoUnit &unit, KoShape *representativeShape)
{
if (!d->allowLocalUnitManagement) {
return; //the unit management is completly transfered to the unitManagers.
}
blockChildSignals(true);
/**
* KoStrokeShape knows nothing about the transformations applied
* to the shape, which doesn't prevent the shape to apply them and
* display the stroke differently. So just take that into account
* and show the user correct values using the multiplier in KoUnit.
*/
KoUnit newUnit(unit);
if (representativeShape) {
newUnit.adjustByPixelTransform(representativeShape->absoluteTransformation(0));
}
d->ui->lineWidth->setUnit(newUnit);
d->capNJoinMenu->miterLimit->setUnit(newUnit);
d->ui->lineWidth->setLineStep(1.0);
d->capNJoinMenu->miterLimit->setLineStep(1.0);
blockChildSignals(false);
}
void KoStrokeConfigWidget::setUnitManagers(KisSpinBoxUnitManager* managerLineWidth,
KisSpinBoxUnitManager *managerMitterLimit)
{
blockChildSignals(true);
d->allowLocalUnitManagement = false;
d->ui->lineWidth->setUnitManager(managerLineWidth);
d->capNJoinMenu->miterLimit->setUnitManager(managerMitterLimit);
blockChildSignals(false);
}
void KoStrokeConfigWidget::updateMarkers(const QList &markers)
{
d->startMarkerSelector->updateMarkers(markers);
d->midMarkerSelector->updateMarkers(markers);
d->endMarkerSelector->updateMarkers(markers);
}
void KoStrokeConfigWidget::activate()
{
KIS_SAFE_ASSERT_RECOVER_RETURN(!d->deactivationLocks.empty());
d->deactivationLocks.clear();
d->fillConfigWidget->activate();
if (!d->noSelectionTrackingMode) {
selectionChanged();
} else {
loadCurrentStrokeFillFromResourceServer();
}
}
void KoStrokeConfigWidget::deactivate()
{
KIS_SAFE_ASSERT_RECOVER_RETURN(d->deactivationLocks.empty());
d->deactivationLocks.push_back(KisAcyclicSignalConnector::Blocker(d->shapeChangedAcyclicConnector));
d->deactivationLocks.push_back(KisAcyclicSignalConnector::Blocker(d->resourceManagerAcyclicConnector));
d->fillConfigWidget->deactivate();
}
void KoStrokeConfigWidget::blockChildSignals(bool block)
{
d->ui->lineWidth->blockSignals(block);
d->capNJoinMenu->capGroup->blockSignals(block);
d->capNJoinMenu->joinGroup->blockSignals(block);
d->capNJoinMenu->miterLimit->blockSignals(block);
d->ui->lineStyle->blockSignals(block);
d->startMarkerSelector->blockSignals(block);
d->midMarkerSelector->blockSignals(block);
d->endMarkerSelector->blockSignals(block);
}
void KoStrokeConfigWidget::setActive(bool active)
{
d->active = active;
}
//------------------------
template
auto applyChangeToStrokes(KoCanvasBase *canvas, ModifyFunction modifyFunction)
-> decltype(modifyFunction(KoShapeStrokeSP()), void())
{
KoSelection *selection = canvas->selectedShapesProxy()->selection();
if (!selection) return;
QList shapes = selection->selectedEditableShapes();
KUndo2Command *command = KoFlake::modifyShapesStrokes(shapes, modifyFunction);
if (command) {
canvas->addCommand(command);
}
}
void KoStrokeConfigWidget::applyDashStyleChanges()
{
applyChangeToStrokes(
d->canvas,
[this] (KoShapeStrokeSP stroke) {
stroke->setLineStyle(lineStyle(), lineDashes());
});
emit sigStrokeChanged();
}
void KoStrokeConfigWidget::applyLineWidthChanges()
{
applyChangeToStrokes(
d->canvas,
[this] (KoShapeStrokeSP stroke) {
stroke->setLineWidth(lineWidth());
});
emit sigStrokeChanged();
}
void KoStrokeConfigWidget::applyJoinCapChanges()
{
applyChangeToStrokes(
d->canvas,
[this] (KoShapeStrokeSP stroke) {
stroke->setCapStyle(static_cast(d->capNJoinMenu->capGroup->checkedId()));
stroke->setJoinStyle(static_cast(d->capNJoinMenu->joinGroup->checkedId()));
stroke->setMiterLimit(miterLimit());
});
emit sigStrokeChanged();
}
void KoStrokeConfigWidget::applyMarkerChanges(int rawPosition)
{
KoSelection *selection = d->canvas->selectedShapesProxy()->selection();
if (!selection) {
emit sigStrokeChanged();
return;
}
QList shapes = selection->selectedEditableShapes();
QList pathShapes;
Q_FOREACH (KoShape *shape, shapes) {
KoPathShape *pathShape = dynamic_cast(shape);
if (pathShape) {
pathShapes << pathShape;
}
}
if (pathShapes.isEmpty()) {
emit sigStrokeChanged();
return;
}
KoFlake::MarkerPosition position = KoFlake::MarkerPosition(rawPosition);
QScopedPointer marker;
switch (position) {
case KoFlake::StartMarker:
if (d->startMarkerSelector->marker()) {
marker.reset(new KoMarker(*d->startMarkerSelector->marker()));
}
break;
case KoFlake::MidMarker:
if (d->midMarkerSelector->marker()) {
marker.reset(new KoMarker(*d->midMarkerSelector->marker()));
}
break;
case KoFlake::EndMarker:
if (d->endMarkerSelector->marker()) {
marker.reset(new KoMarker(*d->endMarkerSelector->marker()));
}
break;
}
KUndo2Command* command = new KoPathShapeMarkerCommand(pathShapes, marker.take(), position);
d->canvas->addCommand(command);
emit sigStrokeChanged();
}
// ----------------------------------------------------------------
struct CheckShapeStrokeStyleBasePolicy
{
typedef KoShapeStrokeSP PointerType;
static PointerType getProperty(KoShape *shape) {
return qSharedPointerDynamicCast(shape->stroke());
}
};
struct CheckShapeStrokeDashesPolicy : public CheckShapeStrokeStyleBasePolicy
{
static bool compareTo(PointerType p1, PointerType p2) {
return p1->lineStyle() == p2->lineStyle() &&
p1->lineDashes() == p2->lineDashes() &&
p1->dashOffset() == p2->dashOffset();
}
};
struct CheckShapeStrokeCapJoinPolicy : public CheckShapeStrokeStyleBasePolicy
{
static bool compareTo(PointerType p1, PointerType p2) {
return p1->capStyle() == p2->capStyle() &&
p1->joinStyle() == p2->joinStyle() &&
p1->miterLimit() == p2->miterLimit();
}
};
struct CheckShapeStrokeWidthPolicy : public CheckShapeStrokeStyleBasePolicy
{
static bool compareTo(PointerType p1, PointerType p2) {
return p1->lineWidth() == p2->lineWidth();
}
};
struct CheckShapeMarkerPolicy
{
CheckShapeMarkerPolicy(KoFlake::MarkerPosition position)
: m_position(position)
{
}
typedef KoMarker* PointerType;
PointerType getProperty(KoShape *shape) const {
KoPathShape *pathShape = dynamic_cast(shape);
return pathShape ? pathShape->marker(m_position) : 0;
}
bool compareTo(PointerType p1, PointerType p2) const {
if ((!p1 || !p2) && p1 != p2) return false;
if (!p1 && p1 == p2) return true;
return p1 == p2 || *p1 == *p2;
}
KoFlake::MarkerPosition m_position;
};
void KoStrokeConfigWidget::selectionChanged()
{
KoSelection *selection = d->canvas->selectedShapesProxy()->selection();
if (!selection) return;
QList shapes = selection->selectedEditableShapes();
KoShape *shape = !shapes.isEmpty() ? shapes.first() : 0;
const KoShapeStrokeSP stroke = shape ? qSharedPointerDynamicCast(shape->stroke()) : KoShapeStrokeSP();
// setUnit uses blockChildSignals() so take care not to use it inside the block
setUnit(d->canvas->unit(), shape);
blockChildSignals(true);
// line width
if (stroke && KoFlake::compareShapePropertiesEqual(shapes)) {
d->ui->lineWidth->changeValue(stroke->lineWidth());
} else {
d->ui->lineWidth->changeValue(0);
}
// caps & joins
if (stroke && KoFlake::compareShapePropertiesEqual(shapes)) {
Qt::PenCapStyle capStyle = stroke->capStyle() >= 0 ? stroke->capStyle() : Qt::FlatCap;
Qt::PenJoinStyle joinStyle = stroke->joinStyle() >= 0 ? stroke->joinStyle() : Qt::MiterJoin;
{
QAbstractButton *button = d->capNJoinMenu->capGroup->button(capStyle);
KIS_SAFE_ASSERT_RECOVER_RETURN(button);
button->setChecked(true);
}
{
QAbstractButton *button = d->capNJoinMenu->joinGroup->button(joinStyle);
KIS_SAFE_ASSERT_RECOVER_RETURN(button);
button->setChecked(true);
}
d->capNJoinMenu->miterLimit->changeValue(stroke->miterLimit());
d->capNJoinMenu->miterLimit->setEnabled(joinStyle == Qt::MiterJoin);
} else {
d->capNJoinMenu->capGroup->button(Qt::FlatCap)->setChecked(true);
d->capNJoinMenu->joinGroup->button(Qt::MiterJoin)->setChecked(true);
d->capNJoinMenu->miterLimit->changeValue(0.0);
d->capNJoinMenu->miterLimit->setEnabled(true);
}
// dashes style
if (stroke && KoFlake::compareShapePropertiesEqual(shapes)) {
d->ui->lineStyle->setLineStyle(stroke->lineStyle(), stroke->lineDashes());
} else {
d->ui->lineStyle->setLineStyle(Qt::SolidLine, QVector());
}
// markers
KoPathShape *pathShape = dynamic_cast(shape);
if (pathShape) {
if (KoFlake::compareShapePropertiesEqual(shapes, CheckShapeMarkerPolicy(KoFlake::StartMarker))) {
d->startMarkerSelector->setMarker(pathShape->marker(KoFlake::StartMarker));
}
if (KoFlake::compareShapePropertiesEqual(shapes, CheckShapeMarkerPolicy(KoFlake::MidMarker))) {
d->midMarkerSelector->setMarker(pathShape->marker(KoFlake::MidMarker));
}
if (KoFlake::compareShapePropertiesEqual(shapes, CheckShapeMarkerPolicy(KoFlake::EndMarker))) {
d->endMarkerSelector->setMarker(pathShape->marker(KoFlake::EndMarker));
}
}
const bool lineOptionsVisible = d->fillConfigWidget->selectedFillIndex() == 0 ? false : true;
+ // This switch statement is to help the tab widget "pages" to be closer to the correct size
+ // if we don't do this the internal widgets get rendered, then the tab page has to get resized to
+ // fill up the space, then the internal widgets have to resize yet again...causing flicker
+ switch(d->fillConfigWidget->selectedFillIndex()) {
+ case 0: // no fill
+ this->setMinimumHeight(130);
+ break;
+ case 1: // solid fill
+ this->setMinimumHeight(200);
+ break;
+ case 2: // gradient fill
+ this->setMinimumHeight(350);
+ case 3: // pattern fill
+ break;
+ }
+
+
d->ui->thicknessLineBreak->setVisible(lineOptionsVisible);
d->ui->lineWidth->setVisible(lineOptionsVisible);
d->ui->capNJoinButton->setVisible(lineOptionsVisible);
d->ui->lineStyle->setVisible(lineOptionsVisible);
d->startMarkerSelector->setVisible(lineOptionsVisible);
d->midMarkerSelector->setVisible(lineOptionsVisible);
d->endMarkerSelector->setVisible(lineOptionsVisible);
d->ui->thicknessLabel->setVisible(lineOptionsVisible);
d->ui->strokeStyleLabel->setVisible(lineOptionsVisible);
blockChildSignals(false);
updateStyleControlsAvailability(!shapes.isEmpty());
}
void KoStrokeConfigWidget::canvasResourceChanged(int key, const QVariant &value)
{
switch (key) {
case KoCanvasResourceManager::Unit:
// we request the whole selection to reload because the
// unit of the stroke width depends on the selected shape
selectionChanged();
break;
case KisCanvasResourceProvider::Size:
if (d->noSelectionTrackingMode) {
d->ui->lineWidth->changeValue(d->canvas->unit().fromUserValue(value.toReal()));
}
break;
}
}
void KoStrokeConfigWidget::loadCurrentStrokeFillFromResourceServer()
{
if (d->canvas) {
const QVariant value = d->canvas->resourceManager()->resource(KisCanvasResourceProvider::Size);
canvasResourceChanged(KisCanvasResourceProvider::Size, value);
updateStyleControlsAvailability(true);
emit sigStrokeChanged();
}
}
diff --git a/libs/ui/widgets/KoStrokeConfigWidget.ui b/libs/ui/widgets/KoStrokeConfigWidget.ui
index 9eb76c8428..e94a0109d6 100644
--- a/libs/ui/widgets/KoStrokeConfigWidget.ui
+++ b/libs/ui/widgets/KoStrokeConfigWidget.ui
@@ -1,106 +1,125 @@
KoStrokeConfigWidget
0
0
226
100
3
0
0
0
0
-
-
Qt::Horizontal
-
+
+ 9
+
+
+ 9
+
-
Thickness:
-
-
...
-
+
+ 9
+
+
+ 9
+
-
Line Style:
-
-
-
+
+
+ 9
+
+
+ 9
+
+
-
Qt::Vertical
20
40
KisDoubleParseUnitSpinBox
QWidget
kis_double_parse_unit_spin_box.h
KoLineStyleSelector
QWidget
diff --git a/plugins/tools/defaulttool/defaulttool/DefaultToolTabbedWidget.cpp b/plugins/tools/defaulttool/defaulttool/DefaultToolTabbedWidget.cpp
index 3851b5b840..8127c711a0 100644
--- a/plugins/tools/defaulttool/defaulttool/DefaultToolTabbedWidget.cpp
+++ b/plugins/tools/defaulttool/defaulttool/DefaultToolTabbedWidget.cpp
@@ -1,90 +1,91 @@
/*
* Copyright (c) 2017 Dmitry Kazakov
*
* 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 "DefaultToolTabbedWidget.h"
#include
#include "kis_icon_utils.h"
#include "DefaultToolGeometryWidget.h"
#include "KoStrokeConfigWidget.h"
#include "KoFillConfigWidget.h"
#include
#include
DefaultToolTabbedWidget::DefaultToolTabbedWidget(KoInteractionTool *tool, QWidget *parent)
: KoTitledTabWidget(parent)
-{
+{
setObjectName("default-tool-tabbed-widget");
DefaultToolGeometryWidget *geometryWidget = new DefaultToolGeometryWidget(tool, this);
geometryWidget->setWindowTitle(i18n("Geometry"));
addTab(geometryWidget, KisIconUtils::loadIcon("geometry"), QString());
m_strokeWidget = new KoStrokeConfigWidget(tool->canvas(), this);
m_strokeWidget->setWindowTitle(i18n("Stroke"));
KisDocumentAwareSpinBoxUnitManager* managerLineWidth = new KisDocumentAwareSpinBoxUnitManager(m_strokeWidget);
KisDocumentAwareSpinBoxUnitManager* managerMitterLimit = new KisDocumentAwareSpinBoxUnitManager(m_strokeWidget);
managerLineWidth->setApparentUnitFromSymbol("px");
managerMitterLimit->setApparentUnitFromSymbol("px"); //set unit to px by default
m_strokeWidget->setUnitManagers(managerLineWidth, managerMitterLimit);
addTab(m_strokeWidget, KisIconUtils::loadIcon("krita_tool_line"), QString());
+
m_fillWidget = new KoFillConfigWidget(tool->canvas(), KoFlake::Fill, this);
m_fillWidget->setWindowTitle(i18n("Fill"));
addTab(m_fillWidget, KisIconUtils::loadIcon("krita_tool_color_fill"), QString());
connect(this, SIGNAL(currentChanged(int)), SLOT(slotCurrentIndexChanged(int)));
m_oldTabIndex = currentIndex();
}
DefaultToolTabbedWidget::~DefaultToolTabbedWidget()
{
}
void DefaultToolTabbedWidget::activate()
{
m_fillWidget->activate();
m_strokeWidget->activate();
}
void DefaultToolTabbedWidget::deactivate()
{
m_fillWidget->deactivate();
m_strokeWidget->deactivate();
}
void DefaultToolTabbedWidget::slotCurrentIndexChanged(int current)
{
if (m_oldTabIndex == FillTab) {
emit sigSwitchModeEditFillGradient(false);
} else if (m_oldTabIndex == StrokeTab) {
emit sigSwitchModeEditStrokeGradient(false);
}
m_oldTabIndex = current;
if (current == FillTab) {
emit sigSwitchModeEditFillGradient(true);
} else if (m_oldTabIndex == StrokeTab) {
emit sigSwitchModeEditStrokeGradient(true);
}
}