diff --git a/libs/basicflakes/tools/KoCreatePathTool.cpp b/libs/basicflakes/tools/KoCreatePathTool.cpp index f17cc2c1b9..c0355d2ecf 100644 --- a/libs/basicflakes/tools/KoCreatePathTool.cpp +++ b/libs/basicflakes/tools/KoCreatePathTool.cpp @@ -1,532 +1,533 @@ /* This file is part of the KDE project * * Copyright (C) 2006 Thorsten Zachmann * Copyright (C) 2008-2010 Jan Hambrecht * * 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. */ #include "KoCreatePathTool.h" #include "KoCreatePathTool_p.h" #include "KoPointerEvent.h" #include "KoPathShape.h" #include "KoSelection.h" #include "KoDocumentResourceManager.h" #include "KoShapePaintingContext.h" #include "KoShapeStroke.h" #include "KoStrokeConfigWidget.h" #include "KoCanvasBase.h" +#include "kis_int_parse_spin_box.h" #include #include #include #include #include #include #include KoCreatePathTool::KoCreatePathTool(KoCanvasBase *canvas) : KoToolBase(*(new KoCreatePathToolPrivate(this, canvas))) { } KoCreatePathTool::~KoCreatePathTool() { } void KoCreatePathTool::paint(QPainter &painter, const KoViewConverter &converter) { Q_D(KoCreatePathTool); if (pathStarted()) { KoShapeStroke *stroke(createStroke()); if (stroke) { d->shape->setStroke(stroke); } painter.save(); paintPath(*(d->shape), painter, converter); painter.restore(); painter.save(); painter.setTransform(d->shape->absoluteTransformation(&converter) * painter.transform()); KoShape::applyConversion(painter, converter); QPen pen(QBrush(Qt::blue), 1); pen.setCosmetic(true); painter.setPen(pen); painter.setBrush(Qt::white); const bool firstPoint = (d->firstPoint == d->activePoint); if (d->pointIsDragged || firstPoint) { const bool onlyPaintActivePoints = false; KoPathPoint::PointTypes paintFlags = KoPathPoint::ControlPoint2; if (d->activePoint->activeControlPoint1()) { paintFlags |= KoPathPoint::ControlPoint1; } d->activePoint->paint(painter, d->handleRadius, paintFlags, onlyPaintActivePoints); } // check if we have to color the first point if (d->mouseOverFirstPoint) { painter.setBrush(Qt::red); } else { painter.setBrush(Qt::white); } d->firstPoint->paint(painter, d->handleRadius, KoPathPoint::Node); painter.restore(); } if (d->hoveredPoint) { painter.save(); painter.setTransform(d->hoveredPoint->parent()->absoluteTransformation(&converter), true); KoShape::applyConversion(painter, converter); QPen pen(QBrush(Qt::blue), 1); pen.setCosmetic(true); painter.setPen(pen); painter.setBrush(Qt::white); d->hoveredPoint->paint(painter, d->handleRadius, KoPathPoint::Node); painter.restore(); } painter.save(); KoShape::applyConversion(painter, converter); canvas()->snapGuide()->paint(painter, converter); painter.restore(); } void KoCreatePathTool::paintPath(KoPathShape& pathShape, QPainter &painter, const KoViewConverter &converter) { Q_D(KoCreatePathTool); painter.setTransform(pathShape.absoluteTransformation(&converter) * painter.transform()); painter.save(); KoShapePaintingContext paintContext; //FIXME pathShape.paint(painter, converter, paintContext); painter.restore(); if (pathShape.stroke()) { painter.save(); pathShape.stroke()->paint(d->shape, painter, converter); painter.restore(); } } void KoCreatePathTool::mousePressEvent(KoPointerEvent *event) { Q_D(KoCreatePathTool); //Right click removes last point if (event->button() == Qt::RightButton) { removeLastPoint(); return; } const bool isOverFirstPoint = d->shape && handleGrabRect(d->firstPoint->point()).contains(event->point); bool haveCloseModifier = (listeningToModifiers() && (event->modifiers() & Qt::ShiftModifier)); if ((event->button() == Qt::LeftButton) && haveCloseModifier && !isOverFirstPoint) { endPathWithoutLastPoint(); return; } d->finishAfterThisPoint = false; if (pathStarted()) { if (isOverFirstPoint) { d->activePoint->setPoint(d->firstPoint->point()); canvas()->updateCanvas(d->shape->boundingRect()); canvas()->updateCanvas(canvas()->snapGuide()->boundingRect()); if (haveCloseModifier) { d->shape->closeMerge(); // we are closing the path, so reset the existing start path point d->existingStartPoint = 0; // finish path endPath(); } else { // the path shape will get closed when the user releases // the mouse button d->finishAfterThisPoint = true; } } else { canvas()->updateCanvas(canvas()->snapGuide()->boundingRect()); QPointF point = canvas()->snapGuide()->snap(event->point, event->modifiers()); // check whether we hit an start/end node of an existing path d->existingEndPoint = d->endPointAtPosition(point); if (d->existingEndPoint.isValid() && d->existingEndPoint != d->existingStartPoint) { point = d->existingEndPoint.path->shapeToDocument(d->existingEndPoint.point->point()); d->activePoint->setPoint(point); // finish path endPath(); } else { d->activePoint->setPoint(point); canvas()->updateCanvas(d->shape->boundingRect()); canvas()->updateCanvas(canvas()->snapGuide()->boundingRect()); } } } else { KoPathShape *pathShape = new KoPathShape(); d->shape = pathShape; pathShape->setShapeId(KoPathShapeId); KoShapeStroke *stroke = new KoShapeStroke(canvas()->resourceManager()->activeStroke()); stroke->setColor(canvas()->resourceManager()->foregroundColor().toQColor()); pathShape->setStroke(stroke); canvas()->updateCanvas(canvas()->snapGuide()->boundingRect()); QPointF point = canvas()->snapGuide()->snap(event->point, event->modifiers()); // check whether we hit an start/end node of an existing path d->existingStartPoint = d->endPointAtPosition(point); if (d->existingStartPoint.isValid()) { point = d->existingStartPoint.path->shapeToDocument(d->existingStartPoint.point->point()); } d->activePoint = pathShape->moveTo(point); d->firstPoint = d->activePoint; canvas()->updateCanvas(handlePaintRect(point)); canvas()->updateCanvas(canvas()->snapGuide()->boundingRect()); canvas()->snapGuide()->setEditedShape(pathShape); d->angleSnapStrategy = new AngleSnapStrategy(d->angleSnappingDelta, d->angleSnapStatus); canvas()->snapGuide()->addCustomSnapStrategy(d->angleSnapStrategy); } if (d->angleSnapStrategy) d->angleSnapStrategy->setStartPoint(d->activePoint->point()); } bool KoCreatePathTool::listeningToModifiers() { Q_D(KoCreatePathTool); return d->listeningToModifiers; } bool KoCreatePathTool::pathStarted() { Q_D(KoCreatePathTool); return ((bool) d->shape); } void KoCreatePathTool::mouseDoubleClickEvent(KoPointerEvent *event) { //remove handle canvas()->updateCanvas(handlePaintRect(event->point)); endPathWithoutLastPoint(); } void KoCreatePathTool::mouseMoveEvent(KoPointerEvent *event) { Q_D(KoCreatePathTool); KoPathPoint *endPoint = d->endPointAtPosition(event->point); if (d->hoveredPoint != endPoint) { if (d->hoveredPoint) { QPointF nodePos = d->hoveredPoint->parent()->shapeToDocument(d->hoveredPoint->point()); canvas()->updateCanvas(handlePaintRect(nodePos)); } d->hoveredPoint = endPoint; if (d->hoveredPoint) { QPointF nodePos = d->hoveredPoint->parent()->shapeToDocument(d->hoveredPoint->point()); canvas()->updateCanvas(handlePaintRect(nodePos)); } } if (!pathStarted()) { canvas()->updateCanvas(canvas()->snapGuide()->boundingRect()); canvas()->snapGuide()->snap(event->point, event->modifiers()); canvas()->updateCanvas(canvas()->snapGuide()->boundingRect()); d->mouseOverFirstPoint = false; return; } d->mouseOverFirstPoint = handleGrabRect(d->firstPoint->point()).contains(event->point); canvas()->updateCanvas(d->shape->boundingRect()); canvas()->updateCanvas(canvas()->snapGuide()->boundingRect()); QPointF snappedPosition = canvas()->snapGuide()->snap(event->point, event->modifiers()); d->repaintActivePoint(); if (event->buttons() & Qt::LeftButton) { d->pointIsDragged = true; QPointF offset = snappedPosition - d->activePoint->point(); d->activePoint->setControlPoint2(d->activePoint->point() + offset); // pressing stops controls points moving symmetrically if ((event->modifiers() & Qt::AltModifier) == 0) { d->activePoint->setControlPoint1(d->activePoint->point() - offset); } d->repaintActivePoint(); } else { d->activePoint->setPoint(snappedPosition); } canvas()->updateCanvas(d->shape->boundingRect()); canvas()->updateCanvas(canvas()->snapGuide()->boundingRect()); } void KoCreatePathTool::mouseReleaseEvent(KoPointerEvent *event) { Q_D(KoCreatePathTool); if (! d->shape || (event->buttons() & Qt::RightButton)) return; d->listeningToModifiers = true; // After the first press-and-release d->repaintActivePoint(); d->pointIsDragged = false; KoPathPoint *lastActivePoint = d->activePoint; if (!d->finishAfterThisPoint) { d->activePoint = d->shape->lineTo(event->point); canvas()->snapGuide()->setIgnoredPathPoints((QList() << d->activePoint)); } // apply symmetric point property if applicable if (lastActivePoint->activeControlPoint1() && lastActivePoint->activeControlPoint2()) { QPointF diff1 = lastActivePoint->point() - lastActivePoint->controlPoint1(); QPointF diff2 = lastActivePoint->controlPoint2() - lastActivePoint->point(); if (qFuzzyCompare(diff1.x(), diff2.x()) && qFuzzyCompare(diff1.y(), diff2.y())) lastActivePoint->setProperty(KoPathPoint::IsSymmetric); } if (d->finishAfterThisPoint) { d->firstPoint->setControlPoint1(d->activePoint->controlPoint1()); delete d->shape->removePoint(d->shape->pathPointIndex(d->activePoint)); d->activePoint = d->firstPoint; d->shape->closeMerge(); // we are closing the path, so reset the existing start path point d->existingStartPoint = 0; // finish path endPath(); } if (d->angleSnapStrategy && lastActivePoint->activeControlPoint2()) { d->angleSnapStrategy->deactivate(); } } void KoCreatePathTool::keyPressEvent(QKeyEvent *event) { if (event->key() == Qt::Key_Escape) { emit done(); } else { event->ignore(); } } void KoCreatePathTool::endPath() { Q_D(KoCreatePathTool); d->addPathShape(); } void KoCreatePathTool::endPathWithoutLastPoint() { Q_D(KoCreatePathTool); if (d->shape) { QRectF dirtyRect = d->shape->boundingRect(); delete d->shape->removePoint(d->shape->pathPointIndex(d->activePoint)); canvas()->updateCanvas(dirtyRect); d->addPathShape(); } } void KoCreatePathTool::cancelPath() { Q_D(KoCreatePathTool); if (d->shape) { canvas()->updateCanvas(handlePaintRect(d->firstPoint->point())); canvas()->updateCanvas(d->shape->boundingRect()); d->firstPoint = 0; d->activePoint = 0; } d->cleanUp(); } void KoCreatePathTool::removeLastPoint() { Q_D(KoCreatePathTool); if ((d->shape)) { KoPathPointIndex lastPointIndex = d->shape->pathPointIndex(d->activePoint); if (lastPointIndex.second > 1) { lastPointIndex.second--; delete d->shape->removePoint(lastPointIndex); d->hoveredPoint = 0; d->repaintActivePoint(); canvas()->updateCanvas(d->shape->boundingRect()); } } } void KoCreatePathTool::activate(ToolActivation, const QSet &) { Q_D(KoCreatePathTool); useCursor(Qt::ArrowCursor); // retrieve the actual global handle radius d->handleRadius = handleRadius(); // reset snap guide canvas()->updateCanvas(canvas()->snapGuide()->boundingRect()); canvas()->snapGuide()->reset(); } void KoCreatePathTool::deactivate() { cancelPath(); } void KoCreatePathTool::documentResourceChanged(int key, const QVariant & res) { Q_D(KoCreatePathTool); switch (key) { case KoDocumentResourceManager::HandleRadius: { d->handleRadius = res.toUInt(); } break; default: return; } } void KoCreatePathTool::addPathShape(KoPathShape *pathShape) { Q_D(KoCreatePathTool); KoPathShape *startShape = 0; KoPathShape *endShape = 0; pathShape->normalize(); // check if existing start/end points are still valid d->existingStartPoint.validate(canvas()); d->existingEndPoint.validate(canvas()); pathShape->setStroke(createStroke()); if (d->connectPaths(pathShape, d->existingStartPoint, d->existingEndPoint)) { if (d->existingStartPoint.isValid()) { startShape = d->existingStartPoint.path; } if (d->existingEndPoint.isValid() && d->existingEndPoint != d->existingStartPoint) { endShape = d->existingEndPoint.path; } } KUndo2Command *cmd = canvas()->shapeController()->addShape(pathShape); if (cmd) { KoSelection *selection = canvas()->shapeManager()->selection(); selection->deselectAll(); selection->select(pathShape); if (startShape) { canvas()->shapeController()->removeShape(startShape, cmd); } if (endShape && startShape != endShape) { canvas()->shapeController()->removeShape(endShape, cmd); } canvas()->addCommand(cmd); } else { canvas()->updateCanvas(pathShape->boundingRect()); delete pathShape; } } QList > KoCreatePathTool::createOptionWidgets() { Q_D(KoCreatePathTool); QList > list; QWidget *angleWidget = new QWidget(); angleWidget->setObjectName("Angle Constraints"); QGridLayout *layout = new QGridLayout(angleWidget); layout->addWidget(new QLabel(i18n("Angle snapping delta:"), angleWidget), 0, 0); - QSpinBox *angleEdit = new QSpinBox(angleWidget); + QSpinBox *angleEdit = new KisIntParseSpinBox(angleWidget); angleEdit->setValue(d->angleSnappingDelta); angleEdit->setRange(1, 360); angleEdit->setSingleStep(1); angleEdit->setSuffix(QChar(Qt::Key_degree)); layout->addWidget(angleEdit, 0, 1); layout->addWidget(new QLabel(i18n("Activate angle snap:"), angleWidget), 1, 0); QCheckBox *angleSnap = new QCheckBox(angleWidget); angleSnap->setChecked(false); angleSnap->setCheckable(true); layout->addWidget(angleSnap, 1, 1); QWidget *specialSpacer = new QWidget(); specialSpacer->setObjectName("SpecialSpacer"); layout->addWidget(specialSpacer, 2, 1); angleWidget->setWindowTitle(i18n("Angle Constraints")); list.append(angleWidget); d->strokeWidget = new KoStrokeConfigWidget(0); d->strokeWidget->setWindowTitle(i18n("Line")); d->strokeWidget->setCanvas(canvas()); d->strokeWidget->setActive(false); list.append(d->strokeWidget); connect(angleEdit, SIGNAL(valueChanged(int)), this, SLOT(angleDeltaChanged(int))); connect(angleSnap, SIGNAL(stateChanged(int)), this, SLOT(angleSnapChanged(int))); return list; } KoShapeStroke *KoCreatePathTool::createStroke() { Q_D(KoCreatePathTool); KoShapeStroke *stroke = 0; if (d->strokeWidget) { stroke = d->strokeWidget->createShapeStroke(); } return stroke; } //have to include this because of Q_PRIVATE_SLOT #include diff --git a/libs/basicflakes/tools/KoPencilTool.cpp b/libs/basicflakes/tools/KoPencilTool.cpp index 7aff814107..4636e9c56b 100644 --- a/libs/basicflakes/tools/KoPencilTool.cpp +++ b/libs/basicflakes/tools/KoPencilTool.cpp @@ -1,558 +1,559 @@ /* This file is part of the KDE project * Copyright (C) 2007,2009,2011 Jan Hambrecht * * 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. */ #include "KoPencilTool.h" #include "KoCurveFit.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "KoCreatePathTool_p.h" +#include "kis_double_parse_spin_box.h" KoPencilTool::KoPencilTool(KoCanvasBase *canvas) : KoToolBase(canvas) , m_mode(ModeCurve) , m_optimizeRaw(false) , m_optimizeCurve(false) , m_combineAngle(15.0) , m_fittingError(5.0) , m_close(false) , m_shape(0) , m_existingStartPoint(0) , m_existingEndPoint(0) , m_hoveredPoint(0) { } KoPencilTool::~KoPencilTool() { } void KoPencilTool::paint(QPainter &painter, const KoViewConverter &converter) { if (m_shape) { painter.save(); painter.setTransform(m_shape->absoluteTransformation(&converter) * painter.transform()); painter.save(); KoShapePaintingContext paintContext; //FIXME m_shape->paint(painter, converter, paintContext); painter.restore(); if (m_shape->stroke()) { painter.save(); m_shape->stroke()->paint(m_shape, painter, converter); painter.restore(); } painter.restore(); } if (m_hoveredPoint) { painter.save(); painter.setTransform(m_hoveredPoint->parent()->absoluteTransformation(&converter), true); KoShape::applyConversion(painter, converter); painter.setPen(Qt::blue); //TODO make configurable painter.setBrush(Qt::white); //TODO make configurable m_hoveredPoint->paint(painter, handleRadius(), KoPathPoint::Node); painter.restore(); } } void KoPencilTool::repaintDecorations() { } void KoPencilTool::mousePressEvent(KoPointerEvent *event) { if (! m_shape) { m_shape = new KoPathShape(); m_shape->setShapeId(KoPathShapeId); m_shape->setStroke(createStroke()); m_points.clear(); QPointF point = event->point; m_existingStartPoint = endPointAtPosition(point); if (m_existingStartPoint) point = m_existingStartPoint->parent()->shapeToDocument(m_existingStartPoint->point()); addPoint(point); } } void KoPencilTool::mouseMoveEvent(KoPointerEvent *event) { if (event->buttons() & Qt::LeftButton) addPoint(event->point); KoPathPoint * endPoint = endPointAtPosition(event->point); if (m_hoveredPoint != endPoint) { if (m_hoveredPoint) { QPointF nodePos = m_hoveredPoint->parent()->shapeToDocument(m_hoveredPoint->point()); canvas()->updateCanvas(handlePaintRect(nodePos)); } m_hoveredPoint = endPoint; if (m_hoveredPoint) { QPointF nodePos = m_hoveredPoint->parent()->shapeToDocument(m_hoveredPoint->point()); canvas()->updateCanvas(handlePaintRect(nodePos)); } } } void KoPencilTool::mouseReleaseEvent(KoPointerEvent *event) { if (! m_shape) return; QPointF point = event->point; m_existingEndPoint = endPointAtPosition(point); if (m_existingEndPoint) point = m_existingEndPoint->parent()->shapeToDocument(m_existingEndPoint->point()); addPoint(point); finish(event->modifiers() & Qt::ShiftModifier); m_existingStartPoint = 0; m_existingEndPoint = 0; m_hoveredPoint = 0; // the original path may be different from the one added canvas()->updateCanvas(m_shape->boundingRect()); delete m_shape; m_shape = 0; m_points.clear(); } void KoPencilTool::keyPressEvent(QKeyEvent *event) { if (m_shape) { event->accept(); } else { event->ignore(); } } void KoPencilTool::activate(ToolActivation, const QSet &) { m_points.clear(); m_close = false; useCursor(Qt::ArrowCursor); } void KoPencilTool::deactivate() { m_points.clear(); delete m_shape; m_shape = 0; m_existingStartPoint = 0; m_existingEndPoint = 0; m_hoveredPoint = 0; } void KoPencilTool::addPoint(const QPointF & point) { if (! m_shape) return; // do a moveTo for the first point added if (m_points.empty()) m_shape->moveTo(point); // do not allow coincident points else if (point != m_points.last()) m_shape->lineTo(point); else return; m_points.append(point); canvas()->updateCanvas(m_shape->boundingRect()); } qreal KoPencilTool::lineAngle(const QPointF &p1, const QPointF &p2) { qreal angle = atan2(p2.y() - p1.y(), p2.x() - p1.x()); if (angle < 0.0) angle += 2 * M_PI; return angle * 180.0 / M_PI; } void KoPencilTool::finish(bool closePath) { if (m_points.count() < 2) return; KoPathShape * path = 0; QList complete; QList *points = &m_points; if (m_mode == ModeStraight || m_optimizeRaw || m_optimizeCurve) { float combineAngle; if (m_mode == ModeStraight) combineAngle = m_combineAngle; else combineAngle = 0.50f; //Add the first two points complete.append(m_points[0]); complete.append(m_points[1]); //Now we need to get the angle of the first line float lastAngle = lineAngle(complete[0], complete[1]); uint pointCount = m_points.count(); for (uint i = 2; i < pointCount; ++i) { float angle = lineAngle(complete.last(), m_points[i]); if (qAbs(angle - lastAngle) < combineAngle) complete.removeLast(); complete.append(m_points[i]); lastAngle = angle; } m_points.clear(); points = &complete; } switch (m_mode) { case ModeCurve: { path = bezierFit(*points, m_fittingError); } break; case ModeStraight: case ModeRaw: { path = new KoPathShape(); uint pointCount = points->count(); path->moveTo(points->at(0)); for (uint i = 1; i < pointCount; ++i) path->lineTo(points->at(i)); } break; } if (! path) return; path->setShapeId(KoPathShapeId); path->setStroke(createStroke()); addPathShape(path, closePath); } QList > KoPencilTool::createOptionWidgets() { QList > widgets; QWidget *optionWidget = new QWidget(); QVBoxLayout * layout = new QVBoxLayout(optionWidget); QHBoxLayout *modeLayout = new QHBoxLayout; modeLayout->setSpacing(3); QLabel *modeLabel = new QLabel(i18n("Precision:"), optionWidget); QComboBox * modeBox = new QComboBox(optionWidget); modeBox->addItem(i18nc("The raw line data", "Raw")); modeBox->addItem(i18n("Curve")); modeBox->addItem(i18n("Straight")); modeLayout->addWidget(modeLabel); modeLayout->addWidget(modeBox, 1); layout->addLayout(modeLayout); QStackedWidget * stackedWidget = new QStackedWidget(optionWidget); QWidget * rawBox = new QWidget(stackedWidget); QVBoxLayout * rawLayout = new QVBoxLayout(rawBox); QCheckBox * optimizeRaw = new QCheckBox(i18n("Optimize"), rawBox); rawLayout->addWidget(optimizeRaw); rawLayout->setContentsMargins(0, 0, 0, 0); QWidget * curveBox = new QWidget(stackedWidget); QHBoxLayout * curveLayout = new QHBoxLayout(curveBox); QCheckBox * optimizeCurve = new QCheckBox(i18n("Optimize"), curveBox); - QDoubleSpinBox * fittingError = new QDoubleSpinBox(curveBox); + QDoubleSpinBox * fittingError = new KisDoubleParseSpinBox(curveBox); fittingError->setValue(0.50); fittingError->setMaximum(400.0); fittingError->setMinimum(0.0); fittingError->setSingleStep(m_fittingError); fittingError->setToolTip(i18n("Exactness:")); curveLayout->addWidget(optimizeCurve); curveLayout->addWidget(fittingError); curveLayout->setContentsMargins(0, 0, 0, 0); QWidget *straightBox = new QWidget(stackedWidget); QVBoxLayout *straightLayout = new QVBoxLayout(straightBox); - QDoubleSpinBox *combineAngle = new QDoubleSpinBox(straightBox); + QDoubleSpinBox *combineAngle = new KisDoubleParseSpinBox(straightBox); combineAngle->setValue(0.50); combineAngle->setMaximum(360.0); combineAngle->setMinimum(0.0); combineAngle->setSingleStep(m_combineAngle); combineAngle->setSuffix(" deg"); // QT5TODO //combineAngle->setLabel(i18n("Combine angle:"), Qt::AlignLeft | Qt::AlignVCenter); straightLayout->addWidget(combineAngle); straightLayout->setContentsMargins(0, 0, 0, 0); stackedWidget->addWidget(rawBox); stackedWidget->addWidget(curveBox); stackedWidget->addWidget(straightBox); layout->addWidget(stackedWidget); layout->addStretch(1); connect(modeBox, SIGNAL(activated(int)), stackedWidget, SLOT(setCurrentIndex(int))); connect(modeBox, SIGNAL(activated(int)), this, SLOT(selectMode(int))); connect(optimizeRaw, SIGNAL(stateChanged(int)), this, SLOT(setOptimize(int))); connect(optimizeCurve, SIGNAL(stateChanged(int)), this, SLOT(setOptimize(int))); connect(fittingError, SIGNAL(valueChanged(double)), this, SLOT(setDelta(double))); connect(combineAngle, SIGNAL(valueChanged(double)), this, SLOT(setDelta(double))); modeBox->setCurrentIndex(m_mode); stackedWidget->setCurrentIndex(m_mode); optionWidget->setObjectName(i18n("Pencil")); optionWidget->setWindowTitle(i18n("Pencil")); widgets.append(optionWidget); m_strokeWidget = new KoStrokeConfigWidget(0); m_strokeWidget->setWindowTitle(i18n("Line")); m_strokeWidget->setCanvas(canvas()); widgets.append(m_strokeWidget); return widgets; } void KoPencilTool::addPathShape(KoPathShape* path, bool closePath) { KoShape * startShape = 0; KoShape * endShape = 0; if (closePath) { path->close(); path->normalize(); } else { path->normalize(); if (connectPaths(path, m_existingStartPoint, m_existingEndPoint)) { if (m_existingStartPoint) startShape = m_existingStartPoint->parent(); if (m_existingEndPoint && m_existingEndPoint != m_existingStartPoint) endShape = m_existingEndPoint->parent(); } } KUndo2Command * cmd = canvas()->shapeController()->addShape(path); if (cmd) { KoSelection *selection = canvas()->shapeManager()->selection(); selection->deselectAll(); selection->select(path); if (startShape) canvas()->shapeController()->removeShape(startShape, cmd); if (endShape && startShape != endShape) canvas()->shapeController()->removeShape(endShape, cmd); canvas()->addCommand(cmd); } else { canvas()->updateCanvas(path->boundingRect()); delete path; } } void KoPencilTool::selectMode(int mode) { m_mode = static_cast(mode); } void KoPencilTool::setOptimize(int state) { if (m_mode == ModeRaw) m_optimizeRaw = state == Qt::Checked ? true : false; else m_optimizeCurve = state == Qt::Checked ? true : false; } void KoPencilTool::setDelta(double delta) { if (m_mode == ModeCurve) m_fittingError = delta; else if (m_mode == ModeStraight) m_combineAngle = delta; } KoShapeStroke* KoPencilTool::createStroke() { KoShapeStroke *stroke = 0; if (m_strokeWidget) { stroke = m_strokeWidget->createShapeStroke(); } return stroke; } KoPathPoint* KoPencilTool::endPointAtPosition(const QPointF &position) { QRectF roi = handleGrabRect(position); QList shapes = canvas()->shapeManager()->shapesAt(roi); KoPathPoint * nearestPoint = 0; qreal minDistance = HUGE_VAL; qreal maxDistance = canvas()->viewConverter()->viewToDocumentX(grabSensitivity()); Q_FOREACH(KoShape * shape, shapes) { KoPathShape * path = dynamic_cast(shape); if (!path) continue; KoParameterShape *paramShape = dynamic_cast(shape); if (paramShape && paramShape->isParametricShape()) continue; KoPathPoint * p = 0; uint subpathCount = path->subpathCount(); for (uint i = 0; i < subpathCount; ++i) { if (path->isClosedSubpath(i)) continue; p = path->pointByIndex(KoPathPointIndex(i, 0)); // check start of subpath qreal d = squareDistance(position, path->shapeToDocument(p->point())); if (d < minDistance && d < maxDistance) { nearestPoint = p; minDistance = d; } // check end of subpath p = path->pointByIndex(KoPathPointIndex(i, path->subpathPointCount(i) - 1)); d = squareDistance(position, path->shapeToDocument(p->point())); if (d < minDistance && d < maxDistance) { nearestPoint = p; minDistance = d; } } } return nearestPoint; } bool KoPencilTool::connectPaths(KoPathShape *pathShape, KoPathPoint *pointAtStart, KoPathPoint *pointAtEnd) { // at least one point must be valid if (!pointAtStart && !pointAtEnd) return false; // do not allow connecting to the same point twice if (pointAtStart == pointAtEnd) pointAtEnd = 0; // we have hit an existing path point on start/finish // what we now do is: // 1. combine the new created path with the ones we hit on start/finish // 2. merge the endpoints of the corresponding subpaths uint newPointCount = pathShape->subpathPointCount(0); KoPathPointIndex newStartPointIndex(0, 0); KoPathPointIndex newEndPointIndex(0, newPointCount - 1); KoPathPoint * newStartPoint = pathShape->pointByIndex(newStartPointIndex); KoPathPoint * newEndPoint = pathShape->pointByIndex(newEndPointIndex); KoPathShape * startShape = pointAtStart ? pointAtStart->parent() : 0; KoPathShape * endShape = pointAtEnd ? pointAtEnd->parent() : 0; // combine with the path we hit on start KoPathPointIndex startIndex(-1, -1); if (pointAtStart) { startIndex = startShape->pathPointIndex(pointAtStart); pathShape->combine(startShape); pathShape->moveSubpath(0, pathShape->subpathCount() - 1); } // combine with the path we hit on finish KoPathPointIndex endIndex(-1, -1); if (pointAtEnd) { endIndex = endShape->pathPointIndex(pointAtEnd); if (endShape != startShape) { endIndex.first += pathShape->subpathCount(); pathShape->combine(endShape); } } // do we connect twice to a single subpath ? bool connectToSingleSubpath = (startShape == endShape && startIndex.first == endIndex.first); if (startIndex.second == 0 && !connectToSingleSubpath) { pathShape->reverseSubpath(startIndex.first); startIndex.second = pathShape->subpathPointCount(startIndex.first) - 1; } if (endIndex.second > 0 && !connectToSingleSubpath) { pathShape->reverseSubpath(endIndex.first); endIndex.second = 0; } // after combining we have a path where with the subpaths in the following // order: // 1. the subpaths of the pathshape we started the new path at // 2. the subpath we just created // 3. the subpaths of the pathshape we finished the new path at // get the path points we want to merge, as these are not going to // change while merging KoPathPoint * existingStartPoint = pathShape->pointByIndex(startIndex); KoPathPoint * existingEndPoint = pathShape->pointByIndex(endIndex); // merge first two points if (existingStartPoint) { KoPathPointData pd1(pathShape, pathShape->pathPointIndex(existingStartPoint)); KoPathPointData pd2(pathShape, pathShape->pathPointIndex(newStartPoint)); KoPathPointMergeCommand cmd1(pd1, pd2); cmd1.redo(); } // merge last two points if (existingEndPoint) { KoPathPointData pd3(pathShape, pathShape->pathPointIndex(newEndPoint)); KoPathPointData pd4(pathShape, pathShape->pathPointIndex(existingEndPoint)); KoPathPointMergeCommand cmd2(pd3, pd4); cmd2.redo(); } return true; } qreal KoPencilTool::getFittingError() { return this->m_fittingError; } void KoPencilTool::setFittingError(qreal fittingError) { this->m_fittingError = fittingError; } diff --git a/libs/ui/CMakeLists.txt b/libs/ui/CMakeLists.txt index a0e9bd345b..fbf75905ad 100644 --- a/libs/ui/CMakeLists.txt +++ b/libs/ui/CMakeLists.txt @@ -1,540 +1,543 @@ # Disable -Wswitch because of the extra definitions we here: # kis_input_manager.cpp: In member function ‘virtual bool KisInputManager::eventFilter(QObject*, QEvent*)’: # warning: case value ‘1001’ not in enumerated type ‘QEvent::Type’ [-Wswitch] # warning: case value ‘1002’ not in enumerated type ‘QEvent::Type’ [-Wswitch] if (CMAKE_COMPILER_IS_GNUCXX) add_definitions(${KDE4_ENABLE_EXCEPTIONS} -Wno-switch) endif () include_directories( ${CMAKE_CURRENT_SOURCE_DIR}/qtlockedfile ${EXIV2_INCLUDE_DIR} ) include_directories(SYSTEM ${EIGEN3_INCLUDE_DIR} ${OCIO_INCLUDE_DIR} ${Boost_INCLUDE_DIRS} ) add_subdirectory( tests ) if (APPLE) find_library(FOUNDATION_LIBRARY Foundation) endif () set(kritaui_LIB_SRCS canvas/kis_canvas_widget_base.cpp canvas/kis_canvas2.cpp canvas/kis_canvas_updates_compressor.cpp canvas/kis_canvas_controller.cpp canvas/kis_paintop_transformation_connector.cpp canvas/kis_display_color_converter.cpp canvas/kis_display_filter.cpp canvas/kis_exposure_gamma_correction_interface.cpp canvas/kis_tool_proxy.cpp canvas/kis_canvas_decoration.cc canvas/kis_coordinates_converter.cpp canvas/kis_grid_manager.cpp canvas/kis_grid_decoration.cpp canvas/kis_grid_config.cpp canvas/kis_prescaled_projection.cpp canvas/kis_qpainter_canvas.cpp canvas/kis_projection_backend.cpp canvas/kis_update_info.cpp canvas/kis_image_patch.cpp canvas/kis_image_pyramid.cpp canvas/kis_infinity_manager.cpp canvas/kis_change_guides_command.cpp canvas/kis_guides_decoration.cpp canvas/kis_guides_manager.cpp canvas/kis_guides_config.cpp canvas/kis_snap_config.cpp canvas/kis_snap_line_strategy.cpp dialogs/kis_about_application.cpp dialogs/kis_dlg_adj_layer_props.cc dialogs/kis_dlg_adjustment_layer.cc dialogs/kis_dlg_filter.cpp dialogs/kis_dlg_generator_layer.cpp dialogs/kis_dlg_file_layer.cpp dialogs/kis_dlg_image_properties.cc dialogs/kis_dlg_layer_properties.cc dialogs/kis_dlg_preferences.cc dialogs/slider_and_spin_box_sync.cpp dialogs/kis_dlg_blacklist_cleanup.cpp dialogs/kis_dlg_layer_style.cpp dialogs/kis_dlg_png_import.cpp dialogs/kis_dlg_import_image_sequence.cpp dialogs/kis_delayed_save_dialog.cpp flake/kis_node_dummies_graph.cpp flake/kis_dummies_facade_base.cpp flake/kis_dummies_facade.cpp flake/kis_node_shapes_graph.cpp flake/kis_node_shape.cpp flake/kis_shape_controller.cpp flake/kis_shape_layer.cc flake/kis_shape_layer_canvas.cpp flake/kis_shape_selection.cpp flake/kis_shape_selection_canvas.cpp flake/kis_shape_selection_model.cpp flake/kis_take_all_shapes_command.cpp brushhud/kis_uniform_paintop_property_widget.cpp brushhud/kis_brush_hud.cpp brushhud/kis_round_hud_button.cpp brushhud/kis_dlg_brush_hud_config.cpp brushhud/kis_brush_hud_properties_list.cpp brushhud/kis_brush_hud_properties_config.cpp kis_aspect_ratio_locker.cpp kis_autogradient.cc kis_bookmarked_configurations_editor.cc kis_bookmarked_configurations_model.cc kis_bookmarked_filter_configurations_model.cc kis_canvas_resource_provider.cpp kis_derived_resources.cpp kis_categories_mapper.cpp kis_categorized_list_model.cpp kis_categorized_item_delegate.cpp kis_clipboard.cc kis_config.cc kis_config_notifier.cpp kis_control_frame.cpp kis_composite_ops_model.cc kis_paint_ops_model.cpp kis_cursor.cc kis_cursor_cache.cpp kis_custom_pattern.cc kis_file_layer.cpp kis_safe_document_loader.cpp kis_splash_screen.cpp kis_filter_manager.cc kis_filters_model.cc kis_histogram_view.cc kis_image_manager.cc kis_image_view_converter.cpp kis_import_catcher.cc kis_layer_manager.cc kis_mask_manager.cc kis_mimedata.cpp kis_node_commands_adapter.cpp kis_node_manager.cpp kis_node_juggler_compressed.cpp kis_node_selection_adapter.cpp kis_node_insertion_adapter.cpp kis_node_model.cpp kis_node_filter_proxy_model.cpp kis_model_index_converter_base.cpp kis_model_index_converter.cpp kis_model_index_converter_show_all.cpp kis_painting_assistant.cc kis_painting_assistants_decoration.cpp kis_painting_assistants_manager.cpp kis_paintop_box.cc kis_paintop_option.cpp kis_paintop_options_model.cpp kis_paintop_settings_widget.cpp kis_popup_palette.cpp kis_png_converter.cpp kis_preference_set_registry.cpp kis_resource_server_provider.cpp kis_selection_decoration.cc kis_selection_manager.cc kis_statusbar.cc kis_zoom_manager.cc kis_favorite_resource_manager.cpp kis_workspace_resource.cpp kis_action.cpp kis_action_manager.cpp kis_view_plugin.cpp kis_canvas_controls_manager.cpp kis_tooltip_manager.cpp kis_multinode_property.cpp kis_async_action_feedback.cpp kisexiv2/kis_exif_io.cpp kisexiv2/kis_exiv2.cpp kisexiv2/kis_iptc_io.cpp kisexiv2/kis_xmp_io.cpp kra/kis_kra_utils.cpp kra/kis_kra_load_visitor.cpp kra/kis_kra_loader.cpp kra/kis_kra_save_visitor.cpp kra/kis_kra_saver.cpp kra/kis_kra_savexml_visitor.cpp opengl/kis_opengl.cpp opengl/kis_opengl_canvas2.cpp opengl/kis_opengl_canvas_debugger.cpp opengl/kis_opengl_image_textures.cpp opengl/kis_texture_tile.cpp kis_fps_decoration.cpp ora/kis_open_raster_stack_load_visitor.cpp ora/kis_open_raster_stack_save_visitor.cpp ora/ora_load_context.cc ora/ora_save_context.cc recorder/kis_node_query_path_editor.cc recorder/kis_recorded_action_creator.cc recorder/kis_recorded_action_creator_factory.cc recorder/kis_recorded_action_creator_factory_registry.cc recorder/kis_recorded_action_editor_factory.cc recorder/kis_recorded_action_editor_factory_registry.cc recorder/kis_recorded_filter_action_editor.cc recorder/kis_recorded_filter_action_creator.cpp recorder/kis_recorded_paint_action_editor.cc tool/kis_selection_tool_helper.cpp tool/kis_selection_tool_config_widget_helper.cpp tool/kis_rectangle_constraint_widget.cpp tool/kis_shape_tool_helper.cpp tool/kis_tool.cc tool/kis_delegated_tool_policies.cpp tool/kis_tool_freehand.cc tool/kis_speed_smoother.cpp tool/kis_painting_information_builder.cpp tool/kis_stabilized_events_sampler.cpp tool/kis_tool_freehand_helper.cpp tool/kis_tool_multihand_helper.cpp tool/kis_figure_painting_tool_helper.cpp tool/kis_recording_adapter.cpp tool/kis_tool_paint.cc tool/kis_tool_shape.cc tool/kis_tool_ellipse_base.cpp tool/kis_tool_rectangle_base.cpp tool/kis_tool_polyline_base.cpp tool/kis_tool_utils.cpp tool/kis_resources_snapshot.cpp tool/kis_smoothing_options.cpp tool/strokes/freehand_stroke.cpp tool/strokes/kis_painter_based_stroke_strategy.cpp tool/strokes/kis_filter_stroke_strategy.cpp tool/strokes/kis_color_picker_stroke_strategy.cpp widgets/kis_cmb_composite.cc widgets/kis_cmb_contour.cpp widgets/kis_cmb_gradient.cpp widgets/kis_paintop_list_widget.cpp widgets/kis_cmb_idlist.cc widgets/kis_color_space_selector.cc widgets/kis_advanced_color_space_selector.cc widgets/kis_cie_tongue_widget.cpp widgets/kis_tone_curve_widget.cpp widgets/kis_curve_widget.cpp widgets/kis_custom_image_widget.cc widgets/kis_image_from_clipboard_widget.cpp widgets/kis_double_widget.cc widgets/kis_filter_selector_widget.cc widgets/kis_gradient_chooser.cc widgets/kis_gradient_slider_widget.cc widgets/kis_gradient_slider.cpp widgets/kis_iconwidget.cc widgets/kis_mask_widgets.cpp widgets/kis_meta_data_merge_strategy_chooser_widget.cc widgets/kis_multi_bool_filter_widget.cc widgets/kis_multi_double_filter_widget.cc widgets/kis_multi_integer_filter_widget.cc widgets/kis_multipliers_double_slider_spinbox.cpp widgets/kis_paintop_presets_popup.cpp widgets/kis_tool_options_popup.cpp widgets/kis_paintop_presets_chooser_popup.cpp widgets/kis_pattern_chooser.cc widgets/kis_popup_button.cc widgets/kis_preset_chooser.cpp widgets/kis_progress_widget.cpp widgets/kis_selection_options.cc widgets/kis_scratch_pad.cpp widgets/kis_scratch_pad_event_filter.cpp widgets/kis_preset_selector_strip.cpp widgets/kis_slider_spin_box.cpp widgets/kis_size_group.cpp widgets/kis_size_group_p.cpp widgets/kis_wdg_generator.cpp widgets/kis_workspace_chooser.cpp widgets/squeezedcombobox.cpp widgets/kis_categorized_list_view.cpp widgets/kis_widget_chooser.cpp widgets/kis_tool_button.cpp widgets/kis_floating_message.cpp widgets/kis_lod_availability_widget.cpp widgets/kis_color_label_selector_widget.cpp widgets/kis_color_filter_combo.cpp widgets/kis_elided_label.cpp + input/kis_input_manager.cpp input/kis_input_manager_p.cpp input/kis_extended_modifiers_mapper.cpp input/kis_abstract_input_action.cpp input/kis_tool_invocation_action.cpp input/kis_pan_action.cpp input/kis_alternate_invocation_action.cpp input/kis_rotate_canvas_action.cpp input/kis_zoom_action.cpp input/kis_change_frame_action.cpp input/kis_gamma_exposure_action.cpp input/kis_show_palette_action.cpp input/kis_change_primary_setting_action.cpp input/kis_abstract_shortcut.cpp input/kis_single_action_shortcut.cpp input/kis_stroke_shortcut.cpp input/kis_shortcut_matcher.cpp input/kis_select_layer_action.cpp operations/kis_operation.cpp operations/kis_operation_configuration.cpp operations/kis_operation_registry.cpp operations/kis_operation_ui_factory.cpp operations/kis_operation_ui_widget.cpp operations/kis_filter_selection_operation.cpp actions/kis_selection_action_factories.cpp input/kis_touch_shortcut.cpp kis_document_undo_store.cpp kis_transaction_based_command.cpp kis_gui_context_command.cpp kis_gui_context_command_p.cpp input/kis_tablet_debugger.cpp input/kis_input_profile_manager.cpp input/kis_input_profile.cpp input/kis_shortcut_configuration.cpp input/config/kis_input_configuration_page.cpp input/config/kis_edit_profiles_dialog.cpp input/config/kis_input_profile_model.cpp input/config/kis_input_configuration_page_item.cpp input/config/kis_action_shortcuts_model.cpp input/config/kis_input_type_delegate.cpp input/config/kis_input_mode_delegate.cpp input/config/kis_input_button.cpp input/config/kis_input_editor_delegate.cpp input/config/kis_mouse_input_editor.cpp input/config/kis_wheel_input_editor.cpp input/config/kis_key_input_editor.cpp processing/fill_processing_visitor.cpp kis_asl_layer_style_serializer.cpp kis_psd_layer_style_resource.cpp canvas/kis_mirror_axis.cpp kis_abstract_perspective_grid.cpp KisApplication.cpp KisAutoSaveRecoveryDialog.cpp KisDetailsPane.cpp KisDocument.cpp KisNodeDelegate.cpp kis_node_view_visibility_delegate.cpp KisNodeToolTip.cpp KisNodeView.cpp kis_node_view_color_scheme.cpp KisFilterChain.cpp KisFilterChainLink.cpp KisFilterChainLinkList.cpp KisImportExportFilter.cpp KisFilterEdge.cpp KisFilterEntry.cpp KisFilterGraph.cpp KisImportExportManager.cpp KisFilterVertex.cpp KisMainWindow.cpp KisOpenPane.cpp KisPart.cpp KisPrintJob.cpp KisTemplate.cpp KisTemplateCreateDia.cpp KisTemplateGroup.cpp KisTemplates.cpp KisTemplatesPane.cpp KisTemplateTree.cpp KisUndoStackAction.cpp KisView.cpp thememanager.cpp kis_mainwindow_observer.cpp KisViewManager.cpp kis_mirror_manager.cpp qtlockedfile/qtlockedfile.cpp qtsingleapplication/qtlocalpeer.cpp qtsingleapplication/qtsingleapplication.cpp KisResourceBundle.cpp KisResourceBundleManifest.cpp kis_md5_generator.cpp KisApplicationArguments.cpp KisNetworkAccessManager.cpp KisMultiFeedRSSModel.cpp KisRemoteFileFetcher.cpp KisPaletteModel.cpp KisColorsetChooser.cpp KisSaveGroupVisitor.cpp ) if(WIN32) if (NOT Qt5Gui_PRIVATE_INCLUDE_DIRS) message(FATAL_ERROR "Qt5Gui Private header are missing!") endif() set(kritaui_LIB_SRCS ${kritaui_LIB_SRCS} input/kis_tablet_event.cpp input/wintab/kis_tablet_support_win.cpp input/wintab/kis_screen_size_choice_dialog.cpp qtlockedfile/qtlockedfile_win.cpp ) include_directories(${Qt5Gui_PRIVATE_INCLUDE_DIRS}) endif() set(kritaui_LIB_SRCS ${kritaui_LIB_SRCS} kis_animation_frame_cache.cpp kis_animation_cache_populator.cpp canvas/kis_animation_player.cpp kis_animation_exporter.cpp kis_animation_importer.cpp ) if(UNIX) set(kritaui_LIB_SRCS ${kritaui_LIB_SRCS} input/kis_tablet_event.cpp input/wintab/kis_tablet_support.cpp qtlockedfile/qtlockedfile_unix.cpp ) if(NOT APPLE) set(kritaui_LIB_SRCS ${kritaui_LIB_SRCS} input/wintab/kis_tablet_support_x11.cpp input/wintab/qxcbconnection_xi2.cpp input/wintab/qxcbconnection.cpp input/wintab/kis_xi2_event_filter.cpp ) endif() endif() if(WIN32) #ki18n_wrap_ui( # input/wintab/kis_screen_size_choice_dialog.ui #) endif() ki18n_wrap_ui(kritaui_LIB_SRCS forms/wdgdlgpngimport.ui forms/wdgfullscreensettings.ui forms/wdgautogradient.ui forms/wdggeneralsettings.ui forms/wdgperformancesettings.ui forms/wdggenerators.ui forms/wdgcustompalette.ui forms/wdgbookmarkedconfigurationseditor.ui forms/wdgapplyprofile.ui forms/wdgcustompattern.ui forms/wdglayerproperties.ui forms/wdgcolorsettings.ui forms/wdgtabletsettings.ui forms/wdgcolorspaceselector.ui forms/wdgcolorspaceselectoradvanced.ui forms/wdgdisplaysettings.ui forms/kis_previewwidgetbase.ui forms/kis_matrix_widget.ui forms/wdgselectionoptions.ui forms/wdggeometryoptions.ui forms/wdgnewimage.ui forms/wdgimageproperties.ui forms/wdgmaskfromselection.ui forms/wdgmasksource.ui forms/wdgfilterdialog.ui forms/wdgmetadatamergestrategychooser.ui forms/wdgpaintoppresets.ui forms/wdgpaintopsettings.ui forms/wdgdlggeneratorlayer.ui forms/wdgdlgfilelayer.ui forms/wdgfilterselector.ui forms/wdgfilternodecreation.ui forms/wdgpaintactioneditor.ui forms/wdgmultipliersdoublesliderspinbox.ui forms/wdgnodequerypatheditor.ui forms/wdgpresetselectorstrip.ui forms/wdgdlgblacklistcleanup.ui forms/wdgrectangleconstraints.ui forms/wdgimportimagesequence.ui forms/KisDetailsPaneBase.ui forms/KisOpenPaneBase.ui brushhud/kis_dlg_brush_hud_config.ui dialogs/kis_delayed_save_dialog.ui input/config/kis_input_configuration_page.ui input/config/kis_edit_profiles_dialog.ui input/config/kis_input_configuration_page_item.ui input/config/kis_mouse_input_editor.ui input/config/kis_wheel_input_editor.ui input/config/kis_key_input_editor.ui layerstyles/wdgBevelAndEmboss.ui layerstyles/wdgblendingoptions.ui layerstyles/WdgColorOverlay.ui layerstyles/wdgContour.ui layerstyles/wdgdropshadow.ui layerstyles/WdgGradientOverlay.ui layerstyles/wdgInnerGlow.ui layerstyles/wdglayerstyles.ui layerstyles/WdgPatternOverlay.ui layerstyles/WdgSatin.ui layerstyles/WdgStroke.ui layerstyles/wdgstylesselector.ui layerstyles/wdgTexture.ui wdgsplash.ui input/wintab/kis_screen_size_choice_dialog.ui + ) QT5_WRAP_CPP(kritaui_HEADERS_MOC KisNodePropertyAction_p.h) add_library(kritaui SHARED ${kritaui_HEADERS_MOC} ${kritaui_LIB_SRCS} ) generate_export_header(kritaui BASE_NAME kritaui) target_link_libraries(kritaui KF5::CoreAddons KF5::Completion KF5::I18n KF5::ItemViews Qt5::Network kritacolor kritaimage kritalibbrush kritawidgets kritawidgetutils ${PNG_LIBRARIES} ${EXIV2_LIBRARIES} ) if (HAVE_KIO) target_link_libraries(kritaui KF5::KIOCore) endif() if (NOT WIN32 AND NOT APPLE) target_link_libraries(kritaui ${X11_X11_LIB} ${X11_Xinput_LIB} ${XCB_LIBRARIES}) endif() if(APPLE) target_link_libraries(kritaui ${FOUNDATION_LIBRARY}) endif () target_link_libraries(kritaui ${OPENEXR_LIBRARIES}) # Add VSync disable workaround if(NOT WIN32 AND NOT APPLE) target_link_libraries(kritaui ${CMAKE_DL_LIBS} Qt5::X11Extras) endif() if(X11_FOUND) target_link_libraries(kritaui Qt5::X11Extras ${X11_LIBRARIES}) endif() target_link_libraries(kritaui LINK_INTERFACE_LIBRARIES kritaimage kritalibbrush kritapigment KF5::Completion KF5::I18n ${GL_INTERFACE_LIBRARIES}) target_include_directories(kritaui PUBLIC $ $ $ $ + $ $ $ ) set_target_properties(kritaui PROPERTIES VERSION ${GENERIC_KRITA_LIB_VERSION} SOVERSION ${GENERIC_KRITA_LIB_SOVERSION} ) install(TARGETS kritaui ${INSTALL_TARGETS_DEFAULT_ARGS}) if (APPLE) install(FILES osx.stylesheet DESTINATION ${DATA_INSTALL_DIR}/krita) endif () diff --git a/libs/ui/KisColorsetChooser.cpp b/libs/ui/KisColorsetChooser.cpp index 955917f51f..2f730f96c9 100644 --- a/libs/ui/KisColorsetChooser.cpp +++ b/libs/ui/KisColorsetChooser.cpp @@ -1,157 +1,159 @@ /* This file is part of the KDE project * Copyright (C) 2013 Sven Langkamp * * 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. */ #include "KisColorsetChooser.h" #include #include #include #include #include #include #include #include #include #include #include #include #include "kis_resource_server_provider.h" #include "KisViewManager.h" #include #include #include #include #include +#include "kis_int_parse_spin_box.h" + class ColorSetDelegate : public QAbstractItemDelegate { public: ColorSetDelegate(QObject * parent = 0) : QAbstractItemDelegate(parent) {} virtual ~ColorSetDelegate() {} /// reimplemented virtual void paint(QPainter *, const QStyleOptionViewItem &, const QModelIndex &) const; /// reimplemented QSize sizeHint(const QStyleOptionViewItem & option, const QModelIndex &) const { return option.decorationSize; } }; void ColorSetDelegate::paint(QPainter * painter, const QStyleOptionViewItem & option, const QModelIndex & index) const { painter->save(); if (! index.isValid()) return; KoResource* resource = static_cast(index.internalPointer()); KoColorSet* colorSet = static_cast(resource); if (option.state & QStyle::State_Selected) { painter->fillRect(option.rect, option.palette.highlight()); painter->setPen(option.palette.highlightedText().color()); } else { painter->setBrush(option.palette.text().color()); } painter->drawText(option.rect.x() + 5, option.rect.y() + painter->fontMetrics().ascent() + 5, colorSet->name()); int size = 7; for (int i = 0; i < colorSet->nColors() && i*size < option.rect.width(); i++) { QRect rect(option.rect.x() + i*size, option.rect.y() + option.rect.height() - size, size, size); painter->fillRect(rect, colorSet->getColor(i).color.toQColor()); } painter->restore(); } KisColorsetChooser::KisColorsetChooser(QWidget* parent): QWidget(parent) { KoResourceServer * rserver = KoResourceServerProvider::instance()->paletteServer(false); QSharedPointer adapter(new KoResourceServerAdapter(rserver)); m_itemChooser = new KoResourceItemChooser(adapter, this); m_itemChooser->setItemDelegate(new ColorSetDelegate(this)); m_itemChooser->setFixedSize(250, 250); m_itemChooser->setRowHeight(30); m_itemChooser->setColumnCount(1); connect(m_itemChooser, SIGNAL(resourceSelected(KoResource*)), this, SLOT(resourceSelected(KoResource*))); QPushButton* saveButton = new QPushButton(i18n("Save")); connect(saveButton, SIGNAL(clicked(bool)), this, SLOT(slotSave())); m_nameEdit = new QLineEdit(this); m_nameEdit->setPlaceholderText(i18n("Insert name")); m_nameEdit->setClearButtonEnabled(true); - m_columnEdit = new QSpinBox(this); + m_columnEdit = new KisIntParseSpinBox(this); m_columnEdit->setRange(1, 30); m_columnEdit->setValue(10); QGridLayout* layout = new QGridLayout(this); layout->addWidget(m_itemChooser, 0, 0, 1, 3); layout->addWidget(new QLabel(i18n("Name:"), this), 1, 0, 1, 1); layout->addWidget(m_nameEdit, 1, 1, 1, 2); layout->addWidget(new QLabel(i18n("Columns:"), this), 2, 0, 1, 1); layout->addWidget(m_columnEdit, 2, 1, 1, 1); layout->addWidget(saveButton, 2, 2, 1, 1); layout->setColumnStretch(1, 1); } KisColorsetChooser::~KisColorsetChooser() { } void KisColorsetChooser::resourceSelected(KoResource* resource) { emit paletteSelected(static_cast(resource)); } void KisColorsetChooser::slotSave() { KoResourceServer * rserver = KoResourceServerProvider::instance()->paletteServer(); KoColorSet* colorset = new KoColorSet(); colorset->setValid(true); QString saveLocation = rserver->saveLocation(); QString name = m_nameEdit->text(); int columns = m_columnEdit->value(); bool newName = false; if(name.isEmpty()) { newName = true; name = i18n("Palette"); } QFileInfo fileInfo(saveLocation + name + colorset->defaultFileExtension()); int i = 1; while (fileInfo.exists()) { fileInfo.setFile(saveLocation + name + QString("%1").arg(i) + colorset->defaultFileExtension()); i++; } colorset->setFilename(fileInfo.filePath()); if(newName) { name = i18n("Palette %1", i); } colorset->setName(name); colorset->setColumnCount(columns); rserver->addResource(colorset); } diff --git a/libs/ui/dialogs/kis_dlg_preferences.cc b/libs/ui/dialogs/kis_dlg_preferences.cc index 6657074862..3835c53c2a 100644 --- a/libs/ui/dialogs/kis_dlg_preferences.cc +++ b/libs/ui/dialogs/kis_dlg_preferences.cc @@ -1,1037 +1,1037 @@ /* * preferencesdlg.cc - part of KImageShop * * Copyright (c) 1999 Michael Koch * Copyright (c) 2003-2011 Boudewijn Rempt * * 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_dlg_preferences.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "KoID.h" #include #include #include #include #include #include "kis_action_registry.h" #include "widgets/squeezedcombobox.h" #include "kis_clipboard.h" #include "widgets/kis_cmb_idlist.h" #include "KoColorSpace.h" #include "KoColorSpaceRegistry.h" #include "KoColorConversionTransformation.h" #include "kis_cursor.h" #include "kis_config.h" #include "kis_canvas_resource_provider.h" #include "kis_preference_set_registry.h" #include "kis_color_manager.h" #include "KisProofingConfiguration.h" #include "kis_image_config.h" #include "slider_and_spin_box_sync.h" // for the performance update #include #include "input/config/kis_input_configuration_page.h" GeneralTab::GeneralTab(QWidget *_parent, const char *_name) : WdgGeneralSettings(_parent, _name) { KisConfig cfg; m_cmbCursorShape->addItem(i18n("No Cursor")); m_cmbCursorShape->addItem(i18n("Tool Icon")); m_cmbCursorShape->addItem(i18n("Arrow")); m_cmbCursorShape->addItem(i18n("Small Circle")); m_cmbCursorShape->addItem(i18n("Crosshair")); m_cmbCursorShape->addItem(i18n("Triangle Righthanded")); m_cmbCursorShape->addItem(i18n("Triangle Lefthanded")); m_cmbCursorShape->addItem(i18n("Black Pixel")); m_cmbCursorShape->addItem(i18n("White Pixel")); m_cmbOutlineShape->addItem(i18n("No Outline")); m_cmbOutlineShape->addItem(i18n("Circle Outline")); m_cmbOutlineShape->addItem(i18n("Preview Outline")); m_cmbOutlineShape->addItem(i18n("Tilt Outline")); m_cmbCursorShape->setCurrentIndex(cfg.newCursorStyle()); m_cmbOutlineShape->setCurrentIndex(cfg.newOutlineStyle()); chkShowRootLayer->setChecked(cfg.showRootLayer()); int autosaveInterval = cfg.autoSaveInterval(); //convert to minutes m_autosaveSpinBox->setValue(autosaveInterval / 60); m_autosaveCheckBox->setChecked(autosaveInterval > 0); m_undoStackSize->setValue(cfg.undoStackLimit()); m_backupFileCheckBox->setChecked(cfg.backupFile()); m_showOutlinePainting->setChecked(cfg.showOutlineWhilePainting()); m_hideSplashScreen->setChecked(cfg.hideSplashScreen()); m_cmbMDIType->setCurrentIndex(cfg.readEntry("mdi_viewmode", (int)QMdiArea::TabbedView)); m_chkRubberBand->setChecked(cfg.readEntry("mdi_rubberband", cfg.useOpenGL())); m_favoritePresetsSpinBox->setValue(cfg.favoritePresets()); m_mdiColor->setColor(cfg.getMDIBackgroundColor()); m_backgroundimage->setText(cfg.getMDIBackgroundImage()); m_chkCanvasMessages->setChecked(cfg.showCanvasMessages()); m_chkCompressKra->setChecked(cfg.compressKra()); m_radioToolOptionsInDocker->setChecked(cfg.toolOptionsInDocker()); m_chkSwitchSelectionCtrlAlt->setChecked(cfg.switchSelectionCtrlAlt()); m_chkConvertOnImport->setChecked(cfg.convertToImageColorspaceOnImport()); connect(m_bnFileName, SIGNAL(clicked()), SLOT(getBackgroundImage())); connect(clearBgImageButton, SIGNAL(clicked()), SLOT(clearBackgroundImage())); } void GeneralTab::setDefault() { KisConfig cfg; m_cmbCursorShape->setCurrentIndex(cfg.newCursorStyle(true)); m_cmbOutlineShape->setCurrentIndex(cfg.newOutlineStyle(true)); chkShowRootLayer->setChecked(cfg.showRootLayer(true)); m_autosaveCheckBox->setChecked(cfg.autoSaveInterval(true) > 0); //convert to minutes m_autosaveSpinBox->setValue(cfg.autoSaveInterval(true) / 60); m_undoStackSize->setValue(cfg.undoStackLimit(true)); m_backupFileCheckBox->setChecked(cfg.backupFile(true)); m_showOutlinePainting->setChecked(cfg.showOutlineWhilePainting(true)); m_hideSplashScreen->setChecked(cfg.hideSplashScreen(true)); m_cmbMDIType->setCurrentIndex((int)QMdiArea::TabbedView); m_chkRubberBand->setChecked(cfg.useOpenGL(true)); m_favoritePresetsSpinBox->setValue(cfg.favoritePresets(true)); m_mdiColor->setColor(cfg.getMDIBackgroundColor(true)); m_backgroundimage->setText(cfg.getMDIBackgroundImage(true)); m_chkCanvasMessages->setChecked(cfg.showCanvasMessages(true)); m_chkCompressKra->setChecked(cfg.compressKra(true)); m_radioToolOptionsInDocker->setChecked(cfg.toolOptionsInDocker(true)); m_chkSwitchSelectionCtrlAlt->setChecked(cfg.switchSelectionCtrlAlt(true)); m_chkConvertOnImport->setChecked(cfg.convertToImageColorspaceOnImport(true)); } CursorStyle GeneralTab::cursorStyle() { return (CursorStyle)m_cmbCursorShape->currentIndex(); } OutlineStyle GeneralTab::outlineStyle() { return (OutlineStyle)m_cmbOutlineShape->currentIndex(); } bool GeneralTab::showRootLayer() { return chkShowRootLayer->isChecked(); } int GeneralTab::autoSaveInterval() { //convert to seconds return m_autosaveCheckBox->isChecked() ? m_autosaveSpinBox->value()*60 : 0; } int GeneralTab::undoStackSize() { return m_undoStackSize->value(); } bool GeneralTab::showOutlineWhilePainting() { return m_showOutlinePainting->isChecked(); } bool GeneralTab::hideSplashScreen() { return m_hideSplashScreen->isChecked(); } int GeneralTab::mdiMode() { return m_cmbMDIType->currentIndex(); } int GeneralTab::favoritePresets() { return m_favoritePresetsSpinBox->value(); } bool GeneralTab::showCanvasMessages() { return m_chkCanvasMessages->isChecked(); } bool GeneralTab::compressKra() { return m_chkCompressKra->isChecked(); } bool GeneralTab::toolOptionsInDocker() { return m_radioToolOptionsInDocker->isChecked(); } bool GeneralTab::switchSelectionCtrlAlt() { return m_chkSwitchSelectionCtrlAlt->isChecked(); } bool GeneralTab::convertToImageColorspaceOnImport() { return m_chkConvertOnImport->isChecked(); } void GeneralTab::getBackgroundImage() { KoFileDialog dialog(this, KoFileDialog::OpenFile, "BackgroundImages"); dialog.setCaption(i18n("Select a Background Image")); dialog.setDefaultDir(QDesktopServices::storageLocation(QDesktopServices::PicturesLocation)); dialog.setImageFilters(); QString fn = dialog.filename(); // dialog box was canceled or somehow no file was selected if (fn.isEmpty()) { return; } QImage image(fn); if (image.isNull()) { QMessageBox::warning(this, i18nc("@title:window", "Krita"), i18n("%1 is not a valid image file!", fn)); } else { m_backgroundimage->setText(fn); } } void GeneralTab::clearBackgroundImage() { // clearing the background image text will implicitly make the background color be used m_backgroundimage->setText(""); } ShortcutSettingsTab::ShortcutSettingsTab(QWidget *parent, const char *name) : QWidget(parent) { setObjectName(name); QGridLayout * l = new QGridLayout(this); l->setMargin(0); m_page = new WdgShortcutSettings(this); l->addWidget(m_page, 0, 0); KisPart::instance()->loadActions(); KisActionRegistry::instance()->setupDialog(m_page); } void ShortcutSettingsTab::setDefault() { m_page->allDefault(); } void ShortcutSettingsTab::saveChanges() { m_page->save(); KisActionRegistry::instance()->settingsPageSaved(); } void ShortcutSettingsTab::revertChanges() { m_page->allDefault(); } ColorSettingsTab::ColorSettingsTab(QWidget *parent, const char *name) : QWidget(parent) { setObjectName(name); // XXX: Make sure only profiles that fit the specified color model // are shown in the profile combos QGridLayout * l = new QGridLayout(this); l->setMargin(0); m_page = new WdgColorSettings(this); l->addWidget(m_page, 0, 0); KisConfig cfg; m_page->chkUseSystemMonitorProfile->setChecked(cfg.useSystemMonitorProfile()); connect(m_page->chkUseSystemMonitorProfile, SIGNAL(toggled(bool)), this, SLOT(toggleAllowMonitorProfileSelection(bool))); // XXX: no color management integration on Windows or OSX yet #ifndef HAVE_X11 m_page->chkUseSystemMonitorProfile->setVisible(false); #endif m_page->cmbWorkingColorSpace->setIDList(KoColorSpaceRegistry::instance()->listKeys()); m_page->cmbWorkingColorSpace->setCurrent(cfg.workingColorSpace()); m_page->bnAddColorProfile->setIcon(KisIconUtils::loadIcon("document-open")); m_page->bnAddColorProfile->setToolTip( i18n("Open Color Profile") ); connect(m_page->bnAddColorProfile, SIGNAL(clicked()), SLOT(installProfile())); QGridLayout *monitorProfileGrid = new QGridLayout(m_page->monitorprofileholder); for(int i = 0; i < QApplication::desktop()->screenCount(); ++i) { QLabel *lbl = new QLabel(i18nc("The number of the screen", "Screen %1:", i + 1)); monitorProfileGrid->addWidget(lbl, i, 0); m_monitorProfileLabels << lbl; SqueezedComboBox *cmb = new SqueezedComboBox(); monitorProfileGrid->addWidget(cmb, i, 1); m_monitorProfileWidgets << cmb; } refillMonitorProfiles(KoID("RGBA", "")); for(int i = 0; i < QApplication::desktop()->screenCount(); ++i) { if (m_monitorProfileWidgets[i]->contains(cfg.monitorProfile(i))) { m_monitorProfileWidgets[i]->setCurrent(cfg.monitorProfile(i)); } } m_page->chkBlackpoint->setChecked(cfg.useBlackPointCompensation()); m_page->chkAllowLCMSOptimization->setChecked(cfg.allowLCMSOptimization()); KisImageConfig cfgImage; KisProofingConfiguration *proofingConfig = cfgImage.defaultProofingconfiguration(); m_gamutWarning = new KoColorPopupAction(this); m_gamutWarning->setToolTip(i18n("Set default color used for out of Gamut Warning")); m_gamutWarning->setCurrentColor(proofingConfig->warningColor); m_page->gamutAlarm->setDefaultAction(m_gamutWarning); m_page->sldAdaptationState->setMaximum(20); m_page->sldAdaptationState->setMinimum(0); m_page->sldAdaptationState->setValue((int)proofingConfig->adaptationState*20); const KoColorSpace *proofingSpace = KoColorSpaceRegistry::instance()->colorSpace(proofingConfig->proofingModel,proofingConfig->proofingDepth,proofingConfig->proofingProfile); m_page->proofingSpaceSelector->setCurrentColorSpace(proofingSpace); m_page->cmbProofingIntent->setCurrentIndex((int)proofingConfig->intent); m_page->ckbProofBlackPoint->setChecked(proofingConfig->conversionFlags.testFlag(KoColorConversionTransformation::BlackpointCompensation)); m_pasteBehaviourGroup.addButton(m_page->radioPasteWeb, PASTE_ASSUME_WEB); m_pasteBehaviourGroup.addButton(m_page->radioPasteMonitor, PASTE_ASSUME_MONITOR); m_pasteBehaviourGroup.addButton(m_page->radioPasteAsk, PASTE_ASK); QAbstractButton *button = m_pasteBehaviourGroup.button(cfg.pasteBehaviour()); Q_ASSERT(button); if (button) { button->setChecked(true); } m_page->cmbMonitorIntent->setCurrentIndex(cfg.monitorRenderIntent()); toggleAllowMonitorProfileSelection(cfg.useSystemMonitorProfile()); } void ColorSettingsTab::installProfile() { KoFileDialog dialog(this, KoFileDialog::OpenFiles, "OpenDocumentICC"); dialog.setCaption(i18n("Install Color Profiles")); dialog.setDefaultDir(QDesktopServices::storageLocation(QDesktopServices::HomeLocation)); dialog.setMimeTypeFilters(QStringList() << "application/vnd.iccprofile", "application/vnd.iccprofile"); QStringList profileNames = dialog.filenames(); KoColorSpaceEngine *iccEngine = KoColorSpaceEngineRegistry::instance()->get("icc"); Q_ASSERT(iccEngine); QString saveLocation = KoResourcePaths::saveLocation("icc_profiles"); Q_FOREACH (const QString &profileName, profileNames) { QUrl file(profileName); if (!QFile::copy(profileName, saveLocation + file.fileName())) { dbgKrita << "Could not install profile!"; return; } iccEngine->addProfile(saveLocation + file.fileName()); } KisConfig cfg; refillMonitorProfiles(KoID("RGBA", "")); for(int i = 0; i < QApplication::desktop()->screenCount(); ++i) { if (m_monitorProfileWidgets[i]->contains(cfg.monitorProfile(i))) { m_monitorProfileWidgets[i]->setCurrent(cfg.monitorProfile(i)); } } } void ColorSettingsTab::toggleAllowMonitorProfileSelection(bool useSystemProfile) { if (useSystemProfile) { KisConfig cfg; QStringList devices = KisColorManager::instance()->devices(); if (devices.size() == QApplication::desktop()->screenCount()) { for(int i = 0; i < QApplication::desktop()->screenCount(); ++i) { m_monitorProfileWidgets[i]->clear(); QString monitorForScreen = cfg.monitorForScreen(i, devices[i]); Q_FOREACH (const QString &device, devices) { m_monitorProfileLabels[i]->setText(i18nc("The display/screen we got from Qt", "Screen %1:", i + 1)); m_monitorProfileWidgets[i]->addSqueezedItem(KisColorManager::instance()->deviceName(device), device); if (devices[i] == monitorForScreen) { m_monitorProfileWidgets[i]->setCurrentIndex(i); } } } } } else { KisConfig cfg; refillMonitorProfiles(KoID("RGBA", "")); for(int i = 0; i < QApplication::desktop()->screenCount(); ++i) { if (m_monitorProfileWidgets[i]->contains(cfg.monitorProfile(i))) { m_monitorProfileWidgets[i]->setCurrent(cfg.monitorProfile(i)); } } } } void ColorSettingsTab::setDefault() { m_page->cmbWorkingColorSpace->setCurrent("RGBA"); refillMonitorProfiles(KoID("RGBA", "")); KisConfig cfg; KisImageConfig cfgImage; KisProofingConfiguration *proofingConfig = cfgImage.defaultProofingconfiguration(); const KoColorSpace *proofingSpace = KoColorSpaceRegistry::instance()->colorSpace(proofingConfig->proofingModel,proofingConfig->proofingDepth,proofingConfig->proofingProfile); m_page->proofingSpaceSelector->setCurrentColorSpace(proofingSpace); m_page->cmbProofingIntent->setCurrentIndex((int)proofingConfig->intent); m_page->ckbProofBlackPoint->setChecked(proofingConfig->conversionFlags.testFlag(KoColorConversionTransformation::BlackpointCompensation)); m_page->sldAdaptationState->setValue(0); m_gamutWarning->setCurrentColor(proofingConfig->warningColor); m_page->chkBlackpoint->setChecked(cfg.useBlackPointCompensation(true)); m_page->chkAllowLCMSOptimization->setChecked(cfg.allowLCMSOptimization(true)); m_page->cmbMonitorIntent->setCurrentIndex(cfg.monitorRenderIntent(true)); m_page->chkUseSystemMonitorProfile->setChecked(cfg.useSystemMonitorProfile(true)); QAbstractButton *button = m_pasteBehaviourGroup.button(cfg.pasteBehaviour(true)); Q_ASSERT(button); if (button) { button->setChecked(true); } } void ColorSettingsTab::refillMonitorProfiles(const KoID & s) { const KoColorSpaceFactory * csf = KoColorSpaceRegistry::instance()->colorSpaceFactory(s.id()); for (int i = 0; i < QApplication::desktop()->screenCount(); ++i) { m_monitorProfileWidgets[i]->clear(); } if (!csf) return; QList profileList = KoColorSpaceRegistry::instance()->profilesFor(csf); Q_FOREACH (const KoColorProfile *profile, profileList) { // //dbgKrita << "Profile" << profile->name() << profile->isSuitableForDisplay() << csf->defaultProfile(); if (profile->isSuitableForDisplay()) { for (int i = 0; i < QApplication::desktop()->screenCount(); ++i) { m_monitorProfileWidgets[i]->addSqueezedItem(profile->name()); } } } for (int i = 0; i < QApplication::desktop()->screenCount(); ++i) { m_monitorProfileLabels[i]->setText(i18nc("The number of the screen", "Screen %1:", i + 1)); m_monitorProfileWidgets[i]->setCurrent(csf->defaultProfile()); } } //--------------------------------------------------------------------------------------------------- void TabletSettingsTab::setDefault() { KisCubicCurve curve; curve.fromString(DEFAULT_CURVE_STRING); m_page->pressureCurve->setCurve(curve); } TabletSettingsTab::TabletSettingsTab(QWidget* parent, const char* name): QWidget(parent) { setObjectName(name); QGridLayout * l = new QGridLayout(this); l->setMargin(0); m_page = new WdgTabletSettings(this); l->addWidget(m_page, 0, 0); KisConfig cfg; KisCubicCurve curve; curve.fromString( cfg.pressureTabletCurve() ); m_page->pressureCurve->setMaximumSize(QSize(QWIDGETSIZE_MAX, QWIDGETSIZE_MAX)); m_page->pressureCurve->setCurve(curve); } //--------------------------------------------------------------------------------------------------- #include "kis_acyclic_signal_connector.h" int getTotalRAM() { KisImageConfig cfg; return cfg.totalRAM(); } int PerformanceTab::realTilesRAM() { return intMemoryLimit->value() - intPoolLimit->value(); } PerformanceTab::PerformanceTab(QWidget *parent, const char *name) : WdgPerformanceSettings(parent, name) { KisImageConfig cfg; const int totalRAM = cfg.totalRAM(); lblTotalMemory->setText(i18n("%1 MiB", totalRAM)); sliderMemoryLimit->setSuffix(i18n(" %")); sliderMemoryLimit->setRange(1, 100, 2); sliderMemoryLimit->setSingleStep(0.01); sliderPoolLimit->setSuffix(i18n(" %")); sliderPoolLimit->setRange(0, 20, 2); sliderMemoryLimit->setSingleStep(0.01); sliderUndoLimit->setSuffix(i18n(" %")); sliderUndoLimit->setRange(0, 50, 2); sliderMemoryLimit->setSingleStep(0.01); intMemoryLimit->setMinimumWidth(80); intPoolLimit->setMinimumWidth(80); intUndoLimit->setMinimumWidth(80); SliderAndSpinBoxSync *sync1 = new SliderAndSpinBoxSync(sliderMemoryLimit, intMemoryLimit, getTotalRAM); sync1->slotParentValueChanged(); m_syncs << sync1; SliderAndSpinBoxSync *sync2 = new SliderAndSpinBoxSync(sliderPoolLimit, intPoolLimit, - std::bind(&QSpinBox::value, + std::bind(&KisIntParseSpinBox::value, intMemoryLimit)); connect(intMemoryLimit, SIGNAL(valueChanged(int)), sync2, SLOT(slotParentValueChanged())); sync2->slotParentValueChanged(); m_syncs << sync2; SliderAndSpinBoxSync *sync3 = new SliderAndSpinBoxSync(sliderUndoLimit, intUndoLimit, std::bind(&PerformanceTab::realTilesRAM, this)); connect(intPoolLimit, SIGNAL(valueChanged(int)), sync3, SLOT(slotParentValueChanged())); sync3->slotParentValueChanged(); m_syncs << sync3; sliderSwapSize->setSuffix(i18n(" GiB")); sliderSwapSize->setRange(1, 64); intSwapSize->setRange(1, 64); KisAcyclicSignalConnector *swapSizeConnector = new KisAcyclicSignalConnector(this); swapSizeConnector->connectForwardInt(sliderSwapSize, SIGNAL(valueChanged(int)), intSwapSize, SLOT(setValue(int))); swapSizeConnector->connectBackwardInt(intSwapSize, SIGNAL(valueChanged(int)), sliderSwapSize, SLOT(setValue(int))); lblSwapFileLocation->setText(cfg.swapDir()); connect(bnSwapFile, SIGNAL(clicked()), SLOT(selectSwapDir())); load(false); } PerformanceTab::~PerformanceTab() { qDeleteAll(m_syncs); } void PerformanceTab::load(bool requestDefault) { KisImageConfig cfg; sliderMemoryLimit->setValue(cfg.memoryHardLimitPercent(requestDefault)); sliderPoolLimit->setValue(cfg.memoryPoolLimitPercent(requestDefault)); sliderUndoLimit->setValue(cfg.memorySoftLimitPercent(requestDefault)); chkPerformanceLogging->setChecked(cfg.enablePerfLog(requestDefault)); chkProgressReporting->setChecked(cfg.enableProgressReporting(requestDefault)); sliderSwapSize->setValue(cfg.maxSwapSize(requestDefault) / 1024); lblSwapFileLocation->setText(cfg.swapDir(requestDefault)); { KisConfig cfg2; chkOpenGLLogging->setChecked(cfg2.enableOpenGLDebugging(requestDefault)); chkDisableVectorOptimizations->setChecked(cfg2.enableAmdVectorizationWorkaround(requestDefault)); } } void PerformanceTab::save() { KisImageConfig cfg; cfg.setMemoryHardLimitPercent(sliderMemoryLimit->value()); cfg.setMemorySoftLimitPercent(sliderUndoLimit->value()); cfg.setMemoryPoolLimitPercent(sliderPoolLimit->value()); cfg.setEnablePerfLog(chkPerformanceLogging->isChecked()); cfg.setEnableProgressReporting(chkProgressReporting->isChecked()); cfg.setMaxSwapSize(sliderSwapSize->value() * 1024); cfg.setSwapDir(lblSwapFileLocation->text()); { KisConfig cfg2; cfg2.setEnableOpenGLDebugging(chkOpenGLLogging->isChecked()); cfg2.setEnableAmdVectorizationWorkaround(chkDisableVectorOptimizations->isChecked()); } } void PerformanceTab::selectSwapDir() { KisImageConfig cfg; QString swapDir = cfg.swapDir(); swapDir = QFileDialog::getExistingDirectory(0, i18nc("@title:window", "Select a swap directory"), swapDir); lblSwapFileLocation->setText(swapDir); } //--------------------------------------------------------------------------------------------------- #include "KoColor.h" #include "KoColorPopupAction.h" DisplaySettingsTab::DisplaySettingsTab(QWidget *parent, const char *name) : WdgDisplaySettings(parent, name) { KisConfig cfg; if (!KisOpenGL::hasOpenGL()) { grpOpenGL->setEnabled(false); grpOpenGL->setChecked(false); chkUseTextureBuffer->setEnabled(false); chkDisableVsync->setEnabled(false); cmbFilterMode->setEnabled(false); } else { grpOpenGL->setEnabled(true); grpOpenGL->setChecked(cfg.useOpenGL()); chkUseTextureBuffer->setEnabled(cfg.useOpenGL()); chkUseTextureBuffer->setChecked(cfg.useOpenGLTextureBuffer()); chkDisableVsync->setVisible(cfg.showAdvancedOpenGLSettings()); chkDisableVsync->setEnabled(cfg.useOpenGL()); chkDisableVsync->setChecked(cfg.disableVSync()); cmbFilterMode->setEnabled(cfg.useOpenGL()); cmbFilterMode->setCurrentIndex(cfg.openGLFilteringMode()); // Don't show the high quality filtering mode if it's not available if (!KisOpenGL::supportsGLSL13()) { cmbFilterMode->removeItem(3); } } if (qApp->applicationName() == "kritasketch" || qApp->applicationName() == "kritagemini") { grpOpenGL->setVisible(false); grpOpenGL->setMaximumHeight(0); } KoColor c; c.fromQColor(cfg.selectionOverlayMaskColor()); m_selectionOverlayColorAction = new KoColorPopupAction(this); m_selectionOverlayColorAction->setCurrentColor(c); m_selectionOverlayColorAction->setToolTip(i18n("Change the background color of the image")); btnSelectionOverlayColor->setDefaultAction(m_selectionOverlayColorAction); intCheckSize->setValue(cfg.checkSize()); chkMoving->setChecked(cfg.scrollCheckers()); colorChecks1->setColor(cfg.checkersColor1()); colorChecks2->setColor(cfg.checkersColor2()); canvasBorder->setColor(cfg.canvasBorderColor()); hideScrollbars->setChecked(cfg.hideScrollbars()); chkCurveAntialiasing->setChecked(cfg.antialiasCurves()); chkSelectionOutlineAntialiasing->setChecked(cfg.antialiasSelectionOutline()); chkChannelsAsColor->setChecked(cfg.showSingleChannelAsColor()); chkHidePopups->setChecked(cfg.hidePopups()); connect(grpOpenGL, SIGNAL(toggled(bool)), SLOT(slotUseOpenGLToggled(bool))); } void DisplaySettingsTab::setDefault() { KisConfig cfg; if (!KisOpenGL::hasOpenGL()) { grpOpenGL->setEnabled(false); grpOpenGL->setChecked(false); chkUseTextureBuffer->setEnabled(false); chkDisableVsync->setEnabled(false); cmbFilterMode->setEnabled(false); } else { grpOpenGL->setEnabled(true); grpOpenGL->setChecked(cfg.useOpenGL(true)); chkUseTextureBuffer->setChecked(cfg.useOpenGLTextureBuffer(true)); chkUseTextureBuffer->setEnabled(true); chkDisableVsync->setEnabled(true); chkDisableVsync->setChecked(cfg.disableVSync(true)); cmbFilterMode->setEnabled(true); cmbFilterMode->setCurrentIndex(cfg.openGLFilteringMode(true)); } chkMoving->setChecked(cfg.scrollCheckers(true)); intCheckSize->setValue(cfg.checkSize(true)); colorChecks1->setColor(cfg.checkersColor1(true)); colorChecks2->setColor(cfg.checkersColor2(true)); canvasBorder->setColor(cfg.canvasBorderColor(true)); hideScrollbars->setChecked(cfg.hideScrollbars(true)); chkCurveAntialiasing->setChecked(cfg.antialiasCurves(true)); chkSelectionOutlineAntialiasing->setChecked(cfg.antialiasSelectionOutline(true)); chkChannelsAsColor->setChecked(cfg.showSingleChannelAsColor(true)); chkHidePopups->setChecked(cfg.hidePopups(true)); } void DisplaySettingsTab::slotUseOpenGLToggled(bool isChecked) { chkUseTextureBuffer->setEnabled(isChecked); chkDisableVsync->setEnabled(isChecked); cmbFilterMode->setEnabled(isChecked); } //--------------------------------------------------------------------------------------------------- FullscreenSettingsTab::FullscreenSettingsTab(QWidget* parent) : WdgFullscreenSettingsBase(parent) { KisConfig cfg; chkDockers->setChecked(cfg.hideDockersFullscreen()); chkMenu->setChecked(cfg.hideMenuFullscreen()); chkScrollbars->setChecked(cfg.hideScrollbarsFullscreen()); chkStatusbar->setChecked(cfg.hideStatusbarFullscreen()); chkTitlebar->setChecked(cfg.hideTitlebarFullscreen()); chkToolbar->setChecked(cfg.hideToolbarFullscreen()); } void FullscreenSettingsTab::setDefault() { KisConfig cfg; chkDockers->setChecked(cfg.hideDockersFullscreen(true)); chkMenu->setChecked(cfg.hideMenuFullscreen(true)); chkScrollbars->setChecked(cfg.hideScrollbarsFullscreen(true)); chkStatusbar->setChecked(cfg.hideStatusbarFullscreen(true)); chkTitlebar->setChecked(cfg.hideTitlebarFullscreen(true)); chkToolbar->setChecked(cfg.hideToolbarFullscreen(true)); } //--------------------------------------------------------------------------------------------------- KisDlgPreferences::KisDlgPreferences(QWidget* parent, const char* name) : KPageDialog(parent) { Q_UNUSED(name); setWindowTitle(i18n("Preferences")); // QT5TODO: help button needs custom wiring up to whatever help should be shown setStandardButtons(QDialogButtonBox::Ok | QDialogButtonBox::Cancel | QDialogButtonBox::Help | QDialogButtonBox::RestoreDefaults); button(QDialogButtonBox::Ok)->setDefault(true); setFaceType(KPageDialog::List); // General KoVBox *vbox = new KoVBox(); KPageWidgetItem *page = new KPageWidgetItem(vbox, i18n("General")); page->setObjectName("general"); page->setHeader(i18n("General")); page->setIcon(KisIconUtils::loadIcon("go-home")); addPage(page); m_general = new GeneralTab(vbox); // Shortcuts vbox = new KoVBox(); page = new KPageWidgetItem(vbox, i18n("Keyboard Shortcuts")); page->setObjectName("shortcuts"); page->setHeader(i18n("Shortcuts")); page->setIcon(KisIconUtils::loadIcon("document-export")); addPage(page); m_shortcutSettings = new ShortcutSettingsTab(vbox); connect(this, SIGNAL(accepted()), m_shortcutSettings, SLOT(saveChanges())); // Canvas input settings m_inputConfiguration = new KisInputConfigurationPage(); page = addPage(m_inputConfiguration, i18n("Canvas Input Settings")); page->setHeader(i18n("Canvas Input")); page->setObjectName("canvasinput"); page->setIcon(KisIconUtils::loadIcon("configure")); // Display vbox = new KoVBox(); page = new KPageWidgetItem(vbox, i18n("Display")); page->setObjectName("display"); page->setHeader(i18n("Display")); page->setIcon(KisIconUtils::loadIcon("preferences-desktop-display")); addPage(page); m_displaySettings = new DisplaySettingsTab(vbox); // Color vbox = new KoVBox(); page = new KPageWidgetItem(vbox, i18n("Color Management")); page->setObjectName("colormanagement"); page->setHeader(i18n("Color")); page->setIcon(KisIconUtils::loadIcon("preferences-desktop-color")); addPage(page); m_colorSettings = new ColorSettingsTab(vbox); // Performance vbox = new KoVBox(); page = new KPageWidgetItem(vbox, i18n("Performance")); page->setObjectName("performance"); page->setHeader(i18n("Performance")); page->setIcon(KisIconUtils::loadIcon("applications-system")); addPage(page); m_performanceSettings = new PerformanceTab(vbox); // Tablet vbox = new KoVBox(); page = new KPageWidgetItem(vbox, i18n("Tablet settings")); page->setObjectName("tablet"); page->setHeader(i18n("Tablet")); page->setIcon(KisIconUtils::loadIcon("document-edit")); addPage(page); m_tabletSettings = new TabletSettingsTab(vbox); // full-screen mode vbox = new KoVBox(); page = new KPageWidgetItem(vbox, i18n("Canvas-only settings")); page->setObjectName("canvasonly"); page->setHeader(i18n("Canvas-only")); page->setIcon(KisIconUtils::loadIcon("folder-pictures")); addPage(page); m_fullscreenSettings = new FullscreenSettingsTab(vbox); // Author profiles m_authorPage = new KoConfigAuthorPage(); page = addPage(m_authorPage, i18nc("@title:tab Author page", "Author" )); page->setObjectName("author"); page->setHeader(i18n("Author")); page->setIcon(KisIconUtils::loadIcon("im-user")); QPushButton *restoreDefaultsButton = button(QDialogButtonBox::RestoreDefaults); connect(this, SIGNAL(accepted()), m_inputConfiguration, SLOT(saveChanges())); connect(this, SIGNAL(rejected()), m_inputConfiguration, SLOT(revertChanges())); KisPreferenceSetRegistry *preferenceSetRegistry = KisPreferenceSetRegistry::instance(); Q_FOREACH (KisAbstractPreferenceSetFactory *preferenceSetFactory, preferenceSetRegistry->values()) { KisPreferenceSet* preferenceSet = preferenceSetFactory->createPreferenceSet(); vbox = new KoVBox(); page = new KPageWidgetItem(vbox, preferenceSet->name()); page->setHeader(preferenceSet->header()); page->setIcon(preferenceSet->icon()); addPage(page); preferenceSet->setParent(vbox); preferenceSet->loadPreferences(); connect(restoreDefaultsButton, SIGNAL(clicked(bool)), preferenceSet, SLOT(loadDefaultPreferences()), Qt::UniqueConnection); connect(this, SIGNAL(accepted()), preferenceSet, SLOT(savePreferences()), Qt::UniqueConnection); } connect(restoreDefaultsButton, SIGNAL(clicked(bool)), this, SLOT(slotDefault())); } KisDlgPreferences::~KisDlgPreferences() { } void KisDlgPreferences::slotDefault() { if (currentPage()->objectName() == "general") { m_general->setDefault(); } else if (currentPage()->objectName() == "shortcuts") { m_shortcutSettings->setDefault(); } else if (currentPage()->objectName() == "display") { m_displaySettings->setDefault(); } else if (currentPage()->objectName() == "colormanagement") { m_colorSettings->setDefault(); } else if (currentPage()->objectName() == "performance") { m_performanceSettings->load(true); } else if (currentPage()->objectName() == "tablet") { m_tabletSettings->setDefault(); } else if (currentPage()->objectName() == "canvasonly") { m_fullscreenSettings->setDefault(); } else if (currentPage()->objectName() == "canvasinput") { m_inputConfiguration->setDefaults(); } } bool KisDlgPreferences::editPreferences() { KisDlgPreferences* dialog; dialog = new KisDlgPreferences(); bool baccept = (dialog->exec() == Accepted); if (baccept) { // General settings KisConfig cfg; cfg.setNewCursorStyle(dialog->m_general->cursorStyle()); cfg.setNewOutlineStyle(dialog->m_general->outlineStyle()); cfg.setShowRootLayer(dialog->m_general->showRootLayer()); cfg.setShowOutlineWhilePainting(dialog->m_general->showOutlineWhilePainting()); cfg.setHideSplashScreen(dialog->m_general->hideSplashScreen()); cfg.writeEntry("mdi_viewmode", dialog->m_general->mdiMode()); cfg.setMDIBackgroundColor(dialog->m_general->m_mdiColor->color()); cfg.setMDIBackgroundImage(dialog->m_general->m_backgroundimage->text()); cfg.setAutoSaveInterval(dialog->m_general->autoSaveInterval()); cfg.setBackupFile(dialog->m_general->m_backupFileCheckBox->isChecked()); cfg.setShowCanvasMessages(dialog->m_general->showCanvasMessages()); cfg.setCompressKra(dialog->m_general->compressKra()); cfg.setToolOptionsInDocker(dialog->m_general->toolOptionsInDocker()); cfg.setSwitchSelectionCtrlAlt(dialog->m_general->switchSelectionCtrlAlt()); cfg.setConvertToImageColorspaceOnImport(dialog->m_general->convertToImageColorspaceOnImport()); KisPart *part = KisPart::instance(); if (part) { Q_FOREACH (QPointer doc, part->documents()) { if (doc) { doc->setAutoSave(dialog->m_general->autoSaveInterval()); doc->setBackupFile(dialog->m_general->m_backupFileCheckBox->isChecked()); doc->undoStack()->setUndoLimit(dialog->m_general->undoStackSize()); } } } cfg.setUndoStackLimit(dialog->m_general->undoStackSize()); cfg.setFavoritePresets(dialog->m_general->favoritePresets()); // Color settings cfg.setUseSystemMonitorProfile(dialog->m_colorSettings->m_page->chkUseSystemMonitorProfile->isChecked()); for (int i = 0; i < QApplication::desktop()->screenCount(); ++i) { if (dialog->m_colorSettings->m_page->chkUseSystemMonitorProfile->isChecked()) { int currentIndex = dialog->m_colorSettings->m_monitorProfileWidgets[i]->currentIndex(); QString monitorid = dialog->m_colorSettings->m_monitorProfileWidgets[i]->itemData(currentIndex).toString(); cfg.setMonitorForScreen(i, monitorid); } else { cfg.setMonitorProfile(i, dialog->m_colorSettings->m_monitorProfileWidgets[i]->itemHighlighted(), dialog->m_colorSettings->m_page->chkUseSystemMonitorProfile->isChecked()); } } cfg.setWorkingColorSpace(dialog->m_colorSettings->m_page->cmbWorkingColorSpace->currentItem().id()); KisImageConfig cfgImage; cfgImage.setDefaultProofingConfig(dialog->m_colorSettings->m_page->proofingSpaceSelector->currentColorSpace(), dialog->m_colorSettings->m_page->cmbProofingIntent->currentIndex(), dialog->m_colorSettings->m_page->ckbProofBlackPoint->isChecked(), dialog->m_colorSettings->m_gamutWarning->currentKoColor(), (double)dialog->m_colorSettings->m_page->sldAdaptationState->value()/20); cfg.setUseBlackPointCompensation(dialog->m_colorSettings->m_page->chkBlackpoint->isChecked()); cfg.setAllowLCMSOptimization(dialog->m_colorSettings->m_page->chkAllowLCMSOptimization->isChecked()); cfg.setPasteBehaviour(dialog->m_colorSettings->m_pasteBehaviourGroup.checkedId()); cfg.setRenderIntent(dialog->m_colorSettings->m_page->cmbMonitorIntent->currentIndex()); // Tablet settings cfg.setPressureTabletCurve( dialog->m_tabletSettings->m_page->pressureCurve->curve().toString() ); dialog->m_performanceSettings->save(); if (!cfg.useOpenGL() && dialog->m_displaySettings->grpOpenGL->isChecked()) cfg.setCanvasState("TRY_OPENGL"); cfg.setUseOpenGL(dialog->m_displaySettings->grpOpenGL->isChecked()); cfg.setUseOpenGLTextureBuffer(dialog->m_displaySettings->chkUseTextureBuffer->isChecked()); cfg.setOpenGLFilteringMode(dialog->m_displaySettings->cmbFilterMode->currentIndex()); cfg.setDisableVSync(dialog->m_displaySettings->chkDisableVsync->isChecked()); cfg.setCheckSize(dialog->m_displaySettings->intCheckSize->value()); cfg.setScrollingCheckers(dialog->m_displaySettings->chkMoving->isChecked()); cfg.setCheckersColor1(dialog->m_displaySettings->colorChecks1->color()); cfg.setCheckersColor2(dialog->m_displaySettings->colorChecks2->color()); cfg.setCanvasBorderColor(dialog->m_displaySettings->canvasBorder->color()); cfg.setHideScrollbars(dialog->m_displaySettings->hideScrollbars->isChecked()); cfg.setSelectionOverlayMaskColor(dialog->m_displaySettings->m_selectionOverlayColorAction->currentKoColor().toQColor()); cfg.setAntialiasCurves(dialog->m_displaySettings->chkCurveAntialiasing->isChecked()); cfg.setAntialiasSelectionOutline(dialog->m_displaySettings->chkSelectionOutlineAntialiasing->isChecked()); cfg.setShowSingleChannelAsColor(dialog->m_displaySettings->chkChannelsAsColor->isChecked()); cfg.setHidePopups(dialog->m_displaySettings->chkHidePopups->isChecked()); cfg.setHideDockersFullscreen(dialog->m_fullscreenSettings->chkDockers->checkState()); cfg.setHideMenuFullscreen(dialog->m_fullscreenSettings->chkMenu->checkState()); cfg.setHideScrollbarsFullscreen(dialog->m_fullscreenSettings->chkScrollbars->checkState()); cfg.setHideStatusbarFullscreen(dialog->m_fullscreenSettings->chkStatusbar->checkState()); cfg.setHideTitlebarFullscreen(dialog->m_fullscreenSettings->chkTitlebar->checkState()); cfg.setHideToolbarFullscreen(dialog->m_fullscreenSettings->chkToolbar->checkState()); dialog->m_authorPage->apply(); } delete dialog; return baccept; } diff --git a/libs/ui/forms/kis_matrix_widget.ui b/libs/ui/forms/kis_matrix_widget.ui index d055bbd75a..d7e7aca22c 100644 --- a/libs/ui/forms/kis_matrix_widget.ui +++ b/libs/ui/forms/kis_matrix_widget.ui @@ -1,130 +1,137 @@ - - - - - KisMatrixWidget - - - - 0 - 0 - 191 - 115 - - - - Matrix Widget - - - - - - -99 - - - - - - - -99 - - - - - - - -99 - - - - - - - -99 - - - - - - - -99 - - - - - - - -99 - - - 1 - - - - - - - -99 - - - - - - - -99 - - - - - - - -99 - - - - - - - - 20 - 41 - - - - Expanding - - - Qt::Vertical - - - - - - - - 21 - 20 - - - - Expanding - - - Qt::Horizontal - - - - - - - m11 - m12 - m13 - m21 - m22 - m23 - m31 - m32 - m33 - + + + KisMatrixWidget + + + + 0 + 0 + 195 + 117 + + + + Matrix Widget + + + + + + -99 + + + + + + + -99 + + + + + + + -99 + + + + + + + -99 + + + + + + + -99 + + + + + + + -99 + + + 1 + + + + + + + -99 + + + + + + + -99 + + + + + + + -99 + + + + + + + Qt::Vertical + + + QSizePolicy::Expanding + + + + 20 + 41 + + + + + + + + Qt::Horizontal + + + QSizePolicy::Expanding + + + + 21 + 20 + + + + + + + + + KisIntParseSpinBox + QSpinBox +
kis_int_parse_spin_box.h
+
+
+ + m11 + m12 + m13 + m21 + m22 + m23 + m31 + m32 + m33 + + +
diff --git a/libs/ui/forms/wdgautogradient.ui b/libs/ui/forms/wdgautogradient.ui index 2cf9bfda69..e6c2ee7608 100644 --- a/libs/ui/forms/wdgautogradient.ui +++ b/libs/ui/forms/wdgautogradient.ui @@ -1,376 +1,390 @@ KisWdgAutogradient 0 0 500 250 500 250 Name: - + 0 1 Qt::ClickFocus Sans Serif 9 50 false false false false Segment Color Sans Serif 9 50 false false false false Opacity: Sans Serif 9 50 false false false false Left: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter 0 0 0 30 Sans Serif 9 50 false false false false Qt::ClickFocus - + 0 0 Sans Serif 9 50 false false false false Qt::ClickFocus 100 100 Sans Serif 9 50 false false false false Right: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter 0 0 0 30 Sans Serif 9 50 false false false false Qt::ClickFocus - + 255 255 255 - + 255 255 255 - + 0 0 Sans Serif 9 50 false false false false Qt::ClickFocus 100 100 - + + 0 + + + 0 + + + 0 + + 0 Qt::Horizontal 40 20 Sans Serif 9 50 false false false false Qt::ClickFocus Linear Curved Sine Sphere Inc. Sphere Dec. Sans Serif 9 50 false false false false Qt::ClickFocus RGB HSV CW HSV CCW + + KisIntParseSpinBox + QSpinBox +
kis_int_parse_spin_box.h
+
KColorButton QPushButton
kcolorbutton.h
1
KisGradientSliderWidget
widgets/kis_gradient_slider_widget.h
diff --git a/libs/ui/forms/wdgdisplaysettings.ui b/libs/ui/forms/wdgdisplaysettings.ui index 9538a90321..0bbd7ed23a 100644 --- a/libs/ui/forms/wdgdisplaysettings.ui +++ b/libs/ui/forms/wdgdisplaysettings.ui @@ -1,355 +1,360 @@ WdgDisplaySettings 0 0 - 500 + 504 685 0 0 Display Miscellaneous Color channels in color false Enable curve anti-aliasing Enable selection outline anti-aliasing Hide layer thumbnail popup Transparency Checkerboard Pattern - Size: + S&ize: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter intCheckSize - + px 256 32 Qt::Horizontal 40 20 Colors: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter Qt::Horizontal 40 20 If checked, the checkers will move when scrolling the canvas. Determines whether the checks will stay put or whether they will scroll together with the canvas &Move checkers when scrolling true Qt::Vertical 20 40 0 0 - OpenGL + Open&GL true 0 0 0 Nearest Neighbour Bilinear Filtering Trilinear Filtering High Quality Filtering <html><head/><body><p>Try to disable vsync for Krita. This makes painting more responsive. Uncheck only when experiencing crashes with some GPU/driver combinations.</p></body></html> Disable vsync (needs restart) true 0 0 <html><head/><body><p>Use Texture Buffering. This can be faster on some GPU/Driver combinations (like Intel) or broken on some others (like AMD/Radeon).</p></body></html> Use texture buffer 0 0 Scaling Mode: Canvas border Color: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter Qt::Horizontal 40 20 Hide Scrollbars false Selection Overlay Color: ... Qt::Horizontal 358 20 + + KisIntParseSpinBox + QSpinBox +
kis_int_parse_spin_box.h
+
KColorButton QPushButton
kcolorbutton.h
1
diff --git a/libs/ui/forms/wdggeneralsettings.ui b/libs/ui/forms/wdggeneralsettings.ui index 24877ff8d6..d38056e557 100644 --- a/libs/ui/forms/wdggeneralsettings.ui +++ b/libs/ui/forms/wdggeneralsettings.ui @@ -1,710 +1,715 @@ WdgGeneralSettings 0 0 552 295 0 0 552 295 Qt::LeftToRight - 0 + 3 Cursor 10 10 10 10 10 10 0 0 Cursor Shape: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter 0 0 Outline Shape: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter 0 0 200 0 Show brush outline while painting Qt::Horizontal 40 20 Qt::Vertical 20 40 Window Qt::Vertical 20 40 10 10 10 10 10 0 0 Multiple Document Mode: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter Window Background: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter 200 0 QFrame::StyledPanel QFrame::Sunken ... 0 0 Clear 0 0 0 0 0 0 0 0 Background Image (overrides color): 0 0 1 Subwindows Tabs 0 0 Don't show contents when moving sub-windows Qt::Horizontal 40 20 Show on-canvas popup messages: Qt::Horizontal 40 20 Qt::Horizontal 40 20 Tools 10 10 10 10 10 Tool Options Location (needs restart) In Doc&ker - In Toolbar + In Tool&bar true Switch Control/Alt Selection Modifiers Qt::Vertical 20 40 Qt::Horizontal 40 20 Miscellaneous 10 10 10 10 10 0 0 Qt::RightToLeft Autosave every: true 0 0 Undo stack size: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter Compress .kra files more (slows loading/saving) Create backup file - + 0 0 75 0 10 30 0 0 Favorite presets: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - + 0 0 75 0 min 1 1440 5 15 - + 0 0 75 0 0 1000 5 30 Show root layer Hide splash screen on startup On importing images as layers, convert to the image colorspace Qt::Vertical 20 40 Qt::Vertical 20 40 + + KisIntParseSpinBox + QSpinBox +
kis_int_parse_spin_box.h
+
KColorButton QPushButton
kcolorbutton.h
1
diff --git a/libs/ui/forms/wdgimportimagesequence.ui b/libs/ui/forms/wdgimportimagesequence.ui index 23da1b7975..7526c61bec 100644 --- a/libs/ui/forms/wdgimportimagesequence.ui +++ b/libs/ui/forms/wdgimportimagesequence.ui @@ -1,122 +1,129 @@ WdgImportImageSequence 0 0 575 428 Dialog Add images... Remove Order Timing Start at - + The frame number for the first image 9999 Step - + Number of frames between images 1 999 Source FPS: + + + KisIntParseSpinBox + QSpinBox +
kis_int_parse_spin_box.h
+
+
diff --git a/libs/ui/forms/wdgnewimage.ui b/libs/ui/forms/wdgnewimage.ui index 293b349512..4d5ee82786 100644 --- a/libs/ui/forms/wdgnewimage.ui +++ b/libs/ui/forms/wdgnewimage.ui @@ -1,679 +1,698 @@ WdgNewImage 0 0 600 422 0 0 600 0 16777215 16777215 New Image 0 0 0 0 0 Dimensions 0 140 16777215 16777215 Image Size Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter false false - &Predefined: + P&redefined: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter cmbPredefined 0 0 Save As: 0 0 Save the current dimensions &Save Landscape ... true true true - + 2 1.000000000000000 100000000.000000000000000 &Height: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter doubleHeight - + 0 1.000000000000000 9999.000000000000000 Resolution: - + 1.000000000000000 100000000.000000000000000 pixels-per-inch ppi - &Width: + W&idth: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter doubleWidth Portrait ... true true true true Qt::Horizontal QSizePolicy::Expanding 191 61 Clipboard 75 75 250 250 QFrame::StyledPanel TextLabel Qt::Vertical 20 40 &Name: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter txtName untitled-1 0 0 Color 0 0 Content Layers: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - Image Background &Opacity: + Ima&ge Background Opacity: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter sliderOpacity - + 0 0 1 200 2 &Image Background Color: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter cmbColor Background: Qt::AlignRight|Qt::AlignTop|Qt::AlignTrailing &Description: Qt::AlignRight|Qt::AlignTop|Qt::AlignTrailing txtDescription 0 0 16777215 100 - As first layer + As fi&rst layer - As canvas color + As ca&nvas color 0 0 50 0 Reset the image background color in the Image Properties dialog - + 255 255 255 - + 255 255 255 QFrame::NoFrame QFrame::Plain - + + 0 + + + 0 + + + 0 + + 0 Qt::Vertical 20 40 label_4 lblBackgroundStyle txtDescription lblDescription intNumLayers opacityPanel lblColor cmbColor lblOpacity Qt::Vertical QSizePolicy::Expanding 10 10 Qt::Horizontal QSizePolicy::Expanding 480 10 &Create true true + + KisColorSpaceSelector + QWidget +
widgets/kis_color_space_selector.h
+ 1 +
+ + KisDoubleParseSpinBox + QDoubleSpinBox +
kis_double_parse_spin_box.h
+
KColorButton QPushButton
kcolorbutton.h
1
KisDoubleSliderSpinBox QWidget
kis_slider_spin_box.h
1
- KisColorSpaceSelector - QWidget -
widgets/kis_color_space_selector.h
- 1 + KisIntParseSpinBox + QSpinBox +
kis_int_parse_spin_box.h
tabWidget txtName cmbPredefined txtPredefinedName bnSaveAsPredefined doubleWidth doubleHeight doubleResolution cmbWidthUnit cmbHeightUnit bnLandscape bnPortrait createButton intNumLayers cmbColor radioBackgroundAsLayer radioBackgroundAsProjection txtDescription
diff --git a/libs/ui/forms/wdgpaintactioneditor.ui b/libs/ui/forms/wdgpaintactioneditor.ui index 76132f678e..5e82cc60a0 100644 --- a/libs/ui/forms/wdgpaintactioneditor.ui +++ b/libs/ui/forms/wdgpaintactioneditor.ui @@ -1,197 +1,202 @@ WdgPaintActionEditor 0 0 - 400 + 405 376 - + 0 Options Paint color: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter 0 0 ... Background color: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter 0 0 ... Qt::Vertical 236 147 Opacity: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - + 0 0 - + 0 - + 100 true Current preset Paint op: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter 0 0 0 4 QFrame::StyledPanel QFrame::Raised Preset Collection - + 4 4 + + KisIntParseSpinBox + QSpinBox +
kis_int_parse_spin_box.h
+
KisPresetChooser QWidget
widgets/kis_preset_chooser.h
1
KisNodeQueryPathEditor QWidget
recorder/kis_node_query_path_editor.h
1
diff --git a/libs/ui/forms/wdgperformancesettings.ui b/libs/ui/forms/wdgperformancesettings.ui index fd5805c0bc..93111dbe4c 100644 --- a/libs/ui/forms/wdgperformancesettings.ui +++ b/libs/ui/forms/wdgperformancesettings.ui @@ -1,300 +1,305 @@ WdgPerformanceSettings 0 0 753 554 RAM (needs restarting Krita) Memory available: 0 0 XXX MiB Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter Krita will not use more memory than this limit. Memory Limit: - + 0 0 Krita will not use more memory than this limit. - + MiB Internal Pool: - + 0 0 - + MiB When undo information reaches this limit, it will be stored in a temporary file and memory will be freed. Undo will be slower. Swap Undo After: - + 0 0 When undo information reaches this limit, it will be stored in a temporary file and memory will be freed. Undo will be slower. - + MiB Swap File Size (needs restarting Krita) The swap file will not be bigger than this limit. File Size Limit: - + 0 0 The swap file will not be bigger than this limit. - + GiB Swap File Location: 0 0 TextLabel Select the location where Krita writes its swap files. ... Advanced (needs restarting Krita) Enable progress reporting (might affect performance) Enable performance logging QFrame::NoFrame <html><head/><body><p>When performance logging is enabled Krita saves timing information into the '&lt;working_dir&gt;/log' folder. If you experience performance problems and want to help us, enable this option and add the contents of the directory to a bug report.</p></body></html> true Enable OpenGL logging Disable vector optimizations (for AMD CPUs) Qt::Vertical 20 40 - KisDoubleSliderSpinBox + KisSliderSpinBox QWidget
kis_slider_spin_box.h
1
- KisSliderSpinBox + KisIntParseSpinBox + QSpinBox +
kis_int_parse_spin_box.h
+
+ + KisDoubleSliderSpinBox QWidget -
kis_slider_spin_box.h
+
kis_slider_spin_box.h
1
diff --git a/libs/ui/forms/wdgrectangleconstraints.ui b/libs/ui/forms/wdgrectangleconstraints.ui index a86fc36566..c232202b2f 100644 --- a/libs/ui/forms/wdgrectangleconstraints.ui +++ b/libs/ui/forms/wdgrectangleconstraints.ui @@ -1,186 +1,198 @@ WdgRectangleConstraints 0 0 - 218 + 230 149 0 0 Size 0 0 0 0 0 7 7 7 7 7 true true true - + Height px 99999 Width: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - + Aspect ratio 10000.000000000000000 0.100000000000000 - + Width px 99999 Ratio: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter Height: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter Qt::Horizontal 40 20 Qt::Vertical 20 40 + + + KisIntParseSpinBox + QSpinBox +
kis_int_parse_spin_box.h
+
+ + KisDoubleParseSpinBox + QDoubleSpinBox +
kis_double_parse_spin_box.h
+
+
diff --git a/libs/ui/kis_aspect_ratio_locker.cpp b/libs/ui/kis_aspect_ratio_locker.cpp index 028181516e..dfd26f524e 100644 --- a/libs/ui/kis_aspect_ratio_locker.cpp +++ b/libs/ui/kis_aspect_ratio_locker.cpp @@ -1,184 +1,188 @@ /* * Copyright (c) 2016 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 "kis_aspect_ratio_locker.h" #include #include #include #include "kis_signals_blocker.h" #include "kis_assert.h" #include "kis_debug.h" #include "kis_slider_spin_box.h" +#include "kis_int_parse_spin_box.h" +#include "kis_double_parse_spin_box.h" struct SliderWrapper { template SliderWrapper(Slider *slider) : m_slider(QVariant::fromValue(slider)), m_object(slider) {} void setValue(qreal value) { if (m_slider.canConvert()) { m_slider.value()->setValue(qRound(value)); } else if (m_slider.canConvert()) { m_slider.value()->setValue(value); } else if (m_slider.canConvert()) { m_slider.value()->setValue(qRound(value)); } else if (m_slider.canConvert()) { m_slider.value()->setValue(value); } } qreal value() const { qreal result = 0.0; if (m_slider.canConvert()) { result = m_slider.value()->value(); } else if (m_slider.canConvert()) { result = m_slider.value()->value(); } else if (m_slider.canConvert()) { result = m_slider.value()->value(); } else if (m_slider.canConvert()) { result = m_slider.value()->value(); } return result; } bool isDragging() const { bool result = false; if (m_slider.canConvert()) { result = m_slider.value()->isDragging(); } else if (m_slider.canConvert()) { result = m_slider.value()->isDragging(); } return result; } QObject* object() const { return m_object; } private: QVariant m_slider; QObject *m_object; }; struct KisAspectRatioLocker::Private { QScopedPointer spinOne; QScopedPointer spinTwo; KoAspectButton *aspectButton = 0; qreal aspectRatio = 1.0; bool blockUpdatesOnDrag = false; }; KisAspectRatioLocker::KisAspectRatioLocker(QObject *parent) : QObject(parent), m_d(new Private) { } KisAspectRatioLocker::~KisAspectRatioLocker() { } template void KisAspectRatioLocker::connectSpinBoxes(SpinBoxType *spinOne, SpinBoxType *spinTwo, KoAspectButton *aspectButton) { m_d->spinOne.reset(new SliderWrapper(spinOne)); m_d->spinTwo.reset(new SliderWrapper(spinTwo)); m_d->aspectButton = aspectButton; if (QVariant::fromValue(spinOne->value()).type() == QVariant::Double) { connect(spinOne, SIGNAL(valueChanged(qreal)), SLOT(slotSpinOneChanged())); connect(spinTwo, SIGNAL(valueChanged(qreal)), SLOT(slotSpinTwoChanged())); } else { connect(spinOne, SIGNAL(valueChanged(int)), SLOT(slotSpinOneChanged())); connect(spinTwo, SIGNAL(valueChanged(int)), SLOT(slotSpinTwoChanged())); } connect(m_d->aspectButton, SIGNAL(keepAspectRatioChanged(bool)), SLOT(slotAspectButtonChanged())); slotAspectButtonChanged(); } template void KisAspectRatioLocker::connectSpinBoxes(QSpinBox *spinOne, QSpinBox *spinTwo, KoAspectButton *aspectButton); template void KisAspectRatioLocker::connectSpinBoxes(QDoubleSpinBox *spinOne, QDoubleSpinBox *spinTwo, KoAspectButton *aspectButton); template void KisAspectRatioLocker::connectSpinBoxes(KisSliderSpinBox *spinOne, KisSliderSpinBox *spinTwo, KoAspectButton *aspectButton); template void KisAspectRatioLocker::connectSpinBoxes(KisDoubleSliderSpinBox *spinOne, KisDoubleSliderSpinBox *spinTwo, KoAspectButton *aspectButton); +template void KisAspectRatioLocker::connectSpinBoxes(KisIntParseSpinBox *spinOne, KisIntParseSpinBox *spinTwo, KoAspectButton *aspectButton); +template void KisAspectRatioLocker::connectSpinBoxes(KisDoubleParseSpinBox *spinOne, KisDoubleParseSpinBox *spinTwo, KoAspectButton *aspectButton); void KisAspectRatioLocker::slotSpinOneChanged() { if (m_d->aspectButton->keepAspectRatio()) { KisSignalsBlocker b(m_d->spinTwo->object()); m_d->spinTwo->setValue(m_d->aspectRatio * m_d->spinOne->value()); } if (!m_d->blockUpdatesOnDrag || !m_d->spinOne->isDragging()) { emit sliderValueChanged(); } } void KisAspectRatioLocker::slotSpinTwoChanged() { if (m_d->aspectButton->keepAspectRatio()) { KisSignalsBlocker b(m_d->spinOne->object()); m_d->spinOne->setValue(m_d->spinTwo->value() / m_d->aspectRatio); } if (!m_d->blockUpdatesOnDrag || !m_d->spinTwo->isDragging()) { emit sliderValueChanged(); } } void KisAspectRatioLocker::slotAspectButtonChanged() { if (m_d->aspectButton->keepAspectRatio() && m_d->spinTwo->value() > 0 && m_d->spinOne->value() > 0) { m_d->aspectRatio = qreal(m_d->spinTwo->value()) / m_d->spinOne->value(); } else { m_d->aspectRatio = 1.0; } if (!m_d->spinTwo->isDragging()) { emit aspectButtonChanged(); } } void KisAspectRatioLocker::setBlockUpdateSignalOnDrag(bool value) { m_d->blockUpdatesOnDrag = value; } diff --git a/libs/ui/layerstyles/WdgGradientOverlay.ui b/libs/ui/layerstyles/WdgGradientOverlay.ui index 5abf47ab2a..5fb0c6e772 100644 --- a/libs/ui/layerstyles/WdgGradientOverlay.ui +++ b/libs/ui/layerstyles/WdgGradientOverlay.ui @@ -1,281 +1,286 @@ WdgGradientOverlay 0 0 - 400 - 266 + 411 + 294 Gradient Overlay Gradient Ble&nd Mode: cmbCompositeOp 0 0 Set the blend mode for the layer - &Opacity: + Opac&ity: intOpacity 0 0 10 15 Set the master opacity for the layer Adjust the transparency of the layer - Gradient: + &Gradient: cmbGradient 11 0 &Reverse St&yle: cmbStyle 0 0 Linear Radial Angle Reflected Diamond Ali&gn with Layer &Angle: dialAngle Set the angle of the light source -179 180 true - + -179 180 S&cale: intScale 0 0 Set size of gradation label_6 intScale label_9 label_7 label_8 cmbCompositeOp intOpacity label_13 label_14 Qt::Vertical 20 40 - KisCompositeOpComboBox - QComboBox -
kis_cmb_composite.h
+ KisIntParseSpinBox + QSpinBox +
kis_int_parse_spin_box.h
KisSliderSpinBox QWidget
kis_slider_spin_box.h
1
+ + KisCompositeOpComboBox + QComboBox +
kis_cmb_composite.h
+
KisCmbGradient QToolButton
kis_cmb_gradient.h
diff --git a/libs/ui/layerstyles/WdgSatin.ui b/libs/ui/layerstyles/WdgSatin.ui index b97f26a525..d40f0c8632 100644 --- a/libs/ui/layerstyles/WdgSatin.ui +++ b/libs/ui/layerstyles/WdgSatin.ui @@ -1,274 +1,279 @@ WdgSatin 0 0 400 - 337 + 345 Satin Structure Ble&nd Mode: cmbCompositeOp 0 0 Set the blend mode for the layer ... - &Opacity: + Opaci&ty: intOpacity 0 0 10 15 Set the master opacity for the layer Adjust the transparency of the layer - &Angle: + An&gle: dialAngle Set the angle of the light source -179 180 true - + -179 180 &Distance: intDistance 0 0 - &Size: + S&ize: intSize 0 0 Contour: Smooth the contour Anti-aliased &Invert cmbContour chkAntiAliased intOpacity label_13 label_14 label_4 intDistance intSize label label_2 label_6 chkInvert Qt::Vertical 20 40 Qt::Vertical 20 40 + + KisIntParseSpinBox + QSpinBox +
kis_int_parse_spin_box.h
+
+ + KisSliderSpinBox + QWidget +
kis_slider_spin_box.h
+ 1 +
KColorButton QPushButton
kcolorbutton.h
1
KisCompositeOpComboBox QComboBox
kis_cmb_composite.h
- - KisSliderSpinBox - QWidget -
kis_slider_spin_box.h
- 1 -
KisCmbContour QWidget
kis_cmb_contour.h
diff --git a/libs/ui/layerstyles/WdgStroke.ui b/libs/ui/layerstyles/WdgStroke.ui index 1603dc72be..513eff70e9 100644 --- a/libs/ui/layerstyles/WdgStroke.ui +++ b/libs/ui/layerstyles/WdgStroke.ui @@ -1,436 +1,441 @@ WdgStroke 0 0 - 400 + 401 642 Stroke Structure - &Size: + S&ize: intSize - + 0 0 - &Position: + Positio&n: cmbPosition 0 0 Outside Inside Center &Blend Mode: cmbCompositeOp 0 0 - O&pacity: + Opacit&y: intOpacity - + 0 0 Fill Color Gradient Pattern - 0 + 1 Color: ... - Gradient: + &Gradient: cmbGradient 0 0 &Reverse St&yle: cmbStyle 0 0 Linear Radial Angle Reflected Diamond Ali&gn with Layer &Angle: dialAngle Set the angle of the light source -179 180 true - + -179 180 S&cale: intScale - + 0 0 Set size of gradation Pattern: 0 0 250 250 QFrame::StyledPanel QFrame::Raised Sn&ap to Origin S&cale: intScale - + Set size of gradation Lin&k with Layer KColorButton QPushButton
kcolorbutton.h
1
KisCompositeOpComboBox QComboBox
kis_cmb_composite.h
KisSliderSpinBox QWidget
kis_slider_spin_box.h
1
KisCmbGradient QToolButton
kis_cmb_gradient.h
KisPatternChooser QFrame
kis_pattern_chooser.h
1
+ + KisIntParseSpinBox + QSpinBox +
kis_int_parse_spin_box.h
+
diff --git a/libs/ui/layerstyles/wdgBevelAndEmboss.ui b/libs/ui/layerstyles/wdgBevelAndEmboss.ui index b0779a2e90..1f918c085f 100644 --- a/libs/ui/layerstyles/wdgBevelAndEmboss.ui +++ b/libs/ui/layerstyles/wdgBevelAndEmboss.ui @@ -1,477 +1,482 @@ WdgBevelAndEmboss 0 0 - 354 - 471 + 399 + 541 Bevel and Emboss Structure - &Style: + St&yle: cmbStyle 0 0 Outer Bevel Inner Bevel Emboss Pillow Emboss Stroke Emboss &Technique: cmbTechnique 0 0 Smooth Chisel Hard Chisel Soft &Depth: intDepth - + 0 0 Direction: 0 0 Up Down Si&ze: intSize - + 0 0 - Sof&ten: + So&ften: intSoften - + 0 0 Shading &Angle: dialAngle Set the angle of the light source -179 180 true - + -179 180 Qt::Vertical 20 18 Use &Global Light - + -179 180 - Gloss Contour: + &Gloss Contour: cmbContour Anti-aliased H&ighlight Mode: cmbHighlightMode Set the blend mode for the layer ... &Opacity: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter intOpacity - + 0 0 10 15 Set the master opacity for the layer Adjust the transparency of the layer Set the blend mode for the layer ... &Opacity: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter intOpacity2 - + 0 0 10 15 Set the master opacity for the layer Adjust the transparency of the layer Altitude: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter dialAngle Sh&adow Mode: cmbShadowMode Qt::Vertical 20 40 + + KisIntParseSpinBox + QSpinBox +
kis_int_parse_spin_box.h
+
+ + KisSliderSpinBox + QWidget +
kis_slider_spin_box.h
+ 1 +
KColorButton QPushButton
kcolorbutton.h
1
KisCompositeOpComboBox QComboBox
kis_cmb_composite.h
- - KisSliderSpinBox - QWidget -
kis_slider_spin_box.h
- 1 -
diff --git a/libs/ui/layerstyles/wdgdropshadow.ui b/libs/ui/layerstyles/wdgdropshadow.ui index 27fc98d09e..d1f81dc6cd 100644 --- a/libs/ui/layerstyles/wdgdropshadow.ui +++ b/libs/ui/layerstyles/wdgdropshadow.ui @@ -1,314 +1,319 @@ WdgDropShadow 0 0 - 367 - 350 + 435 + 390 Drop Shadow Use to obscure the shadow when fill is transparent Layer knocks O&ut Drop Shadow Quality Contour: 0 0 Smooth the contour Anti-aliased &Noise: intNoise 0 0 Add noise to shadow Structure - Ble&nd Mode: + &Blend Mode: cmbCompositeOp 0 0 Set the blend mode for the layer - &Opacity: + Opaci&ty: intOpacity 0 0 10 15 Set the master opacity for the layer Adjust the transparency of the layer - &Angle: + An&gle: dialAngle Set the angle of the light source -179 180 true - + -179 180 Use current setting for global light source Use &Global light &Distance: intDistance 0 0 Sp&read: intSpread 0 0 - &Size: + S&ize: intSize 0 0 Qt::Vertical 20 40 + + KisIntParseSpinBox + QSpinBox +
kis_int_parse_spin_box.h
+
+ + KisSliderSpinBox + QWidget +
kis_slider_spin_box.h
+ 1 +
KColorButton QPushButton
kcolorbutton.h
1
KisCompositeOpComboBox QComboBox
kis_cmb_composite.h
- - KisSliderSpinBox - QWidget -
kis_slider_spin_box.h
- 1 -
KisCmbContour QWidget
kis_cmb_contour.h
diff --git a/libs/ui/tests/CMakeLists.txt b/libs/ui/tests/CMakeLists.txt index a4ace64885..44d6c9549e 100644 --- a/libs/ui/tests/CMakeLists.txt +++ b/libs/ui/tests/CMakeLists.txt @@ -1,273 +1,274 @@ set( EXECUTABLE_OUTPUT_PATH ${CMAKE_CURRENT_BINARY_DIR} ) #add_subdirectory(scratchpad) include_directories(${CMAKE_SOURCE_DIR}/libs/image/metadata ${CMAKE_SOURCE_DIR}/sdk/tests ) macro_add_unittest_definitions() ########### next target ############### set(kis_node_model_test_SRCS kis_node_model_test.cpp modeltest.cpp ) kde4_add_broken_unit_test(kis_node_model_test TESTNAME krita-ui-kis_node_model_test ${kis_node_model_test_SRCS}) target_link_libraries(kis_node_model_test kritaui Qt5::Test) ########### next target ############### set(kis_image_view_converter_test_SRCS kis_image_view_converter_test.cpp ) kde4_add_unit_test(KisImageViewConverterTest TESTNAME krita-ui-KisImageViewConverterTest ${kis_image_view_converter_test_SRCS}) target_link_libraries(KisImageViewConverterTest kritaui Qt5::Test) ########### next target ############### set(kis_shape_controller_test_SRCS kis_shape_controller_test.cpp kis_dummies_facade_base_test.cpp) kde4_add_broken_unit_test(kis_shape_controller_test TESTNAME krita-ui-kis_shape_controller_test ${kis_shape_controller_test_SRCS}) target_link_libraries(kis_shape_controller_test kritaimage kritaui Qt5::Test) ########### next target ############### set(squeezedcombobox_test_SRCS squeezedcombobox_test.cpp ) kde4_add_unit_test(squeezedcombobox_test TESTNAME krita-ui-squeezedcombobox_test ${squeezedcombobox_test_SRCS}) target_link_libraries(squeezedcombobox_test kritaui Qt5::Test) ########### next target ############### set(kis_prescaled_projection_test_SRCS kis_prescaled_projection_test.cpp ) kde4_add_broken_unit_test(KisPrescaledProjectionTest TESTNAME krita-ui-kis_prescaled_projection_test ${kis_prescaled_projection_test_SRCS}) target_link_libraries(KisPrescaledProjectionTest kritaui Qt5::Test) ########### next target ############### set(kis_kra_loader_test_SRCS kis_kra_loader_test.cpp ) kde4_add_broken_unit_test(KisKraLoaderTest TESTNAME krita-ui-KisKraLoaderTest ${kis_kra_loader_test_SRCS}) target_link_libraries(KisKraLoaderTest kritaimage kritaui Qt5::Test) ########### next target ############### set(kis_kra_saver_test_SRCS kis_kra_saver_test.cpp ) kde4_add_broken_unit_test(KisKraSaverTest TESTNAME krita-ui-KisKraSaverTest ${kis_kra_saver_test_SRCS}) target_link_libraries(KisKraSaverTest kritaimage kritaui Qt5::Test) ########### next target ############### set(kis_kra_savexml_visitor_test_SRCS kis_kra_savexml_visitor_test.cpp ) kde4_add_unit_test(KisKraSaveXmlVisitorTest TESTNAME krita-ui-KisKraSaveXmlVisitorTest ${kis_kra_savexml_visitor_test_SRCS}) target_link_libraries(KisKraSaveXmlVisitorTest kritaimage kritaui Qt5::Test) ########### next target ############### set(kis_shape_selection_test_SRCS kis_shape_selection_test.cpp ) kde4_add_unit_test(KisShapeSelectionTest TESTNAME krita-ui-ShapeSelectionTest ${kis_shape_selection_test_SRCS}) target_link_libraries(KisShapeSelectionTest kritaimage kritaui Qt5::Test) ########### next target ############### set(kis_exiv2_test_SRCS kis_exiv2_test.cpp ) kde4_add_broken_unit_test(KisExiv2Test TESTNAME krita-ui-KisExiv2Test ${kis_exiv2_test_SRCS}) target_link_libraries(KisExiv2Test kritaimage kritaui Qt5::Test) ########### next target ############### set(kis_recorded_action_editor_test_SRCS kis_recorded_action_editor_test.cpp ) kde4_add_unit_test(KisRecordedActionEditorTest TESTNAME krita-ui-KisRecordedActionEditor ${kis_recorded_action_editor_test_SRCS}) target_link_libraries(KisRecordedActionEditorTest kritaimage kritaui Qt5::Test) ########### next target ############### set(kis_doc2_test_SRCS kis_doc2_test.cpp ) kde4_add_unit_test(KisDoc2Test TESTNAME krita-ui-KisDoc2Test ${kis_doc2_test_SRCS}) target_link_libraries(KisDoc2Test kritaui kritaimage Qt5::Test) ########### next target ############### set(kis_coordinates_converter_test_SRCS kis_coordinates_converter_test.cpp ) kde4_add_unit_test(KisCoordinatesConverterTest TESTNAME krita-ui-KisCoordinatesConverterTest ${kis_coordinates_converter_test_SRCS}) target_link_libraries(KisCoordinatesConverterTest kritaui kritaimage Qt5::Test) ########### next target ############### set(kis_clipboard_test_SRCS kis_clipboard_test.cpp ) kde4_add_broken_unit_test(KisClipboardTest TESTNAME krita-ui-KisClipboardTest ${kis_clipboard_test_SRCS}) target_link_libraries(KisClipboardTest kritaui kritaimage Qt5::Test) ########### next target ############### set(freehand_stroke_test_SRCS freehand_stroke_test.cpp ${CMAKE_SOURCE_DIR}/sdk/tests/stroke_testing_utils.cpp) kde4_add_broken_unit_test(FreehandStrokeTest TESTNAME krita-ui-FreehandStrokeTest ${freehand_stroke_test_SRCS}) target_link_libraries(FreehandStrokeTest kritaui kritaimage Qt5::Test) ########### next target ############### set(fill_processing_visitor_test_SRCS fill_processing_visitor_test.cpp ${CMAKE_SOURCE_DIR}/sdk/tests/stroke_testing_utils.cpp) kde4_add_broken_unit_test(FillProcessingVisitorTest TESTNAME krita-ui-FillProcessingVisitorTest ${fill_processing_visitor_test_SRCS}) target_link_libraries(FillProcessingVisitorTest kritaui kritaimage Qt5::Test) ########### next target ############### set(filter_stroke_test_SRCS filter_stroke_test.cpp ../../../sdk/tests/stroke_testing_utils.cpp) kde4_add_broken_unit_test(FilterStrokeTest TESTNAME krita-ui-FilterStrokeTest ${filter_stroke_test_SRCS}) target_link_libraries(FilterStrokeTest kritaui kritaimage Qt5::Test) ########### next target ############### set(kis_selection_manager_test_SRCS kis_selection_manager_test.cpp) kde4_add_broken_unit_test(KisSelectionManagerTest TESTNAME krita-ui-KisSelectionManagerTest ${kis_selection_manager_test_SRCS}) target_link_libraries(KisSelectionManagerTest kritaui kritaimage Qt5::Test) #set_tests_properties(krita-ui-KisSelectionManagerTest PROPERTIES TIMEOUT 300) ########### next target ############### set(kis_selection_decoration_test_SRCS kis_selection_decoration_test.cpp ../../../sdk/tests/stroke_testing_utils.cpp) kde4_add_unit_test(KisSelectionDecorationTest TESTNAME krita-ui-KisSelectionDecorationTest ${kis_selection_decoration_test_SRCS}) target_link_libraries(KisSelectionDecorationTest kritaui kritaimage Qt5::Test) ########### next target ############### set(kis_node_manager_test_SRCS kis_node_manager_test.cpp) kde4_add_broken_unit_test(KisNodeManagerTest TESTNAME krita-ui-KisNodeManagerTest ${kis_node_manager_test_SRCS}) target_link_libraries(KisNodeManagerTest kritaui kritaimage Qt5::Test) ########### next target ############### set(kis_node_dummies_graph_test_SRCS kis_node_dummies_graph_test.cpp ../../../sdk/tests/testutil.cpp) kde4_add_unit_test(KisNodeDummiesGraphTest TESTNAME krita-ui-KisNodeDummiesGraphTest ${kis_node_dummies_graph_test_SRCS}) target_link_libraries(KisNodeDummiesGraphTest kritaui kritaimage Qt5::Test) ########### next target ############### set(kis_node_shapes_graph_test_SRCS kis_node_shapes_graph_test.cpp ../../../sdk/tests/testutil.cpp) kde4_add_unit_test(KisNodeShapesGraphTest TESTNAME krita-ui-KisNodeShapesGraphTest ${kis_node_shapes_graph_test_SRCS}) target_link_libraries(KisNodeShapesGraphTest kritaui kritaimage Qt5::Test) ########### next target ############### set(kis_dummies_facade_test_SRCS kis_dummies_facade_test.cpp kis_dummies_facade_base_test.cpp ../../../sdk/tests/testutil.cpp) kde4_add_broken_unit_test(KisDummiesFacadeTest TESTNAME krita-ui-KisDummiesFacadeTest ${kis_dummies_facade_test_SRCS}) target_link_libraries(KisDummiesFacadeTest kritaui kritaimage Qt5::Test) ########### next target ############### set(kis_model_index_converter_test_SRCS kis_model_index_converter_test.cpp ../../../sdk/tests/testutil.cpp) kde4_add_unit_test(KisModelIndexConverterTest TESTNAME krita-ui-KisModelIndexConverterTest ${kis_model_index_converter_test_SRCS}) target_link_libraries(KisModelIndexConverterTest kritaui kritaimage Qt5::Test) ########### next target ############### set(kis_zoom_and_pan_test_SRCS kis_zoom_and_pan_test.cpp ../../../sdk/tests/testutil.cpp) kde4_add_broken_unit_test(KisZoomAndPanTest TESTNAME krita-ui-KisZoomAndPanTest ${kis_zoom_and_pan_test_SRCS}) target_link_libraries(KisZoomAndPanTest kritaui kritaimage Qt5::Test) #set_tests_properties(krita-ui-KisZoomAndPanTest PROPERTIES TIMEOUT 300) ########### next target ############### # set(kis_input_manager_test_SRCS kis_input_manager_test.cpp ../../sdk/tests/testutil.cpp) # kde4_add_unit_test(KisInputManagerTest TESTNAME krita-ui-KisInputManagerTest ${kis_input_manager_test_SRCS}) # target_link_libraries(KisInputManagerTest kritaui kritaimage Qt5::Test) ########### next target ############### set(kis_action_manager_test_SRCS kis_action_manager_test.cpp ) kde4_add_broken_unit_test(KisActionManagerTest TESTNAME krita-ui-KisActionManagerTest ${kis_action_manager_test_SRCS}) target_link_libraries(KisActionManagerTest kritaui kritaimage Qt5::Test) ########### next target ############### set(kis_categories_mapper_test_SRCS kis_categories_mapper_test.cpp testing_categories_mapper.cpp) kde4_add_broken_unit_test(KisCategoriesMapperTest TESTNAME krita-ui-KisCategoriesMapperTest ${kis_categories_mapper_test_SRCS}) target_link_libraries(KisCategoriesMapperTest kritaui kritaimage Qt5::Test) ########### next target ############### set(kis_categorized_list_model_test_SRCS kis_categorized_list_model_test.cpp modeltest.cpp) kde4_add_unit_test(KisCategorizedListModelTest TESTNAME krita-ui-KisCategorizedListModelTest ${kis_categorized_list_model_test_SRCS}) target_link_libraries(KisCategorizedListModelTest kritaui kritaimage Qt5::Test) ########### next target ############### set(kis_resource_server_provider_test_SRCS kis_resource_server_provider_test.cpp modeltest.cpp) kde4_add_unit_test(KisResourceServerProviderTest TESTNAME krita-ui-KisResourceServerProviderTest ${kis_resource_server_provider_test_SRCS}) target_link_libraries(KisResourceServerProviderTest kritaui kritaimage Qt5::Test) ########### next target ############### set(kis_file_layer_test_SRCS kis_file_layer_test.cpp ) kde4_add_unit_test(KisFileLayerTest TESTNAME krita-ui-KisFileLayerTest ${kis_file_layer_test_SRCS}) target_link_libraries(KisFileLayerTest kritaui kritaimage Qt5::Test) ########### next target ############### set(kis_asl_layer_style_serializer_test_SRCS kis_asl_layer_style_serializer_test.cpp ) kde4_add_broken_unit_test(KisAslLayerStyleSerializerTest TESTNAME krita-ui-KisAslLayerStyleSerializerTest ${kis_asl_layer_style_serializer_test_SRCS}) target_link_libraries(KisAslLayerStyleSerializerTest kritaui kritaimage ${QT_QTTEST_LIBRARY}) ########### next target ############### set(kis_node_juggler_compressed_test_SRCS kis_node_juggler_compressed_test.cpp ../../../sdk/tests/testutil.cpp) kde4_add_unit_test(KisNodeJugglerCompressedTest TESTNAME krita-image-BaseNodeTest ${kis_node_juggler_compressed_test_SRCS}) target_link_libraries(KisNodeJugglerCompressedTest kritaimage kritaui Qt5::Test) ########### next target ############### set(kis_node_view_test_SRCS kis_node_view_test.cpp ../../../sdk/tests/testutil.cpp) qt5_add_resources(kis_node_view_test_SRCS ${krita_QRCS}) kde4_add_unit_test(KisNodeViewTest TESTNAME krita-image-BaseNodeTest ${kis_node_view_test_SRCS}) target_link_libraries(KisNodeViewTest kritaimage kritaui Qt5::Test) ########### next target ############### set(kis_multinode_property_test_SRCS kis_multinode_property_test.cpp) kde4_add_unit_test(KisMultinodePropertyTest TESTNAME krita-image-BaseNodeTest ${kis_multinode_property_test_SRCS}) target_link_libraries(KisMultinodePropertyTest kritaimage kritaui Qt5::Test) ########### next target ############### set(kis_grid_config_test_SRCS kis_grid_config_test.cpp) kde4_add_unit_test(KisGridConfigTest TESTNAME krita-image-BaseNodeTest ${kis_grid_config_test_SRCS}) target_link_libraries(KisGridConfigTest kritaui Qt5::Test) ########### next target ############### set(kis_animation_exporter_test_SRCS kis_animation_exporter_test.cpp ) kde4_add_broken_unit_test(KisAnimationExporterTest TESTNAME kritaui-animation_exporter_test ${kis_animation_exporter_test_SRCS}) target_link_libraries(KisAnimationExporterTest kritaui kritaimage ${QT_QTTEST_LIBRARY}) ########### next target ############### set(kis_animation_importer_test_SRCS kis_animation_importer_test.cpp ) kde4_add_broken_unit_test(KisAnimationImporterTest TESTNAME kritaui-animation_importer_test ${kis_animation_importer_test_SRCS}) target_link_libraries(KisAnimationImporterTest kritaui kritaimage ${QT_QTTEST_LIBRARY}) ########### next target ############### set(kis_animation_frame_cache_test_SRCS kis_animation_frame_cache_test.cpp ) kde4_add_broken_unit_test(KisAnimationFrameCacheTest TESTNAME kritaui-animation_frame_cache_test ${kis_animation_frame_cache_test_SRCS}) target_link_libraries(KisAnimationFrameCacheTest kritaui kritaimage ${QT_QTTEST_LIBRARY}) ########### next target ############### set(ResourceBundleTest_SRCS ResourceBundleTest.cpp) kde4_add_broken_unit_test(ResourceBundleTest TESTNAME krita-resourcemanager-ResourceBundleTest ${ResourceBundleTest_SRCS}) target_link_libraries(ResourceBundleTest kritaui kritalibbrush kritalibpaintop Qt5::Test ) ########### next target ############### set(kis_stabilized_events_sampler_test_SRCS kis_stabilized_events_sampler_test.cpp) kde4_add_unit_test(KisStabilizedEventsSamplerTest TESTNAME krita-ui-StabilizedEventsSamplerTest ${kis_stabilized_events_sampler_test_SRCS}) target_link_libraries(KisStabilizedEventsSamplerTest kritaui Qt5::Test) ########### next target ############### set(kis_derived_resources_test_SRCS kis_derived_resources_test.cpp) kde4_add_unit_test(KisDerivedResourcesTest TESTNAME krita-ui-DerivedResourcesTest ${kis_derived_resources_test_SRCS}) target_link_libraries(KisDerivedResourcesTest kritaui Qt5::Test) ########### next target ############### set(kis_brush_hud_properties_config_test_SRCS kis_brush_hud_properties_config_test.cpp) kde4_add_unit_test(KisBrushHudPropertiesConfigTest TESTNAME krita-ui-BrushHudPropertiesConfigTest ${kis_brush_hud_properties_config_test_SRCS}) target_link_libraries(KisBrushHudPropertiesConfigTest kritaui Qt5::Test) + diff --git a/libs/ui/widgets/kis_double_widget.cc b/libs/ui/widgets/kis_double_widget.cc index 6cbcae1f94..ffad82827e 100644 --- a/libs/ui/widgets/kis_double_widget.cc +++ b/libs/ui/widgets/kis_double_widget.cc @@ -1,161 +1,163 @@ /* * kis_double_widget.cc - part of Krita * * Copyright (c) 1999 Carsten Pfeiffer * Copyright (c) 2004 Adrian Page * * 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 "widgets/kis_double_widget.h" #include #include #include #include +#include "kis_double_parse_spin_box.h" + KisDoubleWidget::KisDoubleWidget(QWidget* parent, const char* name) : QWidget(parent) { setObjectName(name); init(0, 1); } KisDoubleWidget::KisDoubleWidget(double min, double max, QWidget* parent, const char* name) : QWidget(parent) { setObjectName(name); init(min, max); } KisDoubleWidget::~KisDoubleWidget() { } void KisDoubleWidget::init(double min, double max) { - m_spinBox = new QDoubleSpinBox(this); + m_spinBox = new KisDoubleParseSpinBox(this); m_spinBox->setMinimum(min); m_spinBox->setMaximum(max); m_spinBox->setSingleStep(0.05); m_spinBox->setValue(0); m_spinBox->setObjectName("spinbox"); connect(m_spinBox, SIGNAL(valueChanged(double)), this, SLOT(setSliderValue(double))); m_slider = new QSlider(Qt::Horizontal, this); m_slider->setMinimum(static_cast(min * 100 + 0.5)); m_slider->setMaximum(static_cast(max * 100 + 0.5)); m_slider->setPageStep(1); m_slider->setValue(0); m_slider->setObjectName("slider"); connect(m_slider, SIGNAL(valueChanged(int)), this, SLOT(sliderValueChanged(int))); connect(m_slider, SIGNAL(sliderPressed()), SIGNAL(sliderPressed())); connect(m_slider, SIGNAL(sliderReleased()), SIGNAL(sliderReleased())); m_layout = new QHBoxLayout(this); m_layout->setObjectName("hbox layout"); m_layout->setMargin(0); m_layout->setSpacing(0); m_layout->addWidget(m_slider); m_layout->addSpacing(5); m_layout->addWidget(m_spinBox); m_layout->addItem(new QSpacerItem(5, 1, QSizePolicy::Expanding, QSizePolicy::Minimum)); } double KisDoubleWidget::value() const { return m_spinBox->value(); } void KisDoubleWidget::setValue(double value) { int intValue; if (value < 0) { intValue = static_cast(value * 100 - 0.5); } else { intValue = static_cast(value * 100 + 0.5); } m_slider->setValue(intValue); } void KisDoubleWidget::setRange(double min, double max) { m_spinBox->setRange(min, max); m_slider->setRange(static_cast(min * 100 + 0.5), static_cast(max * 100 + 0.5)); } void KisDoubleWidget::setTickPosition(QSlider::TickPosition tickPosition) { m_slider->setTickPosition(tickPosition); } void KisDoubleWidget::setTickInterval(double value) { m_slider->setTickInterval(static_cast(value * 100 + 0.5)); } double KisDoubleWidget::tickInterval() const { return m_slider->tickInterval() / 100.0; } void KisDoubleWidget::setSliderValue(double value) { int intValue; if (value < 0) { intValue = static_cast(value * 100 - 0.5); } else { intValue = static_cast(value * 100 + 0.5); } m_slider->setValue(intValue); emit valueChanged(value); } void KisDoubleWidget::sliderValueChanged(int value) { m_spinBox->setValue(value / 100.0); } void KisDoubleWidget::setPrecision(int precision) { m_spinBox->setDecimals(precision); } void KisDoubleWidget::setSingleStep(double step) { m_spinBox->setSingleStep(step); m_slider->setSingleStep(static_cast(step * 100)); } void KisDoubleWidget::setPageStep(double step) { m_slider->setPageStep(static_cast(step * 100)); } void KisDoubleWidget::setTracking(bool tracking) { m_slider->setTracking(tracking); } bool KisDoubleWidget::hasTracking() const { return m_slider->hasTracking(); } diff --git a/libs/ui/widgets/kis_double_widget.h b/libs/ui/widgets/kis_double_widget.h index 39a5bef8ce..c7001e8ea6 100644 --- a/libs/ui/widgets/kis_double_widget.h +++ b/libs/ui/widgets/kis_double_widget.h @@ -1,77 +1,78 @@ /* * widgets/kis_double_widget.h - part of Krita * * Copyright (c) 1999 Carsten Pfeiffer * Copyright (c) 2004 Adrian Page * * 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_DOUBLE_WIDGET_H #define KIS_DOUBLE_WIDGET_H #include #include #include class QHBoxLayout; class QDoubleSpinBox; +class KisDoubleParseSpinBox; class KRITAUI_EXPORT KisDoubleWidget : public QWidget { Q_OBJECT public: KisDoubleWidget(QWidget* parent = 0, const char* name = 0); KisDoubleWidget(double min, double max, QWidget* parent = 0, const char* name = 0); ~KisDoubleWidget(); double value() const; void setRange(double min, double max); void setTickPosition(QSlider::TickPosition tickPosition); void setTickInterval(double tickInterval); double tickInterval() const; void setPrecision(int precision); void setSingleStep(double step); void setPageStep(double step); void setTracking(bool tracking); bool hasTracking() const; Q_SIGNALS: void valueChanged(double); void sliderPressed(); void sliderReleased(); public Q_SLOTS: void setValue(double value); protected Q_SLOTS: void setSliderValue(double); void sliderValueChanged(int); private: void init(double min, double max); protected: QHBoxLayout* m_layout; QSlider* m_slider; - QDoubleSpinBox *m_spinBox; + KisDoubleParseSpinBox *m_spinBox; }; #endif // KIS_DOUBLE_WIDGET_H diff --git a/libs/ui/widgets/kis_multi_double_filter_widget.cc b/libs/ui/widgets/kis_multi_double_filter_widget.cc index d7efe4ae9f..4a7fd922eb 100644 --- a/libs/ui/widgets/kis_multi_double_filter_widget.cc +++ b/libs/ui/widgets/kis_multi_double_filter_widget.cc @@ -1,122 +1,122 @@ /* * Copyright (c) 2004 Cyrille Berger * * 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 "widgets/kis_multi_double_filter_widget.h" #include #include #include #include #include #include #include #include KisDelayedActionDoubleInput::KisDelayedActionDoubleInput(QWidget * parent, const QString & name) - : QDoubleSpinBox(parent) + : KisDoubleParseSpinBox(parent) { setObjectName(name); m_timer = new QTimer(this); m_timer->setObjectName(name); m_timer->setSingleShot(true); connect(m_timer, SIGNAL(timeout()), SLOT(slotValueChanged())); connect(this, SIGNAL(valueChanged(double)), SLOT(slotTimeToUpdate())); } void KisDelayedActionDoubleInput::slotTimeToUpdate() { m_timer->start(50); } void KisDelayedActionDoubleInput::slotValueChanged() { emit valueChangedDelayed(value()); } void KisDelayedActionDoubleInput::cancelDelayedSignal() { m_timer->stop(); } KisDoubleWidgetParam::KisDoubleWidgetParam(double nmin, double nmax, double ninitvalue, const QString & nlabel, const QString & nname) : min(nmin), max(nmax), initvalue(ninitvalue), label(nlabel), name(nname) { } KisMultiDoubleFilterWidget::KisMultiDoubleFilterWidget(const QString & filterid, QWidget * parent, const QString & caption, vKisDoubleWidgetParam dwparam) : KisConfigWidget(parent), m_filterid(filterid) { m_nbdoubleWidgets = dwparam.size(); this->setWindowTitle(caption); QGridLayout *widgetLayout = new QGridLayout(this); widgetLayout->setColumnStretch(1, 1); widgetLayout->setContentsMargins(0,0,0,0); widgetLayout->setHorizontalSpacing(0); m_doubleWidgets = new KisDelayedActionDoubleInput*[ m_nbdoubleWidgets ]; for (qint32 i = 0; i < m_nbdoubleWidgets; ++i) { m_doubleWidgets[i] = new KisDelayedActionDoubleInput(this, dwparam[i].name); m_doubleWidgets[i]->setRange(dwparam[i].min, dwparam[i].max); m_doubleWidgets[i]->setValue(dwparam[i].initvalue); m_doubleWidgets[i]->cancelDelayedSignal(); connect(m_doubleWidgets[i], SIGNAL(valueChangedDelayed(double)), SIGNAL(sigConfigurationItemChanged())); QLabel* lbl = new QLabel(dwparam[i].label + ':', this); widgetLayout->addWidget(lbl, i , 0); widgetLayout->addWidget(m_doubleWidgets[i], i , 1); } widgetLayout->setRowStretch(m_nbdoubleWidgets,1); QSpacerItem * sp = new QSpacerItem(1, 1); widgetLayout->addItem(sp, m_nbdoubleWidgets, 0); } void KisMultiDoubleFilterWidget::setConfiguration(const KisPropertiesConfiguration * config) { if (!config) return; for (int i = 0; i < m_nbdoubleWidgets ; ++i) { KisDelayedActionDoubleInput * w = m_doubleWidgets[i]; if (w) { double val = config->getDouble(m_doubleWidgets[i]->objectName()); m_doubleWidgets[i]->setValue(val); m_doubleWidgets[i]->cancelDelayedSignal(); } } } KisPropertiesConfiguration* KisMultiDoubleFilterWidget::configuration() const { KisFilterConfiguration* config = new KisFilterConfiguration(m_filterid, 0); for (int i = 0; i < nbValues(); ++i) { config->setProperty(m_doubleWidgets[i]->objectName(), m_doubleWidgets[i]->value()); } return config; } diff --git a/libs/ui/widgets/kis_multi_double_filter_widget.h b/libs/ui/widgets/kis_multi_double_filter_widget.h index 90b4fe7efd..88b63c2163 100644 --- a/libs/ui/widgets/kis_multi_double_filter_widget.h +++ b/libs/ui/widgets/kis_multi_double_filter_widget.h @@ -1,82 +1,84 @@ /* * Copyright (c) 2004 Cyrille Berger * * 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_MULTI_DOUBLE_FILTER_WIDGET_H_ #define _KIS_MULTI_DOUBLE_FILTER_WIDGET_H_ #include #include #include #include "kritaui_export.h" -class KisDelayedActionDoubleInput : public QDoubleSpinBox +#include "kis_double_parse_spin_box.h" + +class KisDelayedActionDoubleInput : public KisDoubleParseSpinBox { Q_OBJECT public: KisDelayedActionDoubleInput(QWidget * parent, const QString & name); void cancelDelayedSignal(); private Q_SLOTS: void slotValueChanged(); void slotTimeToUpdate(); Q_SIGNALS: void valueChangedDelayed(double value); private: QTimer * m_timer; }; struct KRITAUI_EXPORT KisDoubleWidgetParam { KisDoubleWidgetParam(double nmin, double nmax, double ninitvalue, const QString & label, const QString & nname); double min; double max; double initvalue; QString label; QString name; }; typedef std::vector vKisDoubleWidgetParam; class KRITAUI_EXPORT KisMultiDoubleFilterWidget : public KisConfigWidget { Q_OBJECT public: KisMultiDoubleFilterWidget(const QString & filterid, QWidget * parent, const QString & caption, vKisDoubleWidgetParam dwparam); virtual void setConfiguration(const KisPropertiesConfiguration * cfg); virtual KisPropertiesConfiguration* configuration() const; public: inline qint32 nbValues() const { return m_nbdoubleWidgets; } inline double valueAt(qint32 i) { return m_doubleWidgets[i]->value(); } private: KisDelayedActionDoubleInput** m_doubleWidgets; qint32 m_nbdoubleWidgets; QString m_filterid; }; #endif diff --git a/libs/ui/widgets/kis_multi_integer_filter_widget.cc b/libs/ui/widgets/kis_multi_integer_filter_widget.cc index d5666bea97..ba8d7415f5 100644 --- a/libs/ui/widgets/kis_multi_integer_filter_widget.cc +++ b/libs/ui/widgets/kis_multi_integer_filter_widget.cc @@ -1,155 +1,155 @@ /* * Copyright (c) 2004 Cyrille Berger * * 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 "widgets/kis_multi_integer_filter_widget.h" #include #include #include #include #include #include #include KisDelayedActionIntegerInput::KisDelayedActionIntegerInput(QWidget * parent, const QString & name) - : QSpinBox(parent) + : KisIntParseSpinBox(parent) { setObjectName(name); m_timer = new QTimer(this); m_timer->setObjectName(name); m_timer->setSingleShot(true); connect(m_timer, SIGNAL(timeout()), SLOT(slotValueChanged())); connect(this, SIGNAL(valueChanged(int)), SLOT(slotTimeToUpdate())); } void KisDelayedActionIntegerInput::slotTimeToUpdate() { m_timer->start(50); } void KisDelayedActionIntegerInput::slotValueChanged() { emit valueChangedDelayed(value()); } void KisDelayedActionIntegerInput::cancelDelayedSignal() { m_timer->stop(); } KisIntegerWidgetParam::KisIntegerWidgetParam(qint32 nmin, qint32 nmax, qint32 ninitvalue, const QString & label, const QString & nname) : min(nmin) , max(nmax) , initvalue(ninitvalue) , label(label) , name(nname) { } KisMultiIntegerFilterWidget::KisMultiIntegerFilterWidget(const QString& filterid, QWidget* parent, const QString& caption, vKisIntegerWidgetParam iwparam) : KisConfigWidget(parent) , m_filterid(filterid) , m_config(new KisFilterConfiguration(filterid, 0)) { this->setWindowTitle(caption); QGridLayout *widgetLayout = new QGridLayout(this); widgetLayout->setColumnStretch(1, 1); widgetLayout->setContentsMargins(0,0,0,0); widgetLayout->setHorizontalSpacing(0); for (uint i = 0; i < iwparam.size(); ++i) { KisDelayedActionIntegerInput *widget = new KisDelayedActionIntegerInput(this, iwparam[i].name); widget->setRange(iwparam[i].min, iwparam[i].max); widget->setValue(iwparam[i].initvalue); widget->cancelDelayedSignal(); connect(widget, SIGNAL(valueChangedDelayed(int)), SIGNAL(sigConfigurationItemChanged())); QLabel* lbl = new QLabel(iwparam[i].label + ':', this); widgetLayout->addWidget(lbl, i , 0); widgetLayout->addWidget(widget, i , 1); m_integerWidgets.append(widget); } widgetLayout->setRowStretch(iwparam.size(),1); QSpacerItem * sp = new QSpacerItem(1, 1); widgetLayout->addItem(sp, iwparam.size(), 0); } KisMultiIntegerFilterWidget::~KisMultiIntegerFilterWidget() { delete m_config; } void KisMultiIntegerFilterWidget::setConfiguration(const KisPropertiesConfiguration* config) { if (!config) return; if (!m_config) { m_config = new KisFilterConfiguration(m_filterid, 0); } m_config->fromXML(config->toXML()); for (int i = 0; i < nbValues(); ++i) { KisDelayedActionIntegerInput* w = m_integerWidgets[i]; if (w) { int val = config->getInt(m_integerWidgets[i]->objectName()); m_integerWidgets[i]->setValue(val); m_integerWidgets[i]->cancelDelayedSignal(); } } } KisPropertiesConfiguration* KisMultiIntegerFilterWidget::configuration() const { KisFilterConfiguration *config = new KisFilterConfiguration(m_filterid, 0); if (m_config) { config->fromXML(m_config->toXML()); } for (int i = 0; i < nbValues(); ++i) { KisDelayedActionIntegerInput* w = m_integerWidgets[i]; if (w) { config->setProperty(w->objectName(), w->value()); } } return config; } qint32 KisMultiIntegerFilterWidget::nbValues() const { return m_integerWidgets.size(); } qint32 KisMultiIntegerFilterWidget::valueAt(qint32 i) { if (i < m_integerWidgets.size()) { return m_integerWidgets[i]->value(); } else { warnKrita << "Trying to access integer widget" << i << "but there are only" << m_integerWidgets.size() << "widgets"; return 0; } } diff --git a/libs/ui/widgets/kis_multi_integer_filter_widget.h b/libs/ui/widgets/kis_multi_integer_filter_widget.h index 119d04537d..81d1fc3d0d 100644 --- a/libs/ui/widgets/kis_multi_integer_filter_widget.h +++ b/libs/ui/widgets/kis_multi_integer_filter_widget.h @@ -1,83 +1,85 @@ /* * Copyright (c) 2004 Cyrille Berger * * 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_MULTI_INTEGER_FILTER_WIDGET_H_ #define _KIS_MULTI_INTEGER_FILTER_WIDGET_H_ #include #include "kritaui_export.h" #include #include #include +#include "kis_int_parse_spin_box.h" + #include -class KisDelayedActionIntegerInput : public QSpinBox +class KisDelayedActionIntegerInput : public KisIntParseSpinBox { Q_OBJECT public: KisDelayedActionIntegerInput(QWidget * parent, const QString & name); void cancelDelayedSignal(); private Q_SLOTS: void slotValueChanged(); void slotTimeToUpdate(); Q_SIGNALS: void valueChangedDelayed(int value); private: QTimer * m_timer; }; struct KRITAUI_EXPORT KisIntegerWidgetParam { KisIntegerWidgetParam(qint32 nmin, qint32 nmax, qint32 ninitvalue, const QString& label, const QString& nname); qint32 min; qint32 max; qint32 initvalue; QString label; QString name; }; typedef std::vector vKisIntegerWidgetParam; class KRITAUI_EXPORT KisMultiIntegerFilterWidget : public KisConfigWidget { Q_OBJECT public: KisMultiIntegerFilterWidget(const QString& filterid, QWidget* parent, const QString& caption, vKisIntegerWidgetParam iwparam); ~KisMultiIntegerFilterWidget(); virtual void setConfiguration(const KisPropertiesConfiguration* config); virtual KisPropertiesConfiguration* configuration() const; private: qint32 nbValues() const; qint32 valueAt(qint32 i); QVector m_integerWidgets; QString m_filterid; KisPropertiesConfiguration* m_config; }; #endif diff --git a/libs/ui/widgets/kis_slider_spin_box.cpp b/libs/ui/widgets/kis_slider_spin_box.cpp index af6effc42b..356ce77487 100644 --- a/libs/ui/widgets/kis_slider_spin_box.cpp +++ b/libs/ui/widgets/kis_slider_spin_box.cpp @@ -1,1011 +1,1029 @@ /* This file is part of the KDE project * Copyright (c) 2010 Justin Noel * Copyright (c) 2010 Cyrille Berger * Copyright (c) 2015 Moritz Molch * * 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. */ #include "kis_slider_spin_box.h" #include #include #include #include #include #include #include #include #include #include #include #include "KisPart.h" #include "input/kis_input_manager.h" +#include "kis_num_parser.h" + class KisAbstractSliderSpinBoxPrivate { public: enum Style { STYLE_NOQUIRK, STYLE_PLASTIQUE, STYLE_BREEZE, STYLE_FUSION, }; QLineEdit* edit; QDoubleValidator* validator; bool upButtonDown; bool downButtonDown; int factor; int fastSliderStep; qreal slowFactor; qreal shiftPercent; bool shiftMode; QString prefix; QString suffix; qreal exponentRatio; int value; int maximum; int minimum; int singleStep; QSpinBox* dummySpinBox; Style style; bool blockUpdateSignalOnDrag; bool isDragging; + bool parseInt; }; KisAbstractSliderSpinBox::KisAbstractSliderSpinBox(QWidget* parent, KisAbstractSliderSpinBoxPrivate* _d) : QWidget(parent) , d_ptr(_d) { Q_D(KisAbstractSliderSpinBox); QEvent e(QEvent::StyleChange); changeEvent(&e); d->upButtonDown = false; d->downButtonDown = false; d->edit = new QLineEdit(this); d->edit->setFrame(false); d->edit->setAlignment(Qt::AlignCenter); d->edit->hide(); d->edit->setContentsMargins(0,0,0,0); d->edit->installEventFilter(this); //Make edit transparent d->edit->setAutoFillBackground(false); QPalette pal = d->edit->palette(); pal.setColor(QPalette::Base, Qt::transparent); d->edit->setPalette(pal); connect(d->edit, SIGNAL(editingFinished()), this, SLOT(editLostFocus())); d->validator = new QDoubleValidator(d->edit); - d->edit->setValidator(d->validator); d->value = 0; d->minimum = 0; d->maximum = 100; d->factor = 1.0; d->singleStep = 1; d->fastSliderStep = 5; d->slowFactor = 0.1; d->shiftMode = false; d->blockUpdateSignalOnDrag = false; d->isDragging = false; + d->parseInt = false; + setExponentRatio(1.0); //Set sane defaults setFocusPolicy(Qt::StrongFocus); setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed); //dummy needed to fix a bug in the polyester theme d->dummySpinBox = new QSpinBox(this); d->dummySpinBox->hide(); } KisAbstractSliderSpinBox::~KisAbstractSliderSpinBox() { Q_D(KisAbstractSliderSpinBox); delete d; } void KisAbstractSliderSpinBox::showEdit() { Q_D(KisAbstractSliderSpinBox); if (d->edit->isVisible()) return; if (d->style == KisAbstractSliderSpinBoxPrivate::STYLE_PLASTIQUE) { d->edit->setGeometry(progressRect(spinBoxOptions()).adjusted(0,0,-2,0)); } else { d->edit->setGeometry(progressRect(spinBoxOptions())); } d->edit->setText(valueString()); d->edit->selectAll(); d->edit->show(); d->edit->setFocus(Qt::OtherFocusReason); update(); KisPart::currentInputManager()->slotFocusOnEnter(false); } void KisAbstractSliderSpinBox::hideEdit() { Q_D(KisAbstractSliderSpinBox); d->edit->hide(); update(); KisPart::currentInputManager()->slotFocusOnEnter(true); } void KisAbstractSliderSpinBox::paintEvent(QPaintEvent* e) { Q_D(KisAbstractSliderSpinBox); Q_UNUSED(e) QPainter painter(this); switch (d->style) { case KisAbstractSliderSpinBoxPrivate::STYLE_FUSION: paintFusion(painter); break; case KisAbstractSliderSpinBoxPrivate::STYLE_PLASTIQUE: paintPlastique(painter); break; case KisAbstractSliderSpinBoxPrivate::STYLE_BREEZE: paintBreeze(painter); break; default: paint(painter); break; } painter.end(); } void KisAbstractSliderSpinBox::paint(QPainter &painter) { Q_D(KisAbstractSliderSpinBox); //Create options to draw spin box parts QStyleOptionSpinBox spinOpts = spinBoxOptions(); spinOpts.rect.adjust(0, 2, 0, -2); //Draw "SpinBox".Clip off the area of the lineEdit to avoid double //borders being drawn painter.save(); painter.setClipping(true); QRect eraseRect(QPoint(rect().x(), rect().y()), QPoint(progressRect(spinOpts).right(), rect().bottom())); painter.setClipRegion(QRegion(rect()).subtracted(eraseRect)); style()->drawComplexControl(QStyle::CC_SpinBox, &spinOpts, &painter, d->dummySpinBox); painter.setClipping(false); painter.restore(); QStyleOptionProgressBar progressOpts = progressBarOptions(); progressOpts.rect.adjust(0, 2, 0, -2); style()->drawControl(QStyle::CE_ProgressBar, &progressOpts, &painter, 0); //Draw focus if necessary if (hasFocus() && d->edit->hasFocus()) { QStyleOptionFocusRect focusOpts; focusOpts.initFrom(this); focusOpts.rect = progressOpts.rect; focusOpts.backgroundColor = palette().color(QPalette::Window); style()->drawPrimitive(QStyle::PE_FrameFocusRect, &focusOpts, &painter, this); } } void KisAbstractSliderSpinBox::paintFusion(QPainter &painter) { Q_D(KisAbstractSliderSpinBox); QStyleOptionSpinBox spinOpts = spinBoxOptions(); spinOpts.frame = true; spinOpts.rect.adjust(0, -1, 0, 1); //spinOpts.palette().setBrush(QPalette::Base, palette().highlight()); QStyleOptionProgressBar progressOpts = progressBarOptions(); style()->drawComplexControl(QStyle::CC_SpinBox, &spinOpts, &painter, d->dummySpinBox); painter.save(); QRect rect = progressOpts.rect.adjusted(1,2,-4,-2); QRect leftRect; int progressIndicatorPos = (progressOpts.progress - qreal(progressOpts.minimum)) / qMax(qreal(1.0), qreal(progressOpts.maximum) - progressOpts.minimum) * rect.width(); if (progressIndicatorPos >= 0 && progressIndicatorPos <= rect.width() && (progressOpts.progress != 0)) { leftRect = QRect(rect.left(), rect.top(), progressIndicatorPos, rect.height()); } else if (progressIndicatorPos > rect.width()) { painter.setPen(palette().highlightedText().color()); } else { painter.setPen(palette().buttonText().color()); } QRegion rightRect = rect; rightRect = rightRect.subtracted(leftRect); QTextOption textOption(Qt::AlignAbsolute | Qt::AlignHCenter | Qt::AlignVCenter); textOption.setWrapMode(QTextOption::NoWrap); if (!(d->edit && d->edit->isVisible())) { painter.setClipRegion(rightRect); painter.setClipping(true); painter.drawText(rect.adjusted(-2,0,2,0), progressOpts.text, textOption); painter.setClipping(false); } if (!leftRect.isNull()) { painter.setClipRect(leftRect.adjusted(0, -1, 1, 1)); painter.setPen(palette().highlight().color()); painter.setBrush(palette().highlight()); spinOpts.palette.setBrush(QPalette::Base, palette().highlight()); style()->drawComplexControl(QStyle::CC_SpinBox, &spinOpts, &painter, d->dummySpinBox); if (!(d->edit && d->edit->isVisible())) { painter.setPen(palette().highlightedText().color()); painter.setClipping(true); painter.drawText(rect.adjusted(-2,0,2,0), progressOpts.text, textOption); } painter.setClipping(false); } painter.restore(); } void KisAbstractSliderSpinBox::paintPlastique(QPainter &painter) { Q_D(KisAbstractSliderSpinBox); QStyleOptionSpinBox spinOpts = spinBoxOptions(); QStyleOptionProgressBar progressOpts = progressBarOptions(); style()->drawComplexControl(QStyle::CC_SpinBox, &spinOpts, &painter, d->dummySpinBox); painter.save(); QRect rect = progressOpts.rect.adjusted(2,0,-2,0); QRect leftRect; int progressIndicatorPos = (progressOpts.progress - qreal(progressOpts.minimum)) / qMax(qreal(1.0), qreal(progressOpts.maximum) - progressOpts.minimum) * rect.width(); if (progressIndicatorPos >= 0 && progressIndicatorPos <= rect.width() && (progressOpts.progress != 0)) { leftRect = QRect(rect.left(), rect.top(), progressIndicatorPos, rect.height()); } else if (progressIndicatorPos > rect.width()) { painter.setPen(palette().highlightedText().color()); } else { painter.setPen(palette().buttonText().color()); } QRegion rightRect = rect; rightRect = rightRect.subtracted(leftRect); QTextOption textOption(Qt::AlignAbsolute | Qt::AlignHCenter | Qt::AlignVCenter); textOption.setWrapMode(QTextOption::NoWrap); if (!(d->edit && d->edit->isVisible())) { painter.setClipRegion(rightRect); painter.setClipping(true); painter.drawText(rect.adjusted(-2,0,2,0), progressOpts.text, textOption); painter.setClipping(false); } if (!leftRect.isNull()) { painter.setPen(palette().highlight().color()); painter.setBrush(palette().highlight()); painter.drawRect(leftRect.adjusted(0,0,0,-1)); if (!(d->edit && d->edit->isVisible())) { painter.setPen(palette().highlightedText().color()); painter.setClipRect(leftRect.adjusted(0,0,1,0)); painter.setClipping(true); painter.drawText(rect.adjusted(-2,0,2,0), progressOpts.text, textOption); painter.setClipping(false); } } painter.restore(); } void KisAbstractSliderSpinBox::paintBreeze(QPainter &painter) { Q_D(KisAbstractSliderSpinBox); QStyleOptionSpinBox spinOpts = spinBoxOptions(); QStyleOptionProgressBar progressOpts = progressBarOptions(); QString valueText = progressOpts.text; progressOpts.text = ""; progressOpts.rect.adjust(0, 1, 0, -1); style()->drawComplexControl(QStyle::CC_SpinBox, &spinOpts, &painter, this); style()->drawControl(QStyle::CE_ProgressBarGroove, &progressOpts, &painter, this); painter.save(); QRect leftRect; int progressIndicatorPos = (progressOpts.progress - qreal(progressOpts.minimum)) / qMax(qreal(1.0), qreal(progressOpts.maximum) - progressOpts.minimum) * progressOpts.rect.width(); if (progressIndicatorPos >= 0 && progressIndicatorPos <= progressOpts.rect.width()) { leftRect = QRect(progressOpts.rect.left(), progressOpts.rect.top(), progressIndicatorPos, progressOpts.rect.height()); } else if (progressIndicatorPos > progressOpts.rect.width()) { painter.setPen(palette().highlightedText().color()); } else { painter.setPen(palette().buttonText().color()); } QRegion rightRect = progressOpts.rect; rightRect = rightRect.subtracted(leftRect); painter.setClipRegion(rightRect); QTextOption textOption(Qt::AlignAbsolute | Qt::AlignHCenter | Qt::AlignVCenter); textOption.setWrapMode(QTextOption::NoWrap); if (!(d->edit && d->edit->isVisible())) { painter.drawText(progressOpts.rect, valueText, textOption); } if (!leftRect.isNull()) { painter.setPen(palette().highlightedText().color()); painter.setClipRect(leftRect); style()->drawControl(QStyle::CE_ProgressBarContents, &progressOpts, &painter, this); if (!(d->edit && d->edit->isVisible())) { painter.drawText(progressOpts.rect, valueText, textOption); } } painter.restore(); } void KisAbstractSliderSpinBox::mousePressEvent(QMouseEvent* e) { Q_D(KisAbstractSliderSpinBox); QStyleOptionSpinBox spinOpts = spinBoxOptions(); //Depress buttons or highlight slider //Also used to emulate mouse grab... if (e->buttons() & Qt::LeftButton) { if (upButtonRect(spinOpts).contains(e->pos())) { d->upButtonDown = true; } else if (downButtonRect(spinOpts).contains(e->pos())) { d->downButtonDown = true; } } else if (e->buttons() & Qt::RightButton) { showEdit(); } update(); } void KisAbstractSliderSpinBox::mouseReleaseEvent(QMouseEvent* e) { Q_D(KisAbstractSliderSpinBox); QStyleOptionSpinBox spinOpts = spinBoxOptions(); d->isDragging = false; //Step up/down for buttons //Emualting mouse grab too if (upButtonRect(spinOpts).contains(e->pos()) && d->upButtonDown) { setInternalValue(d->value + d->singleStep); } else if (downButtonRect(spinOpts).contains(e->pos()) && d->downButtonDown) { setInternalValue(d->value - d->singleStep); } else if (progressRect(spinOpts).contains(e->pos()) && !(d->edit->isVisible()) && !(d->upButtonDown || d->downButtonDown)) { //Snap to percentage for progress area setInternalValue(valueForX(e->pos().x(),e->modifiers())); } else { // Confirm the last known value, since we might be ignoring move events setInternalValue(d->value); } d->upButtonDown = false; d->downButtonDown = false; update(); } void KisAbstractSliderSpinBox::mouseMoveEvent(QMouseEvent* e) { Q_D(KisAbstractSliderSpinBox); if( e->modifiers() & Qt::ShiftModifier ) { if( !d->shiftMode ) { d->shiftPercent = pow( qreal(d->value - d->minimum)/qreal(d->maximum - d->minimum), 1/qreal(d->exponentRatio) ); d->shiftMode = true; } } else { d->shiftMode = false; } //Respect emulated mouse grab. if (e->buttons() & Qt::LeftButton && !(d->downButtonDown || d->upButtonDown)) { d->isDragging = true; setInternalValue(valueForX(e->pos().x(),e->modifiers()), d->blockUpdateSignalOnDrag); update(); } } void KisAbstractSliderSpinBox::keyPressEvent(QKeyEvent* e) { Q_D(KisAbstractSliderSpinBox); switch (e->key()) { case Qt::Key_Up: case Qt::Key_Right: setInternalValue(d->value + d->singleStep); break; case Qt::Key_Down: case Qt::Key_Left: setInternalValue(d->value - d->singleStep); break; case Qt::Key_Shift: d->shiftPercent = pow( qreal(d->value - d->minimum)/qreal(d->maximum - d->minimum), 1/qreal(d->exponentRatio) ); d->shiftMode = true; break; case Qt::Key_Enter: //Line edit isn't "accepting" key strokes... case Qt::Key_Return: case Qt::Key_Escape: case Qt::Key_Control: case Qt::Key_Alt: case Qt::Key_AltGr: case Qt::Key_Super_L: case Qt::Key_Super_R: break; default: showEdit(); d->edit->event(e); break; } } void KisAbstractSliderSpinBox::wheelEvent(QWheelEvent *e) { Q_D(KisAbstractSliderSpinBox); if ( e->delta() > 0) { setInternalValue(d->value + d->singleStep); } else { setInternalValue(d->value - d->singleStep); } update(); e->accept(); } void KisAbstractSliderSpinBox::commitEnteredValue() { Q_D(KisAbstractSliderSpinBox); - QLocale locale; + //QLocale locale; bool ok = false; - qreal value = locale.toDouble(d->edit->text(), &ok) * d->factor; + //qreal value = locale.toDouble(d->edit->text(), &ok) * d->factor; + qreal value; + + if (d->parseInt) { + value = KisNumericParser::parseIntegerMathExpr(d->edit->text(), &ok) * d->factor; + } else { + value = KisNumericParser::parseSimpleMathExpr(d->edit->text(), &ok) * d->factor; + } + if (ok) { setInternalValue(value); } } bool KisAbstractSliderSpinBox::eventFilter(QObject* recv, QEvent* e) { Q_D(KisAbstractSliderSpinBox); if (recv == static_cast(d->edit) && e->type() == QEvent::KeyRelease) { QKeyEvent* keyEvent = static_cast(e); switch (keyEvent->key()) { case Qt::Key_Enter: case Qt::Key_Return: { commitEnteredValue(); hideEdit(); return true; } case Qt::Key_Escape: d->edit->setText(valueString()); hideEdit(); return true; default: break; } } return false; } QSize KisAbstractSliderSpinBox::sizeHint() const { const Q_D(KisAbstractSliderSpinBox); QStyleOptionSpinBox spinOpts = spinBoxOptions(); QFont ft(font()); if (d->style == KisAbstractSliderSpinBoxPrivate::STYLE_NOQUIRK) { // Some styles use bold font in progressbars // unfortunately there is no reliable way to check for that ft.setBold(true); } QFontMetrics fm(ft); QSize hint(fm.boundingRect(d->prefix + QString::number(d->maximum) + d->suffix).size()); hint += QSize(0, 2); switch (d->style) { case KisAbstractSliderSpinBoxPrivate::STYLE_FUSION: hint += QSize(8, 8); break; case KisAbstractSliderSpinBoxPrivate::STYLE_PLASTIQUE: hint += QSize(8, 0); break; case KisAbstractSliderSpinBoxPrivate::STYLE_BREEZE: hint += QSize(2, 0); break; case KisAbstractSliderSpinBoxPrivate::STYLE_NOQUIRK: // almost all "modern" styles have a margin around controls hint += QSize(6, 6); break; default: break; } //Getting the size of the buttons is a pain as the calcs require a rect //that is "big enough". We run the calc twice to get the "smallest" buttons //This code was inspired by QAbstractSpinBox QSize extra(1000, 0); spinOpts.rect.setSize(hint + extra); extra += hint - style()->subControlRect(QStyle::CC_SpinBox, &spinOpts, QStyle::SC_SpinBoxEditField, this).size(); spinOpts.rect.setSize(hint + extra); extra += hint - style()->subControlRect(QStyle::CC_SpinBox, &spinOpts, QStyle::SC_SpinBoxEditField, this).size(); hint += extra; spinOpts.rect.setSize(hint); return style()->sizeFromContents(QStyle::CT_SpinBox, &spinOpts, hint) .expandedTo(QApplication::globalStrut()); } QSize KisAbstractSliderSpinBox::minimumSizeHint() const { return sizeHint(); } QSize KisAbstractSliderSpinBox::minimumSize() const { return QWidget::minimumSize().expandedTo(minimumSizeHint()); } QStyleOptionSpinBox KisAbstractSliderSpinBox::spinBoxOptions() const { const Q_D(KisAbstractSliderSpinBox); QStyleOptionSpinBox opts; opts.initFrom(this); opts.frame = false; opts.buttonSymbols = QAbstractSpinBox::UpDownArrows; opts.subControls = QStyle::SC_SpinBoxUp | QStyle::SC_SpinBoxDown; //Disable non-logical buttons if (d->value == d->minimum) { opts.stepEnabled = QAbstractSpinBox::StepUpEnabled; } else if (d->value == d->maximum) { opts.stepEnabled = QAbstractSpinBox::StepDownEnabled; } else { opts.stepEnabled = QAbstractSpinBox::StepUpEnabled | QAbstractSpinBox::StepDownEnabled; } //Deal with depressed buttons if (d->upButtonDown) { opts.activeSubControls = QStyle::SC_SpinBoxUp; } else if (d->downButtonDown) { opts.activeSubControls = QStyle::SC_SpinBoxDown; } else { opts.activeSubControls = 0; } return opts; } QStyleOptionProgressBar KisAbstractSliderSpinBox::progressBarOptions() const { const Q_D(KisAbstractSliderSpinBox); QStyleOptionSpinBox spinOpts = spinBoxOptions(); //Create opts for drawing the progress portion QStyleOptionProgressBar progressOpts; progressOpts.initFrom(this); progressOpts.maximum = d->maximum; progressOpts.minimum = d->minimum; qreal minDbl = d->minimum; qreal dValues = (d->maximum - minDbl); progressOpts.progress = dValues * pow((d->value - minDbl) / dValues, 1.0 / d->exponentRatio) + minDbl; progressOpts.text = d->prefix + valueString() + d->suffix; progressOpts.textAlignment = Qt::AlignCenter; progressOpts.textVisible = !(d->edit->isVisible()); //Change opts rect to be only the ComboBox's text area progressOpts.rect = progressRect(spinOpts); return progressOpts; } QRect KisAbstractSliderSpinBox::progressRect(const QStyleOptionSpinBox& spinBoxOptions) const { const Q_D(KisAbstractSliderSpinBox); QRect ret = style()->subControlRect(QStyle::CC_SpinBox, &spinBoxOptions, QStyle::SC_SpinBoxEditField); switch (d->style) { case KisAbstractSliderSpinBoxPrivate::STYLE_PLASTIQUE: ret.adjust(-2, 0, 1, 0); break; case KisAbstractSliderSpinBoxPrivate::STYLE_BREEZE: ret.adjust(1, 0, 0, 0); break; default: break; } return ret; } QRect KisAbstractSliderSpinBox::upButtonRect(const QStyleOptionSpinBox& spinBoxOptions) const { return style()->subControlRect(QStyle::CC_SpinBox, &spinBoxOptions, QStyle::SC_SpinBoxUp); } QRect KisAbstractSliderSpinBox::downButtonRect(const QStyleOptionSpinBox& spinBoxOptions) const { return style()->subControlRect(QStyle::CC_SpinBox, &spinBoxOptions, QStyle::SC_SpinBoxDown); } int KisAbstractSliderSpinBox::valueForX(int x, Qt::KeyboardModifiers modifiers) const { const Q_D(KisAbstractSliderSpinBox); QStyleOptionSpinBox spinOpts = spinBoxOptions(); QRect correctedProgRect; if (d->style == KisAbstractSliderSpinBoxPrivate::STYLE_FUSION) { correctedProgRect = progressRect(spinOpts).adjusted(2, 0, -2, 0); } else if (d->style == KisAbstractSliderSpinBoxPrivate::STYLE_BREEZE) { correctedProgRect = progressRect(spinOpts); } else { //Adjust for magic number in style code (margins) correctedProgRect = progressRect(spinOpts).adjusted(2, 2, -2, -2); } //Compute the distance of the progress bar, in pixel qreal leftDbl = correctedProgRect.left(); qreal xDbl = x - leftDbl; //Compute the ration of the progress bar used, linearly (ignoring the exponent) qreal rightDbl = correctedProgRect.right(); qreal minDbl = d->minimum; qreal maxDbl = d->maximum; qreal dValues = (maxDbl - minDbl); qreal percent = (xDbl / (rightDbl - leftDbl)); //If SHIFT is pressed, movement should be slowed. if( modifiers & Qt::ShiftModifier ) { percent = d->shiftPercent + ( percent - d->shiftPercent ) * d->slowFactor; } //Final value qreal realvalue = ((dValues * pow(percent, d->exponentRatio)) + minDbl); //If key CTRL is pressed, round to the closest step. if( modifiers & Qt::ControlModifier ) { qreal fstep = d->fastSliderStep; if( modifiers & Qt::ShiftModifier ) { fstep*=d->slowFactor; } realvalue = floor( (realvalue+fstep/2) / fstep ) * fstep; } //Return the value return int(realvalue); } void KisAbstractSliderSpinBox::setPrefix(const QString& prefix) { Q_D(KisAbstractSliderSpinBox); d->prefix = prefix; } void KisAbstractSliderSpinBox::setSuffix(const QString& suffix) { Q_D(KisAbstractSliderSpinBox); d->suffix = suffix; } void KisAbstractSliderSpinBox::setExponentRatio(qreal dbl) { Q_D(KisAbstractSliderSpinBox); Q_ASSERT(dbl > 0); d->exponentRatio = dbl; } void KisAbstractSliderSpinBox::setBlockUpdateSignalOnDrag(bool blockUpdateSignal) { Q_D(KisAbstractSliderSpinBox); d->blockUpdateSignalOnDrag = blockUpdateSignal; } void KisAbstractSliderSpinBox::contextMenuEvent(QContextMenuEvent* event) { event->accept(); } void KisAbstractSliderSpinBox::editLostFocus() { Q_D(KisAbstractSliderSpinBox); if (!d->edit->hasFocus()) { commitEnteredValue(); hideEdit(); } } void KisAbstractSliderSpinBox::setInternalValue(int value) { setInternalValue(value, false); } bool KisAbstractSliderSpinBox::isDragging() const { Q_D(const KisAbstractSliderSpinBox); return d->isDragging; } class KisSliderSpinBoxPrivate : public KisAbstractSliderSpinBoxPrivate { }; KisSliderSpinBox::KisSliderSpinBox(QWidget* parent) : KisAbstractSliderSpinBox(parent, new KisSliderSpinBoxPrivate) { + Q_D(KisSliderSpinBox); + + d->parseInt = true; + setRange(0,99); } KisSliderSpinBox::~KisSliderSpinBox() { } void KisSliderSpinBox::setRange(int minimum, int maximum) { Q_D(KisSliderSpinBox); d->minimum = minimum; d->maximum = maximum; d->fastSliderStep = (maximum-minimum+1)/20; d->validator->setRange(minimum, maximum, 0); update(); } int KisSliderSpinBox::minimum() const { const Q_D(KisSliderSpinBox); return d->minimum; } void KisSliderSpinBox::setMinimum(int minimum) { Q_D(KisSliderSpinBox); setRange(minimum, d->maximum); } int KisSliderSpinBox::maximum() const { const Q_D(KisSliderSpinBox); return d->maximum; } void KisSliderSpinBox::setMaximum(int maximum) { Q_D(KisSliderSpinBox); setRange(d->minimum, maximum); } int KisSliderSpinBox::fastSliderStep() const { const Q_D(KisSliderSpinBox); return d->fastSliderStep; } void KisSliderSpinBox::setFastSliderStep(int step) { Q_D(KisSliderSpinBox); d->fastSliderStep = step; } int KisSliderSpinBox::value() { Q_D(KisSliderSpinBox); return d->value; } void KisSliderSpinBox::setValue(int value) { setInternalValue(value, false); update(); } QString KisSliderSpinBox::valueString() const { const Q_D(KisSliderSpinBox); QLocale locale; return locale.toString((qreal)d->value, 'f', d->validator->decimals()); } void KisSliderSpinBox::setSingleStep(int value) { Q_D(KisSliderSpinBox); d->singleStep = value; } void KisSliderSpinBox::setPageStep(int value) { Q_UNUSED(value); } void KisSliderSpinBox::setInternalValue(int _value, bool blockUpdateSignal) { Q_D(KisAbstractSliderSpinBox); d->value = qBound(d->minimum, _value, d->maximum); if(!blockUpdateSignal) { emit(valueChanged(value())); } } class KisDoubleSliderSpinBoxPrivate : public KisAbstractSliderSpinBoxPrivate { }; KisDoubleSliderSpinBox::KisDoubleSliderSpinBox(QWidget* parent) : KisAbstractSliderSpinBox(parent, new KisDoubleSliderSpinBoxPrivate) { + Q_D(KisDoubleSliderSpinBox); + d->parseInt = false; } KisDoubleSliderSpinBox::~KisDoubleSliderSpinBox() { } void KisDoubleSliderSpinBox::setRange(qreal minimum, qreal maximum, int decimals) { Q_D(KisDoubleSliderSpinBox); d->factor = pow(10.0, decimals); d->minimum = minimum * d->factor; d->maximum = maximum * d->factor; //This code auto-compute a new step when pressing control. //A flag defaulting to "do not change the fast step" should be added, but it implies changing every call if(maximum - minimum >= 2.0 || decimals <= 0) { //Quick step on integers d->fastSliderStep = int(pow(10.0, decimals)); } else if(decimals == 1) { d->fastSliderStep = (maximum-minimum)*d->factor/10; } else { d->fastSliderStep = (maximum-minimum)*d->factor/20; } d->validator->setRange(minimum, maximum, decimals); update(); setValue(value()); } qreal KisDoubleSliderSpinBox::minimum() const { const Q_D(KisAbstractSliderSpinBox); return d->minimum / d->factor; } void KisDoubleSliderSpinBox::setMinimum(qreal minimum) { Q_D(KisAbstractSliderSpinBox); setRange(minimum, d->maximum); } qreal KisDoubleSliderSpinBox::maximum() const { const Q_D(KisAbstractSliderSpinBox); return d->maximum / d->factor; } void KisDoubleSliderSpinBox::setMaximum(qreal maximum) { Q_D(KisAbstractSliderSpinBox); setRange(d->minimum, maximum); } qreal KisDoubleSliderSpinBox::fastSliderStep() const { const Q_D(KisAbstractSliderSpinBox); return d->fastSliderStep; } void KisDoubleSliderSpinBox::setFastSliderStep(qreal step) { Q_D(KisAbstractSliderSpinBox); d->fastSliderStep = step; } qreal KisDoubleSliderSpinBox::value() { Q_D(KisAbstractSliderSpinBox); return (qreal)d->value / d->factor; } void KisDoubleSliderSpinBox::setValue(qreal value) { Q_D(KisAbstractSliderSpinBox); setInternalValue(d->value = qRound(value * d->factor), false); update(); } void KisDoubleSliderSpinBox::setSingleStep(qreal value) { Q_D(KisAbstractSliderSpinBox); d->singleStep = value * d->factor; } QString KisDoubleSliderSpinBox::valueString() const { const Q_D(KisAbstractSliderSpinBox); QLocale locale; return locale.toString((qreal)d->value / d->factor, 'f', d->validator->decimals()); } void KisDoubleSliderSpinBox::setInternalValue(int _value, bool blockUpdateSignal) { Q_D(KisAbstractSliderSpinBox); d->value = qBound(d->minimum, _value, d->maximum); if(!blockUpdateSignal) { emit(valueChanged(value())); } } void KisAbstractSliderSpinBox::changeEvent(QEvent *e) { Q_D(KisAbstractSliderSpinBox); QWidget::changeEvent(e); switch (e->type()) { case QEvent::StyleChange: if (style()->objectName() == "fusion") { d->style = KisAbstractSliderSpinBoxPrivate::STYLE_FUSION; } else if (style()->objectName() == "plastique") { d->style = KisAbstractSliderSpinBoxPrivate::STYLE_PLASTIQUE; } else if (style()->objectName() == "breeze") { d->style = KisAbstractSliderSpinBoxPrivate::STYLE_BREEZE; } else { d->style = KisAbstractSliderSpinBoxPrivate::STYLE_NOQUIRK; } break; default: break; } } diff --git a/libs/widgets/CMakeLists.txt b/libs/widgets/CMakeLists.txt index 4efe85fc0e..c141267ef5 100644 --- a/libs/widgets/CMakeLists.txt +++ b/libs/widgets/CMakeLists.txt @@ -1,107 +1,113 @@ add_subdirectory( tests ) include_directories(${CMAKE_CURRENT_BINARY_DIR}) set(kritawidgets_LIB_SRCS KoGradientEditWidget.cpp KoVBox.cpp KoDialog.cpp KoGlobal.cpp KoZoomWidget.cpp KoTagToolButton.cpp KoTagChooserWidget.cpp KoTagFilterWidget.cpp KoResourceTaggingManager.cpp KoResourceItemChooserContextMenu.cpp KoAspectButton.cpp - KoPageLayoutDialog.cpp - KoPageLayoutWidget.cpp KoPagePreviewWidget.cpp KoPositionSelector.cpp KoSliderCombo.cpp KoColorPopupButton.cpp KoConfigAuthorPage.cpp KoUnitDoubleSpinBox.cpp KoZoomAction.cpp KoZoomController.cpp KoZoomInput.cpp KoZoomHandler.cpp KoZoomMode.cpp KoDpi.cpp KoGlobal.cpp KoColorPatch.cpp KoColorPopupAction.cpp KoColorSetWidget.cpp KoColorSlider.cpp KoDualColorButton.cpp KoEditColorSetDialog.cpp KoTriangleColorSelector.cpp KoResourcePopupAction.cpp - KoStrokeConfigWidget.cpp KoFillConfigWidget.cpp - KoShadowConfigWidget.cpp KoIconToolTip.cpp KoResourceItemChooser.cpp KoResourceItemChooserSync.cpp KoResourceSelector.cpp KoResourceModel.cpp KoResourceItemDelegate.cpp KoResourceItemView.cpp KoResourceTagStore.cpp KoRuler.cpp #KoRulerController.cpp KoItemToolTip.cpp KoCheckerBoardPainter.cpp KoResourceServerAdapter.cpp KoResourceServerProvider.cpp KoLineStyleSelector.cpp KoLineStyleItemDelegate.cpp KoLineStyleModel.cpp - KoMarkerModel.cpp - KoMarkerItemDelegate.cpp - KoMarkerSelector.cpp KoDockWidgetTitleBar.cpp KoDockWidgetTitleBarButton.cpp KoResourceFiltering.cpp KoResourceModelBase.cpp KoToolBoxButton.cpp KoToolBox.cpp KoToolBoxDocker.cpp KoToolBoxFactory.cpp KoToolDocker.cpp + + KoPageLayoutWidget.cpp + KoPageLayoutDialog.cpp + KoShadowConfigWidget.cpp + KoStrokeConfigWidget.cpp + KoMarkerSelector.cpp + KoMarkerModel.cpp + KoMarkerItemDelegate.cpp + KoDocumentInfoDlg.cpp KoGlobal.cpp KoTableView.cpp WidgetsDebug.cpp kis_file_name_requester.cpp + + kis_double_parse_spin_box.cpp + kis_double_parse_unit_spin_box.cpp + kis_int_parse_spin_box.cpp ) ki18n_wrap_ui( kritawidgets_LIB_SRCS KoConfigAuthorPage.ui koDocumentInfoAboutWidget.ui koDocumentInfoAuthorWidget.ui KoEditColorSet.ui + wdg_file_name_requester.ui KoPageLayoutWidget.ui KoShadowConfigWidget.ui - wdg_file_name_requester.ui ) add_library(kritawidgets SHARED ${kritawidgets_LIB_SRCS}) generate_export_header(kritawidgets BASE_NAME kritawidgets) target_link_libraries(kritawidgets kritaodf kritaflake kritapigment kritawidgetutils Qt5::PrintSupport KF5::CoreAddons KF5::ConfigGui KF5::GuiAddons KF5::WidgetsAddons KF5::ConfigCore KF5::Completion) if(X11_FOUND) target_link_libraries(kritawidgets Qt5::X11Extras ${X11_LIBRARIES}) endif() target_link_libraries(kritawidgets LINK_INTERFACE_LIBRARIES kritaodf kritaflake kritapigment kritawidgetutils Qt5::PrintSupport KF5::CoreAddons KF5::ConfigGui KF5::GuiAddons KF5::WidgetsAddons KF5::ConfigCore KF5::Completion) set_target_properties(kritawidgets PROPERTIES VERSION ${GENERIC_KRITA_LIB_VERSION} SOVERSION ${GENERIC_KRITA_LIB_SOVERSION} ) install(TARGETS kritawidgets ${INSTALL_TARGETS_DEFAULT_ARGS}) diff --git a/libs/widgets/KoPageLayoutWidget.ui b/libs/widgets/KoPageLayoutWidget.ui index 2b52b99a66..a20ef5debc 100644 --- a/libs/widgets/KoPageLayoutWidget.ui +++ b/libs/widgets/KoPageLayoutWidget.ui @@ -1,326 +1,365 @@ KoPageLayoutWidget 0 0 341 417 - + 0 - - - + 0 - - - - Unit: - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - units - - - - - - - - - - - - - - Follow style: - - - pageStyle - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - - - - - - Size: - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - sizes - - - - - - - - - - Width: + + 0 + + + 0 + + + + + 0 - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + 0 - - width + + 0 - - - - - + 0 - - + + + + &Unit: + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + units + + - - + + - + 0 0 + + + + - Height: + &Follow style: + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - height + pageStyle - - + + - - - - - - Orientation: - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - - - Portrait - - - - - - - Landscape - - - - - - - Facing pages: - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - - - Single sided - - - - - - - Facing pages - - - - - - - Text direction: - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - textDirection - - - - + + + + S&ize: + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + sizes + + + + + + + + + + Width: + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + width + + + + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + + + + + 0 + 0 + + + + &Height: + + + height + + + + + + + + + + + + Orientation: + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + Po&rtrait + + + + + + + Landscape + + + + + + + Facing pages: + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + Single sided + + + + + + + Facing pages + + + + + + + &Text direction: + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + textDirection + + + + - + + 0 + 0 + Automatic Left to right Right to left - - + + Margins - + Top: - - topMargin - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + topMargin + - + 999.990000000000009 - Binding edge: - - - bindingEdgeMargin + &Binding edge: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + bindingEdgeMargin + - + 999.990000000000009 - Page edge: - - - pageEdgeMargin + Pa&ge edge: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + pageEdgeMargin + - + 999.990000000000009 - Bottom: - - - bottomMargin + Botto&m: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + bottomMargin + - + 999.990000000000009 Qt::Vertical QSizePolicy::MinimumExpanding + + + 0 + 0 + + - KoUnitDoubleSpinBox + KisDoubleParseUnitSpinBox QDoubleSpinBox -
KoUnitDoubleSpinBox.h
+
kis_double_parse_unit_spin_box.h
units sizes width height portrait landscape singleSided facingPages textDirection topMargin bindingEdgeMargin pageEdgeMargin bottomMargin
diff --git a/libs/widgets/KoShadowConfigWidget.ui b/libs/widgets/KoShadowConfigWidget.ui index 742567f792..72cb42e8e6 100644 --- a/libs/widgets/KoShadowConfigWidget.ui +++ b/libs/widgets/KoShadowConfigWidget.ui @@ -1,117 +1,117 @@ KoShadowConfigWidget 0 0 - 221 - 78 + 238 + 98 0 0 0 0 48 48 359 true 3.700000000000000 0 0 Blur: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - + Distance: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - + - + 0 0 - KoUnitDoubleSpinBox + KisDoubleParseUnitSpinBox QDoubleSpinBox -
KoUnitDoubleSpinBox.h
+
kis_double_parse_unit_spin_box.h
diff --git a/libs/widgets/KoStrokeConfigWidget.cpp b/libs/widgets/KoStrokeConfigWidget.cpp index 1c576e0078..c2308b0539 100644 --- a/libs/widgets/KoStrokeConfigWidget.cpp +++ b/libs/widgets/KoStrokeConfigWidget.cpp @@ -1,549 +1,552 @@ /* 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 +// Krita +#include "kis_double_parse_unit_spin_box.h" + class CapNJoinMenu : public QMenu { public: CapNJoinMenu(QWidget *parent = 0); virtual QSize sizeHint() const; - KoUnitDoubleSpinBox *miterLimit; + 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 KoUnitDoubleSpinBox(this); + 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) { } KoLineStyleSelector *lineStyle; - KoUnitDoubleSpinBox *lineWidth; + KisDoubleParseUnitSpinBox *lineWidth; KoMarkerSelector *startMarkerSelector; KoMarkerSelector *endMarkerSelector; CapNJoinMenu *capNJoinMenu; QToolButton *colorButton; KoColorPopupAction *colorAction; QWidget *spacer; KoCanvasBase *canvas; bool active; }; KoStrokeConfigWidget::KoStrokeConfigWidget(QWidget * parent) : QWidget(parent) , d(new Private()) { setObjectName("Stroke widget"); QVBoxLayout *mainLayout = new QVBoxLayout(this); mainLayout->setMargin(0); QHBoxLayout *firstLineLayout = new QHBoxLayout(); // Start marker QList markers; d->startMarkerSelector = new KoMarkerSelector(KoMarkerData::MarkerStart, this); d->startMarkerSelector->updateMarkers(markers); d->startMarkerSelector->setMaximumWidth(50); firstLineLayout->addWidget(d->startMarkerSelector); // Line style d->lineStyle = new KoLineStyleSelector(this); d->lineStyle->setMinimumWidth(70); firstLineLayout->addWidget(d->lineStyle); // End marker d->endMarkerSelector = new KoMarkerSelector(KoMarkerData::MarkerEnd, this); d->endMarkerSelector->updateMarkers(markers); d->endMarkerSelector->setMaximumWidth(50); firstLineLayout->addWidget(d->endMarkerSelector); QHBoxLayout *secondLineLayout = new QHBoxLayout(); // Line width QLabel *l = new QLabel(this); l->setText(i18n("Thickness:")); l->setAlignment(Qt::AlignRight | Qt::AlignVCenter); l->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed); secondLineLayout->addWidget(l); // set min/max/step and value in points, then set actual unit - d->lineWidth = new KoUnitDoubleSpinBox(this); + d->lineWidth = new KisDoubleParseUnitSpinBox(this); d->lineWidth->setMinMaxStep(0.0, 1000.0, 0.5); d->lineWidth->setDecimals(2); d->lineWidth->setUnit(KoUnit(KoUnit::Point)); d->lineWidth->setToolTip(i18n("Set line width of actual selection")); secondLineLayout->addWidget(d->lineWidth); QToolButton *capNJoinButton = new QToolButton(this); capNJoinButton->setMinimumHeight(25); d->capNJoinMenu = new CapNJoinMenu(this); capNJoinButton->setMenu(d->capNJoinMenu); capNJoinButton->setText("..."); capNJoinButton->setPopupMode(QToolButton::InstantPopup); secondLineLayout->addWidget(capNJoinButton); d->colorButton = new QToolButton(this); secondLineLayout->addWidget(d->colorButton); d->colorAction = new KoColorPopupAction(this); d->colorAction->setIcon(koIcon("format-stroke-color")); d->colorAction->setToolTip(i18n("Change the color of the line/border")); d->colorButton->setDefaultAction(d->colorAction); mainLayout->addLayout(firstLineLayout); mainLayout->addLayout(secondLineLayout); // Spacer d->spacer = new QWidget(); d->spacer->setObjectName("SpecialSpacer"); mainLayout->addWidget(d->spacer); // set sensitive defaults d->lineStyle->setLineStyle(Qt::SolidLine); d->lineWidth->changeValue(1); d->colorAction->setCurrentColor(Qt::black); // Make the signals visible on the outside of this widget. connect(d->lineStyle, SIGNAL(currentIndexChanged(int)), this, SLOT(applyChanges())); connect(d->lineWidth, SIGNAL(valueChangedPt(qreal)), this, SLOT(applyChanges())); connect(d->colorAction, SIGNAL(colorChanged(const KoColor &)), this, SLOT(applyChanges())); connect(d->capNJoinMenu->capGroup, SIGNAL(buttonClicked(int)), this, SLOT(applyChanges())); connect(d->capNJoinMenu->joinGroup, SIGNAL(buttonClicked(int)), this, SLOT(applyChanges())); connect(d->capNJoinMenu->miterLimit, SIGNAL(valueChangedPt(qreal)), this, SLOT(applyChanges())); connect(d->startMarkerSelector, SIGNAL(currentIndexChanged(int)), this, SLOT(startMarkerChanged())); connect(d->endMarkerSelector, SIGNAL(currentIndexChanged(int)), this, SLOT(endMarkerChanged())); } KoStrokeConfigWidget::~KoStrokeConfigWidget() { delete d; } // ---------------------------------------------------------------- // getters and setters Qt::PenStyle KoStrokeConfigWidget::lineStyle() const { return d->lineStyle->lineStyle(); } QVector KoStrokeConfigWidget::lineDashes() const { return d->lineStyle->lineDashes(); } qreal KoStrokeConfigWidget::lineWidth() const { return d->lineWidth->value(); } QColor KoStrokeConfigWidget::color() const { return d->colorAction->currentColor(); } 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()); } KoShapeStroke* KoStrokeConfigWidget::createShapeStroke() const { KoShapeStroke *stroke = new KoShapeStroke(); stroke->setColor(color()); stroke->setLineWidth(lineWidth()); stroke->setCapStyle(capStyle()); stroke->setJoinStyle(joinStyle()); stroke->setMiterLimit(miterLimit()); stroke->setLineStyle(lineStyle(), lineDashes()); return stroke; } // ---------------------------------------------------------------- // Other public functions void KoStrokeConfigWidget::updateControls(KoShapeStrokeModel *stroke, KoMarker *startMarker, KoMarker *endMarker) { blockChildSignals(true); const KoShapeStroke *lineStroke = dynamic_cast(stroke); if (lineStroke) { d->lineWidth->changeValue(lineStroke->lineWidth()); QAbstractButton *button = d->capNJoinMenu->capGroup->button(lineStroke->capStyle()); if (button) { button->setChecked(true); } button = d->capNJoinMenu->joinGroup->button(lineStroke->joinStyle()); if (button) { button->setChecked(true); } d->capNJoinMenu->miterLimit->changeValue(lineStroke->miterLimit()); d->capNJoinMenu->miterLimit->setEnabled(lineStroke->joinStyle() == Qt::MiterJoin); d->lineStyle->setLineStyle(lineStroke->lineStyle(), lineStroke->lineDashes()); d->colorAction->setCurrentColor(lineStroke->color()); } else { d->lineWidth->changeValue(0.0); 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); d->lineStyle->setLineStyle(Qt::NoPen, QVector()); } d->startMarkerSelector->setMarker(startMarker); d->endMarkerSelector->setMarker(endMarker); blockChildSignals(false); } void KoStrokeConfigWidget::setUnit(const KoUnit &unit) { blockChildSignals(true); KoCanvasController* canvasController = KoToolManager::instance()->activeCanvasController(); KoSelection *selection = canvasController->canvas()->shapeManager()->selection(); KoShape * shape = selection->firstSelectedShape(); /** * 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 (shape) { newUnit.adjustByPixelTransform(shape->absoluteTransformation(0)); } d->lineWidth->setUnit(newUnit); d->capNJoinMenu->miterLimit->setUnit(newUnit); blockChildSignals(false); } void KoStrokeConfigWidget::updateMarkers(const QList &markers) { d->startMarkerSelector->updateMarkers(markers); d->endMarkerSelector->updateMarkers(markers); } void KoStrokeConfigWidget::blockChildSignals(bool block) { d->colorAction->blockSignals(block); d->lineWidth->blockSignals(block); d->capNJoinMenu->capGroup->blockSignals(block); d->capNJoinMenu->joinGroup->blockSignals(block); d->capNJoinMenu->miterLimit->blockSignals(block); d->lineStyle->blockSignals(block); d->startMarkerSelector->blockSignals(block); d->endMarkerSelector->blockSignals(block); } void KoStrokeConfigWidget::setActive(bool active) { d->active = active; } //------------------------ void KoStrokeConfigWidget::applyChanges() { KoCanvasController* canvasController = KoToolManager::instance()->activeCanvasController(); KoSelection *selection = canvasController->canvas()->shapeManager()->selection(); //FIXME d->canvas->resourceManager()->setActiveStroke( d->stroke ); if (!selection || !selection->count()) { return; } KoShapeStroke *newStroke = new KoShapeStroke(); KoShapeStroke *oldStroke = dynamic_cast( selection->firstSelectedShape()->stroke() ); if (oldStroke) { newStroke->setLineBrush(oldStroke->lineBrush()); } newStroke->setColor(color()); newStroke->setLineWidth(lineWidth()); newStroke->setCapStyle(static_cast(d->capNJoinMenu->capGroup->checkedId())); newStroke->setJoinStyle(static_cast(d->capNJoinMenu->joinGroup->checkedId())); newStroke->setMiterLimit(miterLimit()); newStroke->setLineStyle(lineStyle(), lineDashes()); if (d->active) { KoShapeStrokeCommand *cmd = new KoShapeStrokeCommand(selection->selectedShapes(), newStroke); canvasController->canvas()->addCommand(cmd); } } void KoStrokeConfigWidget::applyMarkerChanges(KoMarkerData::MarkerPosition position) { KoMarker *marker = 0; if (position == KoMarkerData::MarkerStart) { marker = startMarker(); } else if (position == KoMarkerData::MarkerEnd) { marker = endMarker(); } KoCanvasController* canvasController = KoToolManager::instance()->activeCanvasController(); KoSelection *selection = canvasController->canvas()->shapeManager()->selection(); if (! selection || !selection->count()) { return; } QList shapeList = selection->selectedShapes(); QList pathShapeList; for (QList::iterator itShape = shapeList.begin(); itShape != shapeList.end(); ++itShape) { KoPathShape* pathShape = dynamic_cast(*itShape); if (pathShape) { pathShapeList << pathShape; } } if (pathShapeList.size()) { KoPathShapeMarkerCommand* cmdMarker = new KoPathShapeMarkerCommand(pathShapeList, marker, position); canvasController->canvas()->addCommand(cmdMarker); } } void KoStrokeConfigWidget::startMarkerChanged() { applyMarkerChanges(KoMarkerData::MarkerStart); } void KoStrokeConfigWidget::endMarkerChanged() { applyMarkerChanges(KoMarkerData::MarkerEnd); } // ---------------------------------------------------------------- void KoStrokeConfigWidget::selectionChanged() { // see a comment in setUnit() setUnit(d->canvas->unit()); KoCanvasController* canvasController = KoToolManager::instance()->activeCanvasController(); KoSelection *selection = canvasController->canvas()->shapeManager()->selection(); KoShape * shape = selection->firstSelectedShape(); if (shape && shape->stroke()) { KoPathShape *pathShape = dynamic_cast(shape); if (pathShape) { updateControls(shape->stroke(), pathShape->marker(KoMarkerData::MarkerStart), pathShape->marker(KoMarkerData::MarkerEnd)); } else { updateControls(shape->stroke(), 0 ,0); } } } void KoStrokeConfigWidget::setCanvas( KoCanvasBase *canvas ) { if (canvas) { connect(canvas->shapeManager()->selection(), SIGNAL(selectionChanged()), this, SLOT(selectionChanged())); connect(canvas->shapeManager(), SIGNAL(selectionContentChanged()), this, SLOT(selectionChanged())); connect(canvas->resourceManager(), SIGNAL(canvasResourceChanged(int, const QVariant&)), this, SLOT(canvasResourceChanged(int, const QVariant &))); setUnit(canvas->unit()); KoDocumentResourceManager *resourceManager = canvas->shapeController()->resourceManager(); if (resourceManager) { KoMarkerCollection *collection = resourceManager->resource(KoDocumentResourceManager::MarkerCollection).value(); if (collection) { updateMarkers(collection->markers()); } } } d->canvas = canvas; } void KoStrokeConfigWidget::canvasResourceChanged(int key, const QVariant &value) { switch (key) { case KoCanvasResourceManager::Unit: setUnit(value.value()); break; } } diff --git a/libs/widgets/KoUnitDoubleSpinBox.h b/libs/widgets/KoUnitDoubleSpinBox.h index 3b3fcc840d..8224b1405d 100644 --- a/libs/widgets/KoUnitDoubleSpinBox.h +++ b/libs/widgets/KoUnitDoubleSpinBox.h @@ -1,117 +1,119 @@ /* This file is part of the KDE project Copyright (C) 2002, Rob Buis(buis@kde.org) Copyright (C) 2004, Nicolas GOUTTE Copyright (C) 2007, Thomas Zander 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. */ #ifndef KOUNITDOUBLESPINBOX_H #define KOUNITDOUBLESPINBOX_H #include "kritawidgets_export.h" #include class KoUnit; /** * Spin box for double precision numbers with unit display. * Use this widget for any value that represents a real measurable value for consistency throughout * Krita. * This widget shows the value in the user-selected units (inch, milimeters, etc) but keeps the * Krita-widget default measurement unit internally. This has the advantage that just setting and * getting a value will not change the value due to conversions. * The KoDocument class has a unit() method for consistent (document wide) configuration of the * used unit. * It is adviced to use a QDoubleSpinBox in QtDesigner and then use the context-menu item: 'Promote to Custom Widget' and use the values: 'classname=KoUnitDoubleSpinBox', 'headerfile=KoUnitDoubleSpinBox.h' * This will generate code that uses this spinbox in the correct manner. + * + * This class need to be replaced as much as possible with \see KisDoubleParseUnitSpinBox to add math parsing ability. */ class KRITAWIDGETS_EXPORT KoUnitDoubleSpinBox : public QDoubleSpinBox { Q_OBJECT public: /** * Constructor * Create a new spinBox with very broad range predefined. * This spinbox will have min and max borders of 10000 points and use * the default unit of points. * @param parent the parent widget */ explicit KoUnitDoubleSpinBox( QWidget *parent = 0); ~KoUnitDoubleSpinBox(); /** * Set the new value in points which will then be converted to the current unit for display * @param newValue the new value * @see value() */ virtual void changeValue( double newValue ); /** * This spinbox shows the internal value after a conversion to the unit set here. */ virtual void setUnit( const KoUnit &); /// @return the current value, converted in points double value( ) const; /// Set minimum value in points. void setMinimum(double min); /// Set maximum value in points. void setMaximum(double max); /// Set step size in the current unit. void setLineStep(double step); /// Set step size in points. void setLineStepPt(double step); /// Set minimum, maximum value and the step size (all in points) void setMinMaxStep( double min, double max, double step ); /// reimplemented from superclass, will forward to KoUnitDoubleValidator virtual QValidator::State validate(QString &input, int &pos) const; /** * Transform the double in a nice text, using locale symbols * @param value the number as double * @return the resulting string */ virtual QString textFromValue( double value ) const; /** * Transfrom a string into a double, while taking care of locale specific symbols. * @param str the string to transform into a number * @return the value as double */ virtual double valueFromText( const QString& str ) const; Q_SIGNALS: /// emitted like valueChanged in the parent, but this one emits the point value void valueChangedPt( qreal ); private: class Private; Private * const d; private Q_SLOTS: // exists to do emits for valueChangedPt void privateValueChanged(); }; #endif diff --git a/libs/widgets/kis_double_parse_spin_box.cpp b/libs/widgets/kis_double_parse_spin_box.cpp new file mode 100644 index 0000000000..c4cfaa8f48 --- /dev/null +++ b/libs/widgets/kis_double_parse_spin_box.cpp @@ -0,0 +1,244 @@ +/* + * Copyright (c) 2016 Laurent Valentin Jospin + * + * 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_double_parse_spin_box.h" + +#include "kis_num_parser.h" + +#include +#include +#include +#include +#include + +KisDoubleParseSpinBox::KisDoubleParseSpinBox(QWidget *parent) : + QDoubleSpinBox(parent), + boolLastValid(true) +{ + + lastExprParsed = new QString("0.0"); + + connect(this, SIGNAL(noMoreParsingError()), + this, SLOT(clearErrorStyle())); + + //hack to let the clearError be called, even if the value changed method is the one from QDoubleSpinBox. + connect(this, SIGNAL(valueChanged(double)), + this, SLOT(clearError())); + + connect(this, SIGNAL(errorWhileParsing(QString)), + this, SLOT(setErrorStyle())); + + oldValue = value(); + + warningIcon = new QLabel(this); + + if (QFile(":/./16_light_warning.svg").exists()) { + warningIcon->setPixmap(QIcon(":/./16_light_warning.svg").pixmap(16, 16)); + } else { + warningIcon->setText("!"); + } + + warningIcon->setStyleSheet("background:transparent;"); + warningIcon->move(1, 1); + warningIcon->setVisible(false); + + isOldPaletteSaved = false; + areOldMarginsSaved = false; + +} + +KisDoubleParseSpinBox::~KisDoubleParseSpinBox() +{ + + //needed to avoid a segfault during destruction. + delete lastExprParsed; + +} + +double KisDoubleParseSpinBox::valueFromText(const QString & text) const +{ + + *lastExprParsed = text; + + bool ok; + + double ret; + + if ( (suffix().isEmpty() || !text.endsWith(suffix())) && + (prefix().isEmpty() || !text.startsWith(prefix())) ) { + + ret = KisNumericParser::parseSimpleMathExpr(text, &ok); + + } else { + + QString expr = text; + + if (text.endsWith(suffix())) { + expr.remove(text.size()-suffix().size(), suffix().size()); + } + + if(text.startsWith(prefix())){ + expr.remove(0, prefix().size()); + } + + *lastExprParsed = expr; + + ret = KisNumericParser::parseSimpleMathExpr(expr, &ok); + + } + + if(std::isnan(ret) || std::isinf(ret)){ + ok = false; + } + + if (!ok) { + if (boolLastValid) { + oldValue = value(); + } + + boolLastValid = false; + ret = oldValue; //in case of error set to minimum. + } else { + + if (!boolLastValid) { + oldValue = ret; + } + + boolLastValid = true; + } + + return ret; + +} +QString KisDoubleParseSpinBox::textFromValue(double val) const +{ + + if (!boolLastValid) { + emit errorWhileParsing(*lastExprParsed); + return *lastExprParsed; + } + + emit noMoreParsingError(); + + double v = KisNumericParser::parseSimpleMathExpr(cleanText()); + v = QString("%1").arg(v, 0, 'f', decimals()).toDouble(); + if (hasFocus() && (v == value() || (v >= maximum() && value() == maximum()) || (v <= minimum() && value() == minimum())) ) { //solve a very annoying bug where the formula can collapse while editing. With this trick the formula is not lost until focus is lost. + return cleanText(); + } + + return QDoubleSpinBox::textFromValue(val); +} + +QValidator::State KisDoubleParseSpinBox::validate ( QString & input, int & pos ) const +{ + + Q_UNUSED(input); + Q_UNUSED(pos); + + return QValidator::Acceptable; + +} + +void KisDoubleParseSpinBox::stepBy(int steps) +{ + + boolLastValid = true; //reset to valid state so we can use the up and down buttons. + emit noMoreParsingError(); + + QDoubleSpinBox::stepBy(steps); + +} + +void KisDoubleParseSpinBox::setValue(double value) +{ + if(value == oldValue && hasFocus()){ //avoid to reset the button when it set the value of something that will recall this slot. + return; + } + + if (!hasFocus()) { + clearError(); + } + + QDoubleSpinBox::setValue(value); +} + +void KisDoubleParseSpinBox::setErrorStyle() +{ + + if (!boolLastValid) { + //setStyleSheet(_oldStyleSheet + "Background: red; color: white; padding-left: 18px;"); + + if (!isOldPaletteSaved) { + oldPalette = palette(); + } + isOldPaletteSaved = true; + + QPalette nP = oldPalette; + nP.setColor(QPalette::Background, Qt::red); + nP.setColor(QPalette::Base, Qt::red); + nP.setColor(QPalette::Text, Qt::white); + setPalette(nP); + + if (!areOldMarginsSaved) { + oldMargins = lineEdit()->textMargins(); + } + areOldMarginsSaved = true; + + if (width() - height() >= 3*height()) { //if we have twice as much place as needed by the warning icon then display it. + QMargins newMargins = oldMargins; + newMargins.setLeft( newMargins.left() + height() - 4 ); + lineEdit()->setTextMargins(newMargins); + + int h = warningIcon->height(); + int hp = height()-2; + + if (h != hp) { + warningIcon->resize(hp, hp); + + if (QFile(":/./16_light_warning.svg").exists()) { + warningIcon->setPixmap(QIcon(":/./16_light_warning.svg").pixmap(hp-7, hp-7)); + } + } + + warningIcon->move(oldMargins.left()+4, 1); + warningIcon->setVisible(true); + } + } +} + +void KisDoubleParseSpinBox::clearErrorStyle() +{ + if (boolLastValid) { + warningIcon->setVisible(false); + + //setStyleSheet(""); + + setPalette(oldPalette); + isOldPaletteSaved = false; + + lineEdit()->setTextMargins(oldMargins); + areOldMarginsSaved = false; + } +} +void KisDoubleParseSpinBox::clearError() +{ + boolLastValid = true; + emit noMoreParsingError(); + oldValue = value(); + clearErrorStyle(); +} diff --git a/libs/widgets/kis_double_parse_spin_box.h b/libs/widgets/kis_double_parse_spin_box.h new file mode 100644 index 0000000000..4c2b920773 --- /dev/null +++ b/libs/widgets/kis_double_parse_spin_box.h @@ -0,0 +1,82 @@ +/* + * Copyright (c) 2016 Laurent Valentin Jospin + * + * 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 KISDOUBLEPARSESPINBOX_H +#define KISDOUBLEPARSESPINBOX_H + +#include + +#include "kritawidgets_export.h" + +class QLabel; + +/*! + * \brief The KisDoubleParseSpinBox class is a cleverer doubleSpinBox, able to parse arithmetic expressions. + * + * Use this spinbox instead of the basic one from Qt if you want it to be able to parse arithmetic expressions. + */ +class KRITAWIDGETS_EXPORT KisDoubleParseSpinBox : public QDoubleSpinBox +{ + + Q_OBJECT +public: + KisDoubleParseSpinBox(QWidget* parent = 0); + ~KisDoubleParseSpinBox(); + + virtual double valueFromText(const QString & text) const; + virtual QString textFromValue(double val) const; + virtual QValidator::State validate ( QString & input, int & pos ) const; + + virtual void stepBy(int steps); + + void setValue(double value); //polymorphism won't work directly, we use a signal/slot hack to do so but if signals are disabled this function will still be useful. + + bool isLastValid() const{ return boolLastValid; } + +Q_SIGNALS: + + //! \brief signal emmitted when the last parsed expression create an error. + void errorWhileParsing(QString expr) const; + //! \brief signal emmitted when the last parsed expression is valid. + void noMoreParsingError() const; + +public Q_SLOTS: + + //! \brief useful to let the widget change it's stylesheet when an error occured in the last expression. + void setErrorStyle(); + //! \brief useful to let the widget reset it's stylesheet when there's no more error. + void clearErrorStyle(); + //! \brief say the widget to return to an error free state. + void clearError(); + +protected: + + mutable QString* lastExprParsed; + mutable bool boolLastValid; + mutable double oldValue; + + QLabel* warningIcon; + + QPalette oldPalette; + bool isOldPaletteSaved; + + QMargins oldMargins; + bool areOldMarginsSaved; +}; + +#endif // KISDOUBLEPARSESPINBOX_H diff --git a/libs/widgets/kis_double_parse_unit_spin_box.cpp b/libs/widgets/kis_double_parse_unit_spin_box.cpp new file mode 100644 index 0000000000..47c10515dc --- /dev/null +++ b/libs/widgets/kis_double_parse_unit_spin_box.cpp @@ -0,0 +1,172 @@ +/* + * Copyright (c) 2016 Laurent Valentin Jospin + * + * 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_double_parse_unit_spin_box.h" + + +class Q_DECL_HIDDEN KisDoubleParseUnitSpinBox::Private +{ +public: + Private(double low, double up, double step) + : lowerInPoints(low), + upperInPoints(up), + stepInPoints(step), + unit(KoUnit(KoUnit::Point)) + { + } + + double lowerInPoints; ///< lowest value in points + double upperInPoints; ///< highest value in points + double stepInPoints; ///< step in points + KoUnit unit; +}; + +KisDoubleParseUnitSpinBox::KisDoubleParseUnitSpinBox(QWidget *parent) : + KisDoubleParseSpinBox(parent), + d(new Private(-9999, 9999, 1)) +{ + setUnit( KoUnit(KoUnit::Point) ); + setAlignment( Qt::AlignRight ); + + connect(this, SIGNAL(valueChanged( double )), SLOT(privateValueChanged())); +} + +KisDoubleParseUnitSpinBox::~KisDoubleParseUnitSpinBox() +{ + delete d; +} + +void KisDoubleParseUnitSpinBox::changeValue( double newValue ) +{ + if (d->unit.toUserValue(newValue) == oldValue) { + return; + } + + KisDoubleParseSpinBox::setValue( d->unit.toUserValue(newValue) ); +} + +void KisDoubleParseUnitSpinBox::setUnit( const KoUnit & unit) +{ + if( unit == d->unit) return; + double oldValue = d->unit.fromUserValue( KisDoubleParseSpinBox::value() ); + + KisDoubleParseSpinBox::setMinimum( unit.toUserValue( d->lowerInPoints ) ); + KisDoubleParseSpinBox::setMaximum( unit.toUserValue( d->upperInPoints ) ); + + qreal step = unit.toUserValue( d->stepInPoints ); + + if (unit.type() == KoUnit::Pixel) { + // limit the pixel step by 1.0 + step = qMax(qreal(1.0), step); + } + + KisDoubleParseSpinBox::setSingleStep( step ); + d->unit = unit; + KisDoubleParseSpinBox::setValue( KoUnit::ptToUnit( oldValue, unit ) ); + setSuffix( unit.symbol().prepend(QLatin1Char(' ')) ); +} + +double KisDoubleParseUnitSpinBox::value( ) const +{ + return d->unit.fromUserValue( KisDoubleParseSpinBox::value() ); +} + +void KisDoubleParseUnitSpinBox::setMinimum(double min) +{ + d->lowerInPoints = min; + KisDoubleParseSpinBox::setMinimum( d->unit.toUserValue( min ) ); +} + +void KisDoubleParseUnitSpinBox::setMaximum(double max) +{ + d->upperInPoints = max; + KisDoubleParseSpinBox::setMaximum( d->unit.toUserValue( max ) ); +} + +void KisDoubleParseUnitSpinBox::setLineStep(double step) +{ + d->stepInPoints = KoUnit(KoUnit::Point).toUserValue(step); + KisDoubleParseSpinBox::setSingleStep( step ); +} + +void KisDoubleParseUnitSpinBox::setLineStepPt(double step) +{ + d->stepInPoints = step; + KisDoubleParseSpinBox::setSingleStep( d->unit.toUserValue( step ) ); +} + + +void KisDoubleParseUnitSpinBox::setMinMaxStep( double min, double max, double step ) +{ + setMinimum( min ); + setMaximum( max ); + setLineStepPt( step ); +} + + +QValidator::State KisDoubleParseUnitSpinBox::validate(QString &input, int &pos) const +{ + Q_UNUSED(pos); + + QRegExp regexp ("([ a-zA-Z]+)$"); // Letters or spaces at end + const int res = input.indexOf( regexp ); + + if ( res == -1 ) { + // Nothing like an unit? The user is probably editing the unit + return QValidator::Intermediate; + } + + QString expr ( input.left( res ) ); + const QString unitName ( regexp.cap( 1 ).trimmed().toLower() ); + + bool ok = true; + bool interm = false; + + QValidator::State exprState = KisDoubleParseSpinBox::validate(expr, pos); + + if (exprState == QValidator::Invalid) { + return exprState; + } else if (exprState == QValidator::Intermediate) { + interm = true; + } + + //check if we can parse the unit. + KoUnit::fromSymbol(unitName, &ok); + + if (!ok || interm) { + return QValidator::Intermediate; + } + + return QValidator::Acceptable; +} + +QString KisDoubleParseUnitSpinBox::textFromValue( double value ) const +{ + return KisDoubleParseSpinBox::textFromValue(value); +} + +double KisDoubleParseUnitSpinBox::valueFromText( const QString& str ) const +{ + //KisDoubleParseSpinBox is supposed to remove the suffix and prefix by itself. + return KisDoubleParseSpinBox::valueFromText(str); +} + +void KisDoubleParseUnitSpinBox::privateValueChanged() +{ + emit valueChangedPt( value() ); +} diff --git a/libs/widgets/kis_double_parse_unit_spin_box.h b/libs/widgets/kis_double_parse_unit_spin_box.h new file mode 100644 index 0000000000..83094f8e85 --- /dev/null +++ b/libs/widgets/kis_double_parse_unit_spin_box.h @@ -0,0 +1,100 @@ +/* + * Copyright (c) 2016 Laurent Valentin Jospin + * + * 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_DOUBLEPARSEUNITSPINBOX_H +#define KIS_DOUBLEPARSEUNITSPINBOX_H + +#include + +#include "kis_double_parse_spin_box.h" +#include "kritawidgets_export.h" + +/*! + * \brief The KisDoubleParseUnitSpinBox class is an evolution of the \see KoUnitDoubleSpinBox, but inherit from \see KisDoubleParseSpinBox to be able to parse math expressions. + * + * This class store the + */ +class KRITAWIDGETS_EXPORT KisDoubleParseUnitSpinBox : public KisDoubleParseSpinBox +{ + + Q_OBJECT + +public: + KisDoubleParseUnitSpinBox(QWidget* parent = 0); + ~KisDoubleParseUnitSpinBox(); + + /** + * Set the new value in points which will then be converted to the current unit for display + * @param newValue the new value + * @see value() + */ + virtual void changeValue( double newValue ); + /** + * This spinbox shows the internal value after a conversion to the unit set here. + */ + virtual void setUnit(const KoUnit &unit); + + /// @return the current value, converted in points + double value( ) const; + + /// Set minimum value in points. + void setMinimum(double min); + + /// Set maximum value in points. + void setMaximum(double max); + + /// Set step size in the current unit. + void setLineStep(double step); + + /// Set step size in points. + void setLineStepPt(double step); + + /// Set minimum, maximum value and the step size (all in points) + void setMinMaxStep( double min, double max, double step ); + + /// reimplemented from superclass, will forward to KoUnitDoubleValidator + virtual QValidator::State validate(QString &input, int &pos) const; + + /** + * Transform the double in a nice text, using locale symbols + * @param value the number as double + * @return the resulting string + */ + virtual QString textFromValue( double value ) const; + /** + * Transfrom a string into a double, while taking care of locale specific symbols. + * @param str the string to transform into a number + * @return the value as double + */ + virtual double valueFromText( const QString& str ) const; + +Q_SIGNALS: + /// emitted like valueChanged in the parent, but this one emits the point value + void valueChangedPt( qreal ); + + +private: + class Private; + Private * const d; + +private Q_SLOTS: + // exists to do emits for valueChangedPt + void privateValueChanged(); +}; + +#endif // KIS_DOUBLEPARSEUNITSPINBOX_H diff --git a/libs/widgets/kis_int_parse_spin_box.cpp b/libs/widgets/kis_int_parse_spin_box.cpp new file mode 100644 index 0000000000..376a4cfdc2 --- /dev/null +++ b/libs/widgets/kis_int_parse_spin_box.cpp @@ -0,0 +1,252 @@ +/* + * Copyright (c) 2016 Laurent Valentin Jospin + * + * 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_int_parse_spin_box.h" + +#include "kis_num_parser.h" + +#include +#include +#include +#include +#include + +KisIntParseSpinBox::KisIntParseSpinBox(QWidget *parent) : + QSpinBox(parent), + boolLastValid(true) +{ + lastExprParsed = new QString("0"); + + connect(this, SIGNAL(noMoreParsingError()), + this, SLOT(clearErrorStyle())); + + //hack to let the clearError be called, even if the value changed method is the one from QSpinBox. + connect(this, SIGNAL(valueChanged(int)), + this, SLOT(clearError())); + + connect(this, SIGNAL(errorWhileParsing(QString)), + this, SLOT(setErrorStyle())); + + oldVal = value(); + + warningIcon = new QLabel(this); + + if (QFile(":/./16_light_warning.svg").exists()) { + warningIcon->setPixmap(QIcon(":/./16_light_warning.svg").pixmap(16, 16)); + } else { + warningIcon->setText("!"); + } + + warningIcon->setStyleSheet("background:transparent;"); + warningIcon->move(1, 1); + warningIcon->setVisible(false); + + isOldPaletteSaved = false; + areOldMarginsSaved = false; + +} + +KisIntParseSpinBox::~KisIntParseSpinBox() +{ + + //needed to avoid a segfault during destruction. + delete lastExprParsed; + +} + +int KisIntParseSpinBox::valueFromText(const QString & text) const +{ + + *lastExprParsed = text; + + bool ok; + + int val; + + if ( (suffix().isEmpty() || !text.endsWith(suffix())) && + (prefix().isEmpty() || !text.startsWith(prefix())) ) { + + val = KisNumericParser::parseIntegerMathExpr(text, &ok); + + } else { + + QString expr = text; + + if (text.endsWith(suffix())) { + expr.remove(text.size()-suffix().size(), suffix().size()); + } + + if(text.startsWith(prefix())){ + expr.remove(0, prefix().size()); + } + + *lastExprParsed = expr; + + val = KisNumericParser::parseIntegerMathExpr(expr, &ok); + + } + + if (text.trimmed().isEmpty()) { //an empty text is considered valid in this case. + ok = true; + } + + if (!ok) { + + if (boolLastValid == true) { + oldVal = value(); + } + + boolLastValid = false; + //emit errorWhileParsing(text); //if uncommented become red everytime the string is wrong. + val = oldVal; + } else { + + if (boolLastValid == false) { + oldVal = val; + } + + boolLastValid = true; + //emit noMoreParsingError(); + } + + return val; + +} + +QString KisIntParseSpinBox::textFromValue(int val) const +{ + + if (!boolLastValid) { + emit errorWhileParsing(*lastExprParsed); + return *lastExprParsed; + } + + emit noMoreParsingError(); + + int v = KisNumericParser::parseIntegerMathExpr(cleanText()); + if (hasFocus() && (v == value() || (v >= maximum() && value() == maximum()) || (v <= minimum() && value() == minimum())) ) { //solve a very annoying bug where the formula can collapse while editing. With this trick the formula is not lost until focus is lost. + return cleanText(); + } + + return QSpinBox::textFromValue(val); + +} + +QValidator::State KisIntParseSpinBox::validate ( QString & input, int & pos ) const +{ + + Q_UNUSED(input); + Q_UNUSED(pos); + + //this simple definition is sufficient for the moment + //TODO: see if needed to get something more complex. + return QValidator::Acceptable; + +} + +void KisIntParseSpinBox::stepBy(int steps) +{ + + boolLastValid = true; + emit noMoreParsingError(); + + QSpinBox::stepBy(steps); + +} + +void KisIntParseSpinBox::setValue(int val) +{ + + if(val == oldVal && hasFocus()){ //avoid to reset the button when it set the value of something that will recall this slot. + return; + } + + if (!hasFocus()) { + clearError(); + } + + QSpinBox::setValue(val); +} + +void KisIntParseSpinBox::setErrorStyle() +{ + + if (!boolLastValid) { + //setStyleSheet(_oldStyleSheet + "Background: red; color: white; padding-left: 18px;"); + + if (!isOldPaletteSaved) { + oldPalette = palette(); + } + isOldPaletteSaved = true; + + QPalette nP = oldPalette; + nP.setColor(QPalette::Background, Qt::red); + nP.setColor(QPalette::Base, Qt::red); + nP.setColor(QPalette::Text, Qt::white); + setPalette(nP); + + if (!areOldMarginsSaved) { + oldMargins = lineEdit()->textMargins(); + } + areOldMarginsSaved = true; + + if (width() - height() >= 3*height()) { //if we have twice as much place as needed by the warning icon then display it. + QMargins newMargins = oldMargins; + newMargins.setLeft( newMargins.left() + height() - 4 ); + lineEdit()->setTextMargins(newMargins); + + int h = warningIcon->height(); + int hp = height()-2; + + if (h != hp) { + warningIcon->resize(hp, hp); + + if (QFile(":/./16_light_warning.svg").exists()) { + warningIcon->setPixmap(QIcon(":/./16_light_warning.svg").pixmap(hp-7, hp-7)); + } + } + + warningIcon->move(oldMargins.left()+4, 1); + warningIcon->setVisible(true); + } + } +} + +void KisIntParseSpinBox::clearErrorStyle() +{ + if (boolLastValid) { + warningIcon->setVisible(false); + + //setStyleSheet(""); + + setPalette(oldPalette); + isOldPaletteSaved = false; + + lineEdit()->setTextMargins(oldMargins); + areOldMarginsSaved = false; + } +} + + +void KisIntParseSpinBox::clearError() +{ + boolLastValid = true; + emit noMoreParsingError(); + oldVal = value(); + clearErrorStyle(); +} diff --git a/libs/widgets/kis_int_parse_spin_box.h b/libs/widgets/kis_int_parse_spin_box.h new file mode 100644 index 0000000000..ffd3b5c2dc --- /dev/null +++ b/libs/widgets/kis_int_parse_spin_box.h @@ -0,0 +1,82 @@ +/* + * Copyright (c) 2016 Laurent Valentin Jospin + * + * 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 KISINTPARSESPINBOX_H +#define KISINTPARSESPINBOX_H + +#include + +#include "kritawidgets_export.h" + +class QLabel; + +/*! + * \brief The KisDoubleParseSpinBox class is a cleverer doubleSpinBox, able to parse arithmetic expressions. + * + * Use this spinbox instead of the basic one from Qt if you want it to be able to parse arithmetic expressions. + */ +class KRITAWIDGETS_EXPORT KisIntParseSpinBox : public QSpinBox +{ + Q_OBJECT + +public: + KisIntParseSpinBox(QWidget *parent = 0); + ~KisIntParseSpinBox(); + + virtual int valueFromText(const QString & text) const; + virtual QString textFromValue(int val) const; + virtual QValidator::State validate ( QString & input, int & pos ) const; + + virtual void stepBy(int steps); + + void setValue(int val); //polymorphism won't work directly, we use a signal/slot hack to do so but if signals are disabled this function will still be useful. + + bool isLastValid() const{ return boolLastValid; } + +Q_SIGNALS: + + //! \brief signal emmitted when the last parsed expression create an error. + void errorWhileParsing(QString expr) const; + //! \brief signal emmitted when the last parsed expression is valid. + void noMoreParsingError() const; + +public Q_SLOTS: + + //! \brief useful to let the widget change it's stylesheet when an error occured in the last expression. + void setErrorStyle(); + //! \brief useful to let the widget reset it's stylesheet when there's no more error. + void clearErrorStyle(); + //! \brief say the widget to return to an error free state. + void clearError(); + +protected: + + mutable QString* lastExprParsed; + mutable bool boolLastValid; + mutable int oldVal; //store the last correctly evaluated value. + + QLabel* warningIcon; + + QPalette oldPalette; + bool isOldPaletteSaved; + + QMargins oldMargins; + bool areOldMarginsSaved; +}; + +#endif // KISINTPARSESPINBOX_H diff --git a/libs/widgets/tests/CMakeLists.txt b/libs/widgets/tests/CMakeLists.txt index 29bd019f40..019ec1fac0 100644 --- a/libs/widgets/tests/CMakeLists.txt +++ b/libs/widgets/tests/CMakeLists.txt @@ -1,26 +1,32 @@ set( EXECUTABLE_OUTPUT_PATH ${CMAKE_CURRENT_BINARY_DIR} ) add_definitions(-DFILES_DATA_DIR="${CMAKE_CURRENT_SOURCE_DIR}/data/") add_definitions(-DFILES_OUTPUT_DIR="${CMAKE_CURRENT_BINARY_DIR}") #add_subdirectory(filedialogtester) ########### next target ############### set(zoomhandler_test_SRCS zoomhandler_test.cpp ) kde4_add_unit_test(zoomhandler_test TESTNAME libs-widgets-zoomhandler_test ${zoomhandler_test_SRCS}) target_link_libraries(zoomhandler_test kritawidgets Qt5::Test) ########### next target ############### set(zoomcontroller_test_SRCS zoomcontroller_test.cpp ) kde4_add_unit_test(zoomcontroller_test TESTNAME libs-widgets-zoomcontroller_test ${zoomcontroller_test_SRCS}) target_link_libraries(zoomcontroller_test kritawidgets Qt5::Test) ########### next target ############### set(KoResourceTaggingTest_SRCS KoResourceTaggingTest.cpp ) kde4_add_broken_unit_test(KoResourceTaggingTest TESTNAME libs-widgets-KoResourceTaggingTest ${KoResourceTaggingTest_SRCS}) target_link_libraries(KoResourceTaggingTest kritawidgets Qt5::Test) +########### next target ############### + +set(kis_parse_spin_boxes_test_SRCS kis_parse_spin_boxes_test.cpp) +kde4_add_unit_test(KisParseSpinBoxesTest TESTNAME krita-ui-KisParseSpinBoxesTest ${kis_parse_spin_boxes_test_SRCS}) +target_link_libraries(KisParseSpinBoxesTest kritaui Qt5::Test) + ########### end ############### diff --git a/libs/widgets/tests/kis_parse_spin_boxes_test.cpp b/libs/widgets/tests/kis_parse_spin_boxes_test.cpp new file mode 100644 index 0000000000..3b11abbdf1 --- /dev/null +++ b/libs/widgets/tests/kis_parse_spin_boxes_test.cpp @@ -0,0 +1,365 @@ +/* + * Copyright (c) 2016 Laurent Valentin Jospin + * + * 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_parse_spin_boxes_test.h" + +#include "kis_num_parser.h" +#include "kis_double_parse_spin_box.h" +#include "kis_int_parse_spin_box.h" + +#include +#include + +const QStringList KisParseSpinBoxesTest::doubleExprs = {"1", + "-12", + "7.9 - 12", + "cos(90)*2", + "cos(acos(-1)+1*3^2.0)*2 + sin(3)/2"}; + +const QStringList KisParseSpinBoxesTest::doubleWrongExprs = {"abc", + "1/", + "7.9 + 12*", + "cos(90)*2 + ", + "23.0/0", + "0.0/0.0"}; + +const QStringList KisParseSpinBoxesTest::intExprs = {"12", + "-12", + "-12.3", + "12.7 - 25", + "12.7", + "12*1.5", + "12/2.5", + "518*2/3"}; + +const QStringList KisParseSpinBoxesTest::intWrongExprs = {"abc", + "12.5/2 +", + "12*", + "12/0"}; + +KisParseSpinBoxesTest::KisParseSpinBoxesTest() : QObject() +{ + +} + +void KisParseSpinBoxesTest::testDoubleParseNormal() +{ + + KisDoubleParseSpinBox spinBox; + spinBox.setDecimals(3); + spinBox.setMaximum(9999.0); + spinBox.setMinimum(-9999.0); + + for (int i = 0; i < doubleExprs.size(); i++) { + + spinBox.clearFocus(); + spinBox.clear(); //clear all + QTest::keyClicks(&spinBox, doubleExprs[i]); + spinBox.clearFocus(); + + double resultParser = KisNumericParser::parseSimpleMathExpr(doubleExprs[i]); + double valueSpinBox = spinBox.value(); + + bool test = resultParser == valueSpinBox || qAbs(resultParser - valueSpinBox) < 1e-2; + + QVERIFY2(test, QString("Failed with expression %1, result is %2, value is %3") + .arg(doubleExprs[i]).arg(resultParser).arg(valueSpinBox).toStdString().c_str()); + + spinBox.setValue(0); + + } + + +} + +void KisParseSpinBoxesTest::testDoubleParseProblem() +{ + + //error can happen with incomplete or incorrect expressions, inf or nan values. + + KisDoubleParseSpinBox spinBox; + spinBox.setMaximum(9999.0); + spinBox.setMinimum(-9999.0); + + for (int i = 0; i < doubleWrongExprs.size(); i++) { + + spinBox.clearFocus(); + spinBox.clear(); //clear all + QTest::keyClicks(&spinBox, doubleWrongExprs[i]); + spinBox.clearFocus(); + + QVERIFY2(!spinBox.isLastValid(), QString("SpinBox is in a valid state with expression %1, but shouldn't.") + .arg(doubleWrongExprs[i]).toStdString().c_str()); + + spinBox.setValue(0.0); + + QVERIFY2(spinBox.isLastValid(), QString("SpinBox unsable to recover error free state after a value reset.") + .toStdString().c_str()); + + spinBox.setValue(0); + + } + +} +void KisParseSpinBoxesTest::testDoubleParseWithSuffix(){ + + QString suff = "px"; + + KisDoubleParseSpinBox spinBox; + spinBox.setDecimals(3); + spinBox.setMaximum(9999.0); + spinBox.setMinimum(-9999.0); + spinBox.setSuffix(suff); + + for (int i = 0; i < doubleExprs.size(); i++) { + + spinBox.clearFocus(); + spinBox.clear(); //clear all + QTest::keyClicks(&spinBox, doubleExprs[i]); + spinBox.clearFocus(); + + double resultParser = KisNumericParser::parseSimpleMathExpr(doubleExprs[i]); + double valueSpinBox = spinBox.value(); + + bool test = resultParser == valueSpinBox || qAbs(resultParser - valueSpinBox) < 1e-2; + + QVERIFY2(test, QString("Failed with expression %1, result is %2, value is %3") + .arg(doubleExprs[i]).arg(resultParser).arg(valueSpinBox).toStdString().c_str()); + + spinBox.setValue(0); + + } + + //verify that the suffix don't appear in the clean text in case of error. + for (int i = 0; i < doubleWrongExprs.size(); i++) { + + if (doubleWrongExprs[i].endsWith(suff)) { + continue; + } + + spinBox.clearFocus(); + spinBox.clear(); //clear all + QTest::keyClicks(&spinBox, doubleWrongExprs[i]); + spinBox.clearFocus(); + + QVERIFY2(!spinBox.cleanText().endsWith(suff), "SpinBox failed to remove suffix from clean text in error state."); + + spinBox.setValue(0.0); + + } +} +void KisParseSpinBoxesTest::testDoubleParseWithPrefix() +{ + + QString preff = "px"; + + KisDoubleParseSpinBox spinBox; + spinBox.setDecimals(3); + spinBox.setMaximum(9999.0); + spinBox.setMinimum(-9999.0); + spinBox.setPrefix(preff); + + for (int i = 0; i < doubleExprs.size(); i++) { + + spinBox.clearFocus(); + spinBox.clear(); //clear all + QTest::keyClicks(&spinBox, doubleExprs[i]); + spinBox.clearFocus(); + + double resultParser = KisNumericParser::parseSimpleMathExpr(doubleExprs[i]); + double valueSpinBox = spinBox.value(); + + bool test = resultParser == valueSpinBox || qAbs(resultParser - valueSpinBox) < 1e-2; + + QVERIFY2(test, QString("Failed with expression %1, result is %2, value is %3") + .arg(doubleExprs[i]).arg(resultParser).arg(valueSpinBox).toStdString().c_str()); + + spinBox.setValue(0); + + } + + //verify that the prefix don't appear in the clean text in case of error. + for (int i = 0; i < doubleWrongExprs.size(); i++) { + + if (doubleWrongExprs[i].endsWith(preff)) { + continue; + } + + spinBox.clearFocus(); + spinBox.clear(); //clear all + QTest::keyClicks(&spinBox, doubleWrongExprs[i]); + spinBox.clearFocus(); + + QVERIFY2(!spinBox.cleanText().startsWith(preff), "SpinBox failed to remove prefix from clean text in error state."); + + spinBox.setValue(0.0); + + } +} + +void KisParseSpinBoxesTest::testIntParseNormal() +{ + + KisIntParseSpinBox spinBox; + spinBox.setMaximum(999); + spinBox.setMinimum(-999); + + for (int i = 0; i < intExprs.size(); i++) { + + spinBox.clearFocus(); + spinBox.clear(); //clear all + QTest::keyClicks(&spinBox, intExprs[i]); + spinBox.clearFocus(); + + int resultParser = KisNumericParser::parseIntegerMathExpr(intExprs[i]); + int valueSpinBox = spinBox.value(); + + bool test = resultParser == valueSpinBox; + + QVERIFY2(test, QString("Failed with expression %1, result is %2, value is %3") + .arg(intExprs[i]).arg(resultParser).arg(valueSpinBox).toStdString().c_str()); + + spinBox.setValue(0); + } + +} + +void KisParseSpinBoxesTest::testIntParseProblem() +{ + + //errors can happen with incorrect or incomplete expressions, or division by 0. + + KisIntParseSpinBox spinBox; + spinBox.setMaximum(999); + spinBox.setMinimum(-999); + + for (int i = 0; i < intWrongExprs.size(); i++) { + + spinBox.clearFocus(); + spinBox.clear(); //clear all + QTest::keyClicks(&spinBox, intWrongExprs[i]); + spinBox.clearFocus(); + + QVERIFY2(!spinBox.isLastValid(), QString("SpinBox is in a valid state with expression %1, but shouldn't.") + .arg(intWrongExprs[i]).toStdString().c_str()); + + spinBox.setValue(0); + + QVERIFY2(spinBox.isLastValid(), QString("SpinBox unsable to recover error free state after a value reset.") + .toStdString().c_str()); + + spinBox.setValue(0); + + } + +} + +void KisParseSpinBoxesTest::testIntParseWithSuffix() +{ + QString suff = "px"; + + KisIntParseSpinBox spinBox; + spinBox.setMaximum(999); + spinBox.setMinimum(-999); + spinBox.setSuffix(suff); + + for (int i = 0; i < intExprs.size(); i++) { + + spinBox.clearFocus(); + spinBox.clear(); //clear all + QTest::keyClicks(&spinBox, intExprs[i]); + spinBox.clearFocus(); + + int resultParser = KisNumericParser::parseIntegerMathExpr(intExprs[i]); + int valueSpinBox = spinBox.value(); + + bool test = resultParser == valueSpinBox; + + QVERIFY2(test, QString("Failed with expression %1, result is %2, value is %3") + .arg(intExprs[i]).arg(resultParser).arg(valueSpinBox).toStdString().c_str()); + + spinBox.setValue(0); + } + + //verify that the suffix don't appear in the clean text in case of error. + for (int i = 0; i < intWrongExprs.size(); i++) { + + if (intWrongExprs[i].endsWith(suff)) { + continue; + } + + spinBox.clearFocus(); + spinBox.clear(); //clear all + QTest::keyClicks(&spinBox, intWrongExprs[i]); + spinBox.clearFocus(); + + QVERIFY2(!spinBox.cleanText().endsWith(suff), "SpinBox failed to remove suffix from clean text in error state."); + + spinBox.setValue(0.0); + + } + +} +void KisParseSpinBoxesTest::testIntParseWithPrefix() +{ + QString preff = "px"; + + KisIntParseSpinBox spinBox; + spinBox.setMaximum(999); + spinBox.setMinimum(-999); + spinBox.setPrefix(preff); + + for (int i = 0; i < intExprs.size(); i++) { + + spinBox.clearFocus(); + spinBox.clear(); //clear all + QTest::keyClicks(&spinBox, intExprs[i]); + spinBox.clearFocus(); + + int resultParser = KisNumericParser::parseIntegerMathExpr(intExprs[i]); + int valueSpinBox = spinBox.value(); + + bool test = resultParser == valueSpinBox; + + QVERIFY2(test, QString("Failed with expression %1, result is %2, value is %3") + .arg(intExprs[i]).arg(resultParser).arg(valueSpinBox).toStdString().c_str()); + + spinBox.setValue(0); + } + + //verify that the prefix don't appear in the clean text in case of error. + for (int i = 0; i < intWrongExprs.size(); i++) { + + if (intWrongExprs[i].startsWith(preff)) { + continue; + } + + spinBox.clearFocus(); + spinBox.clear(); //clear all + QTest::keyClicks(&spinBox, intWrongExprs[i]); + spinBox.clearFocus(); + + QVERIFY2(!spinBox.cleanText().startsWith(preff), "SpinBox failed to remove prefix from clean text in error state."); + + spinBox.setValue(0.0); + + } + +} + +QTEST_MAIN(KisParseSpinBoxesTest) diff --git a/libs/widgets/tests/kis_parse_spin_boxes_test.h b/libs/widgets/tests/kis_parse_spin_boxes_test.h new file mode 100644 index 0000000000..509f039036 --- /dev/null +++ b/libs/widgets/tests/kis_parse_spin_boxes_test.h @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2016 Laurent Valentin Jospin + * + * 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 KISPARSESPINBOXESTEST_H +#define KISPARSESPINBOXESTEST_H + +#include +#include + +class KisParseSpinBoxesTest : public QObject +{ + Q_OBJECT + +public: + explicit KisParseSpinBoxesTest(); + +private Q_SLOTS: + + void testDoubleParseNormal(); + void testDoubleParseProblem(); + void testDoubleParseWithSuffix(); + void testDoubleParseWithPrefix(); + void testIntParseNormal(); + void testIntParseProblem(); + void testIntParseWithSuffix(); + void testIntParseWithPrefix(); + +private: + + const static QStringList doubleExprs; + const static QStringList doubleWrongExprs; + const static QStringList intExprs; + const static QStringList intWrongExprs; +}; + +#endif // KISPARSESPINBOXESTEST_H diff --git a/libs/widgetutils/CMakeLists.txt b/libs/widgetutils/CMakeLists.txt index f54a46ee49..182db0ab80 100644 --- a/libs/widgetutils/CMakeLists.txt +++ b/libs/widgetutils/CMakeLists.txt @@ -1,125 +1,127 @@ add_subdirectory(tests) configure_file(xmlgui/config-xmlgui.h.cmake ${CMAKE_CURRENT_BINARY_DIR}/config-xmlgui.h ) include_directories(${CMAKE_CURRENT_SOURCE_DIR}/config) include_directories(${CMAKE_CURRENT_SOURCE_DIR}/xmlgui) set(kritawidgetutils_LIB_SRCS WidgetUtilsDebug.cpp kis_icon_utils.cpp kis_action_registry.cpp KoGroupButton.cpp KoProgressBar.cpp KoProgressUpdater.cpp KoUpdater.cpp KoUpdaterPrivate_p.cpp KoProperties.cpp KoFileDialog.cpp KoResourcePaths.cpp + kis_num_parser.cpp + config/kcolorscheme.cpp config/kcolorschememanager.cpp config/khelpclient.cpp config/klanguagebutton.cpp config/krecentfilesaction.cpp config/kstandardaction.cpp xmlgui/KisShortcutsEditorItem.cpp xmlgui/KisShortcutEditWidget.cpp xmlgui/KisShortcutsEditorDelegate.cpp xmlgui/KisShortcutsDialog.cpp xmlgui/KisShortcutsDialog_p.cpp xmlgui/KisShortcutsEditor.cpp xmlgui/KisShortcutsEditor_p.cpp xmlgui/kshortcutschemeseditor.cpp xmlgui/kshortcutschemeshelper.cpp xmlgui/kaboutkdedialog_p.cpp xmlgui/kactioncategory.cpp xmlgui/kactioncollection.cpp xmlgui/kactionconflictdetector.cpp xmlgui/kbugreport.cpp xmlgui/kcheckaccelerators.cpp xmlgui/kedittoolbar.cpp xmlgui/kgesture.cpp xmlgui/kgesturemap.cpp xmlgui/khelpmenu.cpp xmlgui/kkeysequencewidget.cpp xmlgui/kmainwindow.cpp xmlgui/kmenumenuhandler_p.cpp xmlgui/kshortcutwidget.cpp xmlgui/kswitchlanguagedialog_p.cpp xmlgui/ktoggletoolbaraction.cpp xmlgui/ktoolbar.cpp xmlgui/ktoolbarhandler.cpp xmlgui/kundoactions.cpp xmlgui/kxmlguibuilder.cpp xmlgui/kxmlguiclient.cpp xmlgui/kxmlguifactory.cpp xmlgui/kxmlguifactory_p.cpp xmlgui/kxmlguiversionhandler.cpp xmlgui/kxmlguiwindow.cpp ) if (HAVE_DBUS) set(kritawidgetutils_LIB_SRCS ${kritawidgetutils_LIB_SRCS} xmlgui/kmainwindowiface.cpp ) endif() ki18n_wrap_ui(kritawidgetutils_LIB_SRCS xmlgui/KisShortcutsDialog.ui xmlgui/kshortcutwidget.ui ) qt5_add_resources(kritawidgetutils_LIB_SRCS xmlgui/kxmlgui.qrc) add_library(kritawidgetutils SHARED ${kritawidgetutils_LIB_SRCS}) target_include_directories(kritawidgetutils PUBLIC $ $ ) generate_export_header(kritawidgetutils BASE_NAME kritawidgetutils) if (HAVE_DBUS) set (KRITA_WIDGET_UTILS_EXTRA_LIBS ${KRITA_WIDGET_UTILS_EXTRA_LIBS} Qt5::DBus) endif () if (APPLE) find_library(FOUNDATION_LIBRARY Foundation) set(KRITA_WIDGET_UTILS_EXTRA_LIBS ${KRITA_WIDGET_UTILS_EXTRA_LIBS} ${FOUNDATION_LIBRARY}) endif () target_link_libraries(kritawidgetutils PUBLIC Qt5::Widgets Qt5::Gui Qt5::Xml Qt5::Core KF5::ItemViews kritaglobal PRIVATE Qt5::PrintSupport KF5::I18n KF5::ConfigCore KF5::CoreAddons KF5::ConfigGui KF5::GuiAddons KF5::WidgetsAddons KF5::WindowSystem kritaplugin ${KRITA_WIDGET_UTILS_EXTRA_LIBS} ) set_target_properties(kritawidgetutils PROPERTIES VERSION ${GENERIC_KRITA_LIB_VERSION} SOVERSION ${GENERIC_KRITA_LIB_SOVERSION} ) install(TARGETS kritawidgetutils ${INSTALL_TARGETS_DEFAULT_ARGS}) diff --git a/libs/widgetutils/kis_num_parser.cpp b/libs/widgetutils/kis_num_parser.cpp new file mode 100644 index 0000000000..06f8377907 --- /dev/null +++ b/libs/widgetutils/kis_num_parser.cpp @@ -0,0 +1,567 @@ +/* + * Copyright (c) 2016 Laurent Valentin Jospin + * + * 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_num_parser.h" + +//#include +#include +#include +#include +#include +#include + +#include + +using namespace std; + +const QVector opLevel1 = {'+', '-'}; +const QVector opLevel2 = {'*', '/'}; + +const QStringList supportedFuncs = {"", "cos", "sin", "tan", "acos", "asin", "atan", "exp", "ln", "log10", "abs"}; + +const QRegExp funcExpr("(-)?([a-zA-Z]*)?\\((.+)\\)"); +const QRegExp numberExpr("(-)?([0-9]+\\.?[0-9]*(e[0-9]*)?)"); + +const QRegExp funcExprInteger("(-)?\\((.+)\\)"); +const QRegExp integerExpr("(-)?([0-9]+)"); + +//double functions +double treatFuncs(QString const& expr, bool & noProblem); +double treatLevel1(QString const& expr, bool & noProblem); +double treatLevel2(QString const& expr, bool & noProblem); +double treatLevel3(QString const& expr, bool & noProblem); + +//int functions +double treatLevel1Int(QString const& expr, bool & noProblem); +double treatLevel2Int(QString const& expr, bool & noProblem); +double treatFuncsInt(QString const& expr, bool & noProblem); + +namespace KisNumericParser { + +/*! + * \param expr the expression to parse + * \param noProblem if provided, the value pointed to will be se to true is no problem appeared, false otherwise. + * \return the numerical value the expression eval to (or 0 in case of error). + */ +double parseSimpleMathExpr(const QString &expr, bool *noProblem) +{ + + bool ok = true; //intermediate variable to pass by reference to the sublevel parser (if no pointer is provided). + + //then go down each 3 levels of operation priority. + if (noProblem != nullptr) { + return treatLevel1(expr, *noProblem); + } + + return treatLevel1(expr, ok); + +} + +/*! + * \param expr the expression to parse + * \param noProblem if provided, the value pointed to will be se to true is no problem appeared, false otherwise. + * \return the numerical value the expression eval to (or 0 in case of error). + */ +int parseIntegerMathExpr(QString const& expr, bool* noProblem) +{ + + bool ok = true; //intermediate variable to pass by reference to the sublevel parser (if no pointer is provided). + + if (noProblem != nullptr) { + return qRound(treatLevel1Int(expr, *noProblem)); + } + + return qRound(treatLevel1Int(expr, ok)); + +} + +} //namespace KisNumericParser. + + +//intermediate functions + +/*! + * \brief extractSubExprLevel1 extract from an expression the part of an expression that need to be treated recursivly before computing level 1 operations (+, -). + * \param expr The expression to treat, the part returned will be removed. + * \param nextOp This reference, in case of sucess, will hold the first level operation identified as separator ('+' or '-') + * \param noProblem A reference to a bool, set to true if there was no problem, false otherwise. + * \return The first part of the expression that doesn't contain first level operations not nested within parenthesis. + */ +inline QString extractSubExprLevel1(QString & expr, char & nextOp, bool & noProblem){ + + QString ret; + + int subCount = 0; + + bool lastMetIsNumber = false; + + for(int i = 0; i < expr.size(); i++){ + + if (expr.at(i) == '(') { + subCount++; + } + + if (expr.at(i) == ')') { + subCount--; + } + + if (subCount < 0) { + noProblem = false; + return ret; + } + + if(i == expr.size()-1 && subCount == 0){ + ret = expr; + expr.clear(); + break; + } + + if( (expr.at(i) == '+' || expr.at(i) == '-') && + subCount == 0) { + + if (expr.at(i) == '-' && + i < expr.size()-1) { + + bool cond = !expr.at(i+1).isSpace(); + + if (cond && !lastMetIsNumber) { + continue; + } + + } + + ret = expr.mid(0, i).trimmed(); + nextOp = expr.at(i).toLatin1(); + expr = expr.mid(i+1); + break; + + } + + if (expr.at(i).isDigit()) { + lastMetIsNumber = true; + } else if (expr.at(i) != '.' && + !expr.at(i).isSpace()) { + lastMetIsNumber = false; + } + + } + + noProblem = true; + return ret; +} + + +/*! + * \brief extractSubExprLevel2 extract from an expression the part of an expression that need to be treated recursivly before computing level 2 operations (*, /). + * \param expr The expression to treat, the part returned will be removed. + * \param nextOp This reference, in case of sucess, will hold the first level operation identified as separator ('*' or '/') + * \param noProblem A reference to a bool, set to true if there was no problem, false otherwise. + * \return The first part of the expression that doesn't contain second level operations not nested within parenthesis. + */ +inline QString extractSubExprLevel2(QString & expr, char & nextOp, bool & noProblem){ + + QString ret; + + int subCount = 0; + + for(int i = 0; i < expr.size(); i++){ + + if (expr.at(i) == '(') { + subCount++; + } + + if (expr.at(i) == ')') { + subCount--; + } + + if (subCount < 0) { + noProblem = false; + return ret; + } + + if(i == expr.size()-1 && subCount == 0){ + ret = expr; + expr.clear(); + break; + } + + if( (expr.at(i) == '*' || expr.at(i) == '/') && + subCount == 0) { + + ret = expr.mid(0, i).trimmed(); + nextOp = expr.at(i).toLatin1(); + expr = expr.mid(i+1); + break; + + } + + } + + noProblem = true; + return ret; +} + +/*! + * \brief treatLevel1 treat an expression at the first level of recursion. + * \param expr The expression to treat. + * \param noProblem A reference to a bool set to true if no problem happened, false otherwise. + * \return The value of the parsed expression or subexpression or 0 in case of error. + */ +double treatLevel1(const QString &expr, bool & noProblem) +{ + + noProblem = true; + + QString exprDestructable = expr; + + char nextOp = '+'; + double result = 0.0; + + while (!exprDestructable.isEmpty()) { + + double sign = (nextOp == '-') ? -1 : 1; + QString part = extractSubExprLevel1(exprDestructable, nextOp, noProblem); + + if (!noProblem) { + return 0.0; + } + + if (sign > 0) { + result += treatLevel2(part, noProblem); + } else { + result -= treatLevel2(part, noProblem); + } + + if(!noProblem){ + return 0.0; + } + } + + return result; + +} + +/*! + * \brief treatLevel2 treat a subexpression at the second level of recursion. + * \param expr The subexpression to treat. + * \param noProblem A reference to a bool set to true if no problem happened, false otherwise. + * \return The value of the parsed subexpression or 0 in case of error. + * + * The expression should not contain first level operations not nested in parenthesis. + */ +double treatLevel2(QString const& expr, bool & noProblem) +{ + + noProblem = true; + + QString exprDestructable = expr; + + char nextOp = '*'; + + QString part = extractSubExprLevel2(exprDestructable, nextOp, noProblem); + + double result = treatLevel3(part, noProblem); + + while (!exprDestructable.isEmpty()) { + + if (!noProblem) { + return 0.0; + } + + bool needToMultiply = (nextOp == '*'); + part = extractSubExprLevel2(exprDestructable, nextOp, noProblem); + + if (!noProblem) { + return 0.0; + } + + if (needToMultiply) { + result *= treatLevel3(part, noProblem); + } else { + result /= treatLevel3(part, noProblem); + } + } + + return result; +} + +/*! + * \brief treatLevel3 treat a subexpression at the third level of recursion. + * \param expr The subexpression to treat. + * \param noProblem A reference to a bool set to true if no problem happened, false otherwise. + * \return The value of the parsed subexpression or 0 in case of error. + * + * The expression should not contain first or second level operations not nested in parenthesis. + */ +double treatLevel3(const QString &expr, bool & noProblem) +{ + + noProblem = true; + + int indexPower = -1; + int indexCount = 0; + int subLevels = 0; + + for (int i = 0; i < expr.size(); i++) { + if (expr.at(i) == '(') { + subLevels++; + } else if(expr.at(i) == ')') { + subLevels--; + if (subLevels < 0) { + noProblem = false; + return 0.0; + } + } else if (expr.at(i) == '^') { + if (subLevels == 0) { + indexPower = i; + indexCount++; + } + } + } + + if (indexCount > 1 || indexPower + 1 >= expr.size()) { + noProblem = false; + return 0.0; + } + + if (indexPower > -1) { + + QStringList subExprs; + subExprs << expr.mid(0,indexPower); + subExprs << expr.mid(indexPower+1); + + bool noProb1 = true; + bool noProb2 = true; + + double base = treatFuncs(subExprs[0], noProb1); + double power = treatFuncs(subExprs[1], noProb2); + + return qPow(base, power); + + } else { + return treatFuncs(expr, noProblem); + } + + noProblem = false; + return 0.0; + +} + +/*! + * \brief treatFuncs treat the last level of recursion: parenthesis and functions. + * \param expr The expression to parse. + * \param noProblem A reference to a bool set to true if no problem happened, false otherwise. + * \return The value of the parsed subexpression or 0 in case of error. + * + * The expression should not contain operators not nested anymore. The subexpressions within parenthesis will be treated by recalling the level 1 function. + */ +double treatFuncs(QString const& expr, bool & noProblem) +{ + + noProblem = true; + + QRegExp funcExp = funcExpr; //copy the expression in the current execution stack, to avoid errors for example when multiple thread call this function. + QRegExp numExp = numberExpr; + + if (funcExp.exactMatch(expr.trimmed())) { + + int sign = funcExp.capturedTexts()[1].isEmpty() ? 1 : -1; + QString func = funcExp.capturedTexts()[2].toLower(); + QString subExpr = funcExp.capturedTexts()[3]; + + double val = treatLevel1(subExpr, noProblem); + + if (!noProblem) { + return 0.0; + } + + if (func.isEmpty()) { + return sign*val; + } + + if (!supportedFuncs.contains(func)) { + noProblem = false; + return 0.0; + } + + //trigonometry is done in degree + if (func == "cos") { + val = qCos(val/180*qAcos(-1)); + } else if (func == "sin") { + val = qSin(val/180*qAcos(-1)); + } else if (func == "tan") { + val = qTan(val/180*qAcos(-1)); + } else if(func == "acos") { + val = qAcos(val)*180/qAcos(-1); + } else if (func == "asin") { + val = qAsin(val)*180/qAcos(-1); + } else if (func == "atan") { + val = qAtan(val)*180/qAcos(-1); + } else if (func == "exp") { + val = qExp(val); + } else if (func == "ln") { + val = qLn(val); + } else if (func == "log10") { + val = qLn(val)/qLn(10.0); + } else if (func == "abs") { + val = qAbs(val); + } + + return sign*val; + } else if(numExp.exactMatch(expr.trimmed())) { + return expr.toDouble(&noProblem); + } + + noProblem = false; + return 0.0; + +} + +//int functions +/*! + * \brief treatLevel1 treat an expression at the first level of recursion. + * \param expr The expression to treat. + * \param noProblem A reference to a bool set to true if no problem happened, false otherwise. + * \return The value of the parsed expression or subexpression or 0 in case of error. + */ +double treatLevel1Int(QString const& expr, bool & noProblem) +{ + + noProblem = true; + + QString exprDestructable = expr; + + char nextOp = '+'; + double result = 0.0; + + while (!exprDestructable.isEmpty()) { + + double sign = (nextOp == '-') ? -1 : 1; + QString part = extractSubExprLevel1(exprDestructable, nextOp, noProblem); + + if( !noProblem) { + return 0.0; + } + + if (sign > 0) { + result += treatLevel2Int(part, noProblem); + } else { + result -= treatLevel2Int(part, noProblem); + } + + if(!noProblem){ + return 0.0; + } + } + + return result; + +} + +/*! + * \brief treatLevel2 treat a subexpression at the second level of recursion. + * \param expr The subexpression to treat. + * \param noProblem A reference to a bool set to true if no problem happened, false otherwise. + * \return The value of the parsed subexpression or 0 in case of error. + * + * The expression should not contain first level operations not nested in parenthesis. + */ +double treatLevel2Int(const QString &expr, bool &noProblem) +{ + + noProblem = true; + + QString exprDestructable = expr; + + char nextOp = '*'; + + QString part = extractSubExprLevel2(exprDestructable, nextOp, noProblem); + + double result = treatFuncsInt(part, noProblem); + + while (!exprDestructable.isEmpty()) { + + if (!noProblem) { + return 0.0; + } + + bool needToMultiply = (nextOp == '*'); + part = extractSubExprLevel2(exprDestructable, nextOp, noProblem); + + if (!noProblem) { + return 0.0; + } + + if (needToMultiply) { + result *= treatFuncsInt(part, noProblem); + } else { + + double val = treatFuncsInt(part, noProblem); + + if(std::isinf(result/val) || std::isnan(result/val)){ + noProblem = false; + return 0.0; + } + + result /= val; + } + } + + return result; + +} + +/*! + * \brief treatFuncs treat the last level of recursion: parenthesis + * \param expr The expression to parse. + * \param noProblem A reference to a bool set to true if no problem happened, false otherwise. + * \return The value of the parsed subexpression or 0 in case of error. + * + * The expression should not contain operators not nested anymore. The subexpressions within parenthesis will be treated by recalling the level 1 function. + */ +double treatFuncsInt(QString const& expr, bool & noProblem) +{ + + noProblem = true; + + QRegExp funcExpInteger = funcExprInteger; + QRegExp integerExp = integerExpr; + QRegExp numberExp = numberExpr; + + if (funcExpInteger.exactMatch(expr.trimmed())) { + + int sign = funcExpInteger.capturedTexts()[1].isEmpty() ? 1 : -1; + QString subExpr = funcExpInteger.capturedTexts()[2]; + + double val = treatLevel1Int(subExpr, noProblem); + + if (!noProblem) { + return 0; + } + + return sign*val; + + } else if(numberExp.exactMatch(expr.trimmed())) { + double value = QVariant(expr).toDouble(&noProblem); + return value; + } + + noProblem = false; + return 0; + +} diff --git a/libs/widgetutils/kis_num_parser.h b/libs/widgetutils/kis_num_parser.h new file mode 100644 index 0000000000..21080a5b47 --- /dev/null +++ b/libs/widgetutils/kis_num_parser.h @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2016 Laurent Valentin Jospin + * + * 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_NUMPARSER_H +#define KIS_NUMPARSER_H + +#include + +#include "kritawidgetutils_export.h" + +/*! + * \brief the namespace contains functions to transform math expression written as QString in numbers. + * + * Computation is done in a recursive way, maybe not the most efficient way compared to infix to postfix conversion before parsing. + * (TODO: look if it need to be changed). + */ +namespace KisNumericParser { + + //! \brief parse an expression to a double. + KRITAWIDGETUTILS_EXPORT double parseSimpleMathExpr(QString const& expr, bool* noProblem = 0); + + //! \brief parse an expression to an int. + KRITAWIDGETUTILS_EXPORT int parseIntegerMathExpr(QString const& expr, bool* noProblem = 0); +} + +#endif // KIS_NUMPARSER_H + diff --git a/libs/widgetutils/tests/CMakeLists.txt b/libs/widgetutils/tests/CMakeLists.txt index b7d6923ad1..768241c245 100644 --- a/libs/widgetutils/tests/CMakeLists.txt +++ b/libs/widgetutils/tests/CMakeLists.txt @@ -1,9 +1,14 @@ set( EXECUTABLE_OUTPUT_PATH ${CMAKE_CURRENT_BINARY_DIR} ) include_directories( ${CMAKE_SOURCE_DIR}/libs/widgetutils ) ########### next target ############### set(kopropertiestest_SRCS KoPropertiesTest.cpp ) kde4_add_unit_test(KoPropertiesTest TESTNAME libs-widgetutils-KoPropertiesTest ${kopropertiestest_SRCS}) target_link_libraries(KoPropertiesTest kritawidgetutils Qt5::Test) +########### next target ############### + +set(kis_simple_math_parser_test_SRCS kis_simple_math_parser_test.cpp) +kde4_add_unit_test(KisSimpleMathParserTest TESTNAME krita-ui-KisSimpleMathParserTest ${kis_simple_math_parser_test_SRCS}) +target_link_libraries(KisSimpleMathParserTest kritaui Qt5::Test) diff --git a/libs/widgetutils/tests/kis_simple_math_parser_test.cpp b/libs/widgetutils/tests/kis_simple_math_parser_test.cpp new file mode 100644 index 0000000000..4f7d581348 --- /dev/null +++ b/libs/widgetutils/tests/kis_simple_math_parser_test.cpp @@ -0,0 +1,154 @@ +/* + * Copyright (c) 2016 Laurent Valentin Jospin + * + * 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_simple_math_parser_test.h" + +#include "kis_num_parser.h" + +#include +#include + +KisSimpleMathParserTest::KisSimpleMathParserTest() : QObject() +{ + +} + +void KisSimpleMathParserTest::testDoubleComputation() +{ + + QStringList exprs = {"1", + "2 + 3.4", + "2 + -3.4", + "2 - -3.4", + "5-2", + "7 + 2 - 5", + "4.6 * 2 + 13", + "4.6 / 2 + 3*3", + "4.6 / 0.0 + 3*3", + "-4.6 / 0.0 + 3*3", + "-4.6 / -0.0 + 3*3", + "4.6 / -0.0 + 3*3", + "0.0 / 0.0 + 3*3", + "2^3 - 4 * 1.5", + "2^3.0 - 4 * 1.5", + "cos(1)*2", + "-cos(1)*2", + "cos(1)^3*2", + "cos(1)^3.0*2", + "cos(1)*2 + sin(3)/2", + "cos(acos(-1)+1*3^2.0)*2 + sin(3)/2", + "cos(acos(-1)+1*3^2.0)^2 + sin(3)/2"}; + + QVector expected = {1, + 2 + 3.4, + 2 + -3.4, + 2 - -3.4, + 5-2, + 7 + 2 - 5, + 4.6 * 2 + 13, + 4.6 / 2 + 3*3, + 4.6 / 0.0 + 3*3, + -4.6 / 0.0 + 3*3, + -4.6 / -0.0 + 3*3, + 4.6 / -0.0 + 3*3, + 0.0 / 0.0 + 3*3, + qPow(2,3) - 4 * 1.5, + qPow(2,3.0) - 4 * 1.5, + qCos(1.0/180*qAcos(-1))*2, + -qCos(1.0/180*qAcos(-1))*2, + qPow(qCos(1.0/180*qAcos(-1)),3)*2, + qPow(qCos(1.0/180*qAcos(-1)),3.0)*2, + qCos(1.0/180*qAcos(-1))*2 + qSin(3.0/180*qAcos(-1))/2, + qCos((qAcos(-1.0)*180/qAcos(-1)+1*qPow(3,2.0))/180*qAcos(-1))*2 + qSin(3.0/180*qAcos(-1))/2, + qPow(qCos((qAcos(-1.0)*180/qAcos(-1)+1*qPow(3,2.0))/180*qAcos(-1)),2) + qSin(3.0/180*qAcos(-1))/2}; + + for (int i = 0; i < expected.size(); i++) { + + double result = KisNumericParser::parseSimpleMathExpr(exprs[i]); + + bool test = result == expected[i] || qAbs(result - expected[i]) < 1e-12 || (std::isnan(result) && std::isnan(expected[i])); + + QVERIFY2(test, QString("Failed when %1 should equal %2 but evaluated to %3.").arg(exprs[i]).arg(expected[i]).arg(result).toStdString().c_str()); + } +} + +void KisSimpleMathParserTest::testIntComputation() +{ + + QStringList exprs = {"1", + "2 + 3", + "2 + -3", + "2 - -3", + "5-2", + "7 + 2 - 5", + "4/3", + "12/3", + "4*3", + "581*2/3"}; + + QVector expected = {1, + 2 + 3, + 2 + -3, + 2 - -3, + 5-2, + 7 + 2 - 5, + qRound(4.0/3.0), + qRound(12.0/3.0), + 4*3, + 581*2/3}; + + for (int i = 0; i < expected.size(); i++) { + + int result = KisNumericParser::parseIntegerMathExpr(exprs[i]); + + QCOMPARE(result, expected[i]); + } +} + +void KisSimpleMathParserTest::testIntFlooring() +{ + + QStringList exprs = {"4.5", + "-4.5", + "3.5 + 4.5", + "2.8 - -3.5", + "4.5/2.9", + "7.6*3.2", + "7.6*3.2 + 4.5" + }; + + QVector expected = {qRound(4.5), + qRound(-4.5), + qRound(3.5 + 4.5), + qRound(2.8 - -3.5), + qRound(4.5/2.9), + qRound(7.6*3.2), + qRound(7.6*3.2 + 4.5) + }; + + for (int i = 0; i < expected.size(); i++) { + + int result = KisNumericParser::parseIntegerMathExpr(exprs[i]); + + QCOMPARE(result, expected[i]); + } + +} + +QTEST_APPLESS_MAIN(KisSimpleMathParserTest) + diff --git a/libs/widgetutils/tests/kis_simple_math_parser_test.h b/libs/widgetutils/tests/kis_simple_math_parser_test.h new file mode 100644 index 0000000000..793bed4aaa --- /dev/null +++ b/libs/widgetutils/tests/kis_simple_math_parser_test.h @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2016 Laurent Valentin Jospin + * + * 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 KISSIMPLEMATHPARSERTEST_H +#define KISSIMPLEMATHPARSERTEST_H + +#include + +class KisSimpleMathParserTest : public QObject +{ + Q_OBJECT + +public: + KisSimpleMathParserTest(); + +private Q_SLOTS: + void testDoubleComputation(); + void testIntComputation(); + void testIntFlooring(); +}; + +#endif // KISSIMPLEMATHPARSERTEST_H diff --git a/pics/16_dark_warning.svg b/pics/16_dark_warning.svg new file mode 100644 index 0000000000..9df70559ff --- /dev/null +++ b/pics/16_dark_warning.svg @@ -0,0 +1,89 @@ + + + + + + + + + + image/svg+xml + + + + + + + + + + + + diff --git a/pics/16_light_warning.svg b/pics/16_light_warning.svg new file mode 100644 index 0000000000..0d8ef2b3cc --- /dev/null +++ b/pics/16_light_warning.svg @@ -0,0 +1,89 @@ + + + + + + + + + + image/svg+xml + + + + + + + + + + + + diff --git a/pics/icons.qrc b/pics/icons.qrc index cfbd8d3fc4..d2286d8893 100644 --- a/pics/icons.qrc +++ b/pics/icons.qrc @@ -1,304 +1,305 @@ - - - - 16_dark_align-horizontal-center.svg - 22_dark_align-horizontal-center.svg - 24_dark_align-horizontal-center.svg - 16_light_align-horizontal-center.svg - 22_light_align-horizontal-center.svg - 24_light_align-horizontal-center.svg - 16_dark_align-horizontal-left.svg - 22_dark_align-horizontal-left.svg - 24_dark_align-horizontal-left.svg - 16_light_align-horizontal-left.svg - 22_light_align-horizontal-left.svg - 24_light_align-horizontal-left.svg - 16_dark_align-horizontal-right.svg - 22_dark_align-horizontal-right.svg - 24_dark_align-horizontal-right.svg - 16_light_align-horizontal-right.svg - 22_light_align-horizontal-right.svg - 24_light_align-horizontal-right.svg - 16_dark_align-vertical-bottom.svg - 22_dark_align-vertical-bottom.svg - 24_dark_align-vertical-bottom.svg - 16_light_align-vertical-bottom.svg - 22_light_align-vertical-bottom.svg - 24_light_align-vertical-bottom.svg - 16_dark_align-vertical-center.svg - 22_dark_align-vertical-center.svg - 24_dark_align-vertical-center.svg - 16_light_align-vertical-center.svg - 22_light_align-vertical-center.svg - 24_light_align-vertical-center.svg - 16_dark_align-vertical-top.svg - 22_dark_align-vertical-top.svg - 24_dark_align-vertical-top.svg - 16_light_align-vertical-top.svg - 22_light_align-vertical-top.svg - 24_light_align-vertical-top.svg - 16_dark_application-x-krita.svg - 22_dark_application-x-krita.svg - 32_dark_application-x-krita.svg - 64_dark_application-x-krita.svg - 16_light_application-x-krita.svg - 22_light_application-x-krita.svg - 32_light_application-x-krita.svg - 64_light_application-x-krita.svg - 16_dark_application-x-wmf.svg - 22_dark_application-x-wmf.svg - 32_dark_application-x-wmf.svg - 64_dark_application-x-wmf.svg - 16_light_application-x-wmf.svg - 22_light_application-x-wmf.svg - 32_light_application-x-wmf.svg - 64_light_application-x-wmf.svg - calligrakrita.png - 16_dark_character-set.svg - 22_dark_character-set.svg - 24_dark_character-set.svg - 16_light_character-set.svg - 22_light_character-set.svg - 24_light_character-set.svg - 16_dark_draw-arrow-back.svg - 22_dark_draw-arrow-back.svg - 24_dark_draw-arrow-back.svg - 16_light_draw-arrow-back.svg - 22_light_draw-arrow-back.svg - 24_light_draw-arrow-back.svg - 16_dark_draw-arrow-down.svg - 22_dark_draw-arrow-down.svg - 24_dark_draw-arrow-down.svg - 16_light_draw-arrow-down.svg - 22_light_draw-arrow-down.svg - 24_light_draw-arrow-down.svg - 16_dark_draw-arrow-forward.svg - 22_dark_draw-arrow-forward.svg - 24_dark_draw-arrow-forward.svg - 16_light_draw-arrow-forward.svg - 22_light_draw-arrow-forward.svg - 24_light_draw-arrow-forward.svg - 16_dark_draw-arrow-up.svg - 22_dark_draw-arrow-up.svg - 24_dark_draw-arrow-up.svg - 16_light_draw-arrow-up.svg - 22_light_draw-arrow-up.svg - 24_light_draw-arrow-up.svg - 16_dark_draw-freehand.svg - 22_dark_draw-freehand.svg - 24_dark_draw-freehand.svg - 16_light_draw-freehand.svg - 22_light_draw-freehand.svg - 24_light_draw-freehand.svg - 16_dark_edit-rename.svg - 22_dark_edit-rename.svg - 24_dark_edit-rename.svg - 16_light_edit-rename.svg - 22_light_edit-rename.svg - 24_light_edit-rename.svg - 16_dark_edit-select-all.svg - 22_dark_edit-select-all.svg - 24_dark_edit-select-all.svg - 16_light_edit-select-all.svg - 22_light_edit-select-all.svg - 24_light_edit-select-all.svg - 16_dark_format-indent-less.svg - 22_dark_format-indent-less.svg - 24_dark_format-indent-less.svg - 16_light_format-indent-less.svg - 22_light_format-indent-less.svg - 24_light_format-indent-less.svg - 16_dark_format-indent-more.svg - 22_dark_format-indent-more.svg - 24_dark_format-indent-more.svg - 16_light_format-indent-more.svg - 22_light_format-indent-more.svg - 24_light_format-indent-more.svg - 16_dark_format-justify-center.svg - 22_dark_format-justify-center.svg - 24_dark_format-justify-center.svg - 16_light_format-justify-center.svg - 22_light_format-justify-center.svg - 24_light_format-justify-center.svg - 16_dark_format-justify-fill.svg - 22_dark_format-justify-fill.svg - 24_dark_format-justify-fill.svg - 16_light_format-justify-fill.svg - 22_light_format-justify-fill.svg - 24_light_format-justify-fill.svg - 16_dark_format-justify-left.svg - 22_dark_format-justify-left.svg - 24_dark_format-justify-left.svg - 16_light_format-justify-left.svg - 22_light_format-justify-left.svg - 24_light_format-justify-left.svg - 16_dark_format-justify-right.svg - 22_dark_format-justify-right.svg - 24_dark_format-justify-right.svg - 16_light_format-justify-right.svg - 22_light_format-justify-right.svg - 24_light_format-justify-right.svg - 16_dark_format-list-ordered.svg - 22_dark_format-list-ordered.svg - 24_dark_format-list-ordered.svg - 16_light_format-list-ordered.svg - 22_light_format-list-ordered.svg - 24_light_format-list-ordered.svg - 16_dark_format-stroke-color.svg - 22_dark_format-stroke-color.svg - 24_dark_format-stroke-color.svg - 16_light_format-stroke-color.svg - 22_light_format-stroke-color.svg - 24_light_format-stroke-color.svg - 16_dark_format-text-bold.svg - 22_dark_format-text-bold.svg - 24_dark_format-text-bold.svg - 16_light_format-text-bold.svg - 22_light_format-text-bold.svg - 24_light_format-text-bold.svg - 16_dark_format-text-color.svg - 22_dark_format-text-color.svg - 24_dark_format-text-color.svg - 16_light_format-text-color.svg - 22_light_format-text-color.svg - 24_light_format-text-color.svg - 16_dark_format-text-direction-rtl.svg - 22_dark_format-text-direction-rtl.svg - 24_dark_format-text-direction-rtl.svg - 16_light_format-text-direction-rtl.svg - 22_light_format-text-direction-rtl.svg - 24_light_format-text-direction-rtl.svg - 16_dark_format-text-italic.svg - 22_dark_format-text-italic.svg - 24_dark_format-text-italic.svg - 16_light_format-text-italic.svg - 22_light_format-text-italic.svg - 24_light_format-text-italic.svg - 16_dark_format-text-strikethrough.svg - 22_dark_format-text-strikethrough.svg - 24_dark_format-text-strikethrough.svg - 16_light_format-text-strikethrough.svg - 22_light_format-text-strikethrough.svg - 24_light_format-text-strikethrough.svg - 16_dark_format-text-subscript.svg - 22_dark_format-text-subscript.svg - 24_dark_format-text-subscript.svg - 16_light_format-text-subscript.svg - 22_light_format-text-subscript.svg - 24_light_format-text-subscript.svg - 16_dark_format-text-superscript.svg - 22_dark_format-text-superscript.svg - 24_dark_format-text-superscript.svg - 16_light_format-text-superscript.svg - 22_light_format-text-superscript.svg - 24_light_format-text-superscript.svg - 16_dark_format-text-underline.svg - 22_dark_format-text-underline.svg - 24_dark_format-text-underline.svg - 16_light_format-text-underline.svg - 22_light_format-text-underline.svg - 24_light_format-text-underline.svg - 16_dark_insert-text.svg - 22_dark_insert-text.svg - 24_dark_insert-text.svg - 16_light_insert-text.svg - 22_light_insert-text.svg - 24_light_insert-text.svg - 48_dark_klipper.svg - 48_light_klipper.svg - 16_dark_list-remove.svg - 22_dark_list-remove.svg - 24_dark_list-remove.svg - 16_light_list-remove.svg - 22_light_list-remove.svg - 24_light_list-remove.svg - 16_dark_media-floppy.svg - 22_dark_media-floppy.svg - 16_light_media-floppy.svg - 22_light_media-floppy.svg - 16_dark_object-align-horizontal-center-calligra.svg - 22_dark_object-align-horizontal-center-calligra.svg - 16_light_object-align-horizontal-center-calligra.svg - 22_light_object-align-horizontal-center-calligra.svg - 16_dark_object-align-horizontal-left-calligra.svg - 22_dark_object-align-horizontal-left-calligra.svg - 16_light_object-align-horizontal-left-calligra.svg - 22_light_object-align-horizontal-left-calligra.svg - 16_dark_object-align-vertical-top-calligra.svg - 22_dark_object-align-vertical-top-calligra.svg - 16_light_object-align-vertical-top-calligra.svg - 22_light_object-align-vertical-top-calligra.svg - 16_dark_object-group-calligra.svg - 22_dark_object-group-calligra.svg - 16_light_object-group-calligra.svg - 22_light_object-group-calligra.svg - 16_dark_shape-choose.svg - 22_dark_shape-choose.svg - 16_light_shape-choose.svg - 22_light_shape-choose.svg - 16_dark_snap-extension.svg - 22_dark_snap-extension.svg - 24_dark_snap-extension.svg - 16_light_snap-extension.svg - 22_light_snap-extension.svg - 24_light_snap-extension.svg - 16_dark_snap-guideline.svg - 22_dark_snap-guideline.svg - 24_dark_snap-guideline.svg - 16_light_snap-guideline.svg - 22_light_snap-guideline.svg - 24_light_snap-guideline.svg - 16_dark_snap-intersection.svg - 22_dark_snap-intersection.svg - 24_dark_snap-intersection.svg - 16_light_snap-intersection.svg - 22_light_snap-intersection.svg - 24_light_snap-intersection.svg - 16_dark_snap-node.svg - 22_dark_snap-node.svg - 24_dark_snap-node.svg - 16_light_snap-node.svg - 22_light_snap-node.svg - 24_light_snap-node.svg - 22_dark_snap-orthogonal.svg - 24_dark_snap-orthogonal.svg - 22_light_snap-orthogonal.svg - 24_light_snap-orthogonal.svg - 16_dark_split.svg - 22_dark_split.svg - 24_dark_split.svg - 16_light_split.svg - 22_light_split.svg - 24_light_split.svg - 16_dark_tab-close.svg - 22_dark_tab-close.svg - 24_dark_tab-close.svg - 16_light_tab-close.svg - 22_light_tab-close.svg - 24_light_tab-close.svg - 16_dark_tab-new.svg - 22_dark_tab-new.svg - 24_dark_tab-new.svg - 16_light_tab-new.svg - 22_light_tab-new.svg - 24_light_tab-new.svg - 16_dark_transform-move.svg - 22_dark_transform-move.svg - 24_dark_transform-move.svg - 16_light_transform-move.svg - 22_light_transform-move.svg - 24_light_transform-move.svg - 16_dark_trash-empty.svg - 22_dark_trash-empty.svg - 24_dark_trash-empty.svg - 16_light_trash-empty.svg - 22_light_trash-empty.svg - 24_light_trash-empty.svg - 16_dark_zoom-fit-best.svg - 22_dark_zoom-fit-best.svg - 24_dark_zoom-fit-best.svg - 16_light_zoom-fit-best.svg - 22_light_zoom-fit-best.svg - 24_light_zoom-fit-best.svg - + + + 16_dark_align-horizontal-center.svg + 22_dark_align-horizontal-center.svg + 24_dark_align-horizontal-center.svg + 16_light_align-horizontal-center.svg + 22_light_align-horizontal-center.svg + 24_light_align-horizontal-center.svg + 16_dark_align-horizontal-left.svg + 22_dark_align-horizontal-left.svg + 24_dark_align-horizontal-left.svg + 16_light_align-horizontal-left.svg + 22_light_align-horizontal-left.svg + 24_light_align-horizontal-left.svg + 16_dark_align-horizontal-right.svg + 22_dark_align-horizontal-right.svg + 24_dark_align-horizontal-right.svg + 16_light_align-horizontal-right.svg + 22_light_align-horizontal-right.svg + 24_light_align-horizontal-right.svg + 16_dark_align-vertical-bottom.svg + 22_dark_align-vertical-bottom.svg + 24_dark_align-vertical-bottom.svg + 16_light_align-vertical-bottom.svg + 22_light_align-vertical-bottom.svg + 24_light_align-vertical-bottom.svg + 16_dark_align-vertical-center.svg + 22_dark_align-vertical-center.svg + 24_dark_align-vertical-center.svg + 16_light_align-vertical-center.svg + 22_light_align-vertical-center.svg + 24_light_align-vertical-center.svg + 16_dark_align-vertical-top.svg + 22_dark_align-vertical-top.svg + 24_dark_align-vertical-top.svg + 16_light_align-vertical-top.svg + 22_light_align-vertical-top.svg + 24_light_align-vertical-top.svg + 16_dark_application-x-krita.svg + 22_dark_application-x-krita.svg + 32_dark_application-x-krita.svg + 64_dark_application-x-krita.svg + 16_light_application-x-krita.svg + 22_light_application-x-krita.svg + 32_light_application-x-krita.svg + 64_light_application-x-krita.svg + 16_dark_application-x-wmf.svg + 22_dark_application-x-wmf.svg + 32_dark_application-x-wmf.svg + 64_dark_application-x-wmf.svg + 16_light_application-x-wmf.svg + 22_light_application-x-wmf.svg + 32_light_application-x-wmf.svg + 64_light_application-x-wmf.svg + calligrakrita.png + 16_dark_character-set.svg + 22_dark_character-set.svg + 24_dark_character-set.svg + 16_light_character-set.svg + 22_light_character-set.svg + 24_light_character-set.svg + 16_dark_draw-arrow-back.svg + 22_dark_draw-arrow-back.svg + 24_dark_draw-arrow-back.svg + 16_light_draw-arrow-back.svg + 22_light_draw-arrow-back.svg + 24_light_draw-arrow-back.svg + 16_dark_draw-arrow-down.svg + 22_dark_draw-arrow-down.svg + 24_dark_draw-arrow-down.svg + 16_light_draw-arrow-down.svg + 22_light_draw-arrow-down.svg + 24_light_draw-arrow-down.svg + 16_dark_draw-arrow-forward.svg + 22_dark_draw-arrow-forward.svg + 24_dark_draw-arrow-forward.svg + 16_light_draw-arrow-forward.svg + 22_light_draw-arrow-forward.svg + 24_light_draw-arrow-forward.svg + 16_dark_draw-arrow-up.svg + 22_dark_draw-arrow-up.svg + 24_dark_draw-arrow-up.svg + 16_light_draw-arrow-up.svg + 22_light_draw-arrow-up.svg + 24_light_draw-arrow-up.svg + 16_dark_draw-freehand.svg + 22_dark_draw-freehand.svg + 24_dark_draw-freehand.svg + 16_light_draw-freehand.svg + 22_light_draw-freehand.svg + 24_light_draw-freehand.svg + 16_dark_edit-rename.svg + 22_dark_edit-rename.svg + 24_dark_edit-rename.svg + 16_light_edit-rename.svg + 22_light_edit-rename.svg + 24_light_edit-rename.svg + 16_dark_edit-select-all.svg + 22_dark_edit-select-all.svg + 24_dark_edit-select-all.svg + 16_light_edit-select-all.svg + 22_light_edit-select-all.svg + 24_light_edit-select-all.svg + 16_dark_format-indent-less.svg + 22_dark_format-indent-less.svg + 24_dark_format-indent-less.svg + 16_light_format-indent-less.svg + 22_light_format-indent-less.svg + 24_light_format-indent-less.svg + 16_dark_format-indent-more.svg + 22_dark_format-indent-more.svg + 24_dark_format-indent-more.svg + 16_light_format-indent-more.svg + 22_light_format-indent-more.svg + 24_light_format-indent-more.svg + 16_dark_format-justify-center.svg + 22_dark_format-justify-center.svg + 24_dark_format-justify-center.svg + 16_light_format-justify-center.svg + 22_light_format-justify-center.svg + 24_light_format-justify-center.svg + 16_dark_format-justify-fill.svg + 22_dark_format-justify-fill.svg + 24_dark_format-justify-fill.svg + 16_light_format-justify-fill.svg + 22_light_format-justify-fill.svg + 24_light_format-justify-fill.svg + 16_dark_format-justify-left.svg + 22_dark_format-justify-left.svg + 24_dark_format-justify-left.svg + 16_light_format-justify-left.svg + 22_light_format-justify-left.svg + 24_light_format-justify-left.svg + 16_dark_format-justify-right.svg + 22_dark_format-justify-right.svg + 24_dark_format-justify-right.svg + 16_light_format-justify-right.svg + 22_light_format-justify-right.svg + 24_light_format-justify-right.svg + 16_dark_format-list-ordered.svg + 22_dark_format-list-ordered.svg + 24_dark_format-list-ordered.svg + 16_light_format-list-ordered.svg + 22_light_format-list-ordered.svg + 24_light_format-list-ordered.svg + 16_dark_format-stroke-color.svg + 22_dark_format-stroke-color.svg + 24_dark_format-stroke-color.svg + 16_light_format-stroke-color.svg + 22_light_format-stroke-color.svg + 24_light_format-stroke-color.svg + 16_dark_format-text-bold.svg + 22_dark_format-text-bold.svg + 24_dark_format-text-bold.svg + 16_light_format-text-bold.svg + 22_light_format-text-bold.svg + 24_light_format-text-bold.svg + 16_dark_format-text-color.svg + 22_dark_format-text-color.svg + 24_dark_format-text-color.svg + 16_light_format-text-color.svg + 22_light_format-text-color.svg + 24_light_format-text-color.svg + 16_dark_format-text-direction-rtl.svg + 22_dark_format-text-direction-rtl.svg + 24_dark_format-text-direction-rtl.svg + 16_light_format-text-direction-rtl.svg + 22_light_format-text-direction-rtl.svg + 24_light_format-text-direction-rtl.svg + 16_dark_format-text-italic.svg + 22_dark_format-text-italic.svg + 24_dark_format-text-italic.svg + 16_light_format-text-italic.svg + 22_light_format-text-italic.svg + 24_light_format-text-italic.svg + 16_dark_format-text-strikethrough.svg + 22_dark_format-text-strikethrough.svg + 24_dark_format-text-strikethrough.svg + 16_light_format-text-strikethrough.svg + 22_light_format-text-strikethrough.svg + 24_light_format-text-strikethrough.svg + 16_dark_format-text-subscript.svg + 22_dark_format-text-subscript.svg + 24_dark_format-text-subscript.svg + 16_light_format-text-subscript.svg + 22_light_format-text-subscript.svg + 24_light_format-text-subscript.svg + 16_dark_format-text-superscript.svg + 22_dark_format-text-superscript.svg + 24_dark_format-text-superscript.svg + 16_light_format-text-superscript.svg + 22_light_format-text-superscript.svg + 24_light_format-text-superscript.svg + 16_dark_format-text-underline.svg + 22_dark_format-text-underline.svg + 24_dark_format-text-underline.svg + 16_light_format-text-underline.svg + 22_light_format-text-underline.svg + 24_light_format-text-underline.svg + 16_dark_insert-text.svg + 22_dark_insert-text.svg + 24_dark_insert-text.svg + 16_light_insert-text.svg + 22_light_insert-text.svg + 24_light_insert-text.svg + 48_dark_klipper.svg + 48_light_klipper.svg + 16_dark_list-remove.svg + 22_dark_list-remove.svg + 24_dark_list-remove.svg + 16_light_list-remove.svg + 22_light_list-remove.svg + 24_light_list-remove.svg + 16_dark_media-floppy.svg + 22_dark_media-floppy.svg + 16_light_media-floppy.svg + 22_light_media-floppy.svg + 16_dark_object-align-horizontal-center-calligra.svg + 22_dark_object-align-horizontal-center-calligra.svg + 16_light_object-align-horizontal-center-calligra.svg + 22_light_object-align-horizontal-center-calligra.svg + 16_dark_object-align-horizontal-left-calligra.svg + 22_dark_object-align-horizontal-left-calligra.svg + 16_light_object-align-horizontal-left-calligra.svg + 22_light_object-align-horizontal-left-calligra.svg + 16_dark_object-align-vertical-top-calligra.svg + 22_dark_object-align-vertical-top-calligra.svg + 16_light_object-align-vertical-top-calligra.svg + 22_light_object-align-vertical-top-calligra.svg + 16_dark_object-group-calligra.svg + 22_dark_object-group-calligra.svg + 16_light_object-group-calligra.svg + 22_light_object-group-calligra.svg + 16_dark_shape-choose.svg + 22_dark_shape-choose.svg + 16_light_shape-choose.svg + 22_light_shape-choose.svg + 16_dark_snap-extension.svg + 22_dark_snap-extension.svg + 24_dark_snap-extension.svg + 16_light_snap-extension.svg + 22_light_snap-extension.svg + 24_light_snap-extension.svg + 16_dark_snap-guideline.svg + 22_dark_snap-guideline.svg + 24_dark_snap-guideline.svg + 16_light_snap-guideline.svg + 22_light_snap-guideline.svg + 24_light_snap-guideline.svg + 16_dark_snap-intersection.svg + 22_dark_snap-intersection.svg + 24_dark_snap-intersection.svg + 16_light_snap-intersection.svg + 22_light_snap-intersection.svg + 24_light_snap-intersection.svg + 16_dark_snap-node.svg + 22_dark_snap-node.svg + 24_dark_snap-node.svg + 16_light_snap-node.svg + 22_light_snap-node.svg + 24_light_snap-node.svg + 22_dark_snap-orthogonal.svg + 24_dark_snap-orthogonal.svg + 22_light_snap-orthogonal.svg + 24_light_snap-orthogonal.svg + 16_dark_split.svg + 22_dark_split.svg + 24_dark_split.svg + 16_light_split.svg + 22_light_split.svg + 24_light_split.svg + 16_dark_tab-close.svg + 22_dark_tab-close.svg + 24_dark_tab-close.svg + 16_light_tab-close.svg + 22_light_tab-close.svg + 24_light_tab-close.svg + 16_dark_tab-new.svg + 22_dark_tab-new.svg + 24_dark_tab-new.svg + 16_light_tab-new.svg + 22_light_tab-new.svg + 24_light_tab-new.svg + 16_dark_transform-move.svg + 22_dark_transform-move.svg + 24_dark_transform-move.svg + 16_light_transform-move.svg + 22_light_transform-move.svg + 24_light_transform-move.svg + 16_dark_trash-empty.svg + 22_dark_trash-empty.svg + 24_dark_trash-empty.svg + 16_light_trash-empty.svg + 22_light_trash-empty.svg + 24_light_trash-empty.svg + 16_dark_zoom-fit-best.svg + 22_dark_zoom-fit-best.svg + 24_dark_zoom-fit-best.svg + 16_light_zoom-fit-best.svg + 22_light_zoom-fit-best.svg + 24_light_zoom-fit-best.svg + 16_dark_warning.svg + 16_light_warning.svg + diff --git a/plugins/dockers/advancedcolorselector/kis_shade_selector_line_editor.cpp b/plugins/dockers/advancedcolorselector/kis_shade_selector_line_editor.cpp index 0d192a1acf..d799f1e2d8 100644 --- a/plugins/dockers/advancedcolorselector/kis_shade_selector_line_editor.cpp +++ b/plugins/dockers/advancedcolorselector/kis_shade_selector_line_editor.cpp @@ -1,100 +1,102 @@ /* * Copyright (c) 2010 Adam Celarek * Copyright (c) 2013 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 "kis_shade_selector_line_editor.h" +#include "kis_double_parse_spin_box.h" + KisShadeSelectorLineEditor::KisShadeSelectorLineEditor(QWidget* parent) : KisShadeSelectorLineBase(parent) { QVBoxLayout* layout = new QVBoxLayout(this); QHBoxLayout* lineOne = new QHBoxLayout(); layout->addLayout(lineOne); lineOne->addWidget(new QLabel(i18n("Delta: "))); - m_hueDelta = new QDoubleSpinBox(); + m_hueDelta = new KisDoubleParseSpinBox(); lineOne->addWidget(m_hueDelta); - m_saturationDelta = new QDoubleSpinBox(); + m_saturationDelta = new KisDoubleParseSpinBox(); lineOne->addWidget(m_saturationDelta); - m_valueDelta = new QDoubleSpinBox(); + m_valueDelta = new KisDoubleParseSpinBox(); lineOne->addWidget(m_valueDelta); QHBoxLayout* lineTwo = new QHBoxLayout(); layout->addLayout(lineTwo); lineTwo->addWidget(new QLabel(i18n("Shift: "))); - m_hueShift = new QDoubleSpinBox(); + m_hueShift = new KisDoubleParseSpinBox(); lineTwo->addWidget(m_hueShift); - m_saturationShift = new QDoubleSpinBox(); + m_saturationShift = new KisDoubleParseSpinBox(); lineTwo->addWidget(m_saturationShift); - m_valueShift = new QDoubleSpinBox(); + m_valueShift = new KisDoubleParseSpinBox(); lineTwo->addWidget(m_valueShift); m_hueDelta->setRange(-1, 1); m_saturationDelta->setRange(-1, 1); m_valueDelta->setRange(-1, 1); m_hueShift->setRange(-1, 1); m_saturationShift->setRange(-1, 1); m_valueShift->setRange(-1, 1); m_hueDelta->setSingleStep(0.1); m_saturationDelta->setSingleStep(0.1); m_valueDelta->setSingleStep(0.1); m_hueShift->setSingleStep(0.05); m_saturationShift->setSingleStep(0.05); m_valueShift->setSingleStep(0.05); connect(m_hueDelta, SIGNAL(valueChanged(double)), SLOT(valueChanged())); connect(m_saturationDelta, SIGNAL(valueChanged(double)), SLOT(valueChanged())); connect(m_valueDelta, SIGNAL(valueChanged(double)), SLOT(valueChanged())); connect(m_hueShift, SIGNAL(valueChanged(double)), SLOT(valueChanged())); connect(m_saturationShift, SIGNAL(valueChanged(double)), SLOT(valueChanged())); connect(m_valueShift, SIGNAL(valueChanged(double)), SLOT(valueChanged())); } QString KisShadeSelectorLineEditor::toString() const { return QString("%1|%2|%3|%4|%5|%6|%7") .arg(m_lineNumber) .arg(m_hueDelta->value()) .arg(m_saturationDelta->value()) .arg(m_valueDelta->value()) .arg(m_hueShift->value()) .arg(m_saturationShift->value()) .arg(m_valueShift->value()); } void KisShadeSelectorLineEditor::fromString(const QString &string) { QStringList strili = string.split('|'); m_lineNumber = strili.at(0).toInt(); m_hueDelta->setValue(strili.at(1).toDouble()); m_saturationDelta->setValue(strili.at(2).toDouble()); m_valueDelta->setValue(strili.at(3).toDouble()); if(strili.size()==4) return; // don't crash, if reading old config files. m_hueShift->setValue(strili.at(4).toDouble()); m_saturationShift->setValue(strili.at(5).toDouble()); m_valueShift->setValue(strili.at(6).toDouble()); } void KisShadeSelectorLineEditor::valueChanged() { emit requestActivateLine(this); } diff --git a/plugins/dockers/advancedcolorselector/kis_shade_selector_line_editor.h b/plugins/dockers/advancedcolorselector/kis_shade_selector_line_editor.h index c39c7e7c9f..53bdd91a57 100644 --- a/plugins/dockers/advancedcolorselector/kis_shade_selector_line_editor.h +++ b/plugins/dockers/advancedcolorselector/kis_shade_selector_line_editor.h @@ -1,56 +1,57 @@ /* * Copyright (c) 2010 Adam Celarek * Copyright (c) 2013 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. */ #ifndef __KIS_SHADE_SELECTOR_LINE_EDITOR_H #define __KIS_SHADE_SELECTOR_LINE_EDITOR_H #include #include #include #include #include #include "kis_shade_selector_line.h" +class KisDoubleParseSpinBox; class KisShadeSelectorLineEditor : public KisShadeSelectorLineBase { Q_OBJECT public: KisShadeSelectorLineEditor(QWidget* parent); QString toString() const; void fromString(const QString &string); private Q_SLOTS: void valueChanged(); Q_SIGNALS: void requestActivateLine(QWidget *widget); private: - QDoubleSpinBox* m_hueDelta; - QDoubleSpinBox* m_saturationDelta; - QDoubleSpinBox* m_valueDelta; - QDoubleSpinBox* m_hueShift; - QDoubleSpinBox* m_saturationShift; - QDoubleSpinBox* m_valueShift; + KisDoubleParseSpinBox* m_hueDelta; + KisDoubleParseSpinBox* m_saturationDelta; + KisDoubleParseSpinBox* m_valueDelta; + KisDoubleParseSpinBox* m_hueShift; + KisDoubleParseSpinBox* m_saturationShift; + KisDoubleParseSpinBox* m_valueShift; }; #endif /* __KIS_SHADE_SELECTOR_LINE_EDITOR_H */ diff --git a/plugins/dockers/advancedcolorselector/wdg_color_selector_settings.ui b/plugins/dockers/advancedcolorselector/wdg_color_selector_settings.ui index e105b5a676..a2fd23de57 100644 --- a/plugins/dockers/advancedcolorselector/wdg_color_selector_settings.ui +++ b/plugins/dockers/advancedcolorselector/wdg_color_selector_settings.ui @@ -1,1463 +1,1462 @@ KisColorSelectorSettings 0 0 635 982 0 0 Color Selector Settings Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop 6 20 Docker: 0 0 0 30 0 0 600 421 3 Color Selector Qt::Vertical 20 40 Qt::LeftToRight - Color Model Type: + Color &Model Type: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter colorSelectorConfiguration 0 0 Type Description goes here Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop true 0 0 Luma Coefficients 0 0 6 0 0 Red': Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - + 0 0 50 0 4 0 0 Green': 0 0 Blue': - + 0 0 50 0 4 - + 0 0 50 0 4 - + <html><head/><body><p>This sets the gamma value that the linearised HSY Luminosity is crunched with. 1 makes the selector fully linear, 2.2 is a practical default value.</p></body></html> 1 -3.000000000000000 3.000000000000000 0.100000000000000 2.200000000000000 Gamma: 0 0 - Color Selector Uses Different Color Space than Image + Color Selector Uses Different Color Space than Ima&ge true false 0 0 Behavior Qt::LeftToRight When Docker Resizes: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter true Show Zoom Selector UI: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter Zoom Selector Size: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - + px 100 1000 10 260 Hide Popup on click. Shade Selector Type: Color model: Qt::Vertical 20 10 Qt::Horizontal 20 20 0 Update Selector When: Qt::Vertical 20 6 Right clicking on shade selector Left clicking on shade selector this doesn't include a color change by the shade selector Foreground color changes false this doesn't include a color change by the shade selector Background color change true Qt::Vertical 20 109 Minimal Shade Selector Display: - Gradient + &Gradient - Color Patches + Colo&r Patches 0 0 Qt::Horizontal 59 20 Line Count: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - + 1 10 3 Line Height: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - + px 8 99 16 Patches Per Line: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - + - label_7 - shadeSelectorUpdateOnRightClick - shadeSelectorUpdateOnLeftClick - shadeSelectorUpdateOnForeground - shadeSelectorUpdateOnBackground - myPaintColorModelLabel minimalShadeSelectorGroup - ACSshadeSelectorMyPaintColorModelComboBox - ACSShadeSelectorTypeComboBox - label_16 - verticalSpacer_3 - verticalSpacer_4 verticalSpacer_5 true 0 0 Color History 0 0 - Show Color History + Show Color Histor&y true Patch Options Height: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - + px 16 Width: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - + px 16 Max Patches: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - + 1 30 Qt::Horizontal 40 20 Layout 0 - Vertical + &Vertical true - Columns: + Colu&mns: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter lastUsedColorsNumCols - + 1 20 2 - Horizontal + &Horizontal - Rows: + &Rows: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter lastUsedColorsNumRows - + 1 20 3 Allow scrolling true Qt::Vertical 20 40 Colors from Image true - Show Colors from the image + Show Colors from the ima&ge true Patch Options Height: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - + px 16 Width: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - + px 16 Max Patches: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - + 1 30 Qt::Horizontal 40 20 Layout 6 0 - Vertical + &Vertical - Columns: + Colu&mns: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter commonColorsNumCols - + 1 20 2 - Horizontal + &Horizontal true - Rows: + &Rows: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter commonColorsNumRows - + 1 20 3 this can be slow on big images Update after every stroke Allow scrolling Qt::Vertical 20 138 HSV Sliders to Show Hue Saturation Value HSL Sliders to Show Hue Saturation Lightness HSI Sliders to Show Hue Saturation Intensity HSY' Sliders to Show Hue Saturation Luma Lightness, Saturation and Hue hotkey steps Lightness: - + steps Qt::Horizontal 40 20 Saturation: - + steps Qt::Horizontal 40 20 Hue: - + steps YUV Redder/Greener/Bluer/Yellower hotkey steps Redder/Greener: - + steps Qt::Horizontal 40 20 Bluer/Yellower: - + steps Qt::Vertical 20 40 KisColorSpaceSelector QWidget
widgets/kis_color_space_selector.h
1
KisColorSelectorComboBox QComboBox
kis_color_selector_combo_box.h
KisShadeSelectorLinesSettings QComboBox
kis_shade_selector_lines_settings.h
+ + KisIntParseSpinBox + QSpinBox +
kis_int_parse_spin_box.h
+
+ + KisDoubleParseSpinBox + QDoubleSpinBox +
kis_double_parse_spin_box.h
+
minimalShadeSelectorAsColorPatches toggled(bool) minimalShadeSelectorPatchesPerLine setEnabled(bool) 194 393 520 463
diff --git a/plugins/dockers/animation/tests/timeline_model_test.cpp b/plugins/dockers/animation/tests/timeline_model_test.cpp index 64a8c78320..782d6908d1 100644 --- a/plugins/dockers/animation/tests/timeline_model_test.cpp +++ b/plugins/dockers/animation/tests/timeline_model_test.cpp @@ -1,296 +1,298 @@ /* * Copyright (c) 2015 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 "timeline_model_test.h" #include "kis_image.h" #include "kis_node.h" #include "kis_paint_device.h" #include #include #include #include #include "kis_image_animation_interface.h" #include "KisDocument.h" #include "KisPart.h" #include "kis_name_server.h" #include "flake/kis_shape_controller.h" #include "kis_undo_adapter.h" #include "timeline_frames_view.h" #include "timeline_frames_model.h" #include "kis_node_dummies_graph.h" #include "commands/kis_image_layer_add_command.h" #include "commands/kis_image_layer_remove_command.h" +#include "kis_double_parse_spin_box.h" +#include "kis_int_parse_spin_box.h" void TimelineModelTest::init() { m_doc = KisPart::instance()->createDocument(); m_nameServer = new KisNameServer(); m_shapeController = new KisShapeController(m_doc, m_nameServer); //m_nodeModel = new KisNodeModel(0); initBase(); } void TimelineModelTest::cleanup() { cleanupBase(); //delete m_nodeModel; delete m_shapeController; delete m_nameServer; delete m_doc; } #include "timeline_frames_index_converter.h" void TimelineModelTest::testConverter() { constructImage(); addSelectionMasks(); m_shapeController->setImage(m_image); m_layer1->enableAnimation(); m_layer1->setUseInTimeline(true); m_layer2->setUseInTimeline(true); m_sel3->setUseInTimeline(true); TimelineFramesIndexConverter converter(m_shapeController); QCOMPARE(converter.rowCount(), 3); QCOMPARE(converter.rowForDummy(m_shapeController->dummyForNode(m_layer1)), 2); QCOMPARE(converter.rowForDummy(m_shapeController->dummyForNode(m_layer2)), 1); QCOMPARE(converter.rowForDummy(m_shapeController->dummyForNode(m_sel3)), 0); QCOMPARE(converter.dummyFromRow(2), m_shapeController->dummyForNode(m_layer1)); QCOMPARE(converter.dummyFromRow(1), m_shapeController->dummyForNode(m_layer2)); QCOMPARE(converter.dummyFromRow(0), m_shapeController->dummyForNode(m_sel3)); TimelineNodeListKeeper keeper(0, m_shapeController); QCOMPARE(keeper.rowCount(), 3); QCOMPARE(keeper.rowForDummy(m_shapeController->dummyForNode(m_layer1)), 2); QCOMPARE(keeper.rowForDummy(m_shapeController->dummyForNode(m_layer2)), 1); QCOMPARE(keeper.rowForDummy(m_shapeController->dummyForNode(m_sel3)), 0); QCOMPARE(keeper.dummyFromRow(2), m_shapeController->dummyForNode(m_layer1)); QCOMPARE(keeper.dummyFromRow(1), m_shapeController->dummyForNode(m_layer2)); QCOMPARE(keeper.dummyFromRow(0), m_shapeController->dummyForNode(m_sel3)); TimelineNodeListKeeper::OtherLayersList list = keeper.otherLayersList(); Q_FOREACH (const TimelineNodeListKeeper::OtherLayer &l, list) { qDebug() << ppVar(l.name) << ppVar(l.dummy->node()->name()); } } void TimelineModelTest::testModel() { QScopedPointer model(new TimelineFramesModel(0)); } struct TestingInterface : TimelineFramesModel::NodeManipulationInterface { TestingInterface(KisImageSP image) : m_image(image) {} KisLayerSP addPaintLayer() const { KisNodeSP parent = m_image->root(); KisNodeSP after = parent->lastChild(); KisPaintLayerSP layer = new KisPaintLayer(const_cast(m_image.data()), m_image->nextLayerName(), OPACITY_OPAQUE_U8, m_image->colorSpace()); m_image->undoAdapter()->addCommand( new KisImageLayerAddCommand(m_image, layer, parent, after, false, false)); return layer; } void removeNode(KisNodeSP node) const { m_image->undoAdapter()->addCommand( new KisImageLayerRemoveCommand(m_image, node)); } private: KisImageSP m_image; }; void TimelineModelTest::testView() { QDialog dlg; QFont font; font.setPointSizeF(9); dlg.setFont(font); - QSpinBox *intFps = new QSpinBox(&dlg); + QSpinBox *intFps = new KisIntParseSpinBox(&dlg); intFps->setValue(12); - QSpinBox *intTime = new QSpinBox(&dlg); + QSpinBox *intTime = new KisIntParseSpinBox(&dlg); intTime->setValue(0); intTime->setMaximum(10000); - QSpinBox *intLayer = new QSpinBox(&dlg); + QSpinBox *intLayer = new KisIntParseSpinBox(&dlg); intLayer->setValue(0); intLayer->setMaximum(100); TimelineFramesView *framesTable = new TimelineFramesView(&dlg); TimelineFramesModel *model = new TimelineFramesModel(&dlg); constructImage(); addSelectionMasks(); m_shapeController->setImage(m_image); m_image->animationInterface()->requestTimeSwitchWithUndo(4); framesTable->setModel(model); model->setDummiesFacade(m_shapeController, m_image); model->setNodeManipulationInterface(new TestingInterface(m_image)); m_layer1->enableAnimation(); m_layer1->setUseInTimeline(true); connect(intFps, SIGNAL(valueChanged(int)), m_image->animationInterface(), SLOT(setFramerate(int))); connect(intTime, SIGNAL(valueChanged(int)), SLOT(setCurrentTime(int))); connect(m_image->animationInterface(), SIGNAL(sigTimeChanged(int)), intTime, SLOT(setValue(int))); connect(intLayer, SIGNAL(valueChanged(int)), SLOT(setCurrentLayer(int))); connect(this, SIGNAL(sigRequestNodeChange(KisNodeSP)), model, SLOT(slotCurrentNodeChanged(KisNodeSP))); connect(model, SIGNAL(requestCurrentNodeChanged(KisNodeSP)), this, SLOT(slotGuiChangedNode(KisNodeSP))); QVBoxLayout *layout = new QVBoxLayout(&dlg); layout->addWidget(intFps); layout->addWidget(intTime); layout->addWidget(intLayer); layout->addWidget(framesTable); layout->setStretch(0, 0); layout->setStretch(1, 0); layout->setStretch(2, 0); layout->setStretch(3, 1); dlg.resize(600, 400); dlg.exec(); } void TimelineModelTest::setCurrentTime(int time) { m_image->animationInterface()->requestTimeSwitchWithUndo(time); } KisNodeDummy* findNodeFromRowAny(KisNodeDummy *root, int &startCount) { if (!startCount) { return root; } startCount--; KisNodeDummy *dummy = root->lastChild(); while (dummy) { KisNodeDummy *found = findNodeFromRowAny(dummy, startCount); if (found) return found; dummy = dummy->prevSibling(); } return 0; } void TimelineModelTest::setCurrentLayer(int row) { KisNodeDummy *root = m_shapeController->rootDummy(); KisNodeDummy *dummy = findNodeFromRowAny(root, row); if (!dummy) { qDebug() << "WARNING: Cannot find a node at pos" << row; return; } else { qDebug() << "NonGUI changed active node: " << dummy->node()->name(); } emit sigRequestNodeChange(dummy->node()); } void TimelineModelTest::slotGuiChangedNode(KisNodeSP node) { qDebug() << "GUI changed active node:" << node->name(); } #include "kis_equalizer_column.h" #include "kis_equalizer_slider.h" #include "kis_equalizer_widget.h" void TimelineModelTest::testOnionSkins() { QDialog dlg; QFont font; font.setPointSizeF(9); dlg.setFont(font); QHBoxLayout *layout = new QHBoxLayout(&dlg); KisEqualizerWidget *w = new KisEqualizerWidget(10, &dlg); connect(w, SIGNAL(sigConfigChanged()), SLOT(slotBang())); layout->addWidget(w); dlg.setLayout(layout); dlg.resize(600, 400); dlg.exec(); } void TimelineModelTest::slotBang() { ENTER_FUNCTION() << "!!!!"; } QTEST_MAIN(TimelineModelTest) diff --git a/plugins/dockers/animation/wdg_animation.ui b/plugins/dockers/animation/wdg_animation.ui index 92c7b19283..00f3e3d618 100644 --- a/plugins/dockers/animation/wdg_animation.ui +++ b/plugins/dockers/animation/wdg_animation.ui @@ -1,519 +1,531 @@ WdgAnimation 0 0 535 635 - + 0 0 Qt::AlignCenter 10000 Qt::Horizontal QSizePolicy::Fixed 40 20 6 3 Start: - + 0 0 10000 End: - + 0 0 10000 100 Qt::Vertical 20 40 0 0 QFrame::NoFrame QFrame::Raised Qt::Horizontal 0 0 ... true 0 0 QFrame::Sunken Qt::Vertical 0 0 ... true 0 0 QFrame::Sunken Qt::Vertical 0 0 ... true 0 0 QFrame::Sunken Qt::Vertical 0 0 ... true 0 0 QFrame::Sunken Qt::Vertical 0 0 ... true 0 0 QFrame::Sunken Qt::Vertical 0 0 ... true 0 0 QFrame::Sunken Qt::Vertical 0 0 ... true Qt::Horizontal Qt::Vertical 20 40 0 1 ... true ... true ... true 1 ... true ... true ... true Qt::Horizontal 10 20 3 Play Speed: - + 0.100000000000000 10.000000000000000 0.050000000000000 1.000000000000000 Frame Rate: - + 1 + + + KisDoubleParseSpinBox + QDoubleSpinBox +
kis_double_parse_spin_box.h
+
+ + KisIntParseSpinBox + QSpinBox +
kis_int_parse_spin_box.h
+
+
diff --git a/plugins/dockers/colorslider/kis_color_slider_input.cpp b/plugins/dockers/colorslider/kis_color_slider_input.cpp index 8e0a460668..4e76de0adb 100644 --- a/plugins/dockers/colorslider/kis_color_slider_input.cpp +++ b/plugins/dockers/colorslider/kis_color_slider_input.cpp @@ -1,710 +1,712 @@ /* * Copyright (c) 2008 Cyrille Berger * Copyright (c) 2014 Wolthera van Hövell * Copyright (c) 2015 Moritz Molch * * This library is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; version 2.1 of the License. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser 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_color_slider_input.h" #include #ifdef HAVE_OPENEXR #include #endif #include #include #include #include #include #include #include #include #include #include #include #include "kis_hsv_slider.h" #include "kis_display_color_converter.h" +#include "kis_double_parse_spin_box.h" + KisColorSliderInput::KisColorSliderInput(QWidget* parent, KoColor* color, const int type, KoColorDisplayRendererInterface *displayRenderer, KisCanvas2* canvas) : QWidget(parent), m_type(type), m_color(color), m_displayRenderer(displayRenderer), m_canvas(canvas) { //init } void KisColorSliderInput::init() { QHBoxLayout* m_layout = new QHBoxLayout(this); m_layout->setContentsMargins(0, 0, 0, 0); m_layout->setSpacing(1); QString m_name; switch (m_type){ case 0: m_name=i18n("Hue"); break; case 1: m_name=i18n("Saturation"); break; case 2: m_name=i18n("Value"); break; case 3: m_name=i18n("Hue"); break; case 4: m_name=i18n("Saturation"); break; case 5: m_name=i18n("Lightness"); break; case 6: m_name=i18n("Hue"); break; case 7: m_name=i18n("Saturation"); break; case 8: m_name=i18n("Intensity"); break; case 9: m_name=i18n("Hue"); break; case 10: m_name=i18n("Saturation"); break; case 11: m_name=i18n("Luma"); break; } QLabel* m_label = new QLabel(i18n("%1:", m_name), this); m_layout->addWidget(m_label); m_hsvSlider = new KisHSVSlider(Qt::Horizontal, this, m_displayRenderer, m_canvas); m_hsvSlider->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed); m_layout->addWidget(m_hsvSlider); connect (m_hsvSlider, SIGNAL(sliderPressed()), SLOT(sliderIn())); connect (m_hsvSlider, SIGNAL(sliderReleased()), SLOT(sliderOut())); QWidget* m_input = createInput(); m_hsvSlider->setFixedHeight(m_input->sizeHint().height()); m_layout->addWidget(m_input); } KisHSXColorSliderInput::KisHSXColorSliderInput(QWidget* parent, const int type, KoColor* color, KoColorDisplayRendererInterface *displayRenderer, KisCanvas2* canvas) : KisColorSliderInput(parent, color, type, displayRenderer, canvas), m_canvas(canvas), m_hue(0), m_sat(0), m_val(0), R(0), G(0), B(0), Gamma(0) { m_hueupdating = false; m_satupdating = false; m_toneupdating = false; m_sliderisupdating = false; init(); } void KisHSXColorSliderInput::setValue(double v) { //This function returns the colour based on the type of the slider as well as the value// qreal h=0.0; qreal s=0.0; qreal l=0.0; KConfigGroup cfg = KSharedConfig::openConfig()->group("advancedColorSelector"); R = cfg.readEntry("lumaR", 0.2126); G = cfg.readEntry("lumaG", 0.7152); B = cfg.readEntry("lumaB", 0.0722); Gamma = cfg.readEntry("gamma", 2.2); switch (m_type) { case 0: m_hue = v; h=m_hue/360.0; s=m_sat/100.0; l=m_val/100.0; *m_color = this->converter()->fromHsvF(h, s, l); if (m_hueupdating==false) { emit(hueUpdated(static_cast(m_hue))); } else { m_hueupdating=false; } break; case 3: m_hue = v; h=m_hue/360.0; s=m_sat/100.0; l=m_val/100.0; *m_color = this->converter()->fromHslF(h, s, l); if (m_hueupdating==false) { emit(hueUpdated(static_cast(m_hue))); } else { m_hueupdating=false; } break; case 6: m_hue = v; h=m_hue/360.0; s=m_sat/100.0; l=m_val/100.0; *m_color = this->converter()->fromHsiF(h, s, l); if (m_hueupdating==false) { emit(hueUpdated(static_cast(m_hue))); } else { m_hueupdating=false; } break; case 9: m_hue = v; h=m_hue/360.0f; s=m_sat/100.0f; l=m_val/100.0f; *m_color = this->converter()->fromHsyF(h, s, l, R, G, B, Gamma); if (m_hueupdating==false) { emit(hueUpdated(static_cast(m_hue))); } else { m_hueupdating=false; } break; case 1: m_sat = v; h=m_hue/360.0f; s=m_sat/100.0f; l=m_val/100.0f; *m_color = this->converter()->fromHsvF(h, s, l); if (m_satupdating==false) { emit(satUpdated(static_cast(m_sat), m_type)); } else { m_satupdating=false; } break; case 2: m_val = v; h=m_hue/360.0f; s=m_sat/100.0f; l=m_val/100.0f; *m_color = this->converter()->fromHsvF(h, s, l); if (m_toneupdating==false) { emit(toneUpdated(static_cast(m_val), m_type)); } else { m_toneupdating=false; } break; case 4: m_sat = v; h=m_hue/360.0f; s=m_sat/100.0f; l=m_val/100.0f; *m_color = this->converter()->fromHslF(h, s, l); if (m_satupdating==false) { emit(satUpdated(static_cast(m_sat), m_type)); } else { m_satupdating=false; } break; case 5: m_val = v; h=m_hue/360.0f; s=m_sat/100.0f; l=m_val/100.0f; *m_color = this->converter()->fromHslF(h, s, l); if (m_toneupdating==false) { emit(toneUpdated(static_cast(m_val), m_type)); } else { m_toneupdating=false; } break; case 7: m_sat = v; h=m_hue/360.0f; s=m_sat/100.0f; l=m_val/100.0f; *m_color = this->converter()->fromHsiF(h, s, l); if (m_satupdating==false) { emit(satUpdated(static_cast(m_sat), m_type)); } else { m_satupdating=false; } break; case 8: m_val = v; h=m_hue/360.0f; s=m_sat/100.0f; l=m_val/100.0f; *m_color = this->converter()->fromHsiF(h, s, l); if (m_toneupdating==false) { emit(toneUpdated(static_cast(m_val), m_type)); } else { m_toneupdating=false; } break; case 10: m_sat = v; h=m_hue/360.0f; s=m_sat/100.0f; l=m_val/100.0f; *m_color = this->converter()->fromHsyF(h, s, l, R, G, B, Gamma); if (m_satupdating==false) { emit(satUpdated(static_cast(m_sat), m_type)); } else { m_satupdating=false; } break; case 11: m_val = v; h=m_hue/360.0f; s=m_sat/100.0f; l=m_val/100.0f; *m_color = this->converter()->fromHsyF(h, s, l, R, G, B, Gamma); if (m_toneupdating==false) { emit(toneUpdated(static_cast(m_val), m_type)); } else { m_toneupdating=false; } break; default: Q_ASSERT(false); } emit(updated()); } //update void KisHSXColorSliderInput::update() { KoColor min = *m_color; KoColor max = *m_color; qreal hue, sat, val, hue_backup, sat_backup, val_backup; //gets the hsv for the appropriate type// hue_backup = m_hue; sat_backup = m_sat; val_backup = m_val; switch (m_type) { case 0: this->converter()->getHsvF(*m_color, &hue, &sat, &val); if (m_sliderisupdating==true) { if((sat*100.0)m_sat-2) { sat = (sat_backup*0.01); } if((val*100.0)m_val-2) { val = (val_backup*0.01); } } else{ if((hue*360.0)m_hue-2) { hue = (hue_backup/360.0); } } break; case 1: this->converter()->getHsvF(*m_color, &hue, &sat, &val); if (m_sliderisupdating==true) { if( (hue*360.0)m_hue-2 ) { hue = (hue_backup/360.0); } if((val*100.0)m_val-2) { val = (val_backup*0.01); } } else{ if((sat*100.0)m_sat-2) { sat = (sat_backup*0.01); } } break; case 2: this->converter()->getHsvF(*m_color, &hue, &sat, &val); if (m_sliderisupdating==true) { if((sat*100.0)m_sat-2) { sat = (sat_backup*0.01); } if((hue*360.0)m_hue-2) { hue = (hue_backup/360.0); } } else{ if((val*100.0)m_val-2) { val = (val_backup*0.01); } } break; case 3: this->converter()->getHslF(*m_color, &hue, &sat, &val); if (m_sliderisupdating==true) { if((sat*100.0)m_sat-2) { sat = (sat_backup*0.01); } if((val*100.0)m_val-2) { val = (val_backup*0.01); } } else{ if((hue*360.0)m_hue-2) { hue = (hue_backup/360.0); } } break; case 4: this->converter()->getHslF(*m_color, &hue, &sat, &val); if (m_sliderisupdating==true) { if((hue*360.0)m_hue-2) { hue = (hue_backup/360.0); } if((val*100.0)m_val-2) { val = (val_backup*0.01); } } else{ if((sat*100.0)m_sat-2) { sat = (sat_backup*0.01); } } break; case 5: this->converter()->getHslF(*m_color, &hue, &sat, &val); if (m_sliderisupdating==true) { if((sat*100.0)m_sat-2) { sat = (sat_backup*0.01); } if((hue*360.0)m_hue-2) { hue = (hue_backup/360.0); } } else{ if((val*100.0)m_val-2) { val = (val_backup*0.01); } } break; case 6: this->converter()->getHsiF(*m_color, &hue, &sat, &val); if (m_sliderisupdating==true) { if((sat*100.0)m_sat-2) { sat = (sat_backup*0.01); } if((val*100.0)m_val-2) { val = (val_backup*0.01); } } else{ if((hue*360.0)m_hue-2) { hue = (hue_backup/360.0); } } break; case 7: this->converter()->getHsiF(*m_color, &hue, &sat, &val); if (m_sliderisupdating==true) { if((hue*360.0)m_hue-2) { hue = (hue_backup/360.0); } if((val*100.0)m_val-2) { val = (val_backup*0.01); } } else{ if((sat*100.0)m_sat-2) { sat = (sat_backup*0.01); } } break; case 8: this->converter()->getHsiF(*m_color, &hue, &sat, &val); if (m_sliderisupdating==true) { if((sat*100.0)m_sat-2) { sat = (sat_backup*0.01); } if((hue*360.0)m_hue-2) { hue = (hue_backup/360.0); } } else{ if((val*100.0)m_val-2) { val = (val_backup*0.01); } } break; case 9: this->converter()->getHsyF(*m_color, &hue, &sat, &val, R, G, B, Gamma); if (m_sliderisupdating==true) { if((sat*100.0)m_sat-2) { sat = (sat_backup*0.01); } if((val*100.0)m_val-2) { val = (val_backup*0.01); } } else{ if((hue*360.0)m_hue-2) { hue = (hue_backup/360.0); } } break; case 10: this->converter()->getHsyF(*m_color, &hue, &sat, &val, R, G, B, Gamma); if (m_sliderisupdating==true) { if((hue*360.0)m_hue-2) { hue = (hue_backup/360.0); } if((val*100.0)m_val-2) { val = (val_backup*0.01); } } else{ if((sat*100.0)m_sat-2) { sat = (sat_backup*0.01); } } break; case 11: this->converter()->getHsyF(*m_color, &hue, &sat, &val, R, G, B, Gamma); if (m_sliderisupdating == true) { if((sat*100.0)m_sat-2) { sat = (sat_backup*0.01); } if((hue*360.0)m_hue-2) { hue = (hue_backup/360.0); } } else{ if((val*100.0)m_val-2) { val = (val_backup*0.01); } } break; } //this prevents the hue going to 0 when used with grey// if (sat<=0.0) { m_hue = hue_backup; } else{ m_hue=(hue*360.0); } if (val==0 || val>0.999) { m_sat = sat_backup; } else{ m_sat=(sat*100.0); } m_val=(val*100.0); if (m_hueupdating==true){m_val=val_backup; m_sat = sat_backup; m_hueupdating=false;} else if (m_satupdating==true){m_val=val_backup; m_hue = hue_backup; m_satupdating=false;} else if (m_toneupdating==true){m_sat=sat_backup; m_hue = hue_backup;m_toneupdating=false;} //sets slider and num-input according to type// switch (m_type) { case 0: case 3: case 6: case 9: m_NumInput->setValue(m_hue); m_hsvSlider->setValue(static_cast(m_hue)); break; case 1: m_NumInput->setValue(m_sat); m_hsvSlider->setValue(static_cast(m_sat)); break; case 2: m_NumInput->setValue(m_val); m_hsvSlider->setValue(static_cast(m_val)); break; case 4: m_NumInput->setValue(m_sat); m_hsvSlider->setValue(static_cast(m_sat)); break; case 5: m_NumInput->setValue(m_val); m_hsvSlider->setValue(static_cast(m_val)); break; case 7: m_NumInput->setValue(m_sat); m_hsvSlider->setValue(static_cast(m_sat)); break; case 8: m_NumInput->setValue(m_val); m_hsvSlider->setValue(static_cast(m_val)); break; case 10: m_NumInput->setValue(m_sat); m_hsvSlider->setValue(static_cast(m_sat)); break; case 11: m_NumInput->setValue(m_val); m_hsvSlider->setValue(static_cast(m_val)); break; default: Q_ASSERT(false); } m_hsvSlider->setColors(*m_color,m_type, m_hue, R, G, B, Gamma); } QWidget* KisHSXColorSliderInput::createInput() { - m_NumInput = new QDoubleSpinBox(this); + m_NumInput = new KisDoubleParseSpinBox(this); m_NumInput->setMinimum(0); m_NumInput->setMaximum(100.0); m_NumInput->setKeyboardTracking(false);//this makes sure that only full values are sent after loss of focus. Much more user friendly// m_hsvSlider->setMaximum(100); switch (m_type) { case 0: case 3: case 6: case 9: m_NumInput->setMaximum(360.0); m_NumInput->setWrapping(true); m_hsvSlider->setMaximum(360); m_NumInput->setSingleStep (5.0); break; case 1: case 2: case 4: case 5: case 7: case 8: case 10: case 11: m_NumInput->setMaximum(100.0); m_hsvSlider->setMaximum(100); m_NumInput->setSingleStep (10.0); break; default: Q_ASSERT(false); } connect(m_hsvSlider, SIGNAL(valueChanged(int)), this, SLOT(sliderChanged(int))); connect(m_NumInput, SIGNAL(valueChanged(double)), this, SLOT(numInputChanged(double))); return m_NumInput; } void KisHSXColorSliderInput::sliderChanged(int i) { m_NumInput->setValue(i*1.0); setValue(i*1.0); } void KisHSXColorSliderInput::sliderIn(){ m_sliderisupdating=true; } void KisHSXColorSliderInput::sliderOut(){ m_sliderisupdating=false; } //attempt at getting rid of dancing sliders... #2859 //The nminput should not be changing the sliders if the sliders are the one changing the input. //As numinpit rounds off at 2 decimals(and there's no point at letting it continue the signal circle). void KisHSXColorSliderInput::numInputChanged(double v) { if (m_sliderisupdating==true){ return; } else { setValue(v); } } //this connects to the display converter. Important for OCIO, breaks on missing of m_canvas somehow. KisDisplayColorConverter* KisHSXColorSliderInput::converter() const { return m_canvas ? m_canvas->displayColorConverter() : KisDisplayColorConverter::dumbConverterInstance(); } void KisHSXColorSliderInput::hueUpdate(int h) { if (h<=m_hue-2 || h>=m_hue+2) { m_hue=h; m_hueupdating=true; update(); } } void KisHSXColorSliderInput::satUpdate(int s, int type) { if (m_type==type+1 || m_type==type-1) { if (s<=m_sat-3 || s>=m_sat+3) { m_sat=s; m_satupdating=true; update(); } } } void KisHSXColorSliderInput::toneUpdate(int l, int type) { if (m_type==type-1 || m_type==type-2) { if (l<25 || l>75){ if (l<=m_val-10 || l>=m_val+10) { m_val=l; m_toneupdating=true; update(); } } else { if (l<=m_val-3 || l>=m_val+3) { m_val=l; m_toneupdating=true; update(); } } } } #include "moc_kis_color_slider_input.cpp" diff --git a/plugins/dockers/colorslider/kis_color_slider_input.h b/plugins/dockers/colorslider/kis_color_slider_input.h index eecb8e2f44..2b4b0c7f70 100644 --- a/plugins/dockers/colorslider/kis_color_slider_input.h +++ b/plugins/dockers/colorslider/kis_color_slider_input.h @@ -1,90 +1,91 @@ /* * Copyright (c) 2008 Cyrille Berger * Copyright (c) 2014 Wolthera van Hövell * * This library is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; version 2.1 of the License. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser 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_COLOR_SLIDER_INPUT_H_ #define _KIS_COLOR_SLIDER_INPUT_H_ #include #include "KoColorDisplayRendererInterface.h" #include "kis_canvas2.h" class KoColor; class QWidget; class QDoubleSpinBox; +class KisDoubleParseSpinBox; class KisHSVSlider; class KisDisplayColorConverter; class KisColorSliderInput : public QWidget { Q_OBJECT public: KisColorSliderInput(QWidget* parent, KoColor* color, const int type, KoColorDisplayRendererInterface *displayRenderer, KisCanvas2* canvas); protected: void init(); virtual QWidget* createInput() = 0; Q_SIGNALS: void updated(); protected: const int m_type; KoColor* m_color; KoColorDisplayRendererInterface *m_displayRenderer; KisCanvas2* m_canvas; KisHSVSlider* m_hsvSlider; }; class KisHSXColorSliderInput : public KisColorSliderInput { Q_OBJECT public: KisHSXColorSliderInput(QWidget* parent, const int type, KoColor* color, KoColorDisplayRendererInterface *displayRenderer, KisCanvas2* canvas); KisDisplayColorConverter* converter() const; protected: virtual QWidget* createInput(); KisCanvas2* m_canvas; public Q_SLOTS: void setValue(double); void update(); void hueUpdate(int h); void satUpdate(int s, int type); void toneUpdate(int l, int type); void sliderChanged(int i); void sliderIn(); void sliderOut(); void numInputChanged(double v); Q_SIGNALS: void hueUpdated(int); void satUpdated(int, int); void toneUpdated(int, int); private: - QDoubleSpinBox* m_NumInput; + KisDoubleParseSpinBox* m_NumInput; qreal m_hue; qreal m_sat; qreal m_val; qreal R, G, B, Gamma; bool m_hueupdating; bool m_satupdating; bool m_toneupdating; bool m_sliderisupdating; }; #endif diff --git a/plugins/dockers/griddocker/grid_config_widget.cpp b/plugins/dockers/griddocker/grid_config_widget.cpp index 208685428f..49cece4bb2 100644 --- a/plugins/dockers/griddocker/grid_config_widget.cpp +++ b/plugins/dockers/griddocker/grid_config_widget.cpp @@ -1,237 +1,238 @@ /* * Copyright (c) 2016 Dmitry Kazakov * * This library is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; version 2.1 of the License. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser 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 "grid_config_widget.h" #include "ui_grid_config_widget.h" #include "kis_grid_config.h" #include "kis_guides_config.h" #include "kis_debug.h" #include "kis_aspect_ratio_locker.h" +#include "kis_int_parse_spin_box.h" struct GridConfigWidget::Private { Private() : guiSignalsBlocked(false) {} KisGridConfig gridConfig; KisGuidesConfig guidesConfig; bool guiSignalsBlocked; }; GridConfigWidget::GridConfigWidget(QWidget *parent) : QWidget(parent), ui(new Ui::GridConfigWidget), m_d(new Private) { ui->setupUi(this); ui->colorMain->setAlphaChannelEnabled(true); ui->colorSubdivision->setAlphaChannelEnabled(true); ui->colorGuides->setAlphaChannelEnabled(true); setGridConfig(m_d->gridConfig); setGuidesConfig(m_d->guidesConfig); connect(ui->chkOffset, SIGNAL(toggled(bool)), ui->lblXOffset, SLOT(setVisible(bool))); connect(ui->chkOffset, SIGNAL(toggled(bool)), ui->lblYOffset, SLOT(setVisible(bool))); connect(ui->chkOffset, SIGNAL(toggled(bool)), ui->intXOffset, SLOT(setVisible(bool))); connect(ui->chkOffset, SIGNAL(toggled(bool)), ui->intYOffset, SLOT(setVisible(bool))); connect(ui->chkOffset, SIGNAL(toggled(bool)), ui->offsetAspectButton, SLOT(setVisible(bool))); ui->lblXOffset->setVisible(false); ui->lblYOffset->setVisible(false); ui->intXOffset->setVisible(false); ui->intYOffset->setVisible(false); ui->offsetAspectButton->setVisible(false); connect(ui->chkShowGrid, SIGNAL(stateChanged(int)), SLOT(slotGridGuiChanged())); connect(ui->chkSnapToGrid, SIGNAL(stateChanged(int)), SLOT(slotGridGuiChanged())); connect(ui->chkShowGuides, SIGNAL(stateChanged(int)), SLOT(slotGuidesGuiChanged())); connect(ui->chkSnapToGuides, SIGNAL(stateChanged(int)), SLOT(slotGuidesGuiChanged())); connect(ui->chkLockGuides, SIGNAL(stateChanged(int)), SLOT(slotGuidesGuiChanged())); connect(ui->intSubdivision, SIGNAL(valueChanged(int)), SLOT(slotGridGuiChanged())); connect(ui->selectMainStyle, SIGNAL(currentIndexChanged(int)), SLOT(slotGridGuiChanged())); connect(ui->colorMain, SIGNAL(changed(const QColor&)), SLOT(slotGridGuiChanged())); connect(ui->selectSubdivisionStyle, SIGNAL(currentIndexChanged(int)), SLOT(slotGridGuiChanged())); connect(ui->colorSubdivision, SIGNAL(changed(const QColor&)), SLOT(slotGridGuiChanged())); connect(ui->selectGuidesStyle, SIGNAL(currentIndexChanged(int)), SLOT(slotGuidesGuiChanged())); connect(ui->colorGuides, SIGNAL(changed(const QColor&)), SLOT(slotGuidesGuiChanged())); ui->chkOffset->setChecked(false); KisAspectRatioLocker *offsetLocker = new KisAspectRatioLocker(this); offsetLocker->connectSpinBoxes(ui->intXOffset, ui->intYOffset, ui->offsetAspectButton); KisAspectRatioLocker *spacingLocker = new KisAspectRatioLocker(this); spacingLocker->connectSpinBoxes(ui->intHSpacing, ui->intVSpacing, ui->spacingAspectButton); connect(offsetLocker, SIGNAL(sliderValueChanged()), SLOT(slotGridGuiChanged())); connect(offsetLocker, SIGNAL(aspectButtonChanged()), SLOT(slotGridGuiChanged())); connect(spacingLocker, SIGNAL(sliderValueChanged()), SLOT(slotGridGuiChanged())); connect(spacingLocker, SIGNAL(aspectButtonChanged()), SLOT(slotGridGuiChanged())); } GridConfigWidget::~GridConfigWidget() { delete ui; } void GridConfigWidget::setGridConfig(const KisGridConfig &value) { KisGridConfig currentConfig = fetchGuiGridConfig(); if (currentConfig == value) return; setGridConfigImpl(value); } void GridConfigWidget::setGuidesConfig(const KisGuidesConfig &value) { KisGuidesConfig currentConfig = fetchGuiGuidesConfig(); if (currentConfig == value) return; setGuidesConfigImpl(value); } void GridConfigWidget::setGridConfigImpl(const KisGridConfig &value) { m_d->gridConfig = value; m_d->guiSignalsBlocked = true; ui->offsetAspectButton->setKeepAspectRatio(m_d->gridConfig.offsetAspectLocked()); ui->spacingAspectButton->setKeepAspectRatio(m_d->gridConfig.spacingAspectLocked()); ui->chkShowGrid->setChecked(m_d->gridConfig.showGrid()); ui->chkSnapToGrid->setChecked(m_d->gridConfig.snapToGrid()); ui->intHSpacing->setValue(m_d->gridConfig.spacing().x()); ui->intVSpacing->setValue(m_d->gridConfig.spacing().y()); ui->intXOffset->setValue(m_d->gridConfig.offset().x()); ui->intYOffset->setValue(m_d->gridConfig.offset().y()); ui->intSubdivision->setValue(m_d->gridConfig.subdivision()); ui->selectMainStyle->setCurrentIndex(int(m_d->gridConfig.lineTypeMain())); ui->selectSubdivisionStyle->setCurrentIndex(int(m_d->gridConfig.lineTypeSubdivision())); ui->colorMain->setColor(m_d->gridConfig.colorMain()); ui->colorSubdivision->setColor(m_d->gridConfig.colorSubdivision()); m_d->guiSignalsBlocked = false; emit gridValueChanged(); } void GridConfigWidget::setGuidesConfigImpl(const KisGuidesConfig &value) { m_d->guidesConfig = value; m_d->guiSignalsBlocked = true; ui->chkShowGuides->setChecked(m_d->guidesConfig.showGuides()); ui->chkSnapToGuides->setChecked(m_d->guidesConfig.snapToGuides()); ui->chkLockGuides->setChecked(m_d->guidesConfig.lockGuides()); ui->selectGuidesStyle->setCurrentIndex(int(m_d->guidesConfig.guidesLineType())); ui->colorGuides->setColor(m_d->guidesConfig.guidesColor()); m_d->guiSignalsBlocked = false; emit guidesValueChanged(); } KisGridConfig GridConfigWidget::gridConfig() const { return m_d->gridConfig; } KisGuidesConfig GridConfigWidget::guidesConfig() const { return m_d->guidesConfig; } void GridConfigWidget::setGridDivision(int w, int h) { ui->intHSpacing->setMaximum(w); ui->intVSpacing->setMaximum(h); } KisGridConfig GridConfigWidget::fetchGuiGridConfig() const { KisGridConfig config; config.setShowGrid(ui->chkShowGrid->isChecked()); config.setSnapToGrid(ui->chkSnapToGrid->isChecked()); QPoint pt; pt.rx() = ui->intHSpacing->value(); pt.ry() = ui->intVSpacing->value(); config.setSpacing(pt); pt.rx() = ui->intXOffset->value(); pt.ry() = ui->intYOffset->value(); config.setOffset(pt); config.setSubdivision(ui->intSubdivision->value()); config.setOffsetAspectLocked(ui->offsetAspectButton->keepAspectRatio()); config.setSpacingAspectLocked(ui->spacingAspectButton->keepAspectRatio()); config.setLineTypeMain(KisGridConfig::LineTypeInternal(ui->selectMainStyle->currentIndex())); config.setLineTypeSubdivision(KisGridConfig::LineTypeInternal(ui->selectSubdivisionStyle->currentIndex())); config.setColorMain(ui->colorMain->color()); config.setColorSubdivision(ui->colorSubdivision->color()); return config; } KisGuidesConfig GridConfigWidget::fetchGuiGuidesConfig() const { KisGuidesConfig config = m_d->guidesConfig; config.setShowGuides(ui->chkShowGuides->isChecked()); config.setSnapToGuides(ui->chkSnapToGuides->isChecked()); config.setLockGuides(ui->chkLockGuides->isChecked()); config.setGuidesLineType(KisGuidesConfig::LineTypeInternal(ui->selectGuidesStyle->currentIndex())); config.setGuidesColor(ui->colorGuides->color()); return config; } void GridConfigWidget::slotGridGuiChanged() { if (m_d->guiSignalsBlocked) return; KisGridConfig currentConfig = fetchGuiGridConfig(); if (currentConfig == m_d->gridConfig) return; setGridConfigImpl(currentConfig); } void GridConfigWidget::slotGuidesGuiChanged() { if (m_d->guiSignalsBlocked) return; KisGuidesConfig currentConfig = fetchGuiGuidesConfig(); if (currentConfig == m_d->guidesConfig) return; setGuidesConfigImpl(currentConfig); } diff --git a/plugins/dockers/griddocker/grid_config_widget.ui b/plugins/dockers/griddocker/grid_config_widget.ui index ede7f471c1..e1c884d440 100644 --- a/plugins/dockers/griddocker/grid_config_widget.ui +++ b/plugins/dockers/griddocker/grid_config_widget.ui @@ -1,493 +1,499 @@ GridConfigWidget 0 0 441 342 30 0 187 280 0 Grid Show grid Snap to grid X spacing: - + px 1 500 10 Y spacing: - + px 1 500 10 Subdivision: - + 1 10 2 Grid Offset false X offset: - + px 500 0 Y offset: - + px 500 0 Main Style: Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter 0 Lines Dashed Dots 0 0 30 0 0 0 0 0 0 0 Div Style: Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter 1 Lines Dashed Dots 0 0 30 0 0 0 0 0 0 0 Qt::Vertical 20 13 Guides Show guides Snap to guides Lock guides 0 0 Guides: Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter 0 Lines Dashed Dots 0 0 30 0 0 0 0 0 0 0 Qt::Vertical 20 40 + + KoAspectButton + QWidget +
KoAspectButton.h
+ 1 +
+ + KisIntParseSpinBox + QSpinBox +
kis_int_parse_spin_box.h
+
KColorButton QPushButton
kcolorbutton.h
+ 1
KComboBox QComboBox
kcombobox.h
- - KoAspectButton - QWidget -
KoAspectButton.h
- 1 -
diff --git a/plugins/dockers/historydocker/KisUndoView.cpp b/plugins/dockers/historydocker/KisUndoView.cpp index d7d352726d..defbf500e8 100644 --- a/plugins/dockers/historydocker/KisUndoView.cpp +++ b/plugins/dockers/historydocker/KisUndoView.cpp @@ -1,391 +1,392 @@ /* This file is part of the KDE project * Copyright (C) 2010 Matus Talcik * * 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. */ /**************************************************************************** ** ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). ** All rights reserved. ** Contact: Nokia Corporation (qt-info@nokia.com) ** ** This file is part of the QtGui module of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL$ ** No Commercial Usage ** This file contains pre-release code and may not be distributed. ** You may use this file in accordance with the terms and conditions ** contained in the Technology Preview License Agreement accompanying ** this package. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 2.1 requirements ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, Nokia gives you certain additional ** rights. These rights are described in the Nokia Qt LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ** If you have questions regarding the use of this file, please contact ** Nokia at qt-info@nokia.com. ** ** ** ** ** ** ** ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include #include "KisUndoView.h" #include "KisUndoModel.h" #ifndef QT_NO_UNDOVIEW #include #include #include #include #include #include #include #include #include #include - +#include "kis_double_parse_spin_box.h" +#include "kis_int_parse_spin_box.h" /*! \class KisUndoView \brief The KisUndoView class displays the contents of a KUndo2QStack. \since 4.2 \ingroup advanced KisUndoView is a QListView which displays the list of commands pushed on an undo stack. The most recently executed command is always selected. Selecting a different command results in a call to KUndo2QStack::setIndex(), rolling the state of the document backwards or forward to the new command. The stack can be set explicitly with setStack(). Alternatively, a KUndo2Group object can be set with setGroup(). The view will then update itself automatically whenever the active stack of the group changes. \image KisUndoView.png */ class KisUndoViewPrivate { public: KisUndoViewPrivate() : #ifndef QT_NO_UNDOGROUP group(0), #endif model(0) {} #ifndef QT_NO_UNDOGROUP QPointer group; #endif KisUndoModel *model; KisUndoView* q; void init(KisUndoView* view); }; void KisUndoViewPrivate::init(KisUndoView* view) { q = view; model = new KisUndoModel(q); q->setModel(model); q->setSelectionModel(model->selectionModel()); } /*! Constructs a new view with parent \a parent. */ KisUndoView::KisUndoView(QWidget *parent) : QListView(parent) , d(new KisUndoViewPrivate) { d->init(this); } /*! Constructs a new view with parent \a parent and sets the observed stack to \a stack. */ KisUndoView::KisUndoView(KUndo2QStack *stack, QWidget *parent) : QListView(parent) , d(new KisUndoViewPrivate) { d->init(this); setStack(stack); } #ifndef QT_NO_UNDOGROUP /*! Constructs a new view with parent \a parent and sets the observed group to \a group. The view will update itself automatically whenever the active stack of the group changes. */ KisUndoView::KisUndoView(KUndo2Group *group, QWidget *parent) : QListView(parent) , d(new KisUndoViewPrivate) { d->init(this); setGroup(group); } #endif // QT_NO_UNDOGROUP /*! Destroys this view. */ KisUndoView::~KisUndoView() { delete d; } /*! Returns the stack currently displayed by this view. If the view is looking at a KUndo2Group, this the group's active stack. \sa setStack() setGroup() */ KUndo2QStack *KisUndoView::stack() const { return d->model->stack(); } /*! Sets the stack displayed by this view to \a stack. If \a stack is 0, the view will be empty. If the view was previously looking at a KUndo2Group, the group is set to 0. \sa stack() setGroup() */ void KisUndoView::setStack(KUndo2QStack *stack) { #ifndef QT_NO_UNDOGROUP setGroup(0); #endif d->model->setStack(stack); } #ifndef QT_NO_UNDOGROUP /*! Sets the group displayed by this view to \a group. If \a group is 0, the view will be empty. The view will update itself autmiatically whenever the active stack of the group changes. \sa group() setStack() */ void KisUndoView::setGroup(KUndo2Group *group) { if (d->group == group) return; if (d->group != 0) { disconnect(d->group, SIGNAL(activeStackChanged(KUndo2QStack*)), d->model, SLOT(setStack(KUndo2QStack*))); } d->group = group; if (d->group != 0) { connect(d->group, SIGNAL(activeStackChanged(KUndo2QStack*)), d->model, SLOT(setStack(KUndo2QStack*))); d->model->setStack(d->group->activeStack()); } else { d->model->setStack(0); } } /*! Returns the group displayed by this view. If the view is not looking at group, this function returns 0. \sa setGroup() setStack() */ KUndo2Group *KisUndoView::group() const { return d->group; } #endif // QT_NO_UNDOGROUP /*! \property KisUndoView::emptyLabel \brief the label used for the empty state. The empty label is the topmost element in the list of commands, which represents the state of the document before any commands were pushed on the stack. The default is the string "". */ void KisUndoView::setEmptyLabel(const QString &label) { d->model->setEmptyLabel(label); } QString KisUndoView::emptyLabel() const { return d->model->emptyLabel(); } /*! \property KisUndoView::cleanIcon \brief the icon used to represent the clean state. A stack may have a clean state set with KUndo2QStack::setClean(). This is usually the state of the document at the point it was saved. KisUndoView can display an icon in the list of commands to show the clean state. If this property is a null icon, no icon is shown. The default value is the null icon. */ void KisUndoView::setCleanIcon(const QIcon &icon) { d->model->setCleanIcon(icon); } QIcon KisUndoView::cleanIcon() const { return d->model->cleanIcon(); } void KisUndoView::setCanvas(KisCanvas2 *canvas) { d->model->setCanvas(canvas); } void KisUndoView::mousePressEvent(QMouseEvent *event) { if (event->button() == Qt::RightButton) { QMenu menu(this); QAction* action1 = menu.addAction(KisIconUtils::loadIcon("link"),stack()->useCumulativeUndoRedo()?i18n("Disable Cumulative Undo"):i18n("Enable Cumulative Undo")); connect(action1, SIGNAL(triggered()), this, SLOT(toggleCumulativeUndoRedo())); QLabel *l = new QLabel(i18n("Start merging time")); - QDoubleSpinBox *s = new QDoubleSpinBox(); + QDoubleSpinBox *s = new KisDoubleParseSpinBox(); s->setToolTip(i18nc("@info:tooltip", "The amount of time after a merged stroke before merging again")); s->setRange(3,10); s->setValue(stack()->timeT1()); QGridLayout *g = new QGridLayout(); g->addWidget(l); g->addWidget(s); QWidget *w = new QWidget(); w->setLayout(g); w->setVisible(stack()->useCumulativeUndoRedo()); QWidgetAction* action2 = new QWidgetAction(s); action2->setDefaultWidget(w); connect(s,SIGNAL(valueChanged(double)),SLOT(setStackT1(double))); QLabel *l1 = new QLabel(i18n("Group time")); - QDoubleSpinBox *s1 = new QDoubleSpinBox(); + QDoubleSpinBox *s1 = new KisDoubleParseSpinBox(); s1->setToolTip(i18nc("@info:tooltip", "The amount of time every stroke should be apart from its previous stroke to be classified in one group")); s1->setRange(0.3,s->value()); s1->setValue(stack()->timeT2()); QGridLayout *g1 = new QGridLayout(); g1->addWidget(l1); g1->addWidget(s1); QWidget *w1 = new QWidget(); w1->setLayout(g1); w1->setVisible(stack()->useCumulativeUndoRedo()); QWidgetAction* action3 = new QWidgetAction(s1); action3->setDefaultWidget(w1); connect(s1,SIGNAL(valueChanged(double)),SLOT(setStackT2(double))); QLabel *l2 = new QLabel(i18n("Split Strokes")); - QSpinBox *s2 = new QSpinBox(); + QSpinBox *s2 = new KisIntParseSpinBox(); s2->setToolTip(i18nc("@info:tooltip", "The number of last strokes which Krita should store separately")); s2->setRange(1,stack()->undoLimit()); s2->setValue(stack()->strokesN()); QGridLayout *g2 = new QGridLayout(); g1->addWidget(l2); g1->addWidget(s2); QWidget *w2 = new QWidget(); w2->setLayout(g2); w2->setVisible(stack()->useCumulativeUndoRedo()); QWidgetAction* action4 = new QWidgetAction(s2); action4->setDefaultWidget(w2); connect(s2,SIGNAL(valueChanged(int)),SLOT(setStackN(int))); menu.addAction(action2); menu.addAction(action3); menu.addAction(action4); menu.exec(event->globalPos()); } else{ QListView::mousePressEvent(event); } } void KisUndoView::toggleCumulativeUndoRedo() { stack()->setUseCumulativeUndoRedo(!stack()->useCumulativeUndoRedo() ); KisConfig cfg; cfg.setCumulativeUndoRedo(stack()->useCumulativeUndoRedo()); } void KisUndoView::setStackT1(double value) { stack()->setTimeT1(value); KisConfig cfg; cfg.setStackT1(value); } void KisUndoView::setStackT2(double value) { stack()->setTimeT2(value); KisConfig cfg; cfg.setStackT2(value); } void KisUndoView::setStackN(int value) { stack()->setStrokesN(value); KisConfig cfg; cfg.setStackN(value); } #endif // QT_NO_UNDOVIEW diff --git a/plugins/dockers/specificcolorselector/kis_color_input.cc b/plugins/dockers/specificcolorselector/kis_color_input.cc index ff4a7d67b3..092941b8a8 100644 --- a/plugins/dockers/specificcolorselector/kis_color_input.cc +++ b/plugins/dockers/specificcolorselector/kis_color_input.cc @@ -1,299 +1,305 @@ /* * Copyright (c) 2008 Cyrille Berger * Copyright (c) 2011 Sven Langkamp * Copyright (c) 2015 Moritz Molch * * This library is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; version 2.1 of the License. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser 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_color_input.h" #include #ifdef HAVE_OPENEXR #include #endif #include #include #include #include #include #include #include #include #include #include #include #include +#include "kis_double_parse_spin_box.h" +#include "kis_int_parse_spin_box.h" + KisColorInput::KisColorInput(QWidget* parent, const KoChannelInfo* channelInfo, KoColor* color, KoColorDisplayRendererInterface *displayRenderer) : QWidget(parent), m_channelInfo(channelInfo), m_color(color), m_displayRenderer(displayRenderer) { } void KisColorInput::init() { QHBoxLayout* m_layout = new QHBoxLayout(this); m_layout->setContentsMargins(0,0,0,0); m_layout->setSpacing(1); QLabel* m_label = new QLabel(i18n("%1:", m_channelInfo->name()), this); m_layout->addWidget(m_label); m_colorSlider = new KoColorSlider(Qt::Horizontal, this, m_displayRenderer); m_colorSlider->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed); m_layout->addWidget(m_colorSlider); QWidget* m_input = createInput(); m_colorSlider->setFixedHeight(m_input->sizeHint().height()); m_layout->addWidget(m_input); } KisIntegerColorInput::KisIntegerColorInput(QWidget* parent, const KoChannelInfo* channelInfo, KoColor* color, KoColorDisplayRendererInterface *displayRenderer) : KisColorInput(parent, channelInfo, color, displayRenderer) { init(); } void KisIntegerColorInput::setValue(int v) { quint8* data = m_color->data() + m_channelInfo->pos(); switch (m_channelInfo->channelValueType()) { case KoChannelInfo::UINT8: *(reinterpret_cast(data)) = v; break; case KoChannelInfo::UINT16: *(reinterpret_cast(data)) = v; break; case KoChannelInfo::UINT32: *(reinterpret_cast(data)) = v; break; default: Q_ASSERT(false); } emit(updated()); } void KisIntegerColorInput::update() { KoColor min = *m_color; KoColor max = *m_color; quint8* data = m_color->data() + m_channelInfo->pos(); quint8* dataMin = min.data() + m_channelInfo->pos(); quint8* dataMax = max.data() + m_channelInfo->pos(); switch (m_channelInfo->channelValueType()) { case KoChannelInfo::UINT8: m_intNumInput->setValue(*(reinterpret_cast(data))); m_colorSlider->setValue(*(reinterpret_cast(data))); *(reinterpret_cast(dataMin)) = 0x0; *(reinterpret_cast(dataMax)) = 0xFF; break; case KoChannelInfo::UINT16: m_intNumInput->setValue(*(reinterpret_cast(data))); m_colorSlider->setValue(*(reinterpret_cast(data))); *(reinterpret_cast(dataMin)) = 0x0; *(reinterpret_cast(dataMax)) = 0xFFFF; break; case KoChannelInfo::UINT32: m_intNumInput->setValue(*(reinterpret_cast(data))); m_colorSlider->setValue(*(reinterpret_cast(data))); *(reinterpret_cast(dataMin)) = 0x0; *(reinterpret_cast(dataMax)) = 0xFFFFFFFF; break; default: Q_ASSERT(false); } m_colorSlider->setColors(min, max); } QWidget* KisIntegerColorInput::createInput() { - m_intNumInput = new QSpinBox(this); + m_intNumInput = new KisIntParseSpinBox(this); m_intNumInput->setMinimum(0); - m_colorSlider->setMaximum(0); + m_colorSlider->setMinimum(0); switch (m_channelInfo->channelValueType()) { case KoChannelInfo::UINT8: m_intNumInput->setMaximum(0xFF); m_colorSlider->setMaximum(0xFF); break; case KoChannelInfo::UINT16: m_intNumInput->setMaximum(0xFFFF); m_colorSlider->setMaximum(0xFFFF); break; case KoChannelInfo::UINT32: m_intNumInput->setMaximum(0xFFFFFFFF); m_colorSlider->setMaximum(0xFFFFFFFF); break; default: Q_ASSERT(false); } connect(m_colorSlider, SIGNAL(valueChanged(int)), m_intNumInput, SLOT(setValue(int))); connect(m_intNumInput, SIGNAL(valueChanged(int)), this, SLOT(setValue(int))); return m_intNumInput; } KisFloatColorInput::KisFloatColorInput(QWidget* parent, const KoChannelInfo* channelInfo, KoColor* color, KoColorDisplayRendererInterface *displayRenderer) : KisColorInput(parent, channelInfo, color, displayRenderer) { init(); } void KisFloatColorInput::setValue(double v) { quint8* data = m_color->data() + m_channelInfo->pos(); switch (m_channelInfo->channelValueType()) { #ifdef HAVE_OPENEXR case KoChannelInfo::FLOAT16: *(reinterpret_cast(data)) = v; break; #endif case KoChannelInfo::FLOAT32: *(reinterpret_cast(data)) = v; break; default: Q_ASSERT(false); } emit(updated()); } QWidget* KisFloatColorInput::createInput() { - m_dblNumInput = new QDoubleSpinBox(this); + m_dblNumInput = new KisDoubleParseSpinBox(this); m_dblNumInput->setMinimum(0); m_dblNumInput->setMaximum(1.0); connect(m_colorSlider, SIGNAL(valueChanged(int)), this, SLOT(sliderChanged(int))); connect(m_dblNumInput, SIGNAL(valueChanged(double)), this, SLOT(setValue(double))); + m_dblNumInput->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Preferred); + m_dblNumInput->setMinimumWidth(60); + m_dblNumInput->setMaximumWidth(60); return m_dblNumInput; } void KisFloatColorInput::sliderChanged(int i) { const qreal floatRange = m_maxValue - m_minValue; m_dblNumInput->setValue(m_minValue + (i / 255.0) * floatRange); } void KisFloatColorInput::update() { KoColor min = *m_color; KoColor max = *m_color; quint8* data = m_color->data() + m_channelInfo->pos(); quint8* dataMin = min.data() + m_channelInfo->pos(); quint8* dataMax = max.data() + m_channelInfo->pos(); qreal value = 1.0; m_minValue = m_displayRenderer->minVisibleFloatValue(m_channelInfo); m_maxValue = m_displayRenderer->maxVisibleFloatValue(m_channelInfo); switch (m_channelInfo->channelValueType()) { #ifdef HAVE_OPENEXR case KoChannelInfo::FLOAT16: value = *(reinterpret_cast(data)); m_minValue = qMin(value, m_minValue); m_maxValue = qMax(value, m_maxValue); *(reinterpret_cast(dataMin)) = m_minValue; *(reinterpret_cast(dataMax)) = m_maxValue; break; #endif case KoChannelInfo::FLOAT32: value = *(reinterpret_cast(data)); m_minValue = qMin(value, m_minValue); m_maxValue = qMax(value, m_maxValue); *(reinterpret_cast(dataMin)) = m_minValue; *(reinterpret_cast(dataMax)) = m_maxValue; break; default: Q_ASSERT(false); } m_dblNumInput->setMinimum(m_minValue); m_dblNumInput->setMaximum(m_maxValue); // ensure at least 3 significant digits are always shown int newPrecision = 2 + qMax(qreal(0.0), std::ceil(-std::log10(m_maxValue))); if (newPrecision != m_dblNumInput->decimals()) { m_dblNumInput->setDecimals(newPrecision); m_dblNumInput->updateGeometry(); } m_colorSlider->setColors(min, max); const qreal floatRange = m_maxValue - m_minValue; m_dblNumInput->setValue(value); m_colorSlider->setValue((value - m_minValue) / floatRange * 255); } KisHexColorInput::KisHexColorInput(QWidget* parent, KoColor* color, KoColorDisplayRendererInterface *displayRenderer) : KisColorInput(parent, 0, color, displayRenderer) { QHBoxLayout* m_layout = new QHBoxLayout(this); m_layout->setContentsMargins(0,0,0,0); m_layout->setSpacing(1); QLabel* m_label = new QLabel(i18n("Color name:"), this); m_label->setMinimumWidth(50); m_layout->addWidget(m_label); QWidget* m_input = createInput(); m_input->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Preferred); m_layout->addWidget(m_input); } void KisHexColorInput::setValue() { QString valueString = m_hexInput->text(); valueString.remove(QChar('#')); QList channels = m_color->colorSpace()->channels(); channels = KoChannelInfo::displayOrderSorted(channels); Q_FOREACH (KoChannelInfo* channel, channels) { if (channel->channelType() == KoChannelInfo::COLOR) { Q_ASSERT(channel->channelValueType() == KoChannelInfo::UINT8); quint8* data = m_color->data() + channel->pos(); int value = valueString.left(2).toInt(0, 16); *(reinterpret_cast(data)) = value; valueString.remove(0, 2); } } emit(updated()); } void KisHexColorInput::update() { QString hexString("#"); QList channels = m_color->colorSpace()->channels(); channels = KoChannelInfo::displayOrderSorted(channels); Q_FOREACH (KoChannelInfo* channel, channels) { if (channel->channelType() == KoChannelInfo::COLOR) { Q_ASSERT(channel->channelValueType() == KoChannelInfo::UINT8); quint8* data = m_color->data() + channel->pos(); hexString.append(QString("%1").arg(*(reinterpret_cast(data)), 2, 16, QChar('0'))); } } m_hexInput->setText(hexString); } QWidget* KisHexColorInput::createInput() { m_hexInput = new QLineEdit(this); int digits = 2*m_color->colorSpace()->colorChannelCount(); QString pattern = QString("#?[a-fA-F0-9]{%1,%2}").arg(digits).arg(digits); m_hexInput->setValidator(new QRegExpValidator(QRegExp(pattern), this)); connect(m_hexInput, SIGNAL(editingFinished()), this, SLOT(setValue())); return m_hexInput; } diff --git a/plugins/dockers/specificcolorselector/kis_color_input.h b/plugins/dockers/specificcolorselector/kis_color_input.h index 9016cb75c9..45a3267c46 100644 --- a/plugins/dockers/specificcolorselector/kis_color_input.h +++ b/plugins/dockers/specificcolorselector/kis_color_input.h @@ -1,96 +1,98 @@ /* * Copyright (c) 2008 Cyrille Berger * * This library is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; version 2.1 of the License. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser 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_COLOR_INPUT_H_ #define _KIS_COLOR_INPUT_H_ #include class KoChannelInfo; class KoColor; class QWidget; class QSpinBox; class QDoubleSpinBox; +class KisIntParseSpinBox; +class KisDoubleParseSpinBox; class KoColorSlider; class QLineEdit; #include "KoColorDisplayRendererInterface.h" class KisColorInput : public QWidget { Q_OBJECT public: KisColorInput(QWidget* parent, const KoChannelInfo*, KoColor* color, KoColorDisplayRendererInterface *displayRenderer); protected: void init(); virtual QWidget* createInput() = 0; Q_SIGNALS: void updated(); protected: const KoChannelInfo* m_channelInfo; KoColor* m_color; KoColorSlider* m_colorSlider; KoColorDisplayRendererInterface *m_displayRenderer; }; class KisIntegerColorInput : public KisColorInput { Q_OBJECT public: KisIntegerColorInput(QWidget* parent, const KoChannelInfo*, KoColor* color, KoColorDisplayRendererInterface *displayRenderer); protected: virtual QWidget* createInput(); public Q_SLOTS: void setValue(int); void update(); private: - QSpinBox* m_intNumInput; + KisIntParseSpinBox* m_intNumInput; }; class KisFloatColorInput : public KisColorInput { Q_OBJECT public: KisFloatColorInput(QWidget* parent, const KoChannelInfo*, KoColor* color, KoColorDisplayRendererInterface *displayRenderer); protected: virtual QWidget* createInput(); public Q_SLOTS: void setValue(double); void sliderChanged(int); void update(); private: - QDoubleSpinBox* m_dblNumInput; + KisDoubleParseSpinBox* m_dblNumInput; qreal m_minValue; qreal m_maxValue; }; class KisHexColorInput : public KisColorInput { Q_OBJECT public: KisHexColorInput(QWidget* parent, KoColor* color, KoColorDisplayRendererInterface *displayRenderer); protected: virtual QWidget* createInput(); public Q_SLOTS: void setValue(); void update(); private: QLineEdit* m_hexInput; }; #endif diff --git a/plugins/extensions/clonesarray/wdg_clonesarray.ui b/plugins/extensions/clonesarray/wdg_clonesarray.ui index 9e70f6d5d2..a932096279 100644 --- a/plugins/extensions/clonesarray/wdg_clonesarray.ui +++ b/plugins/extensions/clonesarray/wdg_clonesarray.ui @@ -1,368 +1,380 @@ WdgClonesArray 0 0 - 644 + 710 174 Rotate Image 0 0 - Elements Qt::AlignCenter 0 0 + Elements Qt::AlignCenter 0 0 X offset Qt::AlignCenter 0 0 Y offset Qt::AlignCenter 0 0 Distance Qt::AlignCenter 0 0 Angle Qt::AlignCenter Columns: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter Qt::Horizontal QSizePolicy::MinimumExpanding 13 20 - + - + 1 2 Qt::Horizontal QSizePolicy::MinimumExpanding 13 17 - + px -10000 10000 - + px -10000 10000 Qt::Horizontal QSizePolicy::MinimumExpanding 13 20 Rows: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - + - + 1 2 - + px -10000 10000 - + px -10000 10000 - + ° -360.000000000000000 360.000000000000000 - + ° -360.000000000000000 360.000000000000000 - + px 10000.000000000000000 - + px 10000.000000000000000 Column Preference Qt::Horizontal 40 20 Qt::Vertical QSizePolicy::MinimumExpanding 20 28 + + + KisIntParseSpinBox + QSpinBox +
kis_int_parse_spin_box.h
+
+ + KisDoubleParseSpinBox + QDoubleSpinBox +
kis_double_parse_spin_box.h
+
+
numNegativeColumns numNegativeRows numPositiveColumns numPositiveRows columnXOffset rowXOffset columnYOffset rowYOffset columnDistance rowDistance columnAngle rowAngle columnPreference
diff --git a/plugins/extensions/imagesize/wdg_canvassize.ui b/plugins/extensions/imagesize/wdg_canvassize.ui index 9628325bc2..858140b589 100644 --- a/plugins/extensions/imagesize/wdg_canvassize.ui +++ b/plugins/extensions/imagesize/wdg_canvassize.ui @@ -1,682 +1,692 @@ WdgCanvasSize 0 0 - 367 - 380 + 395 + 387 Canvas Size New Size true - + 1 100000 Height: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - + - + 1 100000 Width: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - + 4 0.000100000000000 10000.000000000000000 0.100000000000000 - + 4 0.000100000000000 10000.000000000000000 0.100000000000000 Qt::Horizontal QSizePolicy::Fixed 25 20 Qt::Horizontal QSizePolicy::MinimumExpanding 40 20 Constrain aspect ratio Constrain proportions true Offset true Qt::Vertical QSizePolicy::MinimumExpanding 20 30 Qt::Vertical QSizePolicy::Fixed 20 16 X: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - + -100000 100000 - + 4 -10000.000000000000000 10000.000000000000000 0.100000000000000 Qt::Horizontal QSizePolicy::Fixed 25 20 Anchor: Qt::AlignRight|Qt::AlignTop|Qt::AlignTrailing Y: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - + -100000 100000 - + 4 -10000.000000000000000 10000.000000000000000 0.100000000000000 0 0 0 0 QFrame::StyledPanel QFrame::Sunken 2 2 2 2 - + 0 0 0 25 25 15 15 true 0 0 25 25 15 15 true 0 0 25 25 15 15 true 0 0 25 25 15 15 true 0 0 25 25 15 15 true 0 0 25 25 15 15 true 0 0 25 25 15 15 true 0 0 25 25 15 15 true false 0 0 25 25 15 15 true Qt::Horizontal QSizePolicy::Maximum 16 20 Qt::Horizontal QSizePolicy::MinimumExpanding 40 20 KoAspectButton QWidget
KoAspectButton.h
1
KCanvasPreview QWidget
kcanvaspreview.h
1
+ + KisDoubleParseSpinBox + QDoubleSpinBox +
kis_double_parse_spin_box.h
+
+ + KisIntParseSpinBox + QSpinBox +
kis_int_parse_spin_box.h
+
newWidth newWidthDouble widthUnit newHeight newHeightDouble heightUnit constrainProportionsCkb xOffset xOffsetDouble xOffUnit yOffset yOffsetDouble yOffUnit topLeft topCenter topRight middleLeft middleCenter middleRight bottomLeft bottomCenter bottomRight
diff --git a/plugins/extensions/imagesize/wdg_imagesize.ui b/plugins/extensions/imagesize/wdg_imagesize.ui index 072f3f71b5..8a45fdf251 100644 --- a/plugins/extensions/imagesize/wdg_imagesize.ui +++ b/plugins/extensions/imagesize/wdg_imagesize.ui @@ -1,437 +1,447 @@ WdgImageSize 0 0 - 372 - 379 + 391 + 386 Scale To New Size Pixel Dimensions true - + 80 0 4 0.000100000000000 10000.000000000000000 0.100000000000000 - + 80 0 1 100000 Qt::Horizontal QSizePolicy::Fixed 25 20 - Width: + W&idth: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter pixelWidth - Filter: + &Filter: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter printWidth - + - Height: + &Height: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter pixelHeight - + 80 0 4 0.000100000000000 10000.000000000000000 0.100000000000000 - + 1 100000 Qt::Horizontal QSizePolicy::MinimumExpanding 40 20 - + Print Size true - Height: + Hei&ght: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter printHeight - + 80 0 4 0.000100000000000 10000.000000000000000 0.100000000000000 - Width: + Wid&th: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter printWidth - + 80 0 4 0.000100000000000 10000.000000000000000 0.100000000000000 - + Resolution: - + 0 0 70 0 4 0.000100000000000 10000.000000000000000 0.100000000000000 Qt::Horizontal QSizePolicy::Fixed 25 20 Qt::Horizontal QSizePolicy::MinimumExpanding 40 20 Qt::Vertical QSizePolicy::Fixed 20 16 Constrain aspect ratio Constrain proportions true Adjust print size separately Qt::Vertical QSizePolicy::MinimumExpanding 20 30 KisCmbIDList
widgets/kis_cmb_idlist.h
KoAspectButton QWidget
KoAspectButton.h
1
+ + KisIntParseSpinBox + QSpinBox +
kis_int_parse_spin_box.h
+
+ + KisDoubleParseSpinBox + QDoubleSpinBox +
kis_double_parse_spin_box.h
+
pixelWidth pixelWidthDouble pixelWidthUnit pixelHeight pixelHeightDouble pixelHeightUnit pixelFilterCmb printWidth printWidthUnit printHeight printHeightUnit printResolution printResolutionUnit constrainProportionsCkb adjustPrintSizeSeparatelyCkb
diff --git a/plugins/extensions/imagesize/wdg_layersize.ui b/plugins/extensions/imagesize/wdg_layersize.ui index 10e035b097..58170c58ad 100644 --- a/plugins/extensions/imagesize/wdg_layersize.ui +++ b/plugins/extensions/imagesize/wdg_layersize.ui @@ -1,238 +1,248 @@ WdgLayerSize 0 0 - 348 - 198 + 366 + 201 Layer Size New Size true - + Qt::Horizontal QSizePolicy::MinimumExpanding 40 20 - Width: + W&idth: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter newWidth - + 80 0 4 0.000100000000000 10000.000000000000000 0.100000000000000 - + 80 0 4 0.000100000000000 10000.000000000000000 0.100000000000000 - + 80 0 1 100000 - + 1 100000 - + Filter: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - Height: + &Height: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter newHeight Constrain aspect ratio Constrain proportions true Qt::Horizontal QSizePolicy::Fixed 25 20 Qt::Vertical QSizePolicy::MinimumExpanding 20 30 KisCmbIDList
widgets/kis_cmb_idlist.h
KoAspectButton QWidget
KoAspectButton.h
1
+ + KisIntParseSpinBox + QSpinBox +
kis_int_parse_spin_box.h
+
+ + KisDoubleParseSpinBox + QDoubleSpinBox +
kis_double_parse_spin_box.h
+
newWidth newWidthDouble newWidthUnit newHeight newHeightDouble newHeightUnit filterCmb
diff --git a/plugins/extensions/imagesplit/wdg_imagesplit.ui b/plugins/extensions/imagesplit/wdg_imagesplit.ui index afd3f158b7..4fd7708036 100644 --- a/plugins/extensions/imagesplit/wdg_imagesplit.ui +++ b/plugins/extensions/imagesplit/wdg_imagesplit.ui @@ -1,117 +1,124 @@ WdgImagesplit 0 0 236 194 Image Size Horizontal Lines Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - + Vertical Lines Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - + 10 Autosave on Split Prefix Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter true File Type Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter Qt::Vertical 20 38 + + + KisIntParseSpinBox + QSpinBox +
kis_int_parse_spin_box.h
+
+
diff --git a/plugins/extensions/metadataeditor/editors/exif.ui b/plugins/extensions/metadataeditor/editors/exif.ui index 646dd864e5..2f12c4579e 100644 --- a/plugins/extensions/metadataeditor/editors/exif.ui +++ b/plugins/extensions/metadataeditor/editors/exif.ui @@ -1,1102 +1,1109 @@ Exif 0 0 559 483 0 Exposure - Brightness value: + &Brightness value: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter editBrightnessValue - ISO: + &ISO: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter editISO - + 3600 100 100 - Exposure time: + Exposure &time: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter editExposureTime - Exposure mode: + E&xposure mode: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter editExposureMode Auto Manual Auto bracket - Exposure program: + Exposure pro&gram: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter editExposureProgram Not defined Manual Normal program Aperture priority Shutter priority Creative program Action program Portrait mode Landscape mode Exposure index: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter editExposureIndex Exposure bias: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter editExposureBiasValue - Aperture: + Ape&rture: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter editApertureValue Shutter speed: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter editShutterSpeedValue - F Number: + &F Number: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter editFNumber Qt::Vertical 517 51 Lens - Focal length: + &Focal length: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter editFocalLength - + 1000 1 35 - Focal length (35mm equivalent): + Focal length (&35mm equivalent): Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter editFocalLengthIn35mmFilm - + 1000 1 35 Max aperture: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter editMaxApertureValue Qt::Vertical 517 101 Autofocus - Subject distance: + Su&bject distance: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter editSubjectDistance - Metering mode: + Meterin&g mode: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter editMeteringMode Unknown Average Center weighted average Spot Multi spot Pattern Partial Other - Distance range: + D&istance range: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter editSubjectDistanceRange Unknown Macro Close view Distant view Qt::Vertical 517 151 Flash Fired - Strobe return: + Stro&be return: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter editStrobeReturn No strobe return detection Undefined No strobe return light detected Strobe return light detected Mode: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter editFlashMode Unknown Compulsory flash fired Compulsory flash suppression Auto mode Function Red-eye removal - Flash energy: + Flash ener&gy: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter editFlashEnergy Qt::Vertical 517 91 Postprocessing - Gain control: + &Gain control: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter editGainControl 1 0 None Low gain up High gain up Low gain down High gain down - Light source: + L&ight source: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter editLightSource Unknown Daylight Fluorescent Tungsten Flash Undefined Undefined Undefined Undefined Fine weather Cloudy weather Shade Daylight fluorescent (D5700 - 7100K) Day white fluorescent (N4600 - 5400K) Cool white fluorescent (W3900 - 4500K) White fluorescent (WW 3200 - 3700K) Undefined Standard light A Standard light B Standard light C D55 D65 D75 D50 ISO studio tungsten other Sharpness: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter editSharpness Normal Soft Hard Contrast: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter editContrast Normal Soft Hard - White balance: + White &balance: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter editWhiteBalance Auto Custom Qt::Vertical 517 91 Misc - Scene capture type: + Scene capture t&ype: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter editSceneCaptureType Standard Landscape Portrait Night scene - Maker: + Ma&ker: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter editMake Model: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter editModel - Sensing method type: + Sens&ing method type: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter editSensingMethod Not Defined Not Defined One-chip color area sensor Two-chip color area sensor Three-chip color area sensor Color sequential area sensor Trilinear sensor Color sequential linear sensor Qt::Vertical 517 71 + + + KisIntParseSpinBox + QSpinBox +
kis_int_parse_spin_box.h
+
+
diff --git a/plugins/extensions/modify_selection/wdg_border_selection.ui b/plugins/extensions/modify_selection/wdg_border_selection.ui index 1b7031bf89..f53f94bd8e 100644 --- a/plugins/extensions/modify_selection/wdg_border_selection.ui +++ b/plugins/extensions/modify_selection/wdg_border_selection.ui @@ -1,124 +1,136 @@ WdgBorderSelection 0 0 - 333 - 86 + 364 + 89 - + 1 100000 1 - + 4 0.000100000000000 10000.000000000000000 0.100000000000000 Qt::Vertical QSizePolicy::Fixed 20 16 Qt::Horizontal QSizePolicy::Fixed 16 20 Qt::Vertical QSizePolicy::MinimumExpanding 20 16 Qt::Horizontal QSizePolicy::MinimumExpanding 16 20 Border width: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + KisIntParseSpinBox + QSpinBox +
kis_int_parse_spin_box.h
+
+ + KisDoubleParseSpinBox + QDoubleSpinBox +
kis_double_parse_spin_box.h
+
+
diff --git a/plugins/extensions/modify_selection/wdg_feather_selection.ui b/plugins/extensions/modify_selection/wdg_feather_selection.ui index bdfc4d8f7f..57f044f5c6 100644 --- a/plugins/extensions/modify_selection/wdg_feather_selection.ui +++ b/plugins/extensions/modify_selection/wdg_feather_selection.ui @@ -1,132 +1,144 @@ WdgFeatherSelection 0 0 - 354 - 86 + 372 + 89 Feather radius: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter Qt::Vertical QSizePolicy::MinimumExpanding 20 16 Qt::Vertical QSizePolicy::Fixed 20 16 - + 1 100000 1 - + 4 0.000100000000000 10000.000000000000000 0.100000000000000 5.000000000000000 Qt::Horizontal QSizePolicy::Fixed 16 20 Qt::Horizontal QSizePolicy::MinimumExpanding 16 20 + + + KisIntParseSpinBox + QSpinBox +
kis_int_parse_spin_box.h
+
+ + KisDoubleParseSpinBox + QDoubleSpinBox +
kis_double_parse_spin_box.h
+
+
spbRadius spbRadiusDouble cmbUnit
diff --git a/plugins/extensions/modify_selection/wdg_grow_selection.ui b/plugins/extensions/modify_selection/wdg_grow_selection.ui index a8241e2573..b97777f2e3 100644 --- a/plugins/extensions/modify_selection/wdg_grow_selection.ui +++ b/plugins/extensions/modify_selection/wdg_grow_selection.ui @@ -1,129 +1,141 @@ WdgGrowSelection 0 0 - 302 - 86 + 327 + 89 Grow by Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter Qt::Vertical QSizePolicy::MinimumExpanding 20 16 Qt::Vertical QSizePolicy::Fixed 20 16 - + 1 100000 1 - + 4 0.000100000000000 10000.000000000000000 0.100000000000000 Qt::Horizontal QSizePolicy::Fixed 16 20 Qt::Horizontal QSizePolicy::MinimumExpanding 16 20 + + + KisIntParseSpinBox + QSpinBox +
kis_int_parse_spin_box.h
+
+ + KisDoubleParseSpinBox + QDoubleSpinBox +
kis_double_parse_spin_box.h
+
+
spbGrowValue spbGrowValueDouble cmbUnit
diff --git a/plugins/extensions/modify_selection/wdg_shrink_selection.ui b/plugins/extensions/modify_selection/wdg_shrink_selection.ui index 90f93f300c..b6a4707d1a 100644 --- a/plugins/extensions/modify_selection/wdg_shrink_selection.ui +++ b/plugins/extensions/modify_selection/wdg_shrink_selection.ui @@ -1,140 +1,152 @@ WdgShrinkSelection 0 0 - 308 - 113 + 334 + 117 Qt::Vertical QSizePolicy::Fixed 20 16 - + 1 100000 1 - + 4 0.000100000000000 10000.000000000000000 0.100000000000000 Shrink by Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter Qt::Horizontal QSizePolicy::Fixed 16 20 Qt::Vertical QSizePolicy::MinimumExpanding 20 16 Qt::Horizontal QSizePolicy::MinimumExpanding 16 20 Shrink from image border true + + + KisIntParseSpinBox + QSpinBox +
kis_int_parse_spin_box.h
+
+ + KisDoubleParseSpinBox + QDoubleSpinBox +
kis_double_parse_spin_box.h
+
+
spbShrinkValue spbShrinkValueDouble cmbUnit ckbShrinkFromImageBorder
diff --git a/plugins/extensions/offsetimage/wdg_offsetimage.ui b/plugins/extensions/offsetimage/wdg_offsetimage.ui index 63d99998ab..dbcf84b6bd 100644 --- a/plugins/extensions/offsetimage/wdg_offsetimage.ui +++ b/plugins/extensions/offsetimage/wdg_offsetimage.ui @@ -1,119 +1,126 @@ WdgOffsetImage 0 0 203 157 Rotate Image Offset 0 0 0 0 X: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - + px 999999999 Y: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - + px 999999999 0 0 Offset by x/2, y/2 Qt::Vertical QSizePolicy::Minimum 0 0 + + + KisIntParseSpinBox + QSpinBox +
kis_int_parse_spin_box.h
+
+
diff --git a/plugins/extensions/rotateimage/wdg_rotateimage.ui b/plugins/extensions/rotateimage/wdg_rotateimage.ui index f4dce45d84..4d6f38abbc 100644 --- a/plugins/extensions/rotateimage/wdg_rotateimage.ui +++ b/plugins/extensions/rotateimage/wdg_rotateimage.ui @@ -1,120 +1,136 @@ WdgRotateImage 0 0 489 447 Rotate Image Orientation &Right true &Left Angle 90 &degrees - 180 d&egrees + &180 degrees 270 de&grees - + + 0 + + + 0 + + + 0 + + 0 &Custom: true - + 360.000000000000000 1.000000000000000 Qt::Vertical QSizePolicy::Expanding 20 91 + + + KisDoubleParseSpinBox + QDoubleSpinBox +
kis_double_parse_spin_box.h
+
+
diff --git a/plugins/extensions/shearimage/wdg_shearimage.ui b/plugins/extensions/shearimage/wdg_shearimage.ui index c43a9b0e84..0ae5c5c422 100644 --- a/plugins/extensions/shearimage/wdg_shearimage.ui +++ b/plugins/extensions/shearimage/wdg_shearimage.ui @@ -1,73 +1,80 @@ WdgShearImage 0 0 323 - 64 + 78 Shear Image Shear angle X: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - + + + ° + + -45 - + 45 - - ° - Shear angle Y: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - + 32767 100 - + + ° + + -45 - + 45 - - ° - + + + KisIntParseSpinBox + QSpinBox +
kis_int_parse_spin_box.h
+
+
diff --git a/plugins/filters/blur/wdg_lens_blur.ui b/plugins/filters/blur/wdg_lens_blur.ui index 343af1fcdd..dddf13e920 100644 --- a/plugins/filters/blur/wdg_lens_blur.ui +++ b/plugins/filters/blur/wdg_lens_blur.ui @@ -1,156 +1,163 @@ WdgLensBlur 0 0 - 199 - 123 + 255 + 153 0 0 Iris Shape: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter Triangle Quadrilateral (4) Pentagon (5) Hexagon (6) Heptagon (7) Octagon (8) Radius: - + 0 0 0 256 Radius: true Rotation: - + 0 0 ° 0 360 Rotation: true Qt::Vertical 20 18 + + + KisIntParseSpinBox + QSpinBox +
kis_int_parse_spin_box.h
+
+
irisShapeCombo irisRadiusSlider irisRotationSlider
diff --git a/plugins/filters/blur/wdg_motion_blur.ui b/plugins/filters/blur/wdg_motion_blur.ui index 18ee5aa1a8..5a31c8e4fa 100644 --- a/plugins/filters/blur/wdg_motion_blur.ui +++ b/plugins/filters/blur/wdg_motion_blur.ui @@ -1,159 +1,166 @@ WdgMotionBlur 0 0 245 256 Qt::Horizontal 40 20 100 100 100 100 360 274 274 false true false Qt::Horizontal 40 20 Angle: - + 0 0 Qt::StrongFocus ° 0 360 Length: - + 0 0 0 256 Qt::Vertical QSizePolicy::Expanding 20 18 + + + KisIntParseSpinBox + QSpinBox +
kis_int_parse_spin_box.h
+
+
blurAngleDial blurAngleSlider blurLength
diff --git a/plugins/filters/blur/wdgblur.ui b/plugins/filters/blur/wdgblur.ui index c053583025..85f18312a5 100644 --- a/plugins/filters/blur/wdgblur.ui +++ b/plugins/filters/blur/wdgblur.ui @@ -1,210 +1,215 @@ WdgBlur 0 0 280 178 0 0 0 0 Horizontal Radius: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter false - + px Qt::Horizontal QSizePolicy::Expanding 0 20 Vertical Radius: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter false - + px Strength: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter false - + 100 100 Angle: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter false - + ° 360 Shape: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter false Circle Rectangle Qt::Horizontal QSizePolicy::Expanding 0 20 Qt::Vertical QSizePolicy::Expanding 20 20 - - KComboBox - QComboBox -
kcombobox.h
-
KoAspectButton QWidget
KoAspectButton.h
1
+ + KisIntParseSpinBox + QSpinBox +
kis_int_parse_spin_box.h
+
+ + KComboBox + QComboBox +
kcombobox.h
+
diff --git a/plugins/filters/colorsfilters/wdg_color_balance.ui b/plugins/filters/colorsfilters/wdg_color_balance.ui index 9045ecb679..0f93f79c80 100644 --- a/plugins/filters/colorsfilters/wdg_color_balance.ui +++ b/plugins/filters/colorsfilters/wdg_color_balance.ui @@ -1,756 +1,772 @@ Form 0 0 381 458 3 - + + 0 + + + 0 + + + 0 + + 0 0 0 0 11 75 true true Shadows Qt::Horizontal 40 1 Reset Shadows 3 Red Magenta Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter Qt::Horizontal Green - + Yellow Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter Blue Qt::Horizontal Cyan Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter Qt::Horizontal - + - + 18 11 75 true true Midtones Qt::Horizontal 40 20 Reset Midtones 3 - + - + - + Qt::Horizontal Green Qt::Horizontal Cyan Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter Qt::Horizontal Red Magenta Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter Yellow Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter Blue 18 11 75 true true Highlights Qt::Horizontal 40 20 Reset Highlights - - 3 - 0 + + 3 + Blue - + Preserve Luminosity - + Cyan Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter Yellow Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter Qt::Horizontal Red Green - + Qt::Horizontal Qt::Horizontal Magenta Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter Qt::Vertical 20 0 + + + KisIntParseSpinBox + QSpinBox +
kis_int_parse_spin_box.h
+
+
cyanRedShadowsSpinbox magentaGreenShadowsSpinbox yellowBlueShadowsSpinbox cyanRedMidtonesSpinbox magentaGreenMidtonesSpinbox yellowBlueMidtonesSpinbox cyanRedHighlightsSpinbox magentaGreenHighlightsSpinbox yellowBlueHighlightsSpinbox chkPreserveLuminosity cyanRedShadowsSlider magentaGreenShadowsSlider yellowBlueShadowsSlider cyanRedMidtonesSlider magentaGreenMidtonesSlider yellowBlueMidtonesSlider cyanRedHighlightsSlider magentaGreenHighlightsSlider yellowBlueHighlightsSlider pushResetShadows pushResetMidtones pushResetHighlights cyanRedShadowsSlider valueChanged(int) cyanRedShadowsSpinbox setValue(int) 173 47 351 39 magentaGreenShadowsSlider valueChanged(int) magentaGreenShadowsSpinbox setValue(int) 173 76 351 68 yellowBlueShadowsSlider valueChanged(int) yellowBlueShadowsSpinbox setValue(int) 175 105 351 97 cyanRedMidtonesSlider valueChanged(int) cyanRedMidtonesSpinbox setValue(int) 173 185 351 185 magentaGreenMidtonesSlider valueChanged(int) magentaGreenMidtonesSpinbox setValue(int) 173 214 351 214 yellowBlueMidtonesSlider valueChanged(int) yellowBlueMidtonesSpinbox setValue(int) 175 243 351 243 cyanRedHighlightsSlider valueChanged(int) cyanRedHighlightsSpinbox setValue(int) 173 323 351 323 magentaGreenHighlightsSlider valueChanged(int) magentaGreenHighlightsSpinbox setValue(int) 173 352 351 352 yellowBlueHighlightsSlider valueChanged(int) yellowBlueHighlightsSpinbox setValue(int) 175 381 351 381 cyanRedMidtonesSpinbox valueChanged(int) cyanRedMidtonesSlider setValue(int) 351 185 173 185 magentaGreenMidtonesSpinbox valueChanged(int) magentaGreenMidtonesSlider setValue(int) 351 214 173 214 yellowBlueMidtonesSpinbox valueChanged(int) yellowBlueMidtonesSlider setValue(int) 351 243 175 243 yellowBlueShadowsSpinbox valueChanged(int) yellowBlueShadowsSlider setValue(int) 351 97 175 103 magentaGreenShadowsSpinbox valueChanged(int) magentaGreenShadowsSlider setValue(int) 351 68 173 74 cyanRedShadowsSpinbox valueChanged(int) cyanRedShadowsSlider setValue(int) 351 39 173 46 cyanRedHighlightsSpinbox valueChanged(int) cyanRedHighlightsSlider setValue(int) 351 323 173 323 magentaGreenHighlightsSpinbox valueChanged(int) magentaGreenHighlightsSlider setValue(int) 351 352 173 352 yellowBlueHighlightsSpinbox valueChanged(int) yellowBlueHighlightsSlider setValue(int) 351 381 175 381
diff --git a/plugins/filters/colorsfilters/wdg_hsv_adjustment.ui b/plugins/filters/colorsfilters/wdg_hsv_adjustment.ui index 337f1420b9..4c02b1243e 100644 --- a/plugins/filters/colorsfilters/wdg_hsv_adjustment.ui +++ b/plugins/filters/colorsfilters/wdg_hsv_adjustment.ui @@ -1,228 +1,235 @@ WdgHSVAdjustment 0 0 - 395 + 406 188 0 0 0 0 5 Qt::Vertical 20 0 - Type: + &Type: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter cmbType &Colorize 0 Hue/Saturation/Value Hue/Saturation/Lightness Hue/Saturation/Intensity Hue/Saturation/Luma Blue Chroma/Red Chroma/Luma -180 180 Qt::Horizontal - + 100 Value: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter 0 100 50 true Qt::Horizontal false false QSlider::NoTicks 0 0 &Saturation: false Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter 0 0 &Hue: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter -100 100 Qt::Horizontal - + -100 100 - + -180 180 + + + KisIntParseSpinBox + QSpinBox +
kis_int_parse_spin_box.h
+
+
cmbType chkColorize
diff --git a/plugins/filters/colorsfilters/wdg_perchannel.ui b/plugins/filters/colorsfilters/wdg_perchannel.ui index e205982319..f53aa0fd38 100644 --- a/plugins/filters/colorsfilters/wdg_perchannel.ui +++ b/plugins/filters/colorsfilters/wdg_perchannel.ui @@ -1,333 +1,338 @@ WdgPerChannel 0 0 317 - 395 + 396 BrightnessCon 0 0 0 0 0 6 Qt::Vertical QSizePolicy::MinimumExpanding 9 9 QLayout::SetDefaultConstraint 0 0 0 256 256 256 256 QFrame::Panel QFrame::Sunken 0 0 0 0 0 - + 0 0 256 256 256 256 0 0 256 20 256 20 QFrame::Panel QFrame::Sunken true 0 0 20 256 20 256 QFrame::Panel QFrame::Sunken true 0 0 Channel: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter Qt::Horizontal 1 20 - + 0 0 0 0 Qt::Horizontal QSizePolicy::MinimumExpanding 20 20 0 0 Output: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - + 0 0 0 0 Input: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter Qt::Horizontal 1 20 + + KisIntParseSpinBox + QSpinBox +
kis_int_parse_spin_box.h
+
KisCurveWidget
widgets/kis_curve_widget.h
cmbChannel intIn intOut
diff --git a/plugins/filters/indexcolors/kiswdgindexcolors.cpp b/plugins/filters/indexcolors/kiswdgindexcolors.cpp index 8fc6501ebf..22a57c9ff9 100644 --- a/plugins/filters/indexcolors/kiswdgindexcolors.cpp +++ b/plugins/filters/indexcolors/kiswdgindexcolors.cpp @@ -1,188 +1,190 @@ /* * Copyright 2014 Manuel Riecke * * Permission to use, copy, modify, and distribute this software * and its documentation for any purpose and without fee is hereby * granted, provided that the above copyright notice appear in all * copies and that both that the copyright notice and this * permission notice and warranty disclaimer appear in supporting * documentation, and that the name of the author not be used in * advertising or publicity pertaining to distribution of the * software without specific, written prior permission. * * The author disclaim all warranties with regard to this * software, including all implied warranties of merchantability * and fitness. In no event shall the author be liable for any * special, indirect or consequential damages or any damages * whatsoever resulting from loss of use, data or profits, whether * in an action of contract, negligence or other tortious action, * arising out of or in connection with the use or performance of * this software. */ #include "filter/kis_color_transformation_configuration.h" #include "kiswdgindexcolors.h" #include "palettegeneratorconfig.h" #include "ui_kiswdgindexcolors.h" +#include "kis_int_parse_spin_box.h" + #include KisWdgIndexColors::KisWdgIndexColors(QWidget* parent, Qt::WFlags f, int delay): KisConfigWidget(parent, f, delay) { ui = new Ui::KisWdgIndexColors; ui->setupUi(this); connect(ui->diagCheck, SIGNAL(toggled(bool)), SIGNAL(sigConfigurationItemChanged())); connect(ui->inbetweenSpinBox, SIGNAL(valueChanged(int)), SIGNAL(sigConfigurationItemChanged())); connect(ui->alphaStepsSpinBox, SIGNAL(valueChanged(int)), SIGNAL(sigConfigurationItemChanged())); connect(ui->colorLimit, SIGNAL(valueChanged(int)), SLOT(slotColorLimitChanged(int))); connect(ui->colorLimit, SIGNAL(valueChanged(int)), SIGNAL(sigConfigurationItemChanged())); connect(ui->colorLimitCheck, SIGNAL(toggled(bool)), SIGNAL(sigConfigurationItemChanged())); connect(ui->luminanceSlider, SIGNAL(valueChanged(int)), SIGNAL(sigConfigurationItemChanged())); connect(ui->aSlider, SIGNAL(valueChanged(int)), SIGNAL(sigConfigurationItemChanged())); connect(ui->bSlider, SIGNAL(valueChanged(int)), SIGNAL(sigConfigurationItemChanged())); } void KisWdgIndexColors::slotColorLimitChanged(int value) { ui->colorLimit->setSuffix(i18ncp("suffix for a spinbox", " color", " colors", value)); } void KisWdgIndexColors::setup(QStringList shadesLabels, int ramps) { int rows = shadesLabels.length(); int collumns = ramps; m_colorSelectors.resize(rows); m_stepSpinners.resize(rows-1); // Labels for the shades for(int row = 0; row < rows; ++row) { QLabel* l = new QLabel(shadesLabels[row], ui->colorsBox); ui->layoutColors->addWidget(l, row+1, 0); m_colorSelectors[row].resize(collumns); } // Labels for the ramps /*for(int col = 0; col < collumns; ++col) { - QLabel* l = new QLabel(rampsLabels[col], ui->colorsBox); - l->setAlignment(Qt::AlignRight | Qt::AlignVCenter); - ui->layoutColors->addWidget(l, 0, col+1); + QLabel* l = new QLabel(rampsLabels[col], ui->colorsBox); + l->setAlignment(Qt::AlignRight | Qt::AlignVCenter); + ui->layoutColors->addWidget(l, 0, col+1); }*/ // Step selectors for the shade gradients for(int row = 0; row < (rows-1); ++row) { QLabel* l0 = new QLabel(shadesLabels[row+1]); QLabel* l1 = new QLabel(QString::fromUtf8("↔")); QLabel* l2 = new QLabel(shadesLabels[row]); - QSpinBox* s = new QSpinBox(); + QSpinBox* s = new KisIntParseSpinBox(); s->setMinimum(0); s->setMaximum(32); s->setValue(2); connect(s, SIGNAL(valueChanged(int)), this, SIGNAL(sigConfigurationItemChanged())); m_stepSpinners[row] = s; ui->layoutRowSteps->addWidget(l0, row, 0); ui->layoutRowSteps->addWidget(l1, row, 1); ui->layoutRowSteps->addWidget(l2, row, 2); ui->layoutRowSteps->addWidget(s, row, 3); } // Color selectors for(int y = 0; y < rows; ++y) for(int x = 0; x < collumns; ++x) { KColorButton* b = new KColorButton; QCheckBox* c = new QCheckBox; c->setChecked(false); b->setEnabled(false); b->setMaximumWidth(50); c->setMaximumWidth(21); // Ugh. I hope this won't be causing any issues. Trying to get rid of the unnecessary spacing after it. connect(c, SIGNAL(toggled(bool)), b, SLOT(setEnabled(bool))); connect(c, SIGNAL(toggled(bool)), this, SIGNAL(sigConfigurationItemChanged())); connect(b, SIGNAL(changed(QColor)), this, SIGNAL(sigConfigurationItemChanged())); QHBoxLayout* cell = new QHBoxLayout(); cell->setSpacing(0); cell->setContentsMargins(0, 0, 0, 0); cell->addWidget(c); cell->addWidget(b); ui->layoutColors->addLayout(cell, 1+y, 1+x); m_colorSelectors[y][x].button = b; m_colorSelectors[y][x].checkbox = c; } } KisPropertiesConfiguration* KisWdgIndexColors::configuration() const { KisColorTransformationConfiguration* config = new KisColorTransformationConfiguration("indexcolors", 1); PaletteGeneratorConfig palCfg; for(int y = 0; y < 4; ++y) for(int x = 0; x < 4; ++x) { palCfg.colors[y][x] = m_colorSelectors[y][x].button->color(); palCfg.colorsEnabled[y][x] = m_colorSelectors[y][x].button->isEnabled(); } for(int y = 0; y < 3; ++y) palCfg.gradientSteps[y] = m_stepSpinners[y]->value(); palCfg.diagonalGradients = ui->diagCheck->isChecked(); palCfg.inbetweenRampSteps = ui->inbetweenSpinBox->value(); IndexColorPalette pal = palCfg.generate(); ui->colorCount->setText(QString::number(pal.numColors())); config->setProperty("paletteGen", palCfg.toByteArray()); config->setProperty("LFactor", ui->luminanceSlider->value() / 100.f); config->setProperty("aFactor", ui->aSlider->value() / 100.f); config->setProperty("bFactor", ui->bSlider->value() / 100.f); config->setProperty("reduceColorsEnabled", ui->colorLimitCheck->isChecked()); config->setProperty("colorLimit", ui->colorLimit->value()); config->setProperty("alphaSteps", ui->alphaStepsSpinBox->value()); return config; } void KisWdgIndexColors::setConfiguration(const KisPropertiesConfiguration* config) { PaletteGeneratorConfig palCfg; palCfg.fromByteArray(config->getProperty("paletteGen").toByteArray()); ui->luminanceSlider->setValue(config->getFloat("LFactor")*100); ui->aSlider->setValue(config->getFloat("aFactor")*100); ui->bSlider->setValue(config->getFloat("bFactor")*100); ui->alphaStepsSpinBox->setValue(config->getInt("alphaSteps")); ui->colorLimitCheck->setChecked(config->getBool("reduceColorsEnabled")); ui->colorLimit->setEnabled(config->getBool("reduceColorsEnabled")); ui->colorLimit->setValue(config->getInt("colorLimit")); ui->diagCheck->setChecked(palCfg.diagonalGradients); ui->inbetweenSpinBox->setValue(palCfg.inbetweenRampSteps); for(int y = 0; y < 4; ++y) for(int x = 0; x < 4; ++x) { m_colorSelectors[y][x].checkbox->setChecked(palCfg.colorsEnabled[y][x]); m_colorSelectors[y][x].button->setEnabled(palCfg.colorsEnabled[y][x]); m_colorSelectors[y][x].button->setColor(palCfg.colors[y][x]); } for(int y = 0; y < 3; ++y) m_stepSpinners[y]->setValue(palCfg.gradientSteps[y]); IndexColorPalette pal = palCfg.generate(); ui->colorCount->setText(QString::number(pal.numColors())); } diff --git a/plugins/filters/indexcolors/kiswdgindexcolors.ui b/plugins/filters/indexcolors/kiswdgindexcolors.ui index 728fcbd217..b467fa3b77 100644 --- a/plugins/filters/indexcolors/kiswdgindexcolors.ui +++ b/plugins/filters/indexcolors/kiswdgindexcolors.ui @@ -1,324 +1,350 @@ KisWdgIndexColors 0 0 383 601 - + + 0 + + + 0 + + + 0 + + 0 Ramps true - + 20 20 QLayout::SetMinimumSize - - 6 + + 0 - + 0 + + 0 + + + 0 + + + 6 + Diagonal Gradients Gradient Steps true Limit to - + true 3 256 31 - + 0 8 0 In-between ramps - - - - 80 - 20 - + + + QLayout::SetMinimumSize - - - QLayout::SetMinimumSize - - - 0 - - - + + 0 + + + 0 + + + 0 + + + 0 + + Color count: 0 Indexing Factors true L* 125 0 0 200 100 Qt::Horizontal QSlider::TicksAbove 50 Qt::Horizontal 0 0 a* 125 0 200 100 Qt::Horizontal QSlider::TicksAbove 50 b* 125 0 200 100 Qt::Horizontal QSlider::TicksAbove 50 Other true QFormLayout::ExpandingFieldsGrow Alpha Steps - + 0 32 1 + + + KisIntParseSpinBox + QSpinBox +
kis_int_parse_spin_box.h
+
+
colorLimitCheck toggled(bool) colorLimit setEnabled(bool) 79 281 158 285
diff --git a/plugins/filters/levelfilter/wdg_level.ui b/plugins/filters/levelfilter/wdg_level.ui index 88f70c44e6..6661c6655c 100644 --- a/plugins/filters/levelfilter/wdg_level.ui +++ b/plugins/filters/levelfilter/wdg_level.ui @@ -1,323 +1,341 @@ WdgLevel + + + 0 + 0 + 259 + 332 + + 0 0 0 0 600 32767 Levels 0 0 0 0 <b>Input Levels</b> false Qt::RightToLeft Logarithmic 0 5 5 200 100 16777215 300 0 true Qt::AlignJustify|Qt::AlignVCenter false 0 -1 - + 256 24 - + QAbstractSpinBox::PlusMinus 255 Qt::Horizontal QSizePolicy::MinimumExpanding 25 20 - + QAbstractSpinBox::PlusMinus 0.100000000000000 10.000000000000000 0.010000000000000 1.000000000000000 Qt::Horizontal QSizePolicy::MinimumExpanding 25 20 - + QAbstractSpinBox::PlusMinus 255 Qt::Vertical QSizePolicy::Fixed 0 0 <b>Output Levels</b> false - + 256 24 - + QAbstractSpinBox::PlusMinus 255 Qt::Horizontal QSizePolicy::MinimumExpanding 50 20 - + QAbstractSpinBox::PlusMinus 255 &Auto Levels Qt::Horizontal 40 20 Qt::Vertical 20 0 + + KisIntParseSpinBox + QSpinBox +
kis_int_parse_spin_box.h
+
KisGradientSlider QWidget
kis_gradient_slider.h
+ + KisDoubleParseSpinBox + QDoubleSpinBox +
kis_double_parse_spin_box.h
+
kis_gradient_slider.h kis_gradient_slider.h
diff --git a/plugins/filters/noisefilter/wdgnoiseoptions.ui b/plugins/filters/noisefilter/wdgnoiseoptions.ui index 80153c76f3..5432c8838f 100644 --- a/plugins/filters/noisefilter/wdgnoiseoptions.ui +++ b/plugins/filters/noisefilter/wdgnoiseoptions.ui @@ -1,94 +1,101 @@ WdgNoiseOptions 0 0 174 - 63 + 66 0 0 0 0 Opacity: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter false Level: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter false - + - + Qt::Horizontal QSizePolicy::Expanding 21 20 Qt::Vertical QSizePolicy::Expanding 20 21 + + + KisIntParseSpinBox + QSpinBox +
kis_int_parse_spin_box.h
+
+
diff --git a/plugins/filters/phongbumpmap/wdgphongbumpmap.ui b/plugins/filters/phongbumpmap/wdgphongbumpmap.ui index 18f09bba02..7c1e8438ff 100644 --- a/plugins/filters/phongbumpmap/wdgphongbumpmap.ui +++ b/plugins/filters/phongbumpmap/wdgphongbumpmap.ui @@ -1,1229 +1,1234 @@ WdgPhongBumpmap 0 0 670 346 0 0 570 323 570 323 QLayout::SetDefaultConstraint 0 0 0 0 0 0 0 General settings 0 0 Material properties true - Specular + Specula&r Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter true true 0 3 0 0 Reflectivity: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - + 1 1 0 20 16777215 23 Shinyness exponent: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - + 1 1 0 20 16777215 23 Qt::Horizontal QSizePolicy::Fixed 150 0 Qt::LeftToRight - Diffuse + Di&ffuse Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter true true 0 3 0 0 Reflectivity: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - + 1 1 0 20 16777215 23 Qt::Horizontal QSizePolicy::Fixed 150 0 Ambient true false 0 3 0 0 6 Reflectivity: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - + 1 1 0 20 16777215 23 Qt::Horizontal QSizePolicy::Fixed 150 0 Heightmap channel: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter 0 0 Qt::Vertical QSizePolicy::Fixed 20 16 Qt::Vertical QSizePolicy::MinimumExpanding 20 9 Use Normalmap false Light Sources 0 0 - Light Source 4 + Light Source &4 true true false QFormLayout::AllNonFixedFieldsGrow 0 3 Color: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter 255 255 0 Direction of the light, the dial tip represents where the light comes from. Azimuth: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - + 0 0 Direction of the light, the dial tip represents where the light comes from. true ° 0 359 15 180 Vertical tilt of the light. 90° is perpendicular to the canvas, 0° is parallel. Inclination: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - + 0 0 Vertical tilt of the light. 90° is perpendicular to the canvas, 0° is parallel. ° 0 90 15 45 Azimuth 359 5 45 180 180 true Qt::Horizontal false false true 45.000000000000000 false 0 0 - Light Source 2 + Light Source &2 true true 0 3 Color: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter 255 0 0 Direction of the light, the dial tip represents where the light comes from. Azimuth: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - + 0 0 Direction of the light, the dial tip represents where the light comes from. true ° 0 359 15 33 Vertical tilt of the light. 90° is perpendicular to the canvas, 0° is parallel. Inclination: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - + 0 0 Vertical tilt of the light. 90° is perpendicular to the canvas, 0° is parallel. ° 0 90 15 45 Azimuth 359 5 45 33 33 true Qt::Horizontal false false true 45.000000000000000 false 0 0 - Light Source 1 + Light Source &1 true true 0 3 6 6 Color: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter 255 255 0 Direction of the light, the dial tip represents where the light comes from. Azimuth: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - + 0 0 Direction of the light, the dial tip represents where the light comes from. true ° 0 359 15 127 Vertical tilt of the light. 90° is perpendicular to the canvas, 0° is parallel. Inclination: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - + 0 0 Vertical tilt of the light. 90° is perpendicular to the canvas, 0° is parallel. ° 0 90 15 45 Azimuth 359 5 45 127 127 true Qt::Horizontal false false true 45.000000000000000 false 0 0 - Light Source 3 + Light Source &3 true true false 0 3 Color: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter 0 255 0 Direction of the light, the dial tip represents where the light comes from. Azimuth: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - + 0 0 Direction of the light, the dial tip represents where the light comes from. true ° 0 359 15 180 Vertical tilt of the light. 90° is perpendicular to the canvas, 0° is parallel. Inclination: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - + 0 0 Vertical tilt of the light. 90° is perpendicular to the canvas, 0° is parallel. ° 0 90 15 45 Azimuth 359 5 45 180 180 true Qt::Horizontal false false true 45.000000000000000 false Qt::Vertical 20 0 + + KisIntParseSpinBox + QSpinBox +
kis_int_parse_spin_box.h
+
KColorCombo QComboBox
kcolorcombo.h
KisDoubleSliderSpinBox QWidget
kis_slider_spin_box.h
1
KisSliderSpinBox QWidget
kis_slider_spin_box.h
1
settingsTabWidget heightChannelComboBox diffuseReflectivityGroup specularReflectivityGroup lightSourceGroupBox1 lightKColorCombo1 azimuthSpinBox1 inclinationSpinBox1 azimuthDial1 lightSourceGroupBox2 lightKColorCombo2 azimuthSpinBox2 inclinationSpinBox2 azimuthDial2 lightSourceGroupBox3 lightKColorCombo3 azimuthSpinBox3 inclinationSpinBox3 azimuthDial3 lightSourceGroupBox4 lightKColorCombo4 azimuthSpinBox4 inclinationSpinBox4 azimuthDial4
diff --git a/plugins/filters/randompickfilter/wdgrandompickoptions.ui b/plugins/filters/randompickfilter/wdgrandompickoptions.ui index a847a1fa3e..4fb0469491 100644 --- a/plugins/filters/randompickfilter/wdgrandompickoptions.ui +++ b/plugins/filters/randompickfilter/wdgrandompickoptions.ui @@ -1,98 +1,105 @@ WdgRandomPickOptions 0 0 293 154 Qt::Horizontal QSizePolicy::Expanding 16 20 Level: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter false - + Size of the window: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter false - + Opacity: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter false - + Qt::Vertical QSizePolicy::Expanding 20 1 + + + KisIntParseSpinBox + QSpinBox +
kis_int_parse_spin_box.h
+
+
diff --git a/plugins/filters/unsharp/wdgunsharp.ui b/plugins/filters/unsharp/wdgunsharp.ui index ec4b08095b..bc3ad24aaf 100644 --- a/plugins/filters/unsharp/wdgunsharp.ui +++ b/plugins/filters/unsharp/wdgunsharp.ui @@ -1,163 +1,175 @@ WdgUnsharp 0 0 331 167 0 0 Radius: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter false - + 0 0 1.000000000000000 Qt::Horizontal 40 20 0 0 Amount: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter false - + 0 0 0.100000000000000 25.000000000000000 0 0 Threshold: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter false - + 0 0 Lightness Only: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter true Qt::Vertical QSizePolicy::Expanding 20 21 + + + KisIntParseSpinBox + QSpinBox +
kis_int_parse_spin_box.h
+
+ + KisDoubleParseSpinBox + QDoubleSpinBox +
kis_double_parse_spin_box.h
+
+
diff --git a/plugins/filters/wavefilter/wdgwaveoptions.ui b/plugins/filters/wavefilter/wdgwaveoptions.ui index c08388d7b2..2ca31c5e87 100644 --- a/plugins/filters/wavefilter/wdgwaveoptions.ui +++ b/plugins/filters/wavefilter/wdgwaveoptions.ui @@ -1,281 +1,313 @@ WdgWaveOptions 0 0 379 475 - + + 0 + + + 0 + + + 0 + + 0 6 Qt::Vertical QSizePolicy::Expanding 20 60 Horizontal Wave - + + 9 + + + 9 + + + 9 + + 9 - + - + Shape: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter false Amplitude: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter false Wavelength: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter false 0 0 130 0 Sinusoidale Triangle Shift: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter false - + Qt::Horizontal 40 20 Vertical Wave - + + 9 + + + 9 + + + 9 + + 9 Wavelength: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter false 0 0 130 0 Sinusoidale Triangle Shift: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter false - + Amplitude: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter false Shape: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter false - + - + Qt::Horizontal 40 20 + + KisIntParseSpinBox + QSpinBox +
kis_int_parse_spin_box.h
+
KComboBox QComboBox
kcombobox.h
intHWavelength intHShift intHAmplitude cbHShape intVWavelength intVShift intVAmplitude cbVShape
diff --git a/plugins/flake/artistictextshape/ArtisticTextShapeConfigWidget.ui b/plugins/flake/artistictextshape/ArtisticTextShapeConfigWidget.ui index 657a35fce4..b081e19102 100644 --- a/plugins/flake/artistictextshape/ArtisticTextShapeConfigWidget.ui +++ b/plugins/flake/artistictextshape/ArtisticTextShapeConfigWidget.ui @@ -1,152 +1,161 @@ ArtisticTextShapeConfigWidget 0 0 259 73 0 0 - + + 0 + + + 0 + + + 0 + + 0 0 0 - + 0 0 Qt::Vertical Qt::Vertical Qt::Horizontal 40 20 Qt::Vertical 20 40 - QSpinBox + KisIntParseSpinBox QSpinBox -
knuminput.h
+
kis_int_parse_spin_box.h
KoFontComboBox QComboBox
KoFontComboBox.h
diff --git a/plugins/flake/artistictextshape/CMakeLists.txt b/plugins/flake/artistictextshape/CMakeLists.txt index f1f2b9b423..5d6d9f656f 100644 --- a/plugins/flake/artistictextshape/CMakeLists.txt +++ b/plugins/flake/artistictextshape/CMakeLists.txt @@ -1,42 +1,42 @@ project( artistictextshape ) include_directories( ${CMAKE_SOURCE_DIR}/libs/widgets ) set ( ArtisticTextShape_SRCS ArtisticTextShapePlugin.cpp ArtisticTextShape.cpp ArtisticTextRange.cpp ArtisticTextShapeFactory.cpp ArtisticTextTool.cpp ArtisticTextToolFactory.cpp ArtisticTextToolSelection.cpp ArtisticTextShapeConfigWidget.cpp ArtisticTextShapeOnPathWidget.cpp ArtisticTextShapeLoadingUpdater.cpp ArtisticTextLoadingContext.cpp AttachTextToPathCommand.cpp DetachTextFromPathCommand.cpp ChangeTextOffsetCommand.cpp ChangeTextFontCommand.cpp ChangeTextAnchorCommand.cpp AddTextRangeCommand.cpp RemoveTextRangeCommand.cpp MoveStartOffsetStrategy.cpp SelectTextStrategy.cpp ReplaceTextRangeCommand.cpp ) ki18n_wrap_ui( ArtisticTextShape_SRCS ArtisticTextShapeConfigWidget.ui ArtisticTextShapeOnPathWidget.ui ) qt5_add_resources(ArtisticTextShape_SRCS artistictextshape.qrc) add_library(krita_shape_artistictext MODULE ${ArtisticTextShape_SRCS} ) -target_link_libraries(krita_shape_artistictext kritaflake) +target_link_libraries(krita_shape_artistictext kritaflake kritaui) install( TARGETS krita_shape_artistictext DESTINATION ${KRITA_PLUGIN_INSTALL_DIR} ) diff --git a/plugins/flake/pathshapes/CMakeLists.txt b/plugins/flake/pathshapes/CMakeLists.txt index 3345a7eaf6..a771105a68 100644 --- a/plugins/flake/pathshapes/CMakeLists.txt +++ b/plugins/flake/pathshapes/CMakeLists.txt @@ -1,40 +1,40 @@ set(pathshapes_SOURCES ellipse/EllipseShape.cpp ellipse/EllipseShapeFactory.cpp ellipse/EllipseShapeConfigWidget.cpp ellipse/EllipseShapeConfigCommand.cpp spiral/SpiralShape.cpp spiral/SpiralShapeFactory.cpp spiral/SpiralShapeConfigWidget.cpp spiral/SpiralShapeConfigCommand.cpp star/StarShape.cpp star/StarShapeFactory.cpp star/StarShapeConfigWidget.cpp star/StarShapeConfigCommand.cpp rectangle/RectangleShape.cpp rectangle/RectangleShapeFactory.cpp rectangle/RectangleShapeConfigWidget.cpp rectangle/RectangleShapeConfigCommand.cpp enhancedpath/EnhancedPathShape.cpp enhancedpath/EnhancedPathShapeFactory.cpp enhancedpath/EnhancedPathCommand.cpp enhancedpath/EnhancedPathParameter.cpp enhancedpath/EnhancedPathFormula.cpp enhancedpath/EnhancedPathHandle.cpp PathShapesPlugin.cpp ) ki18n_wrap_ui(pathshapes_SOURCES star/StarShapeConfigWidget.ui rectangle/RectangleShapeConfigWidget.ui ellipse/EllipseShapeConfigWidget.ui spiral/SpiralShapeConfigWidget.ui ) qt5_add_resources(pathshapes_SOURCES pathshapes.qrc) add_library(krita_shape_paths MODULE ${pathshapes_SOURCES}) -target_link_libraries(krita_shape_paths kritaflake kritawidgets) +target_link_libraries(krita_shape_paths kritaflake kritawidgets kritaui) install(TARGETS krita_shape_paths DESTINATION ${KRITA_PLUGIN_INSTALL_DIR}) diff --git a/plugins/flake/pathshapes/ellipse/EllipseShapeConfigWidget.ui b/plugins/flake/pathshapes/ellipse/EllipseShapeConfigWidget.ui index 8ae2fb5916..22ae46b850 100644 --- a/plugins/flake/pathshapes/ellipse/EllipseShapeConfigWidget.ui +++ b/plugins/flake/pathshapes/ellipse/EllipseShapeConfigWidget.ui @@ -1,84 +1,92 @@ - + + EllipseShapeConfigWidget - - + + 0 0 - 187 + 188 173 - + Ellipse Shape - - - - + + + + Type: - - + + - - - + + + Start angle: - - - + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - + ° - - - + + + End angle: - - - + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - + ° - - - + + + Close ellipse - + - + Qt::Vertical - + 20 40 + + + KisDoubleParseSpinBox + QDoubleSpinBox +
kis_double_parse_spin_box.h
+
+
diff --git a/plugins/flake/pathshapes/rectangle/RectangleShapeConfigWidget.ui b/plugins/flake/pathshapes/rectangle/RectangleShapeConfigWidget.ui index 990eea1287..88af5754e4 100644 --- a/plugins/flake/pathshapes/rectangle/RectangleShapeConfigWidget.ui +++ b/plugins/flake/pathshapes/rectangle/RectangleShapeConfigWidget.ui @@ -1,60 +1,61 @@ - + + RectangleShapeConfigWidget - - + + 0 0 - 198 + 200 108 - + Rectangle Shape - - - - + + + + Corner radius x: - - + + - - - + + + Corner radius y: - - + + - + - + Qt::Vertical - + 20 40 - KoUnitDoubleSpinBox + KisDoubleParseUnitSpinBox QDoubleSpinBox -
KoUnitDoubleSpinBox.h
+
kis_double_parse_unit_spin_box.h
diff --git a/plugins/flake/pathshapes/spiral/SpiralShapeConfigWidget.ui b/plugins/flake/pathshapes/spiral/SpiralShapeConfigWidget.ui index 3f36f47ca1..bf26673702 100644 --- a/plugins/flake/pathshapes/spiral/SpiralShapeConfigWidget.ui +++ b/plugins/flake/pathshapes/spiral/SpiralShapeConfigWidget.ui @@ -1,79 +1,87 @@ - + + SpiralShapeConfigWidget - - + + 0 0 187 173 - + Spiral Shape - - - - + + + + Type: - - + + - - - + + + Fade: - - - + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - + - + 1.000000000000000 - + 0.100000000000000 - + 0.500000000000000 - - - + + + Direction: - - + + - + - + Qt::Vertical - + 20 40 + + + KisDoubleParseSpinBox + QDoubleSpinBox +
kis_double_parse_spin_box.h
+
+
diff --git a/plugins/flake/pathshapes/star/StarShapeConfigWidget.ui b/plugins/flake/pathshapes/star/StarShapeConfigWidget.ui index c207c6e52d..6301134967 100644 --- a/plugins/flake/pathshapes/star/StarShapeConfigWidget.ui +++ b/plugins/flake/pathshapes/star/StarShapeConfigWidget.ui @@ -1,100 +1,101 @@ - + + StarShapeConfigWidget - - + + 0 0 189 175 - + Star shape - - - - + + + + Polygon: - - - + + + Qt::LeftToRight - + - - - + + + Corners: - - + + - - - + + + Inner radius: - - - + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - + + + Outer radius: - - - + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - + - + Qt::Vertical - + 20 40 - QSpinBox + KisIntParseSpinBox QSpinBox -
knuminput.h
+
kis_int_parse_spin_box.h
- KoUnitDoubleSpinBox + KisDoubleParseUnitSpinBox QDoubleSpinBox -
KoUnitDoubleSpinBox.h
+
kis_double_parse_unit_spin_box.h
diff --git a/plugins/impex/heightmap/kis_wdg_options_heightmap.ui b/plugins/impex/heightmap/kis_wdg_options_heightmap.ui index 2e5d967b43..9805b040f1 100644 --- a/plugins/impex/heightmap/kis_wdg_options_heightmap.ui +++ b/plugins/impex/heightmap/kis_wdg_options_heightmap.ui @@ -1,88 +1,95 @@ WdgOptionsHeightMap 0 0 - 177 - 100 + 191 + 145 Qt::Vertical 20 40 Size: - + 1000000 Endianness: Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop Big Endian - Mac + &Mac Little Endian PC + + + KisIntParseSpinBox + QSpinBox +
kis_int_parse_spin_box.h
+
+
diff --git a/plugins/impex/pdf/pdfimportwidgetbase.ui b/plugins/impex/pdf/pdfimportwidgetbase.ui index 18077ee520..63eda628ac 100644 --- a/plugins/impex/pdf/pdfimportwidgetbase.ui +++ b/plugins/impex/pdf/pdfimportwidgetbase.ui @@ -1,367 +1,372 @@ PDFImportWidgetBase 0 0 523 246 PDFImportWidget Pages - &All pages + All pa&ges &First page true - &Selection of page + Selec&tion of page QAbstractItemView::MultiSelection Dimensions false 0 0 0 0 0 Qt::Vertical 20 40 0 0 0 0 Qt::Horizontal QSizePolicy::Fixed 44 20 0 0 0 0 - + 0 0 85 0 px 99999 Width: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - + 0 0 85 0 px 99999 Height: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - + 0 0 0 0 Qt::Horizontal QSizePolicy::Expanding 51 20 0 0 0 0 Qt::Horizontal QSizePolicy::Fixed 21 20 0 0 0 0 - + 0 0 85 0 dpi 1 3200 100 Resolution: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter Qt::Horizontal QSizePolicy::Expanding 51 20 KoAspectButton QWidget
KoAspectButton.h
1
+ + KisIntParseSpinBox + QSpinBox +
kis_int_parse_spin_box.h
+
boolAllPages boolFirstPage boolSelectionPage listPages intResolution intWidth intHeight
diff --git a/plugins/paintops/dynadraw/wdgdynaoptions.ui b/plugins/paintops/dynadraw/wdgdynaoptions.ui index ce2cff3416..6934f1a51e 100644 --- a/plugins/paintops/dynadraw/wdgdynaoptions.ui +++ b/plugins/paintops/dynadraw/wdgdynaoptions.ui @@ -1,334 +1,344 @@ WdgDynaOptions 0 0 337 359 210 60 337 359 - 0 + 1 Dynamics settings Initial width: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - + -99.000000000000000 0.050000000000000 1.500000000000000 Mass: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - + -99.000000000000000 0.050000000000000 0.500000000000000 Drag: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - + -99.000000000000000 0.050000000000000 0.150000000000000 Width range: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - + -99.000000000000000 0.050000000000000 0.050000000000000 Qt::Vertical 20 153 Shape Diameter: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter true Angle: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter false Fixed angle Qt::Horizontal 40 20 Qt::Vertical QSizePolicy::MinimumExpanding 20 15 - Circle + C&ircle true Two Lines - + Line spacing 20.000000000000000 - + Line count 10 - Polygon + Poly&gon - Wire + Wi&re Paint connection true Qt::Vertical 20 40 + + KisIntParseSpinBox + QSpinBox +
kis_int_parse_spin_box.h
+
+ + KisDoubleParseSpinBox + QDoubleSpinBox +
kis_double_parse_spin_box.h
+
KisDoubleSliderSpinBox QWidget
kis_slider_spin_box.h
1
diff --git a/plugins/paintops/hairy/wdgInkOptions.ui b/plugins/paintops/hairy/wdgInkOptions.ui index 5dac483b69..b78e49925e 100644 --- a/plugins/paintops/hairy/wdgInkOptions.ui +++ b/plugins/paintops/hairy/wdgInkOptions.ui @@ -1,251 +1,256 @@ WdgInkOptions 0 0 405 436 0 0 405 400 300 0 - 102 + 113 391 10 Ink Amount - + 10000 1024 Opacity true true Saturation false true Soak ink from the initial position of the stroke Soak ink false Qt::Vertical 20 288 0 0 301 270 0 0 0 0 Ink Depletion Curve - + 9 33 271 228 0 270 281 161 Saturation Weights weighted saturation Bristle Ink Weight: Pressure Weight: - + 0 0 Bristle Length Weight: - + 0 0 - + 0 0 Ink Depletion Curve Weight: - + 0 0 + + KisIntParseSpinBox + QSpinBox +
kis_int_parse_spin_box.h
+
KisDoubleSliderSpinBox QWidget
kis_slider_spin_box.h
1
KisCurveWidget QWidget
widgets/kis_curve_widget.h
1
diff --git a/plugins/paintops/hairy/wdghairyshapeoptions.ui b/plugins/paintops/hairy/wdghairyshapeoptions.ui index 63811c02ba..ac63aef4ff 100644 --- a/plugins/paintops/hairy/wdghairyshapeoptions.ui +++ b/plugins/paintops/hairy/wdghairyshapeoptions.ui @@ -1,128 +1,140 @@ WdgHairyShapeOptions 0 0 425 285 0 0 425 285 - + 50 20 331 89 radius Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - + 5 sigma Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - + 20.000000000000000 - + 50 120 331 138 Shape - 1D + &1D false - 2D + &2D true Qt::Vertical 20 40 + + + KisIntParseSpinBox + QSpinBox +
kis_int_parse_spin_box.h
+
+ + KisDoubleParseSpinBox + QDoubleSpinBox +
kis_double_parse_spin_box.h
+
+
diff --git a/plugins/paintops/hatching/wdghatchingoptions.ui b/plugins/paintops/hatching/wdghatchingoptions.ui index 2d288c70bc..d0467c8098 100644 --- a/plugins/paintops/hatching/wdghatchingoptions.ui +++ b/plugins/paintops/hatching/wdghatchingoptions.ui @@ -1,438 +1,443 @@ WdgHatchingOptions 0 0 588 450 0 0 0 0 0 0 0 0 Qt::LeftToRight QFrame::NoFrame Angle: false Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - + 1 1 0 20 16777215 23 0 0 Separation: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - + 1 1 0 20 16777215 23 0 0 Thickness: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - + 1 1 0 20 16777215 23 0 0 Origin X: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - + 1 1 0 20 16777215 23 0 0 Origin Y: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - + 1 1 0 20 16777215 23 301 161 Crosshatching style false false 0 0 210 0 - No crosshatching + No crosshatch&ing true 0 0 210 0 - Perpendicular plane only + Pe&rpendicular plane only false 0 0 210 0 - -45° plane then +45° plane + -&45° plane then +45° plane 0 0 210 0 - +45° plane then -45° plane + +45° plane &then -45° plane 0 0 210 0 - Moiré pattern + &Moiré pattern 301 95 Separation Style false false Input-based intervals: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - + 0 0 false false 2 7 5 Qt::Vertical 0 0 + + KisIntParseSpinBox + QSpinBox +
kis_int_parse_spin_box.h
+
KisDoubleSliderSpinBox QWidget
kis_slider_spin_box.h
1
diff --git a/plugins/paintops/libpaintop/forms/wdgbrushchooser.ui b/plugins/paintops/libpaintop/forms/wdgbrushchooser.ui index 41455c915c..fecb0fa2dd 100644 --- a/plugins/paintops/libpaintop/forms/wdgbrushchooser.ui +++ b/plugins/paintops/libpaintop/forms/wdgbrushchooser.ui @@ -1,179 +1,184 @@ WdgBrushChooser 0 0 - 527 + 537 300 0 0 0 0 QFrame::StyledPanel QFrame::Plain 0 0 0 0 0 Qt::Horizontal 40 20 QFrame::StyledPanel QFrame::Raised Auto Use to set the size from which the Automatic Precision Setting should begin. The Precision will remain 5 before this value. Starting Brush Size: - + px 0 0 This determines every interval after which the precision should change. For example: if the delta value is set to be 15.00, after every 15 pts change in the size of brush, the precision will change. Delta : - + px 0 0 0 Precision: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - + 0 0 + + KisDoubleParseSpinBox + QDoubleSpinBox +
kis_double_parse_spin_box.h
+
KisSliderSpinBox QWidget
kis_slider_spin_box.h
1
diff --git a/plugins/tools/basictools/wdgcolorpicker.ui b/plugins/tools/basictools/wdgcolorpicker.ui index 86c4c1cdc6..c213ba02fe 100644 --- a/plugins/tools/basictools/wdgcolorpicker.ui +++ b/plugins/tools/basictools/wdgcolorpicker.ui @@ -1,162 +1,167 @@ ColorPickerOptionsWidget 0 0 263 307 Color Picker 2 Channel Value 1 0 0 0 0 Sample radius: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - + px 1 900 Show colors as percentages 1 0 0 0 0 Add to palette: Update current color 0 0 200 0 200 32767 Sample All Visible Layers Current Layer SqueezedComboBox QComboBox
squeezedcombobox.h
+ + KisIntParseSpinBox + QSpinBox +
kis_int_parse_spin_box.h
+
diff --git a/plugins/tools/basictools/wdgmovetool.ui b/plugins/tools/basictools/wdgmovetool.ui index 262b0c89b2..f2e90aa34e 100644 --- a/plugins/tools/basictools/wdgmovetool.ui +++ b/plugins/tools/basictools/wdgmovetool.ui @@ -1,246 +1,261 @@ WdgMoveTool 0 0 - 269 + 271 394 Selection Mode Move the layer that you have currently selected in the layerbox with its masks. Shortcut: ctrl-click. - Move current layer + &Move current layer true Move the first layer with visible content at the place where you click. This will also select that layer in the layerbox. - Move layer with content + Mo&ve layer with content false Move the group containing the first layer that contains visible content. Shortcut: ctrl-shift-click. - Move the whole group + Move &the whole group + + + Shortcut Move Distance - + Number of pixels to move after move shortcut keypress. 1.000000000000000 100000.000000000000000 1.000000000000000 - + When holding shift, move keyboard shortcuts scale up by this amount. 1.000000000000000 1000.000000000000000 10.000000000000000 Large Move Scale - + Show coordinates on canvas Show coordinates - + 0 0 240 70 Position false false false 2 5 0 0 QFormLayout::AllNonFixedFieldsGrow 0 0 Horizontal Translation Qt::LeftToRight - x: + &x: translateXBox - + 0 0 Horizontal Translation Qt::LeftToRight - + 0 0 Vertical Translation 0 0 Vertical Translation - y: + &y: translateYBox - + + + + KisDoubleParseSpinBox + QDoubleSpinBox +
kis_double_parse_spin_box.h
+
+ + KisIntParseSpinBox + QSpinBox +
kis_int_parse_spin_box.h
+
+
diff --git a/plugins/tools/defaulttool/CMakeLists.txt b/plugins/tools/defaulttool/CMakeLists.txt index f76760b624..4417ac60bd 100644 --- a/plugins/tools/defaulttool/CMakeLists.txt +++ b/plugins/tools/defaulttool/CMakeLists.txt @@ -1,37 +1,37 @@ project( defaulttools ) set ( defaulttools_SRCS Plugin.cpp defaulttool/DefaultTool.cpp defaulttool/DefaultToolFactory.cpp defaulttool/DefaultToolWidget.cpp defaulttool/DefaultToolArrangeWidget.cpp defaulttool/DefaultToolTransformWidget.cpp defaulttool/ShapeMoveStrategy.cpp defaulttool/ShapeResizeStrategy.cpp defaulttool/ShapeRotateStrategy.cpp defaulttool/ShapeShearStrategy.cpp defaulttool/SelectionDecorator.cpp defaulttool/SelectionTransformCommand.cpp connectionTool/ConnectionTool.cpp connectionTool/ConnectionToolFactory.cpp connectionTool/AddConnectionPointCommand.cpp connectionTool/RemoveConnectionPointCommand.cpp connectionTool/ChangeConnectionPointCommand.cpp connectionTool/MoveConnectionPointStrategy.cpp connectionTool/ConnectionPointWidget.cpp ) ki18n_wrap_ui(defaulttools_SRCS defaulttool/DefaultToolWidget.ui defaulttool/DefaultToolArrangeWidget.ui defaulttool/DefaultToolTransformWidget.ui connectionTool/ConnectionPointWidget.ui ) qt5_add_resources(defaulttools_SRCS defaulttools.qrc) add_library(krita_flaketools MODULE ${defaulttools_SRCS}) -target_link_libraries(krita_flaketools kritaflake kritawidgets) +target_link_libraries(krita_flaketools kritaflake kritawidgets kritaui) install(TARGETS krita_flaketools DESTINATION ${KRITA_PLUGIN_INSTALL_DIR}) diff --git a/plugins/tools/defaulttool/defaulttool/DefaultToolTransformWidget.ui b/plugins/tools/defaulttool/defaulttool/DefaultToolTransformWidget.ui index 0cbca752d1..9a35520290 100644 --- a/plugins/tools/defaulttool/defaulttool/DefaultToolTransformWidget.ui +++ b/plugins/tools/defaulttool/defaulttool/DefaultToolTransformWidget.ui @@ -1,202 +1,211 @@ - + + DefaultToolTransformWidget - - + + 0 0 222 293 - - - - - + + + + + + + + 2 0 - + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - + ° - + -360.000000000000000 - + 360.000000000000000 - - - + + + Rotate - - - - + + + + 2 0 - + -100.000000000000000 - + 100.000000000000000 - + 0.100000000000000 - - - + + + Shear X - - - - + + + + 2 0 - + -100.000000000000000 - + 100.000000000000000 - + 0.100000000000000 - - - + + + Shear Y - - - - + + + + 2 0 - + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - + % - + -1000.000000000000000 - + 1000.000000000000000 - + 100.000000000000000 - - - + + + Scale X - - - - + + + + 2 0 - + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - + % - + -1000.000000000000000 - + 1000.000000000000000 - + 100.000000000000000 - - - + + + Scale Y - - - + + + Keep aspect ratio - - - - + + + + 0 0 - + Reset Transformations - - - + + + Qt::Vertical - + 191 58 - KoUnitDoubleSpinBox + KisDoubleParseSpinBox + QDoubleSpinBox +
kis_double_parse_spin_box.h
+
+ + KisDoubleParseUnitSpinBox QDoubleSpinBox -
KoUnitDoubleSpinBox.h
+
kis_double_parse_unit_spin_box.h
diff --git a/plugins/tools/defaulttool/defaulttool/DefaultToolWidget.ui b/plugins/tools/defaulttool/defaulttool/DefaultToolWidget.ui index 25994dcd33..c5efcee49c 100644 --- a/plugins/tools/defaulttool/defaulttool/DefaultToolWidget.ui +++ b/plugins/tools/defaulttool/defaulttool/DefaultToolWidget.ui @@ -1,165 +1,175 @@ DefaultToolWidget 0 0 - 158 - 64 + 256 + 76 Qt::NoFocus - + + 0 + + + 0 + + + 0 + + 0 0 0 X: - + 0 0 -10000.000000000000000 10000.000000000000000 - + 0 0 -10000.000000000000000 10000.000000000000000 - + 0 0 - + - + 0 0 Y: - + 0 0 -10000.000000000000000 10000.000000000000000 - + 0 0 -10000.000000000000000 10000.000000000000000 - + 0 0 - - KoUnitDoubleSpinBox - QDoubleSpinBox -
KoUnitDoubleSpinBox.h
-
KoAspectButton - QLabel + QWidget
KoAspectButton.h
+ 1 +
+ + KisDoubleParseUnitSpinBox + QDoubleSpinBox +
kis_double_parse_unit_spin_box.h
KoPositionSelector QWidget
KoPositionSelector.h
1
positionXSpinBox positionYSpinBox widthSpinBox heightSpinBox
diff --git a/plugins/tools/karbonplugins/filtereffects/BlurEffectConfigWidget.cpp b/plugins/tools/karbonplugins/filtereffects/BlurEffectConfigWidget.cpp index ee4bd55eb2..85b57cdba5 100644 --- a/plugins/tools/karbonplugins/filtereffects/BlurEffectConfigWidget.cpp +++ b/plugins/tools/karbonplugins/filtereffects/BlurEffectConfigWidget.cpp @@ -1,65 +1,67 @@ /* This file is part of the KDE project * Copyright (c) 2009 Jan Hambrecht * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 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 Lesser 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. */ #include "BlurEffectConfigWidget.h" #include "BlurEffect.h" #include "KoFilterEffect.h" #include #include #include #include +#include "kis_double_parse_spin_box.h" + BlurEffectConfigWidget::BlurEffectConfigWidget(QWidget *parent) : KoFilterEffectConfigWidgetBase(parent), m_effect(0) { QGridLayout *g = new QGridLayout(this); g->addWidget(new QLabel(i18n("Radius"), this), 0, 0); - m_stdDeviation = new QDoubleSpinBox(this); + m_stdDeviation = new KisDoubleParseSpinBox(this); m_stdDeviation->setRange(0.0, 100); m_stdDeviation->setSingleStep(0.5); g->addWidget(m_stdDeviation, 0, 1); setLayout(g); connect(m_stdDeviation, SIGNAL(valueChanged(double)), this, SLOT(stdDeviationChanged(double))); } bool BlurEffectConfigWidget::editFilterEffect(KoFilterEffect *filterEffect) { m_effect = dynamic_cast(filterEffect); if (!m_effect) { return false; } m_stdDeviation->setValue(m_effect->deviation().x() * 100.0); return true; } void BlurEffectConfigWidget::stdDeviationChanged(double stdDeviation) { if (!m_effect) { return; } qreal newDev = 0.01 * stdDeviation; m_effect->setDeviation(QPointF(newDev, newDev)); emit filterChanged(); } diff --git a/plugins/tools/karbonplugins/filtereffects/CMakeLists.txt b/plugins/tools/karbonplugins/filtereffects/CMakeLists.txt index 9bdf94e0af..10e9997ab5 100644 --- a/plugins/tools/karbonplugins/filtereffects/CMakeLists.txt +++ b/plugins/tools/karbonplugins/filtereffects/CMakeLists.txt @@ -1,43 +1,43 @@ set(karbon_filtereffects_SOURCES FilterEffectsPlugin.cpp BlurEffect.cpp BlurEffectFactory.cpp BlurEffectConfigWidget.cpp OffsetEffect.cpp OffsetEffectFactory.cpp OffsetEffectConfigWidget.cpp MergeEffect.cpp MergeEffectFactory.cpp MergeEffectConfigWidget.cpp ColorMatrixEffect.cpp ColorMatrixEffectFactory.cpp ColorMatrixEffectConfigWidget.cpp FloodEffect.cpp FloodEffectFactory.cpp FloodEffectConfigWidget.cpp CompositeEffect.cpp CompositeEffectFactory.cpp CompositeEffectConfigWidget.cpp BlendEffect.cpp BlendEffectFactory.cpp BlendEffectConfigWidget.cpp ComponentTransferEffect.cpp ComponentTransferEffectFactory.cpp ComponentTransferEffectConfigWidget.cpp ImageEffect.cpp ImageEffectFactory.cpp ImageEffectConfigWidget.cpp MorphologyEffect.cpp MorphologyEffectFactory.cpp MorphologyEffectConfigWidget.cpp ConvolveMatrixEffect.cpp ConvolveMatrixEffectFactory.cpp ConvolveMatrixEffectConfigWidget.cpp MatrixDataModel.cpp ) add_library(krita_filtereffects MODULE ${karbon_filtereffects_SOURCES}) -target_link_libraries(krita_filtereffects kritaflake kritawidgets KF5::Completion) +target_link_libraries(krita_filtereffects kritaflake kritawidgets kritaui KF5::Completion) install(TARGETS krita_filtereffects DESTINATION ${KRITA_PLUGIN_INSTALL_DIR}) diff --git a/plugins/tools/karbonplugins/filtereffects/ColorMatrixEffectConfigWidget.cpp b/plugins/tools/karbonplugins/filtereffects/ColorMatrixEffectConfigWidget.cpp index 7a669ba835..b1880cd462 100644 --- a/plugins/tools/karbonplugins/filtereffects/ColorMatrixEffectConfigWidget.cpp +++ b/plugins/tools/karbonplugins/filtereffects/ColorMatrixEffectConfigWidget.cpp @@ -1,179 +1,181 @@ /* This file is part of the KDE project * Copyright (c) 2009-2010 Jan Hambrecht * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 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 Lesser 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. */ #include "ColorMatrixEffectConfigWidget.h" #include "ColorMatrixEffect.h" #include "KoFilterEffect.h" #include "MatrixDataModel.h" #include #include #include #include #include #include #include #include +#include "kis_double_parse_spin_box.h" + ColorMatrixEffectConfigWidget::ColorMatrixEffectConfigWidget(QWidget *parent) : KoFilterEffectConfigWidgetBase(parent) , m_effect(0) { QGridLayout *g = new QGridLayout(this); m_type = new KComboBox(this); m_type->addItem(i18n("Apply color matrix")); m_type->addItem(i18n("Saturate colors")); m_type->addItem(i18n("Rotate hue")); m_type->addItem(i18n("Luminance to alpha")); g->addWidget(m_type, 0, 0); m_stack = new QStackedWidget(this); m_stack->setContentsMargins(0, 0, 0, 0); g->addWidget(m_stack, 1, 0); m_matrixModel = new MatrixDataModel(this); QTableView *matrixWidget = new QTableView(m_stack); matrixWidget->setModel(m_matrixModel); matrixWidget->horizontalHeader()->hide(); matrixWidget->horizontalHeader()->setResizeMode(QHeaderView::Stretch); matrixWidget->verticalHeader()->hide(); matrixWidget->verticalHeader()->setResizeMode(QHeaderView::ResizeToContents); m_stack->addWidget(matrixWidget); QWidget *saturateWidget = new QWidget(m_stack); QGridLayout *saturateLayout = new QGridLayout(saturateWidget); saturateLayout->addWidget(new QLabel(i18n("Saturate value"), saturateWidget), 0, 0); - m_saturate = new QDoubleSpinBox(saturateWidget); + m_saturate = new KisDoubleParseSpinBox(saturateWidget); m_saturate->setRange(0.0, 1.0); m_saturate->setSingleStep(0.05); saturateLayout->addWidget(m_saturate, 0, 1); saturateLayout->addItem(new QSpacerItem(0, 1, QSizePolicy::Minimum, QSizePolicy::MinimumExpanding), 1, 0); saturateWidget->setLayout(saturateLayout); m_stack->addWidget(saturateWidget); QWidget *hueRotateWidget = new QWidget(m_stack); QGridLayout *hueRotateLayout = new QGridLayout(hueRotateWidget); hueRotateLayout->addWidget(new QLabel(i18n("Angle"), hueRotateWidget), 0, 0); - m_hueRotate = new QDoubleSpinBox(hueRotateWidget); + m_hueRotate = new KisDoubleParseSpinBox(hueRotateWidget); m_hueRotate->setRange(0.0, 360.0); m_hueRotate->setSingleStep(1.0); hueRotateLayout->addWidget(m_hueRotate, 0, 1); hueRotateLayout->addItem(new QSpacerItem(0, 1, QSizePolicy::Minimum, QSizePolicy::MinimumExpanding), 1, 0); hueRotateWidget->setLayout(hueRotateLayout); m_stack->addWidget(hueRotateWidget); QWidget *luminanceWidget = new QWidget(m_stack); m_stack->addWidget(luminanceWidget); setLayout(g); connect(m_type, SIGNAL(currentIndexChanged(int)), m_stack, SLOT(setCurrentIndex(int))); connect(m_type, SIGNAL(currentIndexChanged(int)), this, SLOT(typeChanged(int))); connect(m_saturate, SIGNAL(valueChanged(double)), this, SLOT(saturateChanged(double))); connect(m_hueRotate, SIGNAL(valueChanged(double)), this, SLOT(hueRotateChanged(double))); connect(m_matrixModel, SIGNAL(dataChanged(QModelIndex,QModelIndex)), this, SLOT(matrixChanged())); } bool ColorMatrixEffectConfigWidget::editFilterEffect(KoFilterEffect *filterEffect) { m_effect = dynamic_cast(filterEffect); if (!m_effect) { return false; } m_type->blockSignals(true); switch (m_effect->type()) { case ColorMatrixEffect::Matrix: m_type->setCurrentIndex(0); m_matrixModel->setMatrix(m_effect->colorMatrix(), m_effect->colorMatrixRowCount(), m_effect->colorMatrixColumnCount()); break; case ColorMatrixEffect::Saturate: m_type->setCurrentIndex(1); m_saturate->blockSignals(true); m_saturate->setValue(m_effect->saturate()); m_saturate->blockSignals(false); break; case ColorMatrixEffect::HueRotate: m_type->setCurrentIndex(2); m_hueRotate->blockSignals(true); m_hueRotate->setValue(m_effect->hueRotate()); m_hueRotate->blockSignals(false); break; case ColorMatrixEffect::LuminanceAlpha: m_type->setCurrentIndex(3); break; } m_type->blockSignals(false); m_stack->setCurrentIndex(m_type->currentIndex()); return true; } void ColorMatrixEffectConfigWidget::matrixChanged() { if (!m_effect) { return; } m_effect->setColorMatrix(m_matrixModel->matrix()); emit filterChanged(); } void ColorMatrixEffectConfigWidget::saturateChanged(double saturate) { if (!m_effect) { return; } m_effect->setSaturate(saturate); emit filterChanged(); } void ColorMatrixEffectConfigWidget::hueRotateChanged(double angle) { if (!m_effect) { return; } m_effect->setHueRotate(angle); emit filterChanged(); } void ColorMatrixEffectConfigWidget::typeChanged(int index) { if (!m_effect) { return; } if (index == ColorMatrixEffect::Matrix) { m_effect->setColorMatrix(m_matrixModel->matrix()); } else if (index == ColorMatrixEffect::Saturate) { m_effect->setSaturate(m_saturate->value()); } else if (index == ColorMatrixEffect::HueRotate) { m_effect->setHueRotate(m_hueRotate->value()); } else { m_effect->setLuminanceAlpha(); } emit filterChanged(); } diff --git a/plugins/tools/karbonplugins/filtereffects/ComponentTransferEffectConfigWidget.cpp b/plugins/tools/karbonplugins/filtereffects/ComponentTransferEffectConfigWidget.cpp index 21335b226f..a47c1e1eb4 100644 --- a/plugins/tools/karbonplugins/filtereffects/ComponentTransferEffectConfigWidget.cpp +++ b/plugins/tools/karbonplugins/filtereffects/ComponentTransferEffectConfigWidget.cpp @@ -1,303 +1,305 @@ /* This file is part of the KDE project * Copyright (c) 2009 Jan Hambrecht * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 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 Lesser 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. */ #include "ComponentTransferEffectConfigWidget.h" #include "KoFilterEffect.h" #include #include #include #include #include #include #include #include #include +#include "kis_double_parse_spin_box.h" + const qreal ValueStep = 0.1; ComponentTransferEffectConfigWidget::ComponentTransferEffectConfigWidget(QWidget *parent) : KoFilterEffectConfigWidgetBase(parent) , m_effect(0) , m_currentChannel(ComponentTransferEffect::ChannelR) { QGridLayout *g = new QGridLayout(this); QButtonGroup *group = new QButtonGroup(this); QRadioButton *butR = new QRadioButton("R", this); QRadioButton *butG = new QRadioButton("G", this); QRadioButton *butB = new QRadioButton("B", this); QRadioButton *butA = new QRadioButton("A", this); g->addWidget(butR, 0, 0); g->addWidget(butG, 0, 1); g->addWidget(butB, 0, 2); g->addWidget(butA, 0, 3); group->addButton(butR, ComponentTransferEffect::ChannelR); group->addButton(butG, ComponentTransferEffect::ChannelG); group->addButton(butB, ComponentTransferEffect::ChannelB); group->addButton(butA, ComponentTransferEffect::ChannelA); butR->setChecked(true); g->addWidget(new QLabel(i18n("Function"), this), 1, 0, 1, 2); m_function = new KComboBox(this); m_function->addItem(i18n("Identity")); m_function->addItem(i18n("Table")); m_function->addItem(i18n("Discrete")); m_function->addItem(i18n("Linear")); m_function->addItem(i18n("Gamma")); g->addWidget(m_function, 1, 2, 1, 2); m_stack = new QStackedWidget(this); m_stack->setContentsMargins(0, 0, 0, 0); g->addWidget(m_stack, 2, 0, 1, 4); // Identity widget m_stack->addWidget(new QWidget(this)); // Table widget QWidget *tableWidget = new QWidget(m_stack); QGridLayout *tableLayout = new QGridLayout(tableWidget); tableLayout->addWidget(new QLabel(i18n("Values"), tableWidget), 0, 0); m_tableValues = new KLineEdit(tableWidget); tableLayout->addWidget(m_tableValues, 0, 1); tableLayout->setContentsMargins(0, 0, 0, 0); tableLayout->addItem(new QSpacerItem(0, 1, QSizePolicy::Minimum, QSizePolicy::MinimumExpanding), 1, 0); m_stack->addWidget(tableWidget); // Discrete widget QWidget *discreteWidget = new QWidget(m_stack); QGridLayout *discreteLayout = new QGridLayout(discreteWidget); discreteLayout->addWidget(new QLabel(i18n("Values"), discreteWidget), 0, 0); m_discreteValues = new KLineEdit(discreteWidget); discreteLayout->addWidget(m_discreteValues, 0, 1); discreteLayout->setContentsMargins(0, 0, 0, 0); discreteLayout->addItem(new QSpacerItem(0, 1, QSizePolicy::Minimum, QSizePolicy::MinimumExpanding), 1, 0); m_stack->addWidget(discreteWidget); // Linear widget QWidget *linearWidget = new QWidget(m_stack); QGridLayout *linearLayout = new QGridLayout(linearWidget); linearLayout->addWidget(new QLabel(i18n("Slope"), linearWidget), 0, 0); - m_slope = new QDoubleSpinBox(linearWidget); + m_slope = new KisDoubleParseSpinBox(linearWidget); m_slope->setRange(m_slope->minimum(), m_slope->maximum()); m_slope->setSingleStep(ValueStep); linearLayout->addWidget(m_slope, 0, 1); linearLayout->addWidget(new QLabel(i18n("Intercept")), 1, 0); - m_intercept = new QDoubleSpinBox(linearWidget); + m_intercept = new KisDoubleParseSpinBox(linearWidget); m_intercept->setRange(m_intercept->minimum(), m_intercept->maximum()); m_intercept->setSingleStep(ValueStep); linearLayout->addWidget(m_intercept, 1, 1); linearLayout->addItem(new QSpacerItem(0, 1, QSizePolicy::Minimum, QSizePolicy::MinimumExpanding), 2, 0); linearLayout->setContentsMargins(0, 0, 0, 0); linearWidget->setLayout(linearLayout); m_stack->addWidget(linearWidget); QWidget *gammaWidget = new QWidget(m_stack); QGridLayout *gammaLayout = new QGridLayout(gammaWidget); gammaLayout->addWidget(new QLabel(i18n("Amplitude"), gammaWidget), 0, 0); - m_amplitude = new QDoubleSpinBox(gammaWidget); + m_amplitude = new KisDoubleParseSpinBox(gammaWidget); m_amplitude->setRange(m_amplitude->minimum(), m_amplitude->maximum()); m_amplitude->setSingleStep(ValueStep); gammaLayout->addWidget(m_amplitude, 0, 1); gammaLayout->addWidget(new QLabel(i18n("Exponent"), gammaWidget), 1, 0); - m_exponent = new QDoubleSpinBox(gammaWidget); + m_exponent = new KisDoubleParseSpinBox(gammaWidget); m_exponent->setRange(m_exponent->minimum(), m_exponent->maximum()); m_exponent->setSingleStep(ValueStep); gammaLayout->addWidget(m_exponent, 1, 1); gammaLayout->addWidget(new QLabel(i18n("Offset"), gammaWidget), 2, 0); - m_offset = new QDoubleSpinBox(gammaWidget); + m_offset = new KisDoubleParseSpinBox(gammaWidget); m_offset->setRange(m_offset->minimum(), m_offset->maximum()); m_offset->setSingleStep(ValueStep); gammaLayout->addWidget(m_offset, 2, 1); gammaLayout->addItem(new QSpacerItem(0, 1, QSizePolicy::Minimum, QSizePolicy::MinimumExpanding), 3, 0); gammaLayout->setContentsMargins(0, 0, 0, 0); gammaWidget->setLayout(gammaLayout); m_stack->addWidget(gammaWidget); setLayout(g); connect(m_function, SIGNAL(currentIndexChanged(int)), m_stack, SLOT(setCurrentIndex(int))); connect(m_function, SIGNAL(currentIndexChanged(int)), this, SLOT(functionChanged(int))); connect(m_tableValues, SIGNAL(editingFinished()), this, SLOT(tableValuesChanged())); connect(m_discreteValues, SIGNAL(editingFinished()), this, SLOT(discreteValuesChanged())); connect(m_slope, SIGNAL(valueChanged(double)), this, SLOT(slopeChanged(double))); connect(m_intercept, SIGNAL(valueChanged(double)), this, SLOT(interceptChanged(double))); connect(m_amplitude, SIGNAL(valueChanged(double)), this, SLOT(amplitudeChanged(double))); connect(m_exponent, SIGNAL(valueChanged(double)), this, SLOT(exponentChanged(double))); connect(m_offset, SIGNAL(valueChanged(double)), this, SLOT(offsetChanged(double))); connect(group, SIGNAL(buttonClicked(int)), this, SLOT(channelSelected(int))); } void ComponentTransferEffectConfigWidget::updateControls() { m_function->blockSignals(true); QString values; switch (m_effect->function(m_currentChannel)) { case ComponentTransferEffect::Identity: m_function->setCurrentIndex(0); break; case ComponentTransferEffect::Table: m_function->setCurrentIndex(1); m_tableValues->blockSignals(true); Q_FOREACH (qreal v, m_effect->tableValues(m_currentChannel)) { values += QString("%1;").arg(v); } m_tableValues->setText(values); m_tableValues->blockSignals(false); break; case ComponentTransferEffect::Discrete: m_function->setCurrentIndex(2); m_discreteValues->blockSignals(true); Q_FOREACH (qreal v, m_effect->tableValues(m_currentChannel)) { values += QString("%1;").arg(v); } m_discreteValues->setText(values); m_discreteValues->blockSignals(false); break; case ComponentTransferEffect::Linear: m_function->setCurrentIndex(3); m_slope->blockSignals(true); m_slope->setValue(m_effect->slope(m_currentChannel)); m_slope->blockSignals(false); m_intercept->blockSignals(true); m_intercept->setValue(m_effect->intercept(m_currentChannel)); m_intercept->blockSignals(false); break; case ComponentTransferEffect::Gamma: m_function->setCurrentIndex(4); m_amplitude->blockSignals(true); m_amplitude->setValue(m_effect->amplitude(m_currentChannel)); m_amplitude->blockSignals(false); m_exponent->blockSignals(true); m_exponent->setValue(m_effect->exponent(m_currentChannel)); m_exponent->blockSignals(false); m_offset->blockSignals(true); m_offset->setValue(m_effect->offset(m_currentChannel)); m_offset->blockSignals(false); break; } m_function->blockSignals(false); m_stack->setCurrentIndex(m_function->currentIndex()); } bool ComponentTransferEffectConfigWidget::editFilterEffect(KoFilterEffect *filterEffect) { m_effect = dynamic_cast(filterEffect); if (!m_effect) { return false; } updateControls(); return true; } void ComponentTransferEffectConfigWidget::slopeChanged(double slope) { if (!m_effect) { return; } m_effect->setSlope(m_currentChannel, slope); emit filterChanged(); } void ComponentTransferEffectConfigWidget::interceptChanged(double intercept) { if (!m_effect) { return; } m_effect->setIntercept(m_currentChannel, intercept); emit filterChanged(); } void ComponentTransferEffectConfigWidget::amplitudeChanged(double amplitude) { if (!m_effect) { return; } m_effect->setAmplitude(m_currentChannel, amplitude); emit filterChanged(); } void ComponentTransferEffectConfigWidget::exponentChanged(double exponent) { if (!m_effect) { return; } m_effect->setExponent(m_currentChannel, exponent); emit filterChanged(); } void ComponentTransferEffectConfigWidget::offsetChanged(double offset) { if (!m_effect) { return; } m_effect->setOffset(m_currentChannel, offset); emit filterChanged(); } void ComponentTransferEffectConfigWidget::tableValuesChanged() { QStringList values = m_tableValues->text().split(';', QString::SkipEmptyParts); QList tableValues; Q_FOREACH (const QString &v, values) { tableValues.append(v.toDouble()); } m_effect->setTableValues(m_currentChannel, tableValues); emit filterChanged(); } void ComponentTransferEffectConfigWidget::discreteValuesChanged() { QStringList values = m_discreteValues->text().split(';', QString::SkipEmptyParts); QList tableValues; Q_FOREACH (const QString &v, values) { tableValues.append(v.toDouble()); } m_effect->setTableValues(m_currentChannel, tableValues); emit filterChanged(); } void ComponentTransferEffectConfigWidget::functionChanged(int index) { if (!m_effect) { return; } m_effect->setFunction(m_currentChannel, static_cast(index)); emit filterChanged(); } void ComponentTransferEffectConfigWidget::channelSelected(int channel) { m_currentChannel = static_cast(channel); updateControls(); } diff --git a/plugins/tools/karbonplugins/filtereffects/CompositeEffectConfigWidget.cpp b/plugins/tools/karbonplugins/filtereffects/CompositeEffectConfigWidget.cpp index 5277de7a00..53ea1d4a0e 100644 --- a/plugins/tools/karbonplugins/filtereffects/CompositeEffectConfigWidget.cpp +++ b/plugins/tools/karbonplugins/filtereffects/CompositeEffectConfigWidget.cpp @@ -1,107 +1,109 @@ /* This file is part of the KDE project * Copyright (c) 2009 Jan Hambrecht * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 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 Lesser 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. */ #include "CompositeEffectConfigWidget.h" #include "CompositeEffect.h" #include "KoFilterEffect.h" #include #include #include #include #include +#include "kis_double_parse_spin_box.h" + CompositeEffectConfigWidget::CompositeEffectConfigWidget(QWidget *parent) : KoFilterEffectConfigWidgetBase(parent) , m_effect(0) { QGridLayout *g = new QGridLayout(this); g->addWidget(new QLabel(i18n("Operation"), this), 0, 0); m_operation = new KComboBox(this); m_operation->addItem(i18nc("blending mode", "Over")); m_operation->addItem(i18nc("blending mode", "In")); m_operation->addItem(i18nc("blending mode", "Out")); m_operation->addItem(i18nc("blending mode", "Atop")); m_operation->addItem(i18nc("blending mode", "Xor")); m_operation->addItem(i18nc("blending mode", "Arithmetic")); g->addWidget(m_operation, 0, 1); m_arithmeticWidget = new QWidget(this); QGridLayout *arithmeticLayout = new QGridLayout(m_arithmeticWidget); for (int i = 0; i < 4; ++i) { - m_k[i] = new QDoubleSpinBox(m_arithmeticWidget); + m_k[i] = new KisDoubleParseSpinBox(m_arithmeticWidget); arithmeticLayout->addWidget(new QLabel(QString("k%1").arg(i + 1)), i / 2, (2 * i) % 4); arithmeticLayout->addWidget(m_k[i], i / 2, (2 * i + 1) % 4); connect(m_k[i], SIGNAL(valueChanged(double)), this, SLOT(valueChanged())); } m_arithmeticWidget->setContentsMargins(0, 0, 0, 0); g->addWidget(m_arithmeticWidget, 1, 0, 1, 2); g->addItem(new QSpacerItem(0, 1, QSizePolicy::Minimum, QSizePolicy::MinimumExpanding), 2, 0); connect(m_operation, SIGNAL(currentIndexChanged(int)), this, SLOT(operationChanged(int))); } bool CompositeEffectConfigWidget::editFilterEffect(KoFilterEffect *filterEffect) { m_effect = dynamic_cast(filterEffect); if (!m_effect) { return false; } m_operation->blockSignals(true); m_operation->setCurrentIndex(m_effect->operation()); m_operation->blockSignals(false); const qreal *k = m_effect->arithmeticValues(); for (int i = 0; i < 4; ++i) { m_k[i]->blockSignals(true); m_k[i]->setValue(k[i]); m_k[i]->blockSignals(false); } m_arithmeticWidget->setVisible(m_effect->operation() == CompositeEffect::Arithmetic); return true; } void CompositeEffectConfigWidget::operationChanged(int index) { m_arithmeticWidget->setVisible(index == 6); if (m_effect) { m_effect->setOperation(static_cast(index)); emit filterChanged(); } } void CompositeEffectConfigWidget::valueChanged() { if (!m_effect) { return; } qreal k[4] = {0}; for (int i = 0; i < 4; ++i) { k[i] = m_k[i]->value(); } m_effect->setArithmeticValues(k); emit filterChanged(); } diff --git a/plugins/tools/karbonplugins/filtereffects/ConvolveMatrixEffectConfigWidget.cpp b/plugins/tools/karbonplugins/filtereffects/ConvolveMatrixEffectConfigWidget.cpp index 1e8c1575fe..6bacd30a5a 100644 --- a/plugins/tools/karbonplugins/filtereffects/ConvolveMatrixEffectConfigWidget.cpp +++ b/plugins/tools/karbonplugins/filtereffects/ConvolveMatrixEffectConfigWidget.cpp @@ -1,259 +1,262 @@ /* This file is part of the KDE project * Copyright (c) 2010 Jan Hambrecht * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 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 Lesser 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. */ #include "ConvolveMatrixEffectConfigWidget.h" #include "ConvolveMatrixEffect.h" #include "KoFilterEffect.h" #include "MatrixDataModel.h" #include #include #include #include #include #include #include #include #include #include #include +#include "kis_double_parse_spin_box.h" +#include "kis_int_parse_spin_box.h" + ConvolveMatrixEffectConfigWidget::ConvolveMatrixEffectConfigWidget(QWidget *parent) : KoFilterEffectConfigWidgetBase(parent) , m_effect(0) { QGridLayout *g = new QGridLayout(this); m_edgeMode = new KComboBox(this); m_edgeMode->addItem(i18n("Duplicate")); m_edgeMode->addItem(i18n("Wrap")); m_edgeMode->addItem(i18n("None")); g->addWidget(new QLabel(i18n("Edge mode:"), this), 0, 0); g->addWidget(m_edgeMode, 0, 1, 1, 3); - m_orderX = new QSpinBox(this); + m_orderX = new KisIntParseSpinBox(this); m_orderX->setRange(1, 30); - m_orderY = new QSpinBox(this); + m_orderY = new KisIntParseSpinBox(this); m_orderY->setRange(1, 30); g->addWidget(new QLabel(i18n("Kernel size:"), this), 1, 0); g->addWidget(m_orderX, 1, 1); g->addWidget(new QLabel("X", this), 1, 2, Qt::AlignHCenter); g->addWidget(m_orderY, 1, 3); - m_targetX = new QSpinBox(this); + m_targetX = new KisIntParseSpinBox(this); m_targetX->setRange(0, 30); - m_targetY = new QSpinBox(this); + m_targetY = new KisIntParseSpinBox(this); m_targetY->setRange(0, 30); g->addWidget(new QLabel(i18n("Target point:"), this), 2, 0); g->addWidget(m_targetX, 2, 1); g->addWidget(new QLabel("X", this), 2, 2, Qt::AlignHCenter); g->addWidget(m_targetY, 2, 3); - m_divisor = new QDoubleSpinBox(this); - m_bias = new QDoubleSpinBox(this); + m_divisor = new KisDoubleParseSpinBox(this); + m_bias = new KisDoubleParseSpinBox(this); g->addWidget(new QLabel(i18n("Divisor:"), this), 3, 0); g->addWidget(m_divisor, 3, 1); g->addWidget(new QLabel(i18n("Bias:"), this), 3, 2); g->addWidget(m_bias, 3, 3); m_preserveAlpha = new QCheckBox(i18n("Preserve alpha"), this); g->addWidget(m_preserveAlpha, 4, 1, 1, 3); QPushButton *kernelButton = new QPushButton(i18n("Edit kernel"), this); g->addWidget(kernelButton, 5, 0, 1, 4); setLayout(g); connect(m_edgeMode, SIGNAL(currentIndexChanged(int)), this, SLOT(edgeModeChanged(int))); connect(m_orderX, SIGNAL(valueChanged(int)), this, SLOT(orderChanged(int))); connect(m_orderY, SIGNAL(valueChanged(int)), this, SLOT(orderChanged(int))); connect(m_targetX, SIGNAL(valueChanged(int)), this, SLOT(targetChanged(int))); connect(m_targetY, SIGNAL(valueChanged(int)), this, SLOT(targetChanged(int))); connect(m_divisor, SIGNAL(valueChanged(double)), this, SLOT(divisorChanged(double))); connect(m_bias, SIGNAL(valueChanged(double)), this, SLOT(biasChanged(double))); connect(kernelButton, SIGNAL(clicked(bool)), this, SLOT(editKernel())); connect(m_preserveAlpha, SIGNAL(toggled(bool)), this, SLOT(preserveAlphaChanged(bool))); m_matrixModel = new MatrixDataModel(this); } bool ConvolveMatrixEffectConfigWidget::editFilterEffect(KoFilterEffect *filterEffect) { m_effect = dynamic_cast(filterEffect); if (!m_effect) { return false; } m_edgeMode->blockSignals(true); m_edgeMode->setCurrentIndex(m_effect->edgeMode()); m_edgeMode->blockSignals(false); m_orderX->blockSignals(true); m_orderX->setValue(m_effect->order().x()); m_orderX->blockSignals(false); m_orderY->blockSignals(true); m_orderY->setValue(m_effect->order().y()); m_orderY->blockSignals(false); m_targetX->blockSignals(true); m_targetX->setMaximum(m_orderX->value()); m_targetX->setValue(m_effect->target().x() + 1); m_targetX->blockSignals(false); m_targetY->blockSignals(true); m_targetY->setMaximum(m_orderY->value()); m_targetY->setValue(m_effect->target().y() + 1); m_targetY->blockSignals(false); m_divisor->blockSignals(true); m_divisor->setValue(m_effect->divisor()); m_divisor->blockSignals(false); m_bias->blockSignals(true); m_bias->setValue(m_effect->bias()); m_bias->blockSignals(false); m_preserveAlpha->blockSignals(true); m_preserveAlpha->setChecked(m_effect->isPreserveAlphaEnabled()); m_preserveAlpha->blockSignals(false); return true; } void ConvolveMatrixEffectConfigWidget::edgeModeChanged(int id) { if (!m_effect) { return; } switch (id) { case ConvolveMatrixEffect::Duplicate: m_effect->setEdgeMode(ConvolveMatrixEffect::Duplicate); break; case ConvolveMatrixEffect::Wrap: m_effect->setEdgeMode(ConvolveMatrixEffect::Wrap); break; case ConvolveMatrixEffect::None: m_effect->setEdgeMode(ConvolveMatrixEffect::None); break; } emit filterChanged(); } void ConvolveMatrixEffectConfigWidget::orderChanged(int) { if (!m_effect) { return; } QPoint newOrder(m_orderX->value(), m_orderY->value()); QPoint oldOrder = m_effect->order(); if (newOrder != oldOrder) { m_effect->setOrder(newOrder); emit filterChanged(); } m_targetX->setMaximum(newOrder.x()); m_targetY->setMaximum(newOrder.y()); } void ConvolveMatrixEffectConfigWidget::targetChanged(int) { if (!m_effect) { return; } QPoint newTarget(m_targetX->value() - 1, m_targetY->value() - 1); QPoint oldTarget = m_effect->target(); if (newTarget != oldTarget) { m_effect->setTarget(newTarget); emit filterChanged(); } } void ConvolveMatrixEffectConfigWidget::divisorChanged(double divisor) { if (!m_effect) { return; } if (divisor != m_effect->divisor()) { m_effect->setDivisor(divisor); emit filterChanged(); } } void ConvolveMatrixEffectConfigWidget::biasChanged(double bias) { if (!m_effect) { return; } if (bias != m_effect->bias()) { m_effect->setBias(bias); emit filterChanged(); } } void ConvolveMatrixEffectConfigWidget::preserveAlphaChanged(bool checked) { if (!m_effect) { return; } m_effect->enablePreserveAlpha(checked); emit filterChanged(); } void ConvolveMatrixEffectConfigWidget::editKernel() { if (!m_effect) { return; } QVector oldKernel = m_effect->kernel(); QPoint kernelSize = m_effect->order(); m_matrixModel->setMatrix(oldKernel, kernelSize.y(), kernelSize.x()); connect(m_matrixModel, SIGNAL(dataChanged(QModelIndex,QModelIndex)), this, SLOT(kernelChanged())); QPointer dlg = new QDialog(this); QTableView *table = new QTableView(dlg); table->setModel(m_matrixModel); table->horizontalHeader()->hide(); table->horizontalHeader()->setResizeMode(QHeaderView::Stretch); table->verticalHeader()->hide(); table->verticalHeader()->setResizeMode(QHeaderView::ResizeToContents); QVBoxLayout *mainLayout = new QVBoxLayout; dlg->setLayout(mainLayout); mainLayout->addWidget(table); if (dlg->exec() == QDialog::Accepted) { m_effect->setKernel(m_matrixModel->matrix()); emit filterChanged(); } else { m_effect->setKernel(oldKernel); } delete dlg; disconnect(m_matrixModel, SIGNAL(dataChanged(QModelIndex,QModelIndex)), this, SLOT(kernelChanged())); } void ConvolveMatrixEffectConfigWidget::kernelChanged() { if (!m_effect) { return; } m_effect->setKernel(m_matrixModel->matrix()); emit filterChanged(); } diff --git a/plugins/tools/karbonplugins/filtereffects/MatrixDataModel.cpp b/plugins/tools/karbonplugins/filtereffects/MatrixDataModel.cpp index 542feef32e..ace47513cf 100644 --- a/plugins/tools/karbonplugins/filtereffects/MatrixDataModel.cpp +++ b/plugins/tools/karbonplugins/filtereffects/MatrixDataModel.cpp @@ -1,84 +1,86 @@ /* This file is part of the KDE project * Copyright (c) 2010 Jan Hambrecht * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 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 Lesser 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. */ #include "MatrixDataModel.h" +#include "kis_num_parser.h" + MatrixDataModel::MatrixDataModel(QObject *parent) : QAbstractTableModel(parent) , m_rows(0) , m_cols(0) { } void MatrixDataModel::setMatrix(const QVector &matrix, int rows, int cols) { m_matrix = matrix; m_rows = rows; m_cols = cols; Q_ASSERT(m_rows); Q_ASSERT(m_cols); Q_ASSERT(m_matrix.count() == m_rows * m_cols); reset(); } QVector MatrixDataModel::matrix() const { return m_matrix; } int MatrixDataModel::rowCount(const QModelIndex &/*parent*/) const { return m_rows; } int MatrixDataModel::columnCount(const QModelIndex &/*parent*/) const { return m_cols; } QVariant MatrixDataModel::data(const QModelIndex &index, int role) const { int element = index.row() * m_cols + index.column(); switch (role) { case Qt::DisplayRole: case Qt::EditRole: return QVariant(QString("%1").arg(m_matrix[element], 2)); break; default: return QVariant(); } } bool MatrixDataModel::setData(const QModelIndex &index, const QVariant &value, int /*role*/) { int element = index.row() * m_cols + index.column(); bool valid = false; - qreal elementValue = value.toDouble(&valid); + qreal elementValue = KisNumericParser::parseSimpleMathExpr(value.toString(), &valid); if (!valid) { return false; } m_matrix[element] = elementValue; emit dataChanged(index, index); return true; } Qt::ItemFlags MatrixDataModel::flags(const QModelIndex &/*index*/) const { return Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsEditable; } diff --git a/plugins/tools/karbonplugins/filtereffects/MorphologyEffectConfigWidget.cpp b/plugins/tools/karbonplugins/filtereffects/MorphologyEffectConfigWidget.cpp index 4be93505f9..242a5ff688 100644 --- a/plugins/tools/karbonplugins/filtereffects/MorphologyEffectConfigWidget.cpp +++ b/plugins/tools/karbonplugins/filtereffects/MorphologyEffectConfigWidget.cpp @@ -1,129 +1,131 @@ /* This file is part of the KDE project * Copyright (c) 2010 Jan Hambrecht * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 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 Lesser 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. */ #include "MorphologyEffectConfigWidget.h" #include "MorphologyEffect.h" #include "KoFilterEffect.h" #include #include #include #include #include #include +#include "kis_double_parse_spin_box.h" + MorphologyEffectConfigWidget::MorphologyEffectConfigWidget(QWidget *parent) : KoFilterEffectConfigWidgetBase(parent) , m_effect(0) { QGridLayout *g = new QGridLayout(this); m_operator = new QButtonGroup(this); QRadioButton *erode = new QRadioButton(i18n("Erode"), this); QRadioButton *dilate = new QRadioButton(i18n("Dilate"), this); m_operator->addButton(erode, MorphologyEffect::Erode); m_operator->addButton(dilate, MorphologyEffect::Dilate); g->addWidget(new QLabel(i18n("Operator:"), this), 0, 0); g->addWidget(erode, 0, 1); g->addWidget(dilate, 0, 2); g->addWidget(new QLabel(i18n("Radius x:"), this), 1, 0); - m_radiusX = new QDoubleSpinBox(this); + m_radiusX = new KisDoubleParseSpinBox(this); m_radiusX->setRange(0.0, 100); m_radiusX->setSingleStep(0.5); g->addWidget(m_radiusX, 1, 1, 1, 2); g->addWidget(new QLabel(i18n("Radius y:"), this), 2, 0); - m_radiusY = new QDoubleSpinBox(this); + m_radiusY = new KisDoubleParseSpinBox(this); m_radiusY->setRange(0.0, 100); m_radiusY->setSingleStep(0.5); g->addWidget(m_radiusY, 2, 1, 1, 2); setLayout(g); connect(m_operator, SIGNAL(buttonClicked(int)), this, SLOT(operatorChanged(int))); connect(m_radiusX, SIGNAL(valueChanged(double)), this, SLOT(radiusXChanged(double))); connect(m_radiusY, SIGNAL(valueChanged(double)), this, SLOT(radiusYChanged(double))); } bool MorphologyEffectConfigWidget::editFilterEffect(KoFilterEffect *filterEffect) { m_effect = dynamic_cast(filterEffect); if (!m_effect) { return false; } m_operator->blockSignals(true); m_operator->button(m_effect->morphologyOperator())->setChecked(true); m_operator->blockSignals(false); m_radiusX->blockSignals(true); m_radiusX->setValue(m_effect->morphologyRadius().x() * 100); m_radiusX->blockSignals(false); m_radiusY->blockSignals(true); m_radiusY->setValue(m_effect->morphologyRadius().y() * 100); m_radiusY->blockSignals(false); return true; } void MorphologyEffectConfigWidget::operatorChanged(int id) { if (!m_effect) { return; } switch (id) { case MorphologyEffect::Erode: m_effect->setMorphologyOperator(MorphologyEffect::Erode); break; case MorphologyEffect::Dilate: m_effect->setMorphologyOperator(MorphologyEffect::Dilate); break; } emit filterChanged(); } void MorphologyEffectConfigWidget::radiusXChanged(double x) { if (!m_effect) { return; } QPointF radius = m_effect->morphologyRadius(); if (radius.x() != x) { m_effect->setMorphologyRadius(QPointF(x * 0.01, radius.y())); } emit filterChanged(); } void MorphologyEffectConfigWidget::radiusYChanged(double y) { if (!m_effect) { return; } QPointF radius = m_effect->morphologyRadius(); if (radius.y() != y) { m_effect->setMorphologyRadius(QPointF(radius.x(), y * 0.01)); } emit filterChanged(); } diff --git a/plugins/tools/karbonplugins/filtereffects/OffsetEffectConfigWidget.cpp b/plugins/tools/karbonplugins/filtereffects/OffsetEffectConfigWidget.cpp index 5141ab321f..5c60535ec8 100644 --- a/plugins/tools/karbonplugins/filtereffects/OffsetEffectConfigWidget.cpp +++ b/plugins/tools/karbonplugins/filtereffects/OffsetEffectConfigWidget.cpp @@ -1,78 +1,80 @@ /* This file is part of the KDE project * Copyright (c) 2009 Jan Hambrecht * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 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 Lesser 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. */ #include "OffsetEffectConfigWidget.h" #include "OffsetEffect.h" #include "KoFilterEffect.h" #include #include #include #include +#include "kis_double_parse_spin_box.h" + const qreal OffsetLimit = 100.0; OffsetEffectConfigWidget::OffsetEffectConfigWidget(QWidget *parent) : KoFilterEffectConfigWidgetBase(parent) , m_effect(0) { QGridLayout *g = new QGridLayout(this); g->addWidget(new QLabel(i18n("dx"), this), 0, 0); - m_offsetX = new QDoubleSpinBox(this); + m_offsetX = new KisDoubleParseSpinBox(this); m_offsetX->setRange(-OffsetLimit, OffsetLimit); m_offsetX->setSingleStep(1.0); g->addWidget(m_offsetX, 0, 1); g->addWidget(new QLabel(i18n("dy"), this), 0, 2); - m_offsetY = new QDoubleSpinBox(this); + m_offsetY = new KisDoubleParseSpinBox(this); m_offsetY->setRange(-OffsetLimit, OffsetLimit); m_offsetY->setSingleStep(1.0); g->addWidget(m_offsetY, 0, 3); setLayout(g); connect(m_offsetX, SIGNAL(valueChanged(double)), this, SLOT(offsetChanged(double))); connect(m_offsetY, SIGNAL(valueChanged(double)), this, SLOT(offsetChanged(double))); } bool OffsetEffectConfigWidget::editFilterEffect(KoFilterEffect *filterEffect) { m_effect = dynamic_cast(filterEffect); if (!m_effect) { return false; } m_offsetX->blockSignals(true); m_offsetY->blockSignals(true); m_offsetX->setValue(m_effect->offset().x() * 100.0); m_offsetY->setValue(m_effect->offset().y() * 100.0); m_offsetX->blockSignals(false); m_offsetY->blockSignals(false); return true; } void OffsetEffectConfigWidget::offsetChanged(double /*offset*/) { if (!m_effect) { return; } m_effect->setOffset(0.01 * QPointF(m_offsetX->value(), m_offsetY->value())); emit filterChanged(); } diff --git a/plugins/tools/karbonplugins/tools/CMakeLists.txt b/plugins/tools/karbonplugins/tools/CMakeLists.txt index 83e14f9763..2bdf67690f 100644 --- a/plugins/tools/karbonplugins/tools/CMakeLists.txt +++ b/plugins/tools/karbonplugins/tools/CMakeLists.txt @@ -1,50 +1,50 @@ include_directories( ${CMAKE_CURRENT_SOURCE_DIR}/filterEffectTool ) ########### next target ############### set(karbon_tools_SOURCES KarbonToolsPlugin.cpp KarbonCursor.cpp CalligraphyTool/KarbonCalligraphyTool.cpp CalligraphyTool/KarbonCalligraphyOptionWidget.cpp CalligraphyTool/KarbonCalligraphyToolFactory.cpp CalligraphyTool/KarbonCalligraphicShape.cpp CalligraphyTool/KarbonCalligraphicShapeFactory.cpp CalligraphyTool/KarbonSimplifyPath.cpp KarbonGradientTool.cpp KarbonGradientToolFactory.cpp KarbonGradientEditStrategy.cpp KarbonPatternTool.cpp KarbonPatternToolFactory.cpp KarbonPatternEditStrategy.cpp filterEffectTool/KarbonFilterEffectsTool.cpp filterEffectTool/KarbonFilterEffectsToolFactory.cpp filterEffectTool/FilterEffectEditWidget.cpp filterEffectTool/FilterEffectScene.cpp filterEffectTool/FilterEffectSceneItems.cpp filterEffectTool/FilterInputChangeCommand.cpp filterEffectTool/FilterAddCommand.cpp filterEffectTool/FilterRemoveCommand.cpp filterEffectTool/FilterStackSetCommand.cpp filterEffectTool/FilterRegionChangeCommand.cpp filterEffectTool/FilterEffectResource.cpp filterEffectTool/FilterResourceServerProvider.cpp filterEffectTool/FilterRegionEditStrategy.cpp KarbonPatternOptionsWidget.cpp ) ki18n_wrap_ui(karbon_tools_SOURCES filterEffectTool/FilterEffectEditWidget.ui KarbonPatternOptionsWidget.ui ) qt5_add_resources(karbon_tools_SOURCES karbontools.qrc) add_library(krita_karbontools MODULE ${karbon_tools_SOURCES}) -target_link_libraries(krita_karbontools kritawidgets KF5::Completion) +target_link_libraries(krita_karbontools kritaui kritawidgets KF5::Completion) install(TARGETS krita_karbontools DESTINATION ${KRITA_PLUGIN_INSTALL_DIR}) diff --git a/plugins/tools/karbonplugins/tools/CalligraphyTool/KarbonCalligraphyOptionWidget.cpp b/plugins/tools/karbonplugins/tools/CalligraphyTool/KarbonCalligraphyOptionWidget.cpp index c81e93cc67..23ef45af46 100644 --- a/plugins/tools/karbonplugins/tools/CalligraphyTool/KarbonCalligraphyOptionWidget.cpp +++ b/plugins/tools/karbonplugins/tools/CalligraphyTool/KarbonCalligraphyOptionWidget.cpp @@ -1,629 +1,632 @@ /* This file is part of the KDE project Copyright (C) 2008 Fela Winkelmolen 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. */ #include "KarbonCalligraphyOptionWidget.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include +#include "kis_double_parse_spin_box.h" +#include "kis_int_parse_spin_box.h" + /* Profiles are saved in karboncalligraphyrc In the group "General", profile is the name of profile used Every profile is described in a group, the name of which is "ProfileN" Starting to count from 0 onwards (NOTE: the index in profiles is different from the N) Default profiles are added by the function addDefaultProfiles(), once they have been added, the entry defaultProfilesAdded in the "General" group is set to true TODO: add a reset defaults option? */ // name of the configuration file const QString RCFILENAME = "karboncalligraphyrc"; KarbonCalligraphyOptionWidget::KarbonCalligraphyOptionWidget() : m_changingProfile(false) { QGridLayout *layout = new QGridLayout(this); layout->setContentsMargins(0, 0, 0, 0); m_comboBox = new KComboBox(this); layout->addWidget(m_comboBox, 0, 0); m_saveButton = new QToolButton(this); m_saveButton->setToolTip(i18n("Save profile as...")); m_saveButton->setIcon(koIcon("document-save-as")); layout->addWidget(m_saveButton, 0, 1); m_removeButton = new QToolButton(this); m_removeButton->setToolTip(i18n("Remove profile")); m_removeButton->setIcon(koIcon("list-remove")); layout->addWidget(m_removeButton, 0, 2); QGridLayout *detailsLayout = new QGridLayout(); detailsLayout->setContentsMargins(0, 0, 0, 0); detailsLayout->setVerticalSpacing(0); m_usePath = new QCheckBox(i18n("&Follow selected path"), this); detailsLayout->addWidget(m_usePath, 0, 0, 1, 4); m_usePressure = new QCheckBox(i18n("Use tablet &pressure"), this); detailsLayout->addWidget(m_usePressure, 1, 0, 1, 4); QLabel *widthLabel = new QLabel(i18n("Width:"), this); widthLabel->setAlignment(Qt::AlignRight | Qt::AlignVCenter); - m_widthBox = new QDoubleSpinBox(this); + m_widthBox = new KisDoubleParseSpinBox(this); m_widthBox->setRange(0.0, 999.0); widthLabel->setBuddy(m_widthBox); detailsLayout->addWidget(widthLabel, 2, 2); detailsLayout->addWidget(m_widthBox, 2, 3); QLabel *thinningLabel = new QLabel(i18n("Thinning:"), this); thinningLabel->setAlignment(Qt::AlignRight | Qt::AlignVCenter); - m_thinningBox = new QDoubleSpinBox(this); + m_thinningBox = new KisDoubleParseSpinBox(this); m_thinningBox->setRange(-1.0, 1.0); m_thinningBox->setSingleStep(0.1); thinningLabel->setBuddy(m_thinningBox); detailsLayout->addWidget(thinningLabel, 2, 0); detailsLayout->addWidget(m_thinningBox, 2, 1); m_useAngle = new QCheckBox(i18n("Use tablet &angle"), this); detailsLayout->addWidget(m_useAngle, 3, 0, 1, 4); QLabel *angleLabel = new QLabel(i18n("Angle:"), this); angleLabel->setAlignment(Qt::AlignRight | Qt::AlignVCenter); - m_angleBox = new QSpinBox(this); + m_angleBox = new KisIntParseSpinBox(this); m_angleBox->setRange(0, 179); m_angleBox->setWrapping(true); angleLabel->setBuddy(m_angleBox); detailsLayout->addWidget(angleLabel, 4, 0); detailsLayout->addWidget(m_angleBox, 4, 1); QLabel *fixationLabel = new QLabel(i18n("Fixation:"), this); fixationLabel->setAlignment(Qt::AlignRight | Qt::AlignVCenter); - m_fixationBox = new QDoubleSpinBox(this); + m_fixationBox = new KisDoubleParseSpinBox(this); m_fixationBox->setRange(0.0, 1.0); m_fixationBox->setSingleStep(0.1); fixationLabel->setBuddy(m_fixationBox); detailsLayout->addWidget(fixationLabel, 5, 0); detailsLayout->addWidget(m_fixationBox, 5, 1); QLabel *capsLabel = new QLabel(i18n("Caps:"), this); capsLabel->setAlignment(Qt::AlignRight | Qt::AlignVCenter); - m_capsBox = new QDoubleSpinBox(this); + m_capsBox = new KisDoubleParseSpinBox(this); m_capsBox->setRange(0.0, 2.0); m_capsBox->setSingleStep(0.03); capsLabel->setBuddy(m_capsBox); detailsLayout->addWidget(capsLabel, 5, 2); detailsLayout->addWidget(m_capsBox, 5, 3); QLabel *massLabel = new QLabel(i18n("Mass:"), this); massLabel->setAlignment(Qt::AlignRight | Qt::AlignVCenter); - m_massBox = new QDoubleSpinBox(this); + m_massBox = new KisDoubleParseSpinBox(this); m_massBox->setRange(0.0, 20.0); m_massBox->setDecimals(1); massLabel->setBuddy(m_massBox); detailsLayout->addWidget(massLabel, 6, 0); detailsLayout->addWidget(m_massBox, 6, 1); QLabel *dragLabel = new QLabel(i18n("Drag:"), this); dragLabel->setAlignment(Qt::AlignRight | Qt::AlignVCenter); - m_dragBox = new QDoubleSpinBox(this); + m_dragBox = new KisDoubleParseSpinBox(this); m_dragBox->setRange(0.0, 1.0); m_dragBox->setSingleStep(0.1); dragLabel->setBuddy(m_dragBox); detailsLayout->addWidget(dragLabel, 6, 2); detailsLayout->addWidget(m_dragBox, 6, 3); layout->addLayout(detailsLayout, 1, 0, 1, 3); layout->setRowStretch(2, 1); createConnections(); addDefaultProfiles(); // if they are already added does nothing loadProfiles(); } KarbonCalligraphyOptionWidget::~KarbonCalligraphyOptionWidget() { qDeleteAll(m_profiles); qDebug() << "dtor!!!!"; } void KarbonCalligraphyOptionWidget::emitAll() { emit usePathChanged(m_usePath->isChecked()); emit usePressureChanged(m_usePressure->isChecked()); emit useAngleChanged(m_useAngle->isChecked()); emit widthChanged(m_widthBox->value()); emit thinningChanged(m_thinningBox->value()); emit angleChanged(m_angleBox->value()); emit fixationChanged(m_fixationBox->value()); emit capsChanged(m_capsBox->value()); emit massChanged(m_massBox->value()); emit dragChanged(m_dragBox->value()); } void KarbonCalligraphyOptionWidget::loadProfile(const QString &name) { if (m_changingProfile) { return; } qDebug() << "trying profile" << name; // write the new profile in the config file KConfig config(RCFILENAME); KConfigGroup generalGroup(&config, "General"); generalGroup.writeEntry("profile", name); config.sync(); // and load it loadCurrentProfile(); // don't show Current if it isn't selected if (name != i18n("Current")) { removeProfile(i18n("Current")); } } void KarbonCalligraphyOptionWidget::updateCurrentProfile() { if (!m_changingProfile) { saveProfile("Current"); } } void KarbonCalligraphyOptionWidget::saveProfileAs() { QString name; // loop until a valid name is entered or the user cancelled while (1) { bool ok; name = QInputDialog::getText(this, i18n("Profile name"), i18n("Please insert the name by which " "you want to save this profile:"), QLineEdit::Normal, QString(), &ok); if (!ok) { return; } if (name.isEmpty() || name == i18n("Current")) { KMessageBox::sorry(this, i18n("Sorry, the name you entered is invalid."), i18nc("invalid profile name", "Invalid name.")); // try again saveProfileAs(); continue; // ask again } if (m_profiles.contains(name)) { int ret = KMessageBox::warningYesNo(this, i18n("A profile with that name already exists.\n" "Do you want to overwrite it?")); if (ret == KMessageBox::Yes) { break; // exit while loop (save profile) } // else ask again } else { // the name is valid break; // exit while loop (save profile) } } saveProfile(name); } void KarbonCalligraphyOptionWidget::removeProfile() { removeProfile(m_comboBox->currentText()); } void KarbonCalligraphyOptionWidget::toggleUseAngle(bool checked) { m_angleBox->setEnabled(! checked); } void KarbonCalligraphyOptionWidget::increaseWidth() { m_widthBox->setValue(m_widthBox->value() + 1); } void KarbonCalligraphyOptionWidget::decreaseWidth() { m_widthBox->setValue(m_widthBox->value() - 1); } void KarbonCalligraphyOptionWidget::increaseAngle() { m_angleBox->setValue((m_angleBox->value() + 3) % 180); } void KarbonCalligraphyOptionWidget::decreaseAngle() { m_angleBox->setValue((m_angleBox->value() - 3) % 180); } /****************************************************************************** ************************* Convenience Functions ****************************** ******************************************************************************/ void KarbonCalligraphyOptionWidget::createConnections() { connect(m_comboBox, SIGNAL(currentIndexChanged(QString)), SLOT(loadProfile(QString))); // propagate changes connect(m_usePath, SIGNAL(toggled(bool)), SIGNAL(usePathChanged(bool))); connect(m_usePressure, SIGNAL(toggled(bool)), SIGNAL(usePressureChanged(bool))); connect(m_useAngle, SIGNAL(toggled(bool)), SIGNAL(useAngleChanged(bool))); connect(m_widthBox, SIGNAL(valueChanged(double)), SIGNAL(widthChanged(double))); connect(m_thinningBox, SIGNAL(valueChanged(double)), SIGNAL(thinningChanged(double))); connect(m_angleBox, SIGNAL(valueChanged(int)), SIGNAL(angleChanged(int))); connect(m_fixationBox, SIGNAL(valueChanged(double)), SIGNAL(fixationChanged(double))); connect(m_capsBox, SIGNAL(valueChanged(double)), SIGNAL(capsChanged(double))); connect(m_massBox, SIGNAL(valueChanged(double)), SIGNAL(massChanged(double))); connect(m_dragBox, SIGNAL(valueChanged(double)), SIGNAL(dragChanged(double))); // update profile connect(m_usePath, SIGNAL(toggled(bool)), SLOT(updateCurrentProfile())); connect(m_usePressure, SIGNAL(toggled(bool)), SLOT(updateCurrentProfile())); connect(m_useAngle, SIGNAL(toggled(bool)), SLOT(updateCurrentProfile())); connect(m_widthBox, SIGNAL(valueChanged(double)), SLOT(updateCurrentProfile())); connect(m_thinningBox, SIGNAL(valueChanged(double)), SLOT(updateCurrentProfile())); connect(m_angleBox, SIGNAL(valueChanged(int)), SLOT(updateCurrentProfile())); connect(m_fixationBox, SIGNAL(valueChanged(double)), SLOT(updateCurrentProfile())); connect(m_capsBox, SIGNAL(valueChanged(double)), SLOT(updateCurrentProfile())); connect(m_massBox, SIGNAL(valueChanged(double)), SLOT(updateCurrentProfile())); connect(m_dragBox, SIGNAL(valueChanged(double)), SLOT(updateCurrentProfile())); connect(m_saveButton, SIGNAL(clicked()), SLOT(saveProfileAs())); connect(m_removeButton, SIGNAL(clicked()), SLOT(removeProfile())); // visualization connect(m_useAngle, SIGNAL(toggled(bool)), SLOT(toggleUseAngle(bool))); } void KarbonCalligraphyOptionWidget::addDefaultProfiles() { // check if the profiles where already added KConfig config(RCFILENAME); KConfigGroup generalGroup(&config, "General"); if (generalGroup.readEntry("defaultProfilesAdded", false)) { return; } KConfigGroup profile0(&config, "Profile0"); profile0.writeEntry("name", i18n("Mouse")); profile0.writeEntry("usePath", false); profile0.writeEntry("usePressure", false); profile0.writeEntry("useAngle", false); profile0.writeEntry("width", 30.0); profile0.writeEntry("thinning", 0.2); profile0.writeEntry("angle", 30); profile0.writeEntry("fixation", 1.0); profile0.writeEntry("caps", 0.0); profile0.writeEntry("mass", 3.0); profile0.writeEntry("drag", 0.7); KConfigGroup profile1(&config, "Profile1"); profile1.writeEntry("name", i18n("Graphics Pen")); profile1.writeEntry("width", 50.0); profile1.writeEntry("usePath", false); profile1.writeEntry("usePressure", false); profile1.writeEntry("useAngle", false); profile1.writeEntry("thinning", 0.2); profile1.writeEntry("angle", 30); profile1.writeEntry("fixation", 1.0); profile1.writeEntry("caps", 0.0); profile1.writeEntry("mass", 1.0); profile1.writeEntry("drag", 0.9); generalGroup.writeEntry("profile", i18n("Mouse")); generalGroup.writeEntry("defaultProfilesAdded", true); config.sync(); } void KarbonCalligraphyOptionWidget::loadProfiles() { KConfig config(RCFILENAME); // load profiles as long as they are present int i = 0; while (1) { // forever KConfigGroup profileGroup(&config, "Profile" + QString::number(i)); // invalid profile, assume we reached the last one if (!profileGroup.hasKey("name")) { break; } Profile *profile = new Profile; profile->index = i; profile->name = profileGroup.readEntry("name", QString()); profile->usePath = profileGroup.readEntry("usePath", false); profile->usePressure = profileGroup.readEntry("usePressure", false); profile->useAngle = profileGroup.readEntry("useAngle", false); profile->width = profileGroup.readEntry("width", 30.0); profile->thinning = profileGroup.readEntry("thinning", 0.2); profile->angle = profileGroup.readEntry("angle", 30); profile->fixation = profileGroup.readEntry("fixation", 0.0); profile->caps = profileGroup.readEntry("caps", 0.0); profile->mass = profileGroup.readEntry("mass", 3.0); profile->drag = profileGroup.readEntry("drag", 0.7); m_profiles.insert(profile->name, profile); ++i; } m_changingProfile = true; ProfileMap::const_iterator it = m_profiles.constBegin(); ProfileMap::const_iterator lastIt = m_profiles.constEnd(); for (; it != lastIt; ++it) { m_comboBox->addItem(it.key()); } m_changingProfile = false; loadCurrentProfile(); } void KarbonCalligraphyOptionWidget::loadCurrentProfile() { KConfig config(RCFILENAME); KConfigGroup generalGroup(&config, "General"); QString currentProfile = generalGroup.readEntry("profile", QString()); qDebug() << currentProfile; // find the index needed by the comboBox int index = profilePosition(currentProfile); if (currentProfile.isEmpty() || index < 0) { qDebug() << "invalid karboncalligraphyrc!!" << currentProfile << index; return; } qDebug() << m_comboBox->currentIndex() << index; m_comboBox->setCurrentIndex(index); Profile *profile = m_profiles[currentProfile]; m_changingProfile = true; m_usePath->setChecked(profile->usePath); m_usePressure->setChecked(profile->usePressure); m_useAngle->setChecked(profile->useAngle); m_widthBox->setValue(profile->width); m_thinningBox->setValue(profile->thinning); m_angleBox->setValue(profile->angle); m_fixationBox->setValue(profile->fixation); m_capsBox->setValue(profile->caps); m_massBox->setValue(profile->mass); m_dragBox->setValue(profile->drag); m_changingProfile = false; } void KarbonCalligraphyOptionWidget::saveProfile(const QString &name) { qDebug() << name; Profile *profile = new Profile; profile->name = name; profile->usePath = m_usePath->isChecked(); profile->usePressure = m_usePressure->isChecked(); profile->useAngle = m_useAngle->isChecked(); profile->width = m_widthBox->value(); profile->thinning = m_thinningBox->value(); profile->angle = m_angleBox->value(); profile->fixation = m_fixationBox->value(); profile->caps = m_capsBox->value(); profile->mass = m_massBox->value(); profile->drag = m_dragBox->value(); if (m_profiles.contains(name)) { // there is already a profile with the same name, overwrite profile->index = m_profiles[name]->index; m_profiles.insert(name, profile); } else { // it is a new profile profile->index = m_profiles.count(); m_profiles.insert(name, profile); // add the profile to the combobox qDebug() << "BEFORE:"; QString dbg; for (int i = 0; i < m_comboBox->count(); ++i) { dbg += m_comboBox->itemText(i) + ' '; } qDebug() << dbg; int pos = profilePosition(name); m_changingProfile = true; m_comboBox->insertItem(pos, name); m_changingProfile = false; qDebug() << "AFTER:"; for (int i = 0; i < m_comboBox->count(); ++i) { dbg += m_comboBox->itemText(i) + ' '; } qDebug() << dbg; qDebug() << "new at" << pos << m_comboBox->itemText(pos) << name; } KConfig config(RCFILENAME); QString str = "Profile" + QString::number(profile->index); KConfigGroup profileGroup(&config, str); profileGroup.writeEntry("name", name); profileGroup.writeEntry("usePath", profile->usePath); profileGroup.writeEntry("usePressure", profile->usePressure); profileGroup.writeEntry("useAngle", profile->useAngle); profileGroup.writeEntry("width", profile->width); profileGroup.writeEntry("thinning", profile->thinning); profileGroup.writeEntry("angle", profile->angle); profileGroup.writeEntry("fixation", profile->fixation); profileGroup.writeEntry("caps", profile->caps); profileGroup.writeEntry("mass", profile->mass); profileGroup.writeEntry("drag", profile->drag); KConfigGroup generalGroup(&config, "General"); generalGroup.writeEntry("profile", name); config.sync(); qDebug() << name; int pos = profilePosition(name); qDebug() << "adding in" << pos << m_comboBox->itemText(pos); m_comboBox->setCurrentIndex(profilePosition(name)); qDebug() << m_comboBox->currentText(); } void KarbonCalligraphyOptionWidget::removeProfile(const QString &name) { qDebug() << "removing profile" << name; int index = profilePosition(name); if (index < 0) { return; // no such profile } // remove the file from the config file KConfig config(RCFILENAME); int deletedIndex = m_profiles[name]->index; QString deletedGroup = "Profile" + QString::number(deletedIndex); qDebug() << deletedGroup; config.deleteGroup(deletedGroup); config.sync(); // and from profiles m_profiles.remove(name); m_comboBox->removeItem(index); // now in the config file there is value ProfileN missing, // where N = configIndex, so put the last one there if (m_profiles.isEmpty()) { return; } int lastN = -1; Profile *profile = 0; // profile to be moved, will be the last one Q_FOREACH (Profile *p, m_profiles) { if (p->index > lastN) { lastN = p->index; profile = p; } } Q_ASSERT(profile != 0); // do nothing if the deleted group was the last one if (deletedIndex > lastN) { return; } QString lastGroup = "Profile" + QString::number(lastN); config.deleteGroup(lastGroup); KConfigGroup profileGroup(&config, deletedGroup); profileGroup.writeEntry("name", profile->name); profileGroup.writeEntry("usePath", profile->usePath); profileGroup.writeEntry("usePressure", profile->usePressure); profileGroup.writeEntry("useAngle", profile->useAngle); profileGroup.writeEntry("width", profile->width); profileGroup.writeEntry("thinning", profile->thinning); profileGroup.writeEntry("angle", profile->angle); profileGroup.writeEntry("fixation", profile->fixation); profileGroup.writeEntry("caps", profile->caps); profileGroup.writeEntry("mass", profile->mass); profileGroup.writeEntry("drag", profile->drag); config.sync(); profile->index = deletedIndex; } int KarbonCalligraphyOptionWidget::profilePosition(const QString &profileName) { int res = 0; ProfileMap::const_iterator it = m_profiles.constBegin(); ProfileMap::const_iterator lastIt = m_profiles.constEnd(); for (; it != lastIt; ++it) { if (it.key() == profileName) { return res; } ++res; } return -1; } void KarbonCalligraphyOptionWidget::setUsePathEnabled(bool enabled) { m_usePath->setEnabled(enabled); } diff --git a/plugins/tools/karbonplugins/tools/KarbonPatternOptionsWidget.ui b/plugins/tools/karbonplugins/tools/KarbonPatternOptionsWidget.ui index ab606eca6f..ddd78a06cc 100644 --- a/plugins/tools/karbonplugins/tools/KarbonPatternOptionsWidget.ui +++ b/plugins/tools/karbonplugins/tools/KarbonPatternOptionsWidget.ui @@ -1,141 +1,161 @@ - + + PatternOptionsWidget - - + + 0 0 240 253 - - + + 0 - - - + + 0 + + + 0 + + + 0 + + + + Repeat: - - + + - - - + + + Reference Point: - - + + - - - + + + Reference Point Offset - - - + + + X: - - + + - - - + + + Y: - - + + - - - + + + Tile Offset - - - + + + X: - - + + - - - + + + Y: - - + + - - - + + + Pattern Size - - - + + + W: - - + + - - - + + + H: - - + + - - - + + + Qt::Vertical - + 94 121 + + KisIntParseSpinBox + QSpinBox +
kis_int_parse_spin_box.h
+
+ + KisDoubleParseSpinBox + QDoubleSpinBox +
kis_double_parse_spin_box.h
+
KComboBox QComboBox
kcombobox.h
diff --git a/plugins/tools/karbonplugins/tools/filterEffectTool/KarbonFilterEffectsTool.cpp b/plugins/tools/karbonplugins/tools/filterEffectTool/KarbonFilterEffectsTool.cpp index d5e5e98922..2804161e05 100644 --- a/plugins/tools/karbonplugins/tools/filterEffectTool/KarbonFilterEffectsTool.cpp +++ b/plugins/tools/karbonplugins/tools/filterEffectTool/KarbonFilterEffectsTool.cpp @@ -1,552 +1,554 @@ /* This file is part of the KDE project * Copyright (c) 2009-2011 Jan Hambrecht * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 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 Lesser 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. */ #include "KarbonFilterEffectsTool.h" #include "KoFilterEffect.h" #include "KoFilterEffectStack.h" #include "KoFilterEffectFactoryBase.h" #include "KoFilterEffectRegistry.h" #include "KoFilterEffectConfigWidgetBase.h" #include "KoCanvasBase.h" #include "KoDocumentResourceManager.h" #include "KoShapeManager.h" #include "KoViewConverter.h" #include "KoSelection.h" #include "FilterEffectEditWidget.h" #include "FilterEffectResource.h" #include "FilterResourceServerProvider.h" #include "FilterStackSetCommand.h" #include "FilterRegionChangeCommand.h" #include "FilterRegionEditStrategy.h" #include "KoResourceServerAdapter.h" #include "KoResourceSelector.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include +#include "kis_double_parse_spin_box.h" + class KarbonFilterEffectsTool::Private { public: Private() : filterSelector(0) , configSelector(0) , configStack(0) , posX(0) , posY(0) , posW(0) , posH(0) , clearButton(0) , currentEffect(0) , currentPanel(0) , currentShape(0) { } void fillConfigSelector(KoShape *shape, KarbonFilterEffectsTool *tool) { if (!configSelector) { return; } configSelector->clear(); clearButton->setEnabled(false); if (!shape || !shape->filterEffectStack()) { addWidgetForEffect(0, tool); return; } configSelector->blockSignals(true); int index = 0; Q_FOREACH (KoFilterEffect *effect, shape->filterEffectStack()->filterEffects()) { configSelector->addItem(QString("%1 - ").arg(index) + effect->name()); index++; } configSelector->blockSignals(false); KoFilterEffect *effect = index > 0 ? shape->filterEffectStack()->filterEffects().first() : 0; addWidgetForEffect(effect, tool); clearButton->setEnabled(shape->filterEffectStack() != 0); } void addWidgetForEffect(KoFilterEffect *filterEffect, KarbonFilterEffectsTool *tool) { // remove current widget if new effect is zero or effect type has changed if (!filterEffect || (currentEffect && filterEffect->id() != currentEffect->id())) { while (configStack->count()) { configStack->removeWidget(configStack->widget(0)); } } if (!filterEffect) { currentEffect = 0; currentPanel = 0; } else if (!currentEffect || currentEffect->id() != filterEffect->id()) { // when a effect is set and is differs from the previous one // get the config widget and insert it into the option widget currentEffect = filterEffect; KoFilterEffectRegistry *registry = KoFilterEffectRegistry::instance(); KoFilterEffectFactoryBase *factory = registry->value(currentEffect->id()); if (!factory) { return; } currentPanel = factory->createConfigWidget(); if (!currentPanel) { return; } currentPanel->layout()->setContentsMargins(0, 0, 0, 0); configStack->insertWidget(0, currentPanel); configStack->layout()->setContentsMargins(0, 0, 0, 0); connect(currentPanel, SIGNAL(filterChanged()), tool, SLOT(filterChanged())); } if (currentPanel) { currentPanel->editFilterEffect(filterEffect); } updateFilterRegion(); } void updateFilterRegion() { QRectF region = currentEffect ? currentEffect->filterRect() : QRectF(0, 0, 0, 0); posX->blockSignals(true); posX->setValue(100.0 * region.x()); posX->blockSignals(false); posX->setEnabled(currentEffect != 0); posY->blockSignals(true); posY->setValue(100.0 * region.y()); posY->blockSignals(false); posY->setEnabled(currentEffect != 0); posW->blockSignals(true); posW->setValue(100.0 * region.width()); posW->blockSignals(false); posW->setEnabled(currentEffect != 0); posH->blockSignals(true); posH->setValue(100.0 * region.height()); posH->blockSignals(false); posH->setEnabled(currentEffect != 0); } EditMode editModeFromMousePosition(const QPointF &mousePosition, KarbonFilterEffectsTool *tool) { if (currentShape && currentShape->filterEffectStack() && currentEffect) { // get the size rect of the shape QRectF sizeRect(QPointF(), currentShape->size()); // get the filter rectangle in shape coordinates QRectF filterRect = currentEffect->filterRectForBoundingRect(sizeRect); // get the transformation from document to shape coordinates QTransform transform = currentShape->absoluteTransformation(0).inverted(); // adjust filter rectangle by grab sensitivity const int grabDistance = tool->grabSensitivity(); QPointF border = tool->canvas()->viewConverter()->viewToDocument(QPointF(grabDistance, grabDistance)); filterRect.adjust(-border.x(), -border.y(), border.x(), border.y()); // map event point from document to shape coordinates QPointF shapePoint = transform.map(mousePosition); // check if the mouse is inside/near our filter rect if (filterRect.contains(shapePoint)) { if (qAbs(shapePoint.x() - filterRect.left()) <= border.x()) { return MoveLeft; } else if (qAbs(shapePoint.x() - filterRect.right()) <= border.x()) { return MoveRight; } else if (qAbs(shapePoint.y() - filterRect.top()) <= border.y()) { return MoveTop; } else if (qAbs(shapePoint.y() - filterRect.bottom()) <= border.y()) { return MoveBottom; } else { return MoveAll; } } else { return None; } } return None; } KoResourceSelector *filterSelector; KComboBox *configSelector; QStackedWidget *configStack; QDoubleSpinBox *posX; QDoubleSpinBox *posY; QDoubleSpinBox *posW; QDoubleSpinBox *posH; QToolButton *clearButton; KoFilterEffect *currentEffect; KoFilterEffectConfigWidgetBase *currentPanel; KoShape *currentShape; }; KarbonFilterEffectsTool::KarbonFilterEffectsTool(KoCanvasBase *canvas) : KoInteractionTool(canvas) , d(new Private()) { connect(canvas->shapeManager(), SIGNAL(selectionChanged()), this, SLOT(selectionChanged())); connect(canvas->shapeManager(), SIGNAL(selectionContentChanged()), this, SLOT(selectionChanged())); } KarbonFilterEffectsTool::~KarbonFilterEffectsTool() { delete d; } void KarbonFilterEffectsTool::paint(QPainter &painter, const KoViewConverter &converter) { if (d->currentShape && d->currentShape->filterEffectStack()) { painter.save(); // apply the shape transformation QTransform transform = d->currentShape->absoluteTransformation(&converter); painter.setTransform(transform, true); // apply the zoom transformation KoShape::applyConversion(painter, converter); // get the size rect of the shape QRectF sizeRect(QPointF(), d->currentShape->size()); // get the clipping rect of the filter stack KoFilterEffectStack *filterStack = d->currentShape->filterEffectStack(); QRectF clipRect = filterStack->clipRectForBoundingRect(sizeRect); // finally paint the clipping rect painter.setBrush(Qt::NoBrush); painter.setPen(Qt::blue); painter.drawRect(clipRect); if (currentStrategy()) { currentStrategy()->paint(painter, converter); } else if (d->currentEffect) { QRectF filterRect = d->currentEffect->filterRectForBoundingRect(sizeRect); // paint the filter subregion rect painter.setBrush(Qt::NoBrush); painter.setPen(Qt::red); painter.drawRect(filterRect); } painter.restore(); } } void KarbonFilterEffectsTool::repaintDecorations() { if (d->currentShape && d->currentShape->filterEffectStack()) { QRectF bb = d->currentShape->boundingRect(); const int radius = handleRadius(); canvas()->updateCanvas(bb.adjusted(-radius, -radius, radius, radius)); } } void KarbonFilterEffectsTool::activate(ToolActivation toolActivation, const QSet &shapes) { Q_UNUSED(toolActivation); if (shapes.isEmpty()) { emit done(); return; } d->currentShape = canvas()->shapeManager()->selection()->firstSelectedShape(KoFlake::TopLevelSelection); d->fillConfigSelector(d->currentShape, this); } void KarbonFilterEffectsTool::mouseMoveEvent(KoPointerEvent *event) { if (currentStrategy()) { KoInteractionTool::mouseMoveEvent(event); } else { EditMode mode = d->editModeFromMousePosition(event->point, this); switch (mode) { case MoveAll: useCursor(Qt::SizeAllCursor); break; case MoveLeft: case MoveRight: useCursor(Qt::SizeHorCursor); break; case MoveTop: case MoveBottom: useCursor(Qt::SizeVerCursor); break; case None: useCursor(Qt::ArrowCursor); break; } } } KoInteractionStrategy *KarbonFilterEffectsTool::createStrategy(KoPointerEvent *event) { EditMode mode = d->editModeFromMousePosition(event->point, this); if (mode == None) { return 0; } return new FilterRegionEditStrategy(this, d->currentShape, d->currentEffect, mode); } void KarbonFilterEffectsTool::presetSelected(KoResource *resource) { if (!d->currentShape) { return; } FilterEffectResource *effectResource = dynamic_cast(resource); if (!effectResource) { return; } KoFilterEffectStack *filterStack = effectResource->toFilterStack(); if (!filterStack) { return; } canvas()->addCommand(new FilterStackSetCommand(filterStack, d->currentShape)); d->fillConfigSelector(d->currentShape, this); } void KarbonFilterEffectsTool::editFilter() { QPointer dlg = new QDialog(); dlg->setWindowTitle(i18n("Filter Effect Editor")); QDialogButtonBox *buttonBox = new QDialogButtonBox(QDialogButtonBox::Close); QWidget *mainWidget = new QWidget(0); QVBoxLayout *mainLayout = new QVBoxLayout; dlg->setLayout(mainLayout); mainLayout->addWidget(mainWidget); connect(buttonBox->button(QDialogButtonBox::Close), SIGNAL(clicked()), dlg, SLOT(close())); FilterEffectEditWidget *editor = new FilterEffectEditWidget(dlg); editor->editShape(d->currentShape, canvas()); mainLayout->addWidget(editor); mainLayout->addWidget(buttonBox); dlg->exec(); delete dlg; d->fillConfigSelector(d->currentShape, this); } void KarbonFilterEffectsTool::clearFilter() { if (!d->currentShape) { return; } if (!d->currentShape->filterEffectStack()) { return; } canvas()->addCommand(new FilterStackSetCommand(0, d->currentShape)); d->fillConfigSelector(d->currentShape, this); } void KarbonFilterEffectsTool::filterChanged() { if (!d->currentShape) { return; } d->currentShape->update(); } void KarbonFilterEffectsTool::filterSelected(int index) { if (!d->currentShape || ! d->currentShape->filterEffectStack()) { return; } KoFilterEffect *effect = 0; QList filterEffects = d->currentShape->filterEffectStack()->filterEffects(); if (index >= 0 && index < filterEffects.count()) { effect = filterEffects[index]; } d->addWidgetForEffect(effect, this); repaintDecorations(); } void KarbonFilterEffectsTool::selectionChanged() { d->currentShape = canvas()->shapeManager()->selection()->firstSelectedShape(KoFlake::TopLevelSelection); d->fillConfigSelector(d->currentShape, this); } void KarbonFilterEffectsTool::regionXChanged(double x) { if (!d->currentEffect) { return; } QRectF region = d->currentEffect->filterRect(); region.setX(x / 100.0); canvas()->addCommand(new FilterRegionChangeCommand(d->currentEffect, region, d->currentShape)); } void KarbonFilterEffectsTool::regionYChanged(double y) { if (!d->currentEffect) { return; } QRectF region = d->currentEffect->filterRect(); region.setY(y / 100.0); canvas()->addCommand(new FilterRegionChangeCommand(d->currentEffect, region, d->currentShape)); } void KarbonFilterEffectsTool::regionWidthChanged(double width) { if (!d->currentEffect) { return; } QRectF region = d->currentEffect->filterRect(); region.setWidth(width / 100.0); canvas()->addCommand(new FilterRegionChangeCommand(d->currentEffect, region, d->currentShape)); } void KarbonFilterEffectsTool::regionHeightChanged(double height) { if (!d->currentEffect) { return; } QRectF region = d->currentEffect->filterRect(); region.setHeight(height / 100.0); canvas()->addCommand(new FilterRegionChangeCommand(d->currentEffect, region, d->currentShape)); } QList > KarbonFilterEffectsTool::createOptionWidgets() { QList > widgets; FilterResourceServerProvider *serverProvider = FilterResourceServerProvider::instance(); KoResourceServer *server = serverProvider->filterEffectServer(); QSharedPointer adapter(new KoResourceServerAdapter(server)); //--------------------------------------------------------------------- QWidget *addFilterWidget = new QWidget(); addFilterWidget->setObjectName("AddEffect"); QGridLayout *addFilterLayout = new QGridLayout(addFilterWidget); d->filterSelector = new KoResourceSelector(addFilterWidget); d->filterSelector->setResourceAdapter(adapter); d->filterSelector->setDisplayMode(KoResourceSelector::TextMode); d->filterSelector->setColumnCount(1); addFilterLayout->addWidget(new QLabel(i18n("Effects"), addFilterWidget), 0, 0); addFilterLayout->addWidget(d->filterSelector, 0, 1); connect(d->filterSelector, SIGNAL(resourceSelected(KoResource*)), this, SLOT(presetSelected(KoResource*))); connect(d->filterSelector, SIGNAL(resourceApplied(KoResource*)), this, SLOT(presetSelected(KoResource*))); QToolButton *editButton = new QToolButton(addFilterWidget); editButton->setIcon(koIcon("view-filter")); editButton->setToolTip(i18n("View and edit filter")); addFilterLayout->addWidget(editButton, 0, 2); connect(editButton, SIGNAL(clicked()), this, SLOT(editFilter())); d->clearButton = new QToolButton(addFilterWidget); d->clearButton->setIcon(koIcon("edit-delete")); d->clearButton->setToolTip(i18n("Remove filter from object")); addFilterLayout->addWidget(d->clearButton, 0, 3); connect(d->clearButton, SIGNAL(clicked()), this, SLOT(clearFilter())); addFilterWidget->setWindowTitle(i18n("Add Filter")); widgets.append(addFilterWidget); //--------------------------------------------------------------------- QWidget *configFilterWidget = new QWidget(); configFilterWidget->setObjectName("ConfigEffect"); QGridLayout *configFilterLayout = new QGridLayout(configFilterWidget); d->configSelector = new KComboBox(configFilterWidget); configFilterLayout->addWidget(d->configSelector, 0, 0); connect(d->configSelector, SIGNAL(currentIndexChanged(int)), this, SLOT(filterSelected(int))); d->configStack = new QStackedWidget(configFilterWidget); configFilterLayout->addWidget(d->configStack, 1, 0); configFilterLayout->setContentsMargins(0, 0, 0, 0); configFilterWidget->setWindowTitle(i18n("Effect Properties")); widgets.append(configFilterWidget); //--------------------------------------------------------------------- QWidget *filterRegionWidget = new QWidget(); filterRegionWidget->setObjectName("EffectRegion"); QGridLayout *filterRegionLayout = new QGridLayout(filterRegionWidget); - d->posX = new QDoubleSpinBox(filterRegionWidget); + d->posX = new KisDoubleParseSpinBox(filterRegionWidget); d->posX->setSuffix("%"); connect(d->posX, SIGNAL(valueChanged(double)), this, SLOT(regionXChanged(double))); filterRegionLayout->addWidget(new QLabel(i18n("X:")), 0, 0); filterRegionLayout->addWidget(d->posX, 0, 1); - d->posY = new QDoubleSpinBox(filterRegionWidget); + d->posY = new KisDoubleParseSpinBox(filterRegionWidget); d->posY->setSuffix("%"); connect(d->posY, SIGNAL(valueChanged(double)), this, SLOT(regionYChanged(double))); filterRegionLayout->addWidget(new QLabel(i18n("Y:")), 1, 0); filterRegionLayout->addWidget(d->posY, 1, 1); - d->posW = new QDoubleSpinBox(filterRegionWidget); + d->posW = new KisDoubleParseSpinBox(filterRegionWidget); d->posW->setSuffix("%"); connect(d->posW, SIGNAL(valueChanged(double)), this, SLOT(regionWidthChanged(double))); filterRegionLayout->addWidget(new QLabel(i18n("W:")), 0, 2); filterRegionLayout->addWidget(d->posW, 0, 3); - d->posH = new QDoubleSpinBox(filterRegionWidget); + d->posH = new KisDoubleParseSpinBox(filterRegionWidget); d->posH->setSuffix("%"); connect(d->posH, SIGNAL(valueChanged(double)), this, SLOT(regionHeightChanged(double))); filterRegionLayout->addWidget(new QLabel(i18n("H:")), 1, 2); filterRegionLayout->addWidget(d->posH, 1, 3); filterRegionLayout->addItem(new QSpacerItem(0, 0, QSizePolicy::Minimum, QSizePolicy::Expanding), 2, 0); filterRegionLayout->setContentsMargins(0, 0, 0, 0); filterRegionWidget->setWindowTitle(i18n("Effect Region")); widgets.append(filterRegionWidget); //--------------------------------------------------------------------- d->fillConfigSelector(d->currentShape, this); return widgets; } diff --git a/plugins/tools/tool_crop/wdg_tool_crop.ui b/plugins/tools/tool_crop/wdg_tool_crop.ui index 0f182e6771..962cde2a92 100644 --- a/plugins/tools/tool_crop/wdg_tool_crop.ui +++ b/plugins/tools/tool_crop/wdg_tool_crop.ui @@ -1,485 +1,497 @@ WdgToolCrop 0 0 - 230 - 200 + 288 + 242 Crop 0 0 0 0 0 0 0 5 5 5 5 5 Resize keeping center fixed Center Vertical Position - Y: + &Y: intY Horizontal Position - X: + &X: intX - + 60 0 16777215 16777215 Horizontal Position px 30000 - + 60 0 16777215 16777215 Vertical Position px 30000 Allow growing the image by dragging outside bounds of the image Grow Qt::Vertical 20 0 Qt::Horizontal 0 20 5 5 5 5 5 Qt::Vertical 20 40 Height H: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - + 60 0 16777215 16777215 Height px 30000 - + 60 0 16777215 16777215 Width px 30000 - + 60 0 16777215 16777215 Ratio 2 Ratio: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter Width W: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter Lock the width true Lock the height true Lock the aspect ratio true false 5 0 5 5 1 Layer Image &Crop Applies to: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter None Thirds Fifths Passport photo Crosshair Decoration: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter Qt::Vertical 20 40 + + + KisIntParseSpinBox + QSpinBox +
kis_int_parse_spin_box.h
+
+ + KisDoubleParseSpinBox + QDoubleSpinBox +
kis_double_parse_spin_box.h
+
+
intX intY intWidth intHeight cmbType
diff --git a/plugins/tools/tool_transform2/wdg_tool_transform.ui b/plugins/tools/tool_transform2/wdg_tool_transform.ui index ab0b96f5aa..c46c98b77e 100755 --- a/plugins/tools/tool_transform2/wdg_tool_transform.ui +++ b/plugins/tools/tool_transform2/wdg_tool_transform.ui @@ -1,2184 +1,2189 @@ WdgToolTransform 0 0 - 424 - 558 + 479 + 591 0 0 0 0 16777215 16777215 0 0 Qt::LeftToRight 0 0 0 0 0 4 QFrame::NoFrame QFrame::Plain 0 1 1 1 1 0 0 0 Free Free Transform true true true true 0 0 Perspective Perspective true true true 0 0 Warp Warp true false true true 0 0 Cage Cage true true true 0 0 Liquify Liquify true true true 0 0 Free Transform Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter QFrame::StyledPanel QFrame::Raised 0 0 0 0 0 0 0 12 QLayout::SetFixedSize 10 10 20 10 15 0 0 Qt::RightToLeft - Filter: + &Filter: Qt::AlignCenter cmbFilter QLayout::SetDefaultConstraint 0 true 0 0 true true 0 0 true true 0 0 true true 0 0 true true true 0 0 true true 0 0 true true 0 0 true true 0 0 true true 0 0 true true - + 0 0 - Position + Posi&tion true freeTransformRadioGroup - Rotate + &Rotate freeTransformRadioGroup Scale freeTransformRadioGroup Shear freeTransformRadioGroup 0 0 0 0 75 true Qt::LeftToRight false off canvas Qt::RichText false true Qt::NoTextInteraction Qt::Horizontal 40 20 true 0 0 240 100 Rotation false false false 2 5 0 7 0 QFormLayout::AllNonFixedFieldsGrow 5 5 0 0 0 0 Rotate around X-Axis Qt::LeftToRight - x: + &x: aXBox - + Rotate around X-Axis 0 0 0 0 Rotate around Y-Axis Qt::LeftToRight - y: + &y: aYBox - + Rotate around Y-Axis - + 0 0 Rotate around Z-Axis 0 0 0 0 Rotate around Z-Axis Qt::LeftToRight - z: + &z: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter aZBox 0 0 240 70 Scale false false false 2 5 0 0 5 0 0 0 0 Horizontal Scale - width: + w&idth: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter scaleXBox - + 0 0 Horizontal Scale - + % - + 0 0 Vertical Scale - + % 0 0 0 0 Vertical Scale - height: + &height: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter scaleYBox - + 0 0 20 25 0 0 240 70 Position false false false 2 5 0 0 QFormLayout::AllNonFixedFieldsGrow 0 0 Horizontal Translation Qt::LeftToRight x: translateXBox - + 0 0 Horizontal Translation Qt::LeftToRight - + 0 0 Vertical Translation 0 0 Vertical Translation y: translateYBox 0 0 240 80 false Shear Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter false false false 2 5 0 0 QFormLayout::AllNonFixedFieldsGrow 8 20 0 0 Horizontal Shear x: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter shearXBox - + 0 0 Vertical Shear 0 0 0 0 Vertical Shear y: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter shearYBox - + 0 0 Horizontal Shear Qt::Vertical QSizePolicy::Preferred 20 20 6 0 0 32 16777215 Flip selection horizontally 0 0 32 16777215 Flip selection vertically Qt::Horizontal QSizePolicy::Preferred 20 20 0 0 32 16777215 Rotate selection counter-clockwise 90 degrees 0 0 32 16777215 Rotate the selection clockwise 90 degrees Qt::Horizontal QSizePolicy::Expanding 20 20 Qt::Vertical QSizePolicy::Preferred 20 20 10 0 251 51 10 0 - + 0 0 0 0 2 0 - Flexibility: + &Flexibility: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter alphaBox 0 0 0 0 - Anchor Strength: + Anc&hor Strength: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter cmbWarpType 10 70 260 111 false Anchor Points false false 10 30 241 - 26 + 29 0 0 0 0 0 0 0 - Subdivide + Subd&ivide true true buttonGroup - + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter 0 3 10 60 - 241 - 31 + 290 + 47 0 0 0 0 0 0 0 Draw true buttonGroup - + false 0 0 0 0 0 Clear Points Lock Points Create 3 points on the canvas to begin - Add/Edit Anchor Points + Add/Ed&it Anchor Points true cageTransformButtonGroup true - Deform Layer + De&form Layer cageTransformButtonGroup Qt::Vertical 20 40 0 0 0 <html><head/><body><p><br/></p></body></html> QFrame::NoFrame QFrame::Plain 0 2 2 15 0 0 Move true true true true 0 0 Scale true true true 0 0 Rotate true true true 0 0 Offset true true true 0 0 Undo true true true 3 5 0 0 51 0 Reverse: - + 0 0 49 0 Spacing: 0 0 32 0 Flow: - + 0 0 27 0 Size: - + 0 0 51 0 Amount: - + 0 0 38 0 Mode: 0 0 0 Build Up Wash true 0 0 true Pressure true true true Pressure true true true Qt::Vertical 20 40 6 6 0 0 32 16777215 Show Decorations true false 0 0 32 16777215 Work Recursively true true Qt::Horizontal 13 13 Qt::LeftToRight Qt::Horizontal QDialogButtonBox::Apply|QDialogButtonBox::Reset true - + + + KisCmbIDList + +
widgets/kis_cmb_idlist.h
+
KoAspectButton QWidget
KoAspectButton.h
1
- KisCmbIDList - QComboBox -
widgets/kis_cmb_idlist.h
+ KisIntParseSpinBox + QSpinBox +
kis_int_parse_spin_box.h
KisDoubleSliderSpinBox QWidget
kis_slider_spin_box.h
1
+ -