diff --git a/libs/flake/KisGamutMaskViewConverter.cpp b/libs/flake/KisGamutMaskViewConverter.cpp index 2135f61c2e..dd499dfe51 100644 --- a/libs/flake/KisGamutMaskViewConverter.cpp +++ b/libs/flake/KisGamutMaskViewConverter.cpp @@ -1,174 +1,175 @@ /* * Copyright (c) 2018 Anna Medonosova * - * 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 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 library is distributed in the hope that it will be useful, + * 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 Lesser General Public License for more details. + * GNU General Public License for more details. * - * You should have received a copy of the GNU Lesser General Public License + * 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 "KisGamutMaskViewConverter.h" #include #include #include #include //#define DEBUG_GAMUT_MASK_CONVERTER KisGamutMaskViewConverter::KisGamutMaskViewConverter() : m_viewSize(1.0) , m_maskSize(QSizeF(1,1)) , m_maskResolution(1) { computeAndSetZoom(); } KisGamutMaskViewConverter::~KisGamutMaskViewConverter() { } QSize KisGamutMaskViewConverter::viewSize() const { return QSize(m_viewSize, m_viewSize); } QPointF KisGamutMaskViewConverter::documentToView(const QPointF &documentPoint) const { return QPointF(documentToViewX(documentPoint.x()), documentToViewY(documentPoint.y())); } QPointF KisGamutMaskViewConverter::viewToDocument(const QPointF &viewPoint) const { return QPointF(viewToDocumentX(viewPoint.x()), viewToDocumentY(viewPoint.y())); } QRectF KisGamutMaskViewConverter::documentToView(const QRectF &documentRect) const { return QRectF(documentToView(documentRect.topLeft()), documentToView(documentRect.size())); } QRectF KisGamutMaskViewConverter::viewToDocument(const QRectF &viewRect) const { return QRectF(viewToDocument(viewRect.topLeft()), viewToDocument(viewRect.size())); } QSizeF KisGamutMaskViewConverter::documentToView(const QSizeF &documentSize) const { return QSizeF(documentToViewX(documentSize.width()), documentToViewY(documentSize.height())); } QSizeF KisGamutMaskViewConverter::viewToDocument(const QSizeF &viewSize) const { return QSizeF(viewToDocumentX(viewSize.width()), viewToDocumentY(viewSize.height())); } qreal KisGamutMaskViewConverter::documentToViewX(qreal documentX) const { qreal translated = documentX * m_zoomLevel; #ifdef DEBUG_GAMUT_MASK_CONVERTER debugFlake << "KisGamutMaskViewConverter::DocumentToViewX: " << "documentX: " << documentX << " -> translated: " << translated; #endif return translated; } qreal KisGamutMaskViewConverter::documentToViewY(qreal documentY) const { qreal translated = documentY * m_zoomLevel; #ifdef DEBUG_GAMUT_MASK_CONVERTER debugFlake << "KisGamutMaskViewConverter::DocumentToViewY: " << "documentY: " << documentY << " -> translated: " << translated; #endif return translated; } qreal KisGamutMaskViewConverter::viewToDocumentX(qreal viewX) const { qreal translated = viewX / m_zoomLevel; #ifdef DEBUG_GAMUT_MASK_CONVERTER debugFlake << "KisGamutMaskViewConverter::viewToDocumentX: " << "viewX: " << viewX << " -> translated: " << translated; #endif return translated; } qreal KisGamutMaskViewConverter::viewToDocumentY(qreal viewY) const { qreal translated = viewY / m_zoomLevel; #ifdef DEBUG_GAMUT_MASK_CONVERTER debugFlake << "KisGamutMaskViewConverter::viewToDocumentY: " << "viewY: " << viewY << " -> translated: " << translated; #endif return translated; } void KisGamutMaskViewConverter::setZoom(qreal zoom) { if (qFuzzyCompare(zoom, qreal(0.0)) || qFuzzyCompare(zoom, qreal(1.0))) { zoom = 1; } #ifdef DEBUG_GAMUT_MASK_CONVERTER debugFlake << "KisGamutMaskViewConverter::setZoom: setting to " << zoom; #endif m_zoomLevel = zoom; } void KisGamutMaskViewConverter::zoom(qreal *zoomX, qreal *zoomY) const { *zoomX = m_zoomLevel; *zoomY = m_zoomLevel; } void KisGamutMaskViewConverter::setViewSize(QSize viewSize) { m_viewSize = viewSize.width(); computeAndSetZoom(); } void KisGamutMaskViewConverter::setMaskSize(QSizeF maskSize) { m_maskSize = maskSize; m_maskResolution = maskSize.width(); computeAndSetZoom(); } void KisGamutMaskViewConverter::computeAndSetZoom() { qreal zoom = m_viewSize / m_maskResolution; #ifdef DEBUG_GAMUT_MASK_CONVERTER debugFlake << "KisGamutMaskViewConverter::computeAndSetZoom: " << "m_viewSize: " << m_viewSize << " m_maskSize: " << m_maskResolution; #endif setZoom(zoom); } diff --git a/libs/flake/KisGamutMaskViewConverter.h b/libs/flake/KisGamutMaskViewConverter.h index 73073efae8..6155528abf 100644 --- a/libs/flake/KisGamutMaskViewConverter.h +++ b/libs/flake/KisGamutMaskViewConverter.h @@ -1,70 +1,71 @@ /* * Copyright (c) 2018 Anna Medonosova * - * 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 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 library is distributed in the hope that it will be useful, + * 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 Lesser General Public License for more details. + * GNU General Public License for more details. * - * You should have received a copy of the GNU Lesser General Public License + * 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 KISGAMUTMASKVIEWCONVERTER_H #define KISGAMUTMASKVIEWCONVERTER_H #include "kritaflake_export.h" #include #include #include class QPointF; class QRectF; /** * @brief view convertor for gamut mask calculations and painting */ class KRITAFLAKE_EXPORT KisGamutMaskViewConverter : public KoViewConverter { public: KisGamutMaskViewConverter(); ~KisGamutMaskViewConverter(); QSize viewSize() const; void setViewSize(QSize viewSize); void setMaskSize(QSizeF maskSize); QPointF documentToView(const QPointF &documentPoint) const override; QPointF viewToDocument(const QPointF &viewPoint) const override; QRectF documentToView(const QRectF &documentRect) const override; QRectF viewToDocument(const QRectF &viewRect) const override; QSizeF documentToView(const QSizeF& documentSize) const override; QSizeF viewToDocument(const QSizeF& viewSize) const override; qreal documentToViewX(qreal documentX) const override; qreal documentToViewY(qreal documentY) const override; qreal viewToDocumentX(qreal viewX) const override; qreal viewToDocumentY(qreal viewY) const override; void setZoom(qreal zoom) override; void zoom(qreal *zoomX, qreal *zoomY) const override; private: void computeAndSetZoom(); qreal m_zoomLevel; // 1.0 is 100% int m_viewSize; QSizeF m_maskSize; qreal m_maskResolution; }; #endif // KISGAMUTMASKVIEWCONVERTER_H diff --git a/libs/flake/resources/KoGamutMask.cpp b/libs/flake/resources/KoGamutMask.cpp index 5fecaea1bb..d7da355b0d 100644 --- a/libs/flake/resources/KoGamutMask.cpp +++ b/libs/flake/resources/KoGamutMask.cpp @@ -1,427 +1,428 @@ /* * Copyright (c) 2018 Anna Medonosova * - * 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 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 library is distributed in the hope that it will be useful, + * 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 Lesser General Public License for more details. + * GNU General Public License for more details. * - * You should have received a copy of the GNU Lesser General Public License + * 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 "KoGamutMask.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include KoGamutMaskShape::KoGamutMaskShape(KoShape* shape) : m_maskShape(shape) , m_shapePaintingContext(KoShapePaintingContext()) { } KoGamutMaskShape::KoGamutMaskShape() {}; KoGamutMaskShape::~KoGamutMaskShape() {}; KoShape* KoGamutMaskShape::koShape() { return m_maskShape; } bool KoGamutMaskShape::coordIsClear(const QPointF& coord, const KoViewConverter& viewConverter, int maskRotation) const { // apply mask rotation to coord const KisGamutMaskViewConverter& converter = dynamic_cast(viewConverter); QPointF centerPoint(converter.viewSize().width()*0.5, converter.viewSize().height()*0.5); QTransform rotationTransform; rotationTransform.translate(centerPoint.x(), centerPoint.y()); rotationTransform.rotate(-maskRotation); rotationTransform.translate(-centerPoint.x(), -centerPoint.y()); QPointF rotatedCoord = rotationTransform.map(coord); QPointF translatedPoint = viewConverter.viewToDocument(rotatedCoord); bool isClear = m_maskShape->hitTest(translatedPoint); return isClear; } void KoGamutMaskShape::paint(QPainter &painter, const KoViewConverter& viewConverter, int maskRotation) { painter.save(); // apply mask rotation before drawing QPointF centerPoint(painter.viewport().width()*0.5, painter.viewport().height()*0.5); painter.translate(centerPoint); painter.rotate(maskRotation); painter.translate(-centerPoint); painter.setTransform(m_maskShape->absoluteTransformation(&viewConverter) * painter.transform()); m_maskShape->paint(painter, viewConverter, m_shapePaintingContext); painter.restore(); } void KoGamutMaskShape::paintStroke(QPainter &painter, const KoViewConverter &viewConverter, int maskRotation) { painter.save(); // apply mask rotation before drawing QPointF centerPoint(painter.viewport().width()*0.5, painter.viewport().height()*0.5); painter.translate(centerPoint); painter.rotate(maskRotation); painter.translate(-centerPoint); painter.setTransform(m_maskShape->absoluteTransformation(&viewConverter) * painter.transform()); m_maskShape->paintStroke(painter, viewConverter, m_shapePaintingContext); painter.restore(); } struct Q_DECL_HIDDEN KoGamutMask::Private { QString name; QString title; QString description; QByteArray data; QVector maskShapes; QVector previewShapes; QSizeF maskSize; int rotation; }; KoGamutMask::KoGamutMask(const QString& filename) : KoResource(filename) , d(new Private()) { d->maskSize = QSizeF(144.0,144.0); setRotation(0); } KoGamutMask::KoGamutMask() : KoResource(QString()) , d(new Private()) { d->maskSize = QSizeF(144.0,144.0); setRotation(0); } KoGamutMask::KoGamutMask(KoGamutMask* rhs) : QObject(0) , KoResource(QString()) , d(new Private()) { setFilename(rhs->filename()); setTitle(rhs->title()); setDescription(rhs->description()); d->maskSize = rhs->d->maskSize; QList newShapes; for(KoShape* sh: rhs->koShapes()) { newShapes.append(sh->cloneShape()); } setMaskShapes(newShapes); setValid(true); } bool KoGamutMask::coordIsClear(const QPointF& coord, KoViewConverter &viewConverter, bool preview) { QVector* shapeVector; if (preview && !d->previewShapes.isEmpty()) { shapeVector = &d->previewShapes; } else { shapeVector = &d->maskShapes; } for(KoGamutMaskShape* shape: *shapeVector) { if (shape->coordIsClear(coord, viewConverter, rotation()) == true) { return true; } } return false; } void KoGamutMask::paint(QPainter &painter, KoViewConverter& viewConverter, bool preview) { QVector* shapeVector; if (preview && !d->previewShapes.isEmpty()) { shapeVector = &d->previewShapes; } else { shapeVector = &d->maskShapes; } for(KoGamutMaskShape* shape: *shapeVector) { shape->paint(painter, viewConverter, rotation()); } } void KoGamutMask::paintStroke(QPainter &painter, KoViewConverter &viewConverter, bool preview) { QVector* shapeVector; if (preview && !d->previewShapes.isEmpty()) { shapeVector = &d->previewShapes; } else { shapeVector = &d->maskShapes; } for(KoGamutMaskShape* shape: *shapeVector) { shape->paintStroke(painter, viewConverter, rotation()); } } bool KoGamutMask::load() { QFile file(filename()); if (file.size() == 0) return false; if (!file.open(QIODevice::ReadOnly)) { warnFlake << "Can't open file " << filename(); return false; } bool res = loadFromDevice(&file); file.close(); return res; } bool KoGamutMask::loadFromDevice(QIODevice *dev) { if (!dev->isOpen()) dev->open(QIODevice::ReadOnly); d->data = dev->readAll(); // TODO: test KIS_ASSERT_RECOVER_RETURN_VALUE(d->data.size() != 0, false); if (filename().isNull()) { warnFlake << "Cannot load gamut mask" << name() << "there is no filename set"; return false; } if (d->data.isNull()) { QFile file(filename()); if (file.size() == 0) { warnFlake << "Cannot load gamut mask" << name() << "there is no data available"; return false; } file.open(QIODevice::ReadOnly); d->data = file.readAll(); file.close(); } QBuffer buf(&d->data); buf.open(QBuffer::ReadOnly); QScopedPointer store(KoStore::createStore(&buf, KoStore::Read, "application/x-krita-gamutmask", KoStore::Zip)); if (!store || store->bad()) return false; bool storeOpened = store->open("gamutmask.svg"); if (!storeOpened) { return false; } QByteArray data; data.resize(store->size()); QByteArray ba = store->read(store->size()); store->close(); QString errorMsg; int errorLine = 0; int errorColumn = 0; KoXmlDocument xmlDocument = SvgParser::createDocumentFromSvg(ba, &errorMsg, &errorLine, &errorColumn); if (xmlDocument.isNull()) { errorFlake << "Parsing error in " << filename() << "! Aborting!" << endl << " In line: " << errorLine << ", column: " << errorColumn << endl << " Error message: " << errorMsg << endl; errorFlake << "Parsing error in the main document at line" << errorLine << ", column" << errorColumn << endl << "Error message: " << errorMsg; return false; } KoDocumentResourceManager manager; SvgParser parser(&manager); parser.setResolution(QRectF(0,0,100,100), 72); // initialize with default values QSizeF fragmentSize; QList shapes = parser.parseSvg(xmlDocument.documentElement(), &fragmentSize); d->maskSize = fragmentSize; d->title = parser.documentTitle(); setName(d->title); d->description = parser.documentDescription(); setMaskShapes(shapes); if (store->open("preview.png")) { KoStoreDevice previewDev(store.data()); previewDev.open(QIODevice::ReadOnly); QImage preview = QImage(); preview.load(&previewDev, "PNG"); setImage(preview); (void)store->close(); } buf.close(); setValid(true); return true; } void KoGamutMask::setMaskShapes(QList shapes) { setMaskShapesToVector(shapes, d->maskShapes); } bool KoGamutMask::save() { QFile file(filename()); if (!file.open(QIODevice::WriteOnly | QIODevice::Truncate)) { return false; } saveToDevice(&file); file.close(); return true; } QList KoGamutMask::koShapes() const { QList shapes; for(KoGamutMaskShape* maskShape: d->maskShapes) { shapes.append(maskShape->koShape()); } return shapes; } bool KoGamutMask::saveToDevice(QIODevice *dev) const { KoStore* store(KoStore::createStore(dev, KoStore::Write, "application/x-krita-gamutmask", KoStore::Zip)); if (!store || store->bad()) return false; QList shapes = koShapes(); std::sort(shapes.begin(), shapes.end(), KoShape::compareShapeZIndex); if (!store->open("gamutmask.svg")) { return false; } KoStoreDevice storeDev(store); storeDev.open(QIODevice::WriteOnly); SvgWriter writer(shapes); writer.setDocumentTitle(d->title); writer.setDocumentDescription(d->description); writer.save(storeDev, d->maskSize); if (!store->close()) { return false; } if (!store->open("preview.png")) { return false; } KoStoreDevice previewDev(store); previewDev.open(QIODevice::WriteOnly); image().save(&previewDev, "PNG"); if (!store->close()) { return false; } return store->finalize(); } QString KoGamutMask::title() { return d->title; } void KoGamutMask::setTitle(QString title) { d->title = title; setName(title); } QString KoGamutMask::description() { return d->description; } void KoGamutMask::setDescription(QString description) { d->description = description; } int KoGamutMask::rotation() { return d->rotation; } void KoGamutMask::setRotation(int rotation) { d->rotation = rotation; } QSizeF KoGamutMask::maskSize() { return d->maskSize; } void KoGamutMask::setPreviewMaskShapes(QList shapes) { setMaskShapesToVector(shapes, d->previewShapes); } void KoGamutMask::setMaskShapesToVector(QList shapes, QVector &targetVector) { targetVector.clear(); for(KoShape* sh: shapes) { KoGamutMaskShape* maskShape = new KoGamutMaskShape(sh); targetVector.append(maskShape); } } // clean up when ending mask preview void KoGamutMask::clearPreview() { d->previewShapes.clear(); } diff --git a/libs/flake/resources/KoGamutMask.h b/libs/flake/resources/KoGamutMask.h index a530b83fd8..bcaa2edb3a 100644 --- a/libs/flake/resources/KoGamutMask.h +++ b/libs/flake/resources/KoGamutMask.h @@ -1,99 +1,100 @@ /* * Copyright (c) 2018 Anna Medonosova * - * 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 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 library is distributed in the hope that it will be useful, + * 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 Lesser General Public License for more details. + * GNU General Public License for more details. * - * You should have received a copy of the GNU Lesser General Public License + * 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 KOGAMUTMASK_H #define KOGAMUTMASK_H #include #include #include #include #include #include #include #include #include class KoViewConverter; class KoGamutMaskShape { public: KoGamutMaskShape(KoShape* shape); KoGamutMaskShape(); ~KoGamutMaskShape(); bool coordIsClear(const QPointF& coord, const KoViewConverter& viewConverter, int maskRotation) const; QPainterPath outline(); void paint(QPainter &painter, const KoViewConverter& viewConverter, int maskRotation); void paintStroke(QPainter &painter, const KoViewConverter& viewConverter, int maskRotation); KoShape* koShape(); private: KoShape* m_maskShape; KoShapePaintingContext m_shapePaintingContext; }; /** * @brief The resource type for gamut masks used by the artistic color selector */ class KRITAFLAKE_EXPORT KoGamutMask : public QObject, public KoResource { Q_OBJECT public: KoGamutMask(const QString &filename); KoGamutMask(); KoGamutMask(KoGamutMask *rhs); bool coordIsClear(const QPointF& coord, KoViewConverter& viewConverter, bool preview); bool load() override; bool loadFromDevice(QIODevice *dev) override; bool save() override; bool saveToDevice(QIODevice* dev) const override; void paint(QPainter &painter, KoViewConverter& viewConverter, bool preview); void paintStroke(QPainter &painter, KoViewConverter& viewConverter, bool preview); QString title(); void setTitle(QString title); QString description(); void setDescription(QString description); int rotation(); void setRotation(int rotation); QSizeF maskSize(); void setMaskShapes(QList shapes); void setPreviewMaskShapes(QList shapes); QList koShapes() const; void clearPreview(); private: void setMaskShapesToVector(QList shapes, QVector& targetVector); struct Private; Private* const d; }; #endif // KOGAMUTMASK_H diff --git a/libs/image/kis_perspectivetransform_worker.cpp b/libs/image/kis_perspectivetransform_worker.cpp index 514e0ecac5..adfa76ed03 100644 --- a/libs/image/kis_perspectivetransform_worker.cpp +++ b/libs/image/kis_perspectivetransform_worker.cpp @@ -1,190 +1,192 @@ /* * This file is part of Krita * * Copyright (c) 2006 Cyrille Berger * Copyright (c) 2009 Edward Apap * Copyright (c) 2010 Marc Pegon * - * 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 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 library is distributed in the hope that it will be useful, + * 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 Lesser General Public License for more details. + * GNU General Public License for more details. * - * You should have received a copy of the GNU Lesser General Public License + * 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_perspectivetransform_worker.h" #include #include #include #include #include #include #include #include "kis_paint_device.h" #include "kis_perspective_math.h" #include "kis_random_accessor_ng.h" #include "kis_random_sub_accessor.h" #include "kis_selection.h" #include #include "krita_utils.h" #include "kis_progress_update_helper.h" #include "kis_painter.h" #include "kis_image.h" KisPerspectiveTransformWorker::KisPerspectiveTransformWorker(KisPaintDeviceSP dev, QPointF center, double aX, double aY, double distance, KoUpdaterPtr progress) : m_dev(dev), m_progressUpdater(progress) { QMatrix4x4 m; m.rotate(180. * aX / M_PI, QVector3D(1, 0, 0)); m.rotate(180. * aY / M_PI, QVector3D(0, 1, 0)); QTransform project = m.toTransform(distance); QTransform t = QTransform::fromTranslate(center.x(), center.y()); QTransform forwardTransform = t.inverted() * project * t; init(forwardTransform); } KisPerspectiveTransformWorker::KisPerspectiveTransformWorker(KisPaintDeviceSP dev, const QTransform &transform, KoUpdaterPtr progress) : m_dev(dev), m_progressUpdater(progress) { init(transform); } void KisPerspectiveTransformWorker::fillParams(const QRectF &srcRect, const QRect &dstBaseClipRect, QRegion *dstRegion, QPolygonF *dstClipPolygon) { QPolygonF bounds = srcRect; QPolygonF newBounds = m_forwardTransform.map(bounds); newBounds = newBounds.intersected(QRectF(dstBaseClipRect)); QPainterPath path; path.addPolygon(newBounds); *dstRegion = KritaUtils::splitPath(path); *dstClipPolygon = newBounds; } void KisPerspectiveTransformWorker::init(const QTransform &transform) { m_isIdentity = transform.isIdentity(); m_forwardTransform = transform; m_backwardTransform = transform.inverted(); if (m_dev) { m_srcRect = m_dev->exactBounds(); QPolygonF dstClipPolygonUnused; fillParams(m_srcRect, m_dev->defaultBounds()->bounds(), &m_dstRegion, &dstClipPolygonUnused); } } KisPerspectiveTransformWorker::~KisPerspectiveTransformWorker() { } void KisPerspectiveTransformWorker::setForwardTransform(const QTransform &transform) { init(transform); } void KisPerspectiveTransformWorker::run() { KIS_ASSERT_RECOVER_RETURN(m_dev); if (m_isIdentity) return; KisPaintDeviceSP cloneDevice = new KisPaintDevice(*m_dev.data()); // Clear the destination device, since all the tiles are already // shared with cloneDevice m_dev->clear(); KIS_ASSERT_RECOVER_NOOP(!m_isIdentity); KisProgressUpdateHelper progressHelper(m_progressUpdater, 100, m_dstRegion.rectCount()); KisRandomSubAccessorSP srcAcc = cloneDevice->createRandomSubAccessor(); KisRandomAccessorSP accessor = m_dev->createRandomAccessorNG(0, 0); Q_FOREACH (const QRect &rect, m_dstRegion.rects()) { for (int y = rect.y(); y < rect.y() + rect.height(); ++y) { for (int x = rect.x(); x < rect.x() + rect.width(); ++x) { QPointF dstPoint(x, y); QPointF srcPoint = m_backwardTransform.map(dstPoint); if (m_srcRect.contains(srcPoint)) { accessor->moveTo(dstPoint.x(), dstPoint.y()); srcAcc->moveTo(srcPoint.x(), srcPoint.y()); srcAcc->sampledOldRawData(accessor->rawData()); } } } progressHelper.step(); } } void KisPerspectiveTransformWorker::runPartialDst(KisPaintDeviceSP srcDev, KisPaintDeviceSP dstDev, const QRect &dstRect) { if (m_isIdentity) { KisPainter::copyAreaOptimizedOldData(dstRect.topLeft(), srcDev, dstDev, dstRect); return; } QRectF srcClipRect = srcDev->exactBounds(); if (srcClipRect.isEmpty()) return; KisProgressUpdateHelper progressHelper(m_progressUpdater, 100, dstRect.height()); KisRandomSubAccessorSP srcAcc = srcDev->createRandomSubAccessor(); KisRandomAccessorSP accessor = dstDev->createRandomAccessorNG(dstRect.x(), dstRect.y()); for (int y = dstRect.y(); y < dstRect.y() + dstRect.height(); ++y) { for (int x = dstRect.x(); x < dstRect.x() + dstRect.width(); ++x) { QPointF dstPoint(x, y); QPointF srcPoint = m_backwardTransform.map(dstPoint); if (srcClipRect.contains(srcPoint)) { accessor->moveTo(dstPoint.x(), dstPoint.y()); srcAcc->moveTo(srcPoint.x(), srcPoint.y()); srcAcc->sampledOldRawData(accessor->rawData()); } } progressHelper.step(); } } QTransform KisPerspectiveTransformWorker::forwardTransform() const { return m_forwardTransform; } QTransform KisPerspectiveTransformWorker::backwardTransform() const { return m_backwardTransform; } diff --git a/libs/image/kis_perspectivetransform_worker.h b/libs/image/kis_perspectivetransform_worker.h index f148ea61a2..c80697fbd1 100644 --- a/libs/image/kis_perspectivetransform_worker.h +++ b/libs/image/kis_perspectivetransform_worker.h @@ -1,69 +1,68 @@ /* - * This file is part of Krita - * * Copyright (c) 2006 Cyrille Berger * Copyright (c) 2010 Marc Pegon * - * 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 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 library is distributed in the hope that it will be useful, + * 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 Lesser General Public License for more details. + * GNU General Public License for more details. * - * You should have received a copy of the GNU Lesser General Public License + * 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_PERSPECTIVETRANSFORM_WORKER_H #define KIS_PERSPECTIVETRANSFORM_WORKER_H #include "kis_types.h" #include "kritaimage_export.h" #include #include #include #include class KRITAIMAGE_EXPORT KisPerspectiveTransformWorker { public: KisPerspectiveTransformWorker(KisPaintDeviceSP dev, QPointF center, double aX, double aY, double distance, KoUpdaterPtr progress); KisPerspectiveTransformWorker(KisPaintDeviceSP dev, const QTransform &transform, KoUpdaterPtr progress); ~KisPerspectiveTransformWorker(); void run(); void runPartialDst(KisPaintDeviceSP srcDev, KisPaintDeviceSP dstDev, const QRect &dstRect); void setForwardTransform(const QTransform &transform); QTransform forwardTransform() const; QTransform backwardTransform() const; private: void init(const QTransform &transform); void fillParams(const QRectF &srcRect, const QRect &dstBaseClipRect, QRegion *dstRegion, QPolygonF *dstClipPolygon); private: KisPaintDeviceSP m_dev; KoUpdaterPtr m_progressUpdater; QRegion m_dstRegion; QRectF m_srcRect; QTransform m_backwardTransform; QTransform m_forwardTransform; bool m_isIdentity; }; #endif diff --git a/libs/ui/canvas/KisMirrorAxisConfig.cpp b/libs/ui/canvas/KisMirrorAxisConfig.cpp index 2a316f9ee5..c99e74f133 100644 --- a/libs/ui/canvas/KisMirrorAxisConfig.cpp +++ b/libs/ui/canvas/KisMirrorAxisConfig.cpp @@ -1,250 +1,251 @@ /* * Copyright (c) 2019 Anna Medonosova * - * 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 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 library is distributed in the hope that it will be useful, + * 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 Lesser General Public License for more details. + * GNU General Public License for more details. * - * You should have received a copy of the GNU Lesser General Public License + * 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 #include #include "KisMirrorAxisConfig.h" class Q_DECL_HIDDEN KisMirrorAxisConfig::Private { public: Private() : mirrorHorizontal(false) , mirrorVertical(false) , lockHorizontal(false) , lockVertical(false) , hideVerticalDecoration(false) , hideHorizontalDecoration(false) , handleSize(32.f) , horizontalHandlePosition(64.f) , verticalHandlePosition(64.f) , axisPosition(QPointF(0.f,0.f)) {} bool operator==(const Private& rhs) { return mirrorHorizontal == rhs.mirrorHorizontal && mirrorVertical == rhs.mirrorVertical && lockHorizontal == rhs.lockHorizontal && lockVertical == rhs.lockVertical && hideHorizontalDecoration == rhs.hideHorizontalDecoration && hideVerticalDecoration == rhs.hideVerticalDecoration && handleSize == rhs.handleSize && horizontalHandlePosition == rhs.horizontalHandlePosition && verticalHandlePosition == rhs.verticalHandlePosition && axisPosition == rhs.axisPosition; } bool mirrorHorizontal; bool mirrorVertical; bool lockHorizontal; bool lockVertical; bool hideVerticalDecoration; bool hideHorizontalDecoration; float handleSize; float horizontalHandlePosition; float verticalHandlePosition; QPointF axisPosition; }; KisMirrorAxisConfig::KisMirrorAxisConfig() : QObject() , d(new Private()) { } KisMirrorAxisConfig::~KisMirrorAxisConfig() { } KisMirrorAxisConfig::KisMirrorAxisConfig(const KisMirrorAxisConfig &rhs) : QObject() , d(new Private(*rhs.d)) { } KisMirrorAxisConfig &KisMirrorAxisConfig::operator=(const KisMirrorAxisConfig &rhs) { if (&rhs != this) { *d = *rhs.d; } return *this; } bool KisMirrorAxisConfig::operator==(const KisMirrorAxisConfig &rhs) const { KIS_ASSERT(d); KIS_ASSERT(rhs.d); return *d == *rhs.d; } bool KisMirrorAxisConfig::mirrorHorizontal() { return d->mirrorHorizontal; } void KisMirrorAxisConfig::setMirrorHorizontal(bool state) { d->mirrorHorizontal = state; } bool KisMirrorAxisConfig::mirrorVertical() { return d->mirrorVertical; } void KisMirrorAxisConfig::setMirrorVertical(bool state) { d->mirrorVertical = state; } bool KisMirrorAxisConfig::lockHorizontal() { return d->lockHorizontal; } void KisMirrorAxisConfig::setLockHorizontal(bool state) { d->lockHorizontal = state; } bool KisMirrorAxisConfig::lockVertical() { return d->lockVertical; } void KisMirrorAxisConfig::setLockVertical(bool state) { d->lockVertical = state; } bool KisMirrorAxisConfig::hideVerticalDecoration() { return d->hideVerticalDecoration; } void KisMirrorAxisConfig::setHideVerticalDecoration(bool state) { d->hideVerticalDecoration = state; } bool KisMirrorAxisConfig::hideHorizontalDecoration() { return d->hideHorizontalDecoration; } void KisMirrorAxisConfig::setHideHorizontalDecoration(bool state) { d->hideHorizontalDecoration = state; } float KisMirrorAxisConfig::handleSize() { return d->handleSize; } void KisMirrorAxisConfig::setHandleSize(float size) { d->handleSize = size; } float KisMirrorAxisConfig::horizontalHandlePosition() { return d->horizontalHandlePosition; } void KisMirrorAxisConfig::setHorizontalHandlePosition(float position) { d->horizontalHandlePosition = position; } float KisMirrorAxisConfig::verticalHandlePosition() { return d->verticalHandlePosition; } void KisMirrorAxisConfig::setVerticalHandlePosition(float position) { d->verticalHandlePosition = position; } QPointF KisMirrorAxisConfig::axisPosition() { return d->axisPosition; } void KisMirrorAxisConfig::setAxisPosition(QPointF position) { d->axisPosition = position; } QDomElement KisMirrorAxisConfig::saveToXml(QDomDocument &doc, const QString &tag) const { QDomElement mirrorAxisElement = doc.createElement(tag); KisDomUtils::saveValue(&mirrorAxisElement, "mirrorHorizontal", d->mirrorHorizontal); KisDomUtils::saveValue(&mirrorAxisElement, "mirrorVertical", d->mirrorVertical); KisDomUtils::saveValue(&mirrorAxisElement, "lockHorizontal", d->lockHorizontal); KisDomUtils::saveValue(&mirrorAxisElement, "lockVertical", d->lockVertical); KisDomUtils::saveValue(&mirrorAxisElement, "hideHorizontalDecoration", d->hideHorizontalDecoration); KisDomUtils::saveValue(&mirrorAxisElement, "hideVerticalDecoration", d->hideVerticalDecoration); KisDomUtils::saveValue(&mirrorAxisElement, "handleSize", d->handleSize); KisDomUtils::saveValue(&mirrorAxisElement, "horizontalHandlePosition", d->horizontalHandlePosition); KisDomUtils::saveValue(&mirrorAxisElement, "verticalHandlePosition", d->verticalHandlePosition); KisDomUtils::saveValue(&mirrorAxisElement, "axisPosition", d->axisPosition); return mirrorAxisElement; } bool KisMirrorAxisConfig::loadFromXml(const QDomElement &parent) { bool result = true; result &= KisDomUtils::loadValue(parent, "mirrorHorizontal", &d->mirrorHorizontal); result &= KisDomUtils::loadValue(parent, "mirrorVertical", &d->mirrorVertical); result &= KisDomUtils::loadValue(parent, "lockHorizontal", &d->lockHorizontal); result &= KisDomUtils::loadValue(parent, "lockVertical", &d->lockVertical); result &= KisDomUtils::loadValue(parent, "hideHorizontalDecoration", &d->hideHorizontalDecoration); result &= KisDomUtils::loadValue(parent, "hideVerticalDecoration", &d->hideVerticalDecoration); result &= KisDomUtils::loadValue(parent, "handleSize", &d->handleSize); result &= KisDomUtils::loadValue(parent, "horizontalHandlePosition", &d->horizontalHandlePosition); result &= KisDomUtils::loadValue(parent, "verticalHandlePosition", &d->verticalHandlePosition); result &= KisDomUtils::loadValue(parent, "axisPosition", &d->axisPosition); return result; } bool KisMirrorAxisConfig::isDefault() const { KisMirrorAxisConfig defaultConfig; return *this == defaultConfig; } diff --git a/libs/ui/canvas/KisMirrorAxisConfig.h b/libs/ui/canvas/KisMirrorAxisConfig.h index d2421297c3..53cb3ab075 100644 --- a/libs/ui/canvas/KisMirrorAxisConfig.h +++ b/libs/ui/canvas/KisMirrorAxisConfig.h @@ -1,103 +1,104 @@ /* * Copyright (c) 2019 Anna Medonosova * - * 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 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 library is distributed in the hope that it will be useful, + * 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 Lesser General Public License for more details. + * GNU General Public License for more details. * - * You should have received a copy of the GNU Lesser General Public License + * 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 KISMIRRORAXISCONFIG_H #define KISMIRRORAXISCONFIG_H #include #include "kritaui_export.h" #include class QDomElement; class QDomDocument; /** * @brief The KisMirrorAxisConfig class stores configuration for the KisMirrorAxis * canvas decoration. Contents are saved to/loaded from KRA documents. */ class KRITAUI_EXPORT KisMirrorAxisConfig : public QObject, boost::equality_comparable { Q_OBJECT public: KisMirrorAxisConfig(); ~KisMirrorAxisConfig(); KisMirrorAxisConfig(const KisMirrorAxisConfig &rhs); KisMirrorAxisConfig& operator=(const KisMirrorAxisConfig& rhs); bool operator==(const KisMirrorAxisConfig& rhs) const; bool mirrorHorizontal(); void setMirrorHorizontal(bool state); bool mirrorVertical(); void setMirrorVertical(bool state); bool lockHorizontal(); void setLockHorizontal(bool state); bool lockVertical(); void setLockVertical(bool state); bool hideVerticalDecoration(); void setHideVerticalDecoration(bool state); bool hideHorizontalDecoration(); void setHideHorizontalDecoration(bool state); float handleSize(); void setHandleSize(float size); float horizontalHandlePosition(); void setHorizontalHandlePosition(float position); float verticalHandlePosition(); void setVerticalHandlePosition(float position); QPointF axisPosition(); void setAxisPosition(QPointF position); /** * @brief saveToXml() function for KisKraSaver * @param doc * @param tag * @return */ QDomElement saveToXml(QDomDocument& doc, const QString &tag) const; /** * @brief loadFromXml() function for KisKraLoader * @param parent element * @return */ bool loadFromXml(const QDomElement &parent); /** * @brief Check whether the config object was changed, or is the class default. * @return true, if the object is default; false, if the config was changed */ bool isDefault() const; private: class Private; const QScopedPointer d; }; #endif // KISMIRRORAXISCONFIG_H diff --git a/libs/ui/canvas/KisSnapPixelStrategy.cpp b/libs/ui/canvas/KisSnapPixelStrategy.cpp index d924e19962..cdb79db7a6 100644 --- a/libs/ui/canvas/KisSnapPixelStrategy.cpp +++ b/libs/ui/canvas/KisSnapPixelStrategy.cpp @@ -1,56 +1,57 @@ /* * Copyright (c) 2019 Kuntal Majumder * * 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. + * 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 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 "KisSnapPixelStrategy.h" #include #include "kis_global.h" #include "kis_canvas2.h" #include "KoSnapProxy.h" KisSnapPixelStrategy::KisSnapPixelStrategy(KoSnapGuide::Strategy type): KoSnapStrategy(type) { } KisSnapPixelStrategy::~KisSnapPixelStrategy() { } bool KisSnapPixelStrategy::snap(const QPointF &mousePosition, KoSnapProxy *proxy, qreal maxSnapDistance) { Q_UNUSED(maxSnapDistance); KisCanvas2 *canvas2 = dynamic_cast(proxy->canvas()); KIS_SAFE_ASSERT_RECOVER_RETURN_VALUE(canvas2, false); const QPointF imagePos = canvas2->coordinatesConverter()->documentToImage(mousePosition); const QPointF alignedDocPoint = canvas2->coordinatesConverter()->imageToDocument(imagePos.toPoint()); setSnappedPosition(alignedDocPoint); return true; } QPainterPath KisSnapPixelStrategy::decoration(const KoViewConverter &converter) const { QSizeF unzoomedSize = converter.viewToDocument(QSizeF(5, 5)); QPainterPath decoration; decoration.moveTo(snappedPosition() - QPointF(unzoomedSize.width(), 0)); decoration.lineTo(snappedPosition() + QPointF(unzoomedSize.width(), 0)); decoration.moveTo(snappedPosition() - QPointF(0, unzoomedSize.height())); decoration.lineTo(snappedPosition() + QPointF(0, unzoomedSize.height())); return decoration; } diff --git a/libs/ui/kis_selection_decoration.cc b/libs/ui/kis_selection_decoration.cc index deecb1a39d..492276fecb 100644 --- a/libs/ui/kis_selection_decoration.cc +++ b/libs/ui/kis_selection_decoration.cc @@ -1,228 +1,229 @@ /* * Copyright (c) 2008 Sven Langkamp * * 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. + * the Free Software Foundation; 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 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_selection_decoration.h" #include #include #include #include #include "kis_types.h" #include "KisViewManager.h" #include "kis_selection.h" #include "kis_image.h" #include "flake/kis_shape_selection.h" #include "kis_pixel_selection.h" #include "kis_update_outline_job.h" #include "kis_selection_manager.h" #include "canvas/kis_canvas2.h" #include "kis_canvas_resource_provider.h" #include "kis_coordinates_converter.h" #include "kis_config.h" #include "kis_config_notifier.h" #include "kis_image_config.h" #include "KisImageConfigNotifier.h" #include "kis_painting_tweaks.h" #include "KisView.h" #include "kis_selection_mask.h" #include static const unsigned int ANT_LENGTH = 4; static const unsigned int ANT_SPACE = 4; static const unsigned int ANT_ADVANCE_WIDTH = ANT_LENGTH + ANT_SPACE; KisSelectionDecoration::KisSelectionDecoration(QPointerview) : KisCanvasDecoration("selection", view), m_signalCompressor(500 /*ms*/, KisSignalCompressor::FIRST_INACTIVE), m_offset(0), m_mode(Ants) { KisPaintingTweaks::initAntsPen(&m_antsPen, &m_outlinePen, ANT_LENGTH, ANT_SPACE); connect(KisConfigNotifier::instance(), SIGNAL(configChanged()), SLOT(slotConfigChanged())); connect(KisImageConfigNotifier::instance(), SIGNAL(configChanged()), SLOT(slotConfigChanged())); slotConfigChanged(); m_antsTimer = new QTimer(this); m_antsTimer->setInterval(150); m_antsTimer->setSingleShot(false); connect(m_antsTimer, SIGNAL(timeout()), SLOT(antsAttackEvent())); connect(&m_signalCompressor, SIGNAL(timeout()), SLOT(slotStartUpdateSelection())); // selections should be at the top of the stack setPriority(100); } KisSelectionDecoration::~KisSelectionDecoration() { } KisSelectionDecoration::Mode KisSelectionDecoration::mode() const { return m_mode; } void KisSelectionDecoration::setMode(Mode mode) { m_mode = mode; selectionChanged(); } bool KisSelectionDecoration::selectionIsActive() { KisImageWSP image = view()->image(); Q_ASSERT(image); Q_UNUSED(image); KisSelectionSP selection = view()->selection(); return visible() && selection && (selection->hasPixelSelection() || selection->hasShapeSelection()) && selection->isVisible(); } void KisSelectionDecoration::selectionChanged() { KisSelectionMaskSP mask = qobject_cast(view()->currentNode().data()); if (!mask || !mask->active() || !mask->visible(true)) { mask = 0; } if (!view()->isCurrent() || view()->viewManager()->mainWindow() == KisPart::instance()->currentMainwindow()) { view()->image()->setOverlaySelectionMask(mask); } KisSelectionSP selection = view()->selection(); if (!mask && selection && selectionIsActive()) { if ((m_mode == Ants && selection->outlineCacheValid()) || (m_mode == Mask && selection->thumbnailImageValid())) { m_signalCompressor.stop(); if (m_mode == Ants) { m_outlinePath = selection->outlineCache(); m_antsTimer->start(); } else { m_thumbnailImage = selection->thumbnailImage(); m_thumbnailImageTransform = selection->thumbnailImageTransform(); } if (view() && view()->canvasBase()) { view()->canvasBase()->updateCanvas(); } } else { m_signalCompressor.start(); } } else { m_signalCompressor.stop(); m_outlinePath = QPainterPath(); m_thumbnailImage = QImage(); m_thumbnailImageTransform = QTransform(); view()->canvasBase()->updateCanvas(); m_antsTimer->stop(); } } void KisSelectionDecoration::slotStartUpdateSelection() { KisSelectionSP selection = view()->selection(); if (!selection) return; view()->image()->addSpontaneousJob(new KisUpdateOutlineJob(selection, m_mode == Mask, m_maskColor)); } void KisSelectionDecoration::slotConfigChanged() { KisImageConfig imageConfig(true); KisConfig cfg(true); m_maskColor = imageConfig.selectionOverlayMaskColor(); m_antialiasSelectionOutline = cfg.antialiasSelectionOutline(); } void KisSelectionDecoration::antsAttackEvent() { KisSelectionSP selection = view()->selection(); if (!selection) return; if (selectionIsActive()) { m_offset = (m_offset + 1) % ANT_ADVANCE_WIDTH; m_antsPen.setDashOffset(m_offset); view()->canvasBase()->updateCanvas(); } } void KisSelectionDecoration::drawDecoration(QPainter& gc, const QRectF& updateRect, const KisCoordinatesConverter *converter, KisCanvas2 *canvas) { Q_UNUSED(updateRect); Q_UNUSED(canvas); if (!selectionIsActive()) return; if ((m_mode == Ants && m_outlinePath.isEmpty()) || (m_mode == Mask && m_thumbnailImage.isNull())) return; QTransform transform = converter->imageToWidgetTransform(); gc.save(); gc.setTransform(transform, false); if (m_mode == Mask) { gc.setRenderHints(QPainter::SmoothPixmapTransform | QPainter::HighQualityAntialiasing, false); gc.setTransform(m_thumbnailImageTransform, true); gc.drawImage(QPoint(), m_thumbnailImage); QRect r1 = m_thumbnailImageTransform.inverted().mapRect(view()->image()->bounds()); QRect r2 = m_thumbnailImage.rect(); QPainterPath p1; p1.addRect(r1); QPainterPath p2; p2.addRect(r2); gc.setBrush(m_maskColor); gc.setPen(Qt::NoPen); gc.drawPath(p1 - p2); } else /* if (m_mode == Ants) */ { gc.setRenderHints(QPainter::Antialiasing | QPainter::HighQualityAntialiasing, m_antialiasSelectionOutline); // render selection outline in white gc.setPen(m_outlinePen); gc.drawPath(m_outlinePath); // render marching ants in black (above the white outline) gc.setPen(m_antsPen); gc.drawPath(m_outlinePath); } gc.restore(); } void KisSelectionDecoration::setVisible(bool v) { KisCanvasDecoration::setVisible(v); selectionChanged(); } diff --git a/libs/ui/kis_selection_decoration.h b/libs/ui/kis_selection_decoration.h index 7c6a896818..ea90ebb475 100644 --- a/libs/ui/kis_selection_decoration.h +++ b/libs/ui/kis_selection_decoration.h @@ -1,75 +1,76 @@ /* * Copyright (c) 2008 Sven Langkamp * * 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. + * the Free Software Foundation; 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 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_SELECTION_DECORATION_H_ #define _KIS_SELECTION_DECORATION_H_ #include #include #include #include #include "canvas/kis_canvas_decoration.h" class KisView; class KRITAUI_EXPORT KisSelectionDecoration : public KisCanvasDecoration { Q_OBJECT public: KisSelectionDecoration(QPointer view); ~KisSelectionDecoration() override; enum Mode { Ants, Mask }; Mode mode() const; void setMode(Mode mode); void setVisible(bool v) override; protected: void drawDecoration(QPainter& gc, const QRectF& updateRect, const KisCoordinatesConverter *converter,KisCanvas2* canvas) override; private Q_SLOTS: void slotStartUpdateSelection(); void slotConfigChanged(); public Q_SLOTS: void selectionChanged(); void antsAttackEvent(); private: bool selectionIsActive(); private: KisSignalCompressor m_signalCompressor; QPainterPath m_outlinePath; QImage m_thumbnailImage; QTransform m_thumbnailImageTransform; QTimer* m_antsTimer; int m_offset; QPen m_antsPen; QPen m_outlinePen; Mode m_mode; QColor m_maskColor; bool m_antialiasSelectionOutline; }; #endif diff --git a/libs/ui/kis_tooltip_manager.cpp b/libs/ui/kis_tooltip_manager.cpp index 1bc93e3db3..c2c26678e3 100644 --- a/libs/ui/kis_tooltip_manager.cpp +++ b/libs/ui/kis_tooltip_manager.cpp @@ -1,99 +1,100 @@ /* * Copyright (c) 2014 Sven Langkamp * * 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. + * the Free Software Foundation; 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 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_tooltip_manager.h" #include #include #include #include #include #include #include #include #include "KisViewManager.h" KisTooltipManager::KisTooltipManager(KisViewManager* view) : QObject(view), m_view(view), m_recording(false) { m_view->mainWindow()->menuBar()->installEventFilter(this); } KisTooltipManager::~KisTooltipManager() { if (m_recording) { QFile f("tooltips.txt"); f.open(QFile::WriteOnly); QDomDocument doc; QDomElement root; root = doc.createElement("tooltips"); doc.appendChild(root); QMapIterator it(m_tooltipMap); while (it.hasNext()) { it.next(); QDomElement tooltip = doc.createElement("tooltip"); tooltip.setAttribute("action", it.key()); tooltip.appendChild(doc.createTextNode(it.value())); root.appendChild(tooltip); } QTextStream stream(&f); stream.setCodec("UTF-8"); stream << doc.toString(); f.close(); } } void KisTooltipManager::record() { m_recording = true; QList actions = m_view->actionCollection()->actions(); Q_FOREACH (KXMLGUIClient* client, m_view->mainWindow()->childClients() ) { actions.append(client->actionCollection()->actions()); } Q_FOREACH (QAction* action, actions) { action->disconnect(); connect(action, SIGNAL(triggered()), this, SLOT(captureToolip())); } } void KisTooltipManager::captureToolip() { QString id = sender()->objectName(); QString oldTooltip; if (m_tooltipMap.contains(id)) { oldTooltip = m_tooltipMap[id]; } bool ok; QString tooltip = QInputDialog::getText(m_view->mainWindow(), "Add Tooltip", "New Tooltip:", QLineEdit::Normal, oldTooltip, &ok); if (ok && !tooltip.isEmpty()) { dynamic_cast(sender())->setToolTip(tooltip); m_tooltipMap[id] = tooltip; } } diff --git a/libs/ui/kis_tooltip_manager.h b/libs/ui/kis_tooltip_manager.h index d5a6f88064..74c3e85114 100644 --- a/libs/ui/kis_tooltip_manager.h +++ b/libs/ui/kis_tooltip_manager.h @@ -1,44 +1,45 @@ /* * Copyright (c) 2014 Sven Langkamp * * 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. + * the Free Software Foundation; 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 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 KISTOOLTIPMANAGER_H #define KISTOOLTIPMANAGER_H #include #include class KisViewManager; class KisTooltipManager : public QObject { Q_OBJECT public: KisTooltipManager(KisViewManager* view); ~KisTooltipManager() override; void record(); private Q_SLOTS: void captureToolip(); private: KisViewManager* m_view; bool m_recording; QMap m_tooltipMap; }; #endif // KISTOOLTIPMANAGER_H diff --git a/libs/ui/kisexiv2/kis_exif_io.cpp b/libs/ui/kisexiv2/kis_exif_io.cpp index 654f6fca0c..da86e64559 100644 --- a/libs/ui/kisexiv2/kis_exif_io.cpp +++ b/libs/ui/kisexiv2/kis_exif_io.cpp @@ -1,639 +1,640 @@ /* * Copyright (c) 2007 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. + * the Free Software Foundation; 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 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_exif_io.h" #include #include #include #include #include #include #include #include #include #include #include #include "kis_exiv2.h" #include #include #include #include #include struct KisExifIO::Private { }; // ---- Exception conversion functions ---- // // convert ExifVersion and FlashpixVersion to a KisMetaData value KisMetaData::Value exifVersionToKMDValue(const Exiv2::Value::AutoPtr value) { const Exiv2::DataValue* dvalue = dynamic_cast(&*value); if (dvalue) { Q_ASSERT(dvalue); QByteArray array(dvalue->count(), 0); dvalue->copy((Exiv2::byte*)array.data()); return KisMetaData::Value(QString(array)); } else { Q_ASSERT(value->typeId() == Exiv2::asciiString); return KisMetaData::Value(QString::fromLatin1(value->toString().c_str())); } } // convert from KisMetaData value to ExifVersion and FlashpixVersion Exiv2::Value* kmdValueToExifVersion(const KisMetaData::Value& value) { Exiv2::DataValue* dvalue = new Exiv2::DataValue; QString ver = value.asVariant().toString(); dvalue->read((const Exiv2::byte*)ver.toLatin1().constData(), ver.size()); return dvalue; } // Convert an exif array of integer string to a KisMetaData array of integer KisMetaData::Value exifArrayToKMDIntOrderedArray(const Exiv2::Value::AutoPtr value) { QList v; const Exiv2::DataValue* dvalue = dynamic_cast(&*value); if (dvalue) { QByteArray array(dvalue->count(), 0); dvalue->copy((Exiv2::byte*)array.data()); for (int i = 0; i < array.size(); i++) { QChar c((char)array[i]); v.push_back(KisMetaData::Value(QString(c).toInt(0))); } } else { Q_ASSERT(value->typeId() == Exiv2::asciiString); QString str = QString::fromLatin1(value->toString().c_str()); v.push_back(KisMetaData::Value(str.toInt())); } return KisMetaData::Value(v, KisMetaData::Value::OrderedArray); } // Convert a KisMetaData array of integer to an exif array of integer string Exiv2::Value* kmdIntOrderedArrayToExifArray(const KisMetaData::Value& value) { QList v = value.asArray(); QByteArray s; for (QList::iterator it = v.begin(); it != v.end(); ++it) { int val = it->asVariant().toInt(0); s += QByteArray::number(val); } return new Exiv2::DataValue((const Exiv2::byte*)s.data(), s.size()); } QDateTime exivValueToDateTime(const Exiv2::Value::AutoPtr value) { return QDateTime::fromString(value->toString().c_str(), Qt::ISODate); } template inline T fixEndianess(T v, Exiv2::ByteOrder order) { switch (order) { case Exiv2::invalidByteOrder: return v; case Exiv2::littleEndian: return qFromLittleEndian(v); case Exiv2::bigEndian: return qFromBigEndian(v); } warnKrita << "KisExifIO: unknown byte order"; return v; } Exiv2::ByteOrder invertByteOrder(Exiv2::ByteOrder order) { switch (order) { case Exiv2::littleEndian: return Exiv2::bigEndian; case Exiv2::bigEndian: return Exiv2::littleEndian; case Exiv2::invalidByteOrder: warnKrita << "KisExifIO: Can't invert Exiv2::invalidByteOrder"; return Exiv2::invalidByteOrder; } return Exiv2::invalidByteOrder; } KisMetaData::Value exifOECFToKMDOECFStructure(const Exiv2::Value::AutoPtr value, Exiv2::ByteOrder order) { QMap oecfStructure; const Exiv2::DataValue* dvalue = dynamic_cast(&*value); Q_ASSERT(dvalue); QByteArray array(dvalue->count(), 0); dvalue->copy((Exiv2::byte*)array.data()); int columns = fixEndianess((reinterpret_cast(array.data()))[0], order); int rows = fixEndianess((reinterpret_cast(array.data()))[1], order); if ((columns * rows + 4) > dvalue->count()) { // Sometime byteOrder get messed up (especially if metadata got saved with kexiv2 library, or any library that doesn't save back with the same byte order as the camera) order = invertByteOrder(order); columns = fixEndianess((reinterpret_cast(array.data()))[0], order); rows = fixEndianess((reinterpret_cast(array.data()))[1], order); Q_ASSERT((columns * rows + 4) > dvalue->count()); } oecfStructure["Columns"] = KisMetaData::Value(columns); oecfStructure["Rows"] = KisMetaData::Value(rows); int index = 4; QList names; for (int i = 0; i < columns; i++) { int lastIndex = array.indexOf((char)0, index); QString name = array.mid(index, lastIndex - index); if (index != lastIndex) { index = lastIndex + 1; dbgMetaData << "Name [" << i << "] =" << name; names.append(KisMetaData::Value(name)); } else { names.append(KisMetaData::Value("")); } } oecfStructure["Names"] = KisMetaData::Value(names, KisMetaData::Value::OrderedArray); QList values; qint32* dataIt = reinterpret_cast(array.data() + index); for (int i = 0; i < columns; i++) { for (int j = 0; j < rows; j++) { values.append(KisMetaData::Value(KisMetaData::Rational(fixEndianess(dataIt[0], order), fixEndianess(dataIt[1], order)))); dataIt += 2; } } oecfStructure["Values"] = KisMetaData::Value(values, KisMetaData::Value::OrderedArray); dbgMetaData << "OECF: " << ppVar(columns) << ppVar(rows) << ppVar(dvalue->count()); return KisMetaData::Value(oecfStructure); } Exiv2::Value* kmdOECFStructureToExifOECF(const KisMetaData::Value& value) { QMap oecfStructure = value.asStructure(); quint16 columns = oecfStructure["Columns"].asVariant().toInt(0); quint16 rows = oecfStructure["Rows"].asVariant().toInt(0); QList names = oecfStructure["Names"].asArray(); QList values = oecfStructure["Values"].asArray(); Q_ASSERT(columns*rows == values.size()); int length = 4 + rows * columns * 8; // The 4 byte for storing rows/columns and the rows*columns*sizeof(rational) bool saveNames = (!names.empty() && names[0].asVariant().toString().size() > 0); if (saveNames) { for (int i = 0; i < columns; i++) { length += names[i].asVariant().toString().size() + 1; } } QByteArray array(length, 0); (reinterpret_cast(array.data()))[0] = columns; (reinterpret_cast(array.data()))[1] = rows; int index = 4; if (saveNames) { for (int i = 0; i < columns; i++) { QByteArray name = names[i].asVariant().toString().toLatin1(); name.append((char)0); memcpy(array.data() + index, name.data(), name.size()); index += name.size(); } } qint32* dataIt = reinterpret_cast(array.data() + index); for (QList::iterator it = values.begin(); it != values.end(); ++it) { dataIt[0] = it->asRational().numerator; dataIt[1] = it->asRational().denominator; dataIt += 2; } return new Exiv2::DataValue((const Exiv2::byte*)array.data(), array.size()); } KisMetaData::Value deviceSettingDescriptionExifToKMD(const Exiv2::Value::AutoPtr value) { QMap deviceSettingStructure; QByteArray array; const Exiv2::DataValue* dvalue = dynamic_cast(&*value); if(dvalue) { array.resize(dvalue->count()); dvalue->copy((Exiv2::byte*)array.data()); } else { Q_ASSERT(value->typeId() == Exiv2::unsignedShort); array.resize(2 * value->count()); value->copy((Exiv2::byte*)array.data(), Exiv2::littleEndian); } int columns = (reinterpret_cast(array.data()))[0]; int rows = (reinterpret_cast(array.data()))[1]; deviceSettingStructure["Columns"] = KisMetaData::Value(columns); deviceSettingStructure["Rows"] = KisMetaData::Value(rows); QList settings; QByteArray null(2, 0); for (int index = 4; index < array.size(); ) { const int lastIndex = array.indexOf(null, index); const int numChars = (lastIndex - index) / 2; // including trailing zero QString setting = QString::fromUtf16((ushort*)(void*)( array.data() + index), numChars); index = lastIndex + 2; dbgMetaData << "Setting << " << setting; settings.append(KisMetaData::Value(setting)); } deviceSettingStructure["Settings"] = KisMetaData::Value(settings, KisMetaData::Value::OrderedArray); return KisMetaData::Value(deviceSettingStructure); } Exiv2::Value* deviceSettingDescriptionKMDToExif(const KisMetaData::Value& value) { QMap deviceSettingStructure = value.asStructure(); quint16 columns = deviceSettingStructure["Columns"].asVariant().toInt(0); quint16 rows = deviceSettingStructure["Rows"].asVariant().toInt(0); QTextCodec* codec = QTextCodec::codecForName("UTF-16"); QList settings = deviceSettingStructure["Settings"].asArray(); QByteArray array(4, 0); (reinterpret_cast(array.data()))[0] = columns; (reinterpret_cast(array.data()))[1] = rows; for (int i = 0; i < settings.count(); i++) { QString str = settings[i].asVariant().toString(); QByteArray setting = codec->fromUnicode(str); array.append(setting); } return new Exiv2::DataValue((const Exiv2::byte*)array.data(), array.size()); } KisMetaData::Value cfaPatternExifToKMD(const Exiv2::Value::AutoPtr value, Exiv2::ByteOrder order) { QMap cfaPatternStructure; const Exiv2::DataValue* dvalue = dynamic_cast(&*value); Q_ASSERT(dvalue); QByteArray array(dvalue->count(), 0); dvalue->copy((Exiv2::byte*)array.data()); int columns = fixEndianess((reinterpret_cast(array.data()))[0], order); int rows = fixEndianess((reinterpret_cast(array.data()))[1], order); if ((columns * rows + 4) != dvalue->count()) { // Sometime byteOrder get messed up (especially if metadata got saved with kexiv2 library, or any library that doesn't save back with the same byte order as the camera) order = invertByteOrder(order); columns = fixEndianess((reinterpret_cast(array.data()))[0], order); rows = fixEndianess((reinterpret_cast(array.data()))[1], order); Q_ASSERT((columns * rows + 4) == dvalue->count()); } cfaPatternStructure["Columns"] = KisMetaData::Value(columns); cfaPatternStructure["Rows"] = KisMetaData::Value(rows); QList values; int index = 4; for (int i = 0; i < columns * rows; i++) { values.append(KisMetaData::Value(*(array.data() + index))); index++; } cfaPatternStructure["Values"] = KisMetaData::Value(values, KisMetaData::Value::OrderedArray); dbgMetaData << "CFAPattern " << ppVar(columns) << " " << ppVar(rows) << ppVar(values.size()) << ppVar(dvalue->count()); return KisMetaData::Value(cfaPatternStructure); } Exiv2::Value* cfaPatternKMDToExif(const KisMetaData::Value& value) { QMap cfaStructure = value.asStructure(); quint16 columns = cfaStructure["Columns"].asVariant().toInt(0); quint16 rows = cfaStructure["Rows"].asVariant().toInt(0); QList values = cfaStructure["Values"].asArray(); Q_ASSERT(columns*rows == values.size()); QByteArray array(4 + columns*rows, 0); (reinterpret_cast(array.data()))[0] = columns; (reinterpret_cast(array.data()))[1] = rows; for (int i = 0; i < columns * rows; i++) { quint8 val = values[i].asVariant().toUInt(); *(array.data() + 4 + i) = val; } dbgMetaData << "Cfa Array " << ppVar(columns) << ppVar(rows) << ppVar(array.size()); return new Exiv2::DataValue((const Exiv2::byte*)array.data(), array.size()); } // Read and write Flash // KisMetaData::Value flashExifToKMD(const Exiv2::Value::AutoPtr value) { uint16_t v = value->toLong(); QMap flashStructure; bool fired = (v & 0x01); // bit 1 is whether flash was fired or not flashStructure["Fired"] = QVariant(fired); int ret = ((v >> 1) & 0x03); // bit 2 and 3 are Return flashStructure["Return"] = QVariant(ret); int mode = ((v >> 3) & 0x03); // bit 4 and 5 are Mode flashStructure["Mode"] = QVariant(mode); bool function = ((v >> 5) & 0x01); // bit 6 if function flashStructure["Function"] = QVariant(function); bool redEye = ((v >> 6) & 0x01); // bit 7 if function flashStructure["RedEyeMode"] = QVariant(redEye); return KisMetaData::Value(flashStructure); } Exiv2::Value* flashKMDToExif(const KisMetaData::Value& value) { uint16_t v = 0; QMap flashStructure = value.asStructure(); v = flashStructure["Fired"].asVariant().toBool(); v |= ((flashStructure["Return"].asVariant().toInt() & 0x03) << 1); v |= ((flashStructure["Mode"].asVariant().toInt() & 0x03) << 3); v |= ((flashStructure["Function"].asVariant().toInt() & 0x03) << 5); v |= ((flashStructure["RedEyeMode"].asVariant().toInt() & 0x03) << 6); return new Exiv2::ValueType(v); } // ---- Implementation of KisExifIO ----// KisExifIO::KisExifIO() : d(new Private) { } KisExifIO::~KisExifIO() { delete d; } bool KisExifIO::saveTo(KisMetaData::Store* store, QIODevice* ioDevice, HeaderType headerType) const { ioDevice->open(QIODevice::WriteOnly); Exiv2::ExifData exifData; if (headerType == KisMetaData::IOBackend::JpegHeader) { QByteArray header(6, 0); header[0] = 0x45; header[1] = 0x78; header[2] = 0x69; header[3] = 0x66; header[4] = 0x00; header[5] = 0x00; ioDevice->write(header); } for (QHash::const_iterator it = store->begin(); it != store->end(); ++it) { try { const KisMetaData::Entry& entry = *it; dbgMetaData << "Trying to save: " << entry.name() << " of " << entry.schema()->prefix() << ":" << entry.schema()->uri(); QString exivKey; if (entry.schema()->uri() == KisMetaData::Schema::TIFFSchemaUri) { exivKey = "Exif.Image." + entry.name(); } else if (entry.schema()->uri() == KisMetaData::Schema::EXIFSchemaUri) { // Distinguish between exif and gps if (entry.name().left(3) == "GPS") { exivKey = "Exif.GPS." + entry.name(); } else { exivKey = "Exif.Photo." + entry.name(); } } else if (entry.schema()->uri() == KisMetaData::Schema::DublinCoreSchemaUri) { if (entry.name() == "description") { exivKey = "Exif.Image.ImageDescription"; } else if (entry.name() == "creator") { exivKey = "Exif.Image.Artist"; } else if (entry.name() == "rights") { exivKey = "Exif.Image.Copyright"; } } else if (entry.schema()->uri() == KisMetaData::Schema::XMPSchemaUri) { if (entry.name() == "ModifyDate") { exivKey = "Exif.Image.DateTime"; } else if (entry.name() == "CreatorTool") { exivKey = "Exif.Image.Software"; } } else if (entry.schema()->uri() == KisMetaData::Schema::MakerNoteSchemaUri) { if (entry.name() == "RawData") { exivKey = "Exif.Photo.MakerNote"; } } dbgMetaData << "Saving " << entry.name() << " to " << exivKey; if (exivKey.isEmpty()) { dbgMetaData << entry.qualifiedName() << " is unsavable to EXIF"; } else { Exiv2::ExifKey exifKey(qPrintable(exivKey)); Exiv2::Value* v = 0; if (exivKey == "Exif.Photo.ExifVersion" || exivKey == "Exif.Photo.FlashpixVersion") { v = kmdValueToExifVersion(entry.value()); } else if (exivKey == "Exif.Photo.FileSource") { char s[] = { 0x03 }; v = new Exiv2::DataValue((const Exiv2::byte*)s, 1); } else if (exivKey == "Exif.Photo.SceneType") { char s[] = { 0x01 }; v = new Exiv2::DataValue((const Exiv2::byte*)s, 1); } else if (exivKey == "Exif.Photo.ComponentsConfiguration") { v = kmdIntOrderedArrayToExifArray(entry.value()); } else if (exivKey == "Exif.Image.Artist") { // load as dc:creator KisMetaData::Value creator = entry.value(); if (entry.value().asArray().size() > 0) { creator = entry.value().asArray()[0]; } #if !EXIV2_TEST_VERSION(0,21,0) v = kmdValueToExivValue(creator, Exiv2::ExifTags::tagType(exifKey.tag(), exifKey.ifdId())); #else v = kmdValueToExivValue(creator, exifKey.defaultTypeId()); #endif } else if (exivKey == "Exif.Photo.OECF") { v = kmdOECFStructureToExifOECF(entry.value()); } else if (exivKey == "Exif.Photo.DeviceSettingDescription") { v = deviceSettingDescriptionKMDToExif(entry.value()); } else if (exivKey == "Exif.Photo.CFAPattern") { v = cfaPatternKMDToExif(entry.value()); } else if (exivKey == "Exif.Photo.Flash") { v = flashKMDToExif(entry.value()); } else if (exivKey == "Exif.Photo.UserComment") { Q_ASSERT(entry.value().type() == KisMetaData::Value::LangArray); QMap langArr = entry.value().asLangArray(); if (langArr.contains("x-default")) { #if !EXIV2_TEST_VERSION(0,21,0) v = kmdValueToExivValue(langArr.value("x-default"), Exiv2::ExifTags::tagType(exifKey.tag(), exifKey.ifdId())); #else v = kmdValueToExivValue(langArr.value("x-default"), exifKey.defaultTypeId()); #endif } else if (langArr.size() > 0) { #if !EXIV2_TEST_VERSION(0,21,0) v = kmdValueToExivValue(langArr.begin().value(), Exiv2::ExifTags::tagType(exifKey.tag(), exifKey.ifdId())); #else v = kmdValueToExivValue(langArr.begin().value(), exifKey.defaultTypeId()); #endif } } else { dbgMetaData << exifKey.tag(); #if !EXIV2_TEST_VERSION(0,21,0) v = kmdValueToExivValue(entry.value(), Exiv2::ExifTags::tagType(exifKey.tag(), exifKey.ifdId())); #else v = kmdValueToExivValue(entry.value(), exifKey.defaultTypeId()); #endif } if (v && v->typeId() != Exiv2::invalidTypeId) { dbgMetaData << "Saving key" << exivKey << " of KMD value" << entry.value(); exifData.add(exifKey, v); } else { dbgMetaData << "No exif value was created for" << entry.qualifiedName() << " as" << exivKey;// << " of KMD value" << entry.value(); } } } catch (Exiv2::AnyError& e) { dbgMetaData << "exiv error " << e.what(); } } #if !EXIV2_TEST_VERSION(0,18,0) Exiv2::DataBuf rawData = exifData.copy(); ioDevice->write((const char*) rawData.pData_, rawData.size_); #else Exiv2::Blob rawData; Exiv2::ExifParser::encode(rawData, Exiv2::littleEndian, exifData); ioDevice->write((const char*) &*rawData.begin(), rawData.size()); #endif ioDevice->close(); return true; } bool KisExifIO::canSaveAllEntries(KisMetaData::Store* /*store*/) const { return false; // It's a known fact that exif can't save all information, but TODO: write the check } bool KisExifIO::loadFrom(KisMetaData::Store* store, QIODevice* ioDevice) const { ioDevice->open(QIODevice::ReadOnly); if (!ioDevice->isOpen()) { return false; } QByteArray arr = ioDevice->readAll(); Exiv2::ExifData exifData; Exiv2::ByteOrder byteOrder; #if !EXIV2_TEST_VERSION(0,18,0) exifData.load((const Exiv2::byte*)arr.data(), arr.size()); byteOrder = exifData.byteOrder(); #else try { byteOrder = Exiv2::ExifParser::decode(exifData, (const Exiv2::byte*)arr.data(), arr.size()); } catch (const std::exception& ex) { warnKrita << "Received exception trying to parse exiv data" << ex.what(); return false; } catch (...) { dbgKrita << "Received unknown exception trying to parse exiv data"; return false; } #endif dbgMetaData << "Byte order = " << byteOrder << ppVar(Exiv2::bigEndian) << ppVar(Exiv2::littleEndian); dbgMetaData << "There are" << exifData.count() << " entries in the exif section"; const KisMetaData::Schema* tiffSchema = KisMetaData::SchemaRegistry::instance()->schemaFromUri(KisMetaData::Schema::TIFFSchemaUri); Q_ASSERT(tiffSchema); const KisMetaData::Schema* exifSchema = KisMetaData::SchemaRegistry::instance()->schemaFromUri(KisMetaData::Schema::EXIFSchemaUri); Q_ASSERT(exifSchema); const KisMetaData::Schema* dcSchema = KisMetaData::SchemaRegistry::instance()->schemaFromUri(KisMetaData::Schema::DublinCoreSchemaUri); Q_ASSERT(dcSchema); const KisMetaData::Schema* xmpSchema = KisMetaData::SchemaRegistry::instance()->schemaFromUri(KisMetaData::Schema::XMPSchemaUri); Q_ASSERT(xmpSchema); for (Exiv2::ExifMetadata::const_iterator it = exifData.begin(); it != exifData.end(); ++it) { if (it->key() == "Exif.Photo.StripOffsets" || it->key() == "RowsPerStrip" || it->key() == "StripByteCounts" || it->key() == "JPEGInterchangeFormat" || it->key() == "JPEGInterchangeFormatLength" || it->tagName() == "0x0000" ) { dbgMetaData << it->key().c_str() << " is ignored"; } else if (it->key() == "Exif.Photo.MakerNote") { const KisMetaData::Schema* makerNoteSchema = KisMetaData::SchemaRegistry::instance()->schemaFromUri(KisMetaData::Schema::MakerNoteSchemaUri); store->addEntry(KisMetaData::Entry(makerNoteSchema, "RawData", exivValueToKMDValue(it->getValue(), false))); } else if (it->key() == "Exif.Image.DateTime") { // load as xmp:ModifyDate store->addEntry(KisMetaData::Entry(xmpSchema, "ModifyDate", KisMetaData::Value(exivValueToDateTime(it->getValue())))); } else if (it->key() == "Exif.Image.ImageDescription") { // load as "dc:description" store->addEntry(KisMetaData::Entry(dcSchema, "description", exivValueToKMDValue(it->getValue(), false))); } else if (it->key() == "Exif.Image.Software") { // load as "xmp:CreatorTool" store->addEntry(KisMetaData::Entry(xmpSchema, "CreatorTool", exivValueToKMDValue(it->getValue(), false))); } else if (it->key() == "Exif.Image.Artist") { // load as dc:creator QList creators; creators.push_back(exivValueToKMDValue(it->getValue(), false)); store->addEntry(KisMetaData::Entry(dcSchema, "creator", KisMetaData::Value(creators, KisMetaData::Value::OrderedArray))); } else if (it->key() == "Exif.Image.Copyright") { // load as dc:rights store->addEntry(KisMetaData::Entry(dcSchema, "rights", exivValueToKMDValue(it->getValue(), false))); } else if (it->groupName() == "Image") { // Tiff tags QString fixedTN = it->tagName().c_str(); if (it->key() == "Exif.Image.ExifTag") { dbgMetaData << "Ignoring " << it->key().c_str(); } else if (KisMetaData::Entry::isValidName(fixedTN)) { store->addEntry(KisMetaData::Entry(tiffSchema, fixedTN, exivValueToKMDValue(it->getValue(), false))) ; } else { dbgMetaData << "Invalid tag name: " << fixedTN; } } else if (it->groupName() == "Photo" || (it->groupName() == "GPS")) { // Exif tags (and GPS tags) KisMetaData::Value metaDataValue; if (it->key() == "Exif.Photo.ExifVersion" || it->key() == "Exif.Photo.FlashpixVersion") { metaDataValue = exifVersionToKMDValue(it->getValue()); } else if (it->key() == "Exif.Photo.FileSource") { metaDataValue = KisMetaData::Value(3); } else if (it->key() == "Exif.Photo.SceneType") { metaDataValue = KisMetaData::Value(1); } else if (it->key() == "Exif.Photo.ComponentsConfiguration") { metaDataValue = exifArrayToKMDIntOrderedArray(it->getValue()); } else if (it->key() == "Exif.Photo.OECF") { metaDataValue = exifOECFToKMDOECFStructure(it->getValue(), byteOrder); } else if (it->key() == "Exif.Photo.DateTimeDigitized" || it->key() == "Exif.Photo.DateTimeOriginal") { metaDataValue = KisMetaData::Value(exivValueToDateTime(it->getValue())); } else if (it->key() == "Exif.Photo.DeviceSettingDescription") { metaDataValue = deviceSettingDescriptionExifToKMD(it->getValue()); } else if (it->key() == "Exif.Photo.CFAPattern") { metaDataValue = cfaPatternExifToKMD(it->getValue(), byteOrder); } else if (it->key() == "Exif.Photo.Flash") { metaDataValue = flashExifToKMD(it->getValue()); } else if (it->key() == "Exif.Photo.UserComment") { if (it->getValue()->typeId() != Exiv2::undefined) { KisMetaData::Value vUC = exivValueToKMDValue(it->getValue(), false); Q_ASSERT(vUC.type() == KisMetaData::Value::Variant); QVariant commentVar = vUC.asVariant(); QString comment; if (commentVar.type() == QVariant::String) { comment = commentVar.toString(); } else if (commentVar.type() == QVariant::ByteArray) { const QByteArray commentString = commentVar.toByteArray(); comment = QString::fromLatin1(commentString.constData(), commentString.size()); } else { warnKrita << "KisExifIO: Unhandled UserComment value type."; } KisMetaData::Value vcomment(comment); vcomment.addPropertyQualifier("xml:lang", KisMetaData::Value("x-default")); QList alt; alt.append(vcomment); metaDataValue = KisMetaData::Value(alt, KisMetaData::Value::LangArray); } } else { bool forceSeq = false; KisMetaData::Value::ValueType arrayType = KisMetaData::Value::UnorderedArray; if (it->key() == "Exif.Photo.ISOSpeedRatings") { forceSeq = true; arrayType = KisMetaData::Value::OrderedArray; } metaDataValue = exivValueToKMDValue(it->getValue(), forceSeq, arrayType); } if (it->key() == "Exif.Photo.InteroperabilityTag" || it->key() == "Exif.Photo.0xea1d" || metaDataValue.type() == KisMetaData::Value::Invalid) { // InteroperabilityTag isn't useful for XMP, 0xea1d isn't a valid Exif tag warnMetaData << "Ignoring " << it->key().c_str(); } else { store->addEntry(KisMetaData::Entry(exifSchema, it->tagName().c_str(), metaDataValue)); } } else if (it->groupName() == "Thumbnail") { dbgMetaData << "Ignoring thumbnail tag :" << it->key().c_str(); } else { dbgMetaData << "Unknown exif tag, cannot load:" << it->key().c_str(); } } ioDevice->close(); return true; } diff --git a/libs/ui/kisexiv2/kis_exif_io.h b/libs/ui/kisexiv2/kis_exif_io.h index d9a133c82f..4a73e6973e 100644 --- a/libs/ui/kisexiv2/kis_exif_io.h +++ b/libs/ui/kisexiv2/kis_exif_io.h @@ -1,53 +1,54 @@ /* * Copyright (c) 2007 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. + * the Free Software Foundation; 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 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_EXIF_IO_H_ #define _KIS_EXIF_IO_H_ #include #include class KisExifIO : public KisMetaData::IOBackend { struct Private; public: KisExifIO(); ~KisExifIO() override; QString id() const override { return "exif"; } QString name() const override { return i18n("Exif"); } BackendType type() const override { return Binary; } bool supportSaving() const override { return true; } bool saveTo(KisMetaData::Store* store, QIODevice* ioDevice, HeaderType headerType = NoHeader) const override; bool canSaveAllEntries(KisMetaData::Store* store) const override; bool supportLoading() const override { return true; } bool loadFrom(KisMetaData::Store* store, QIODevice* ioDevice) const override; private: Private* const d; }; #endif diff --git a/libs/ui/kisexiv2/kis_xmp_io.cpp b/libs/ui/kisexiv2/kis_xmp_io.cpp index 97e0d70af3..10631c2abc 100644 --- a/libs/ui/kisexiv2/kis_xmp_io.cpp +++ b/libs/ui/kisexiv2/kis_xmp_io.cpp @@ -1,399 +1,400 @@ /* * Copyright (c) 2008-2010 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. + * the Free Software Foundation; 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 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_xmp_io.h" #include #include "kis_exiv2.h" #include #include #include #include #include #include #include #include KisXMPIO::KisXMPIO() { } KisXMPIO::~KisXMPIO() { } inline std::string exiv2Prefix(const KisMetaData::Schema* _schema) { const QByteArray latin1SchemaUri = _schema->uri().toLatin1(); std::string prefix = Exiv2::XmpProperties::prefix(latin1SchemaUri.constData()); if (prefix.empty()) { dbgMetaData << "Unknown namespace " << ppVar(_schema->uri()) << ppVar(_schema->prefix()); prefix = _schema->prefix().toLatin1().constData(); Exiv2::XmpProperties::registerNs(latin1SchemaUri.constData(), prefix); } return prefix; } namespace { void saveStructure(Exiv2::XmpData& xmpData_, const QString& name, const std::string& prefix, const QMap& structure, const KisMetaData::Schema* structureSchema) { std::string structPrefix = exiv2Prefix(structureSchema); for (QMap::const_iterator it = structure.begin(); it != structure.end(); ++it) { Q_ASSERT(it.value().type() != KisMetaData::Value::Structure); // Can't nest structure QString key = QString("%1/%2:%3").arg(name).arg(structPrefix.c_str()).arg(it.key()); Exiv2::XmpKey ekey(prefix, key.toLatin1().constData()); dbgMetaData << ppVar(key) << ppVar(ekey.key().c_str()); Exiv2::Value *v = kmdValueToExivXmpValue(it.value()); if (v) { xmpData_.add(ekey, v); } } } } bool KisXMPIO::saveTo(KisMetaData::Store* store, QIODevice* ioDevice, HeaderType headerType) const { dbgMetaData << "Save XMP Data"; Exiv2::XmpData xmpData_; for (QHash::const_iterator it = store->begin(); it != store->end(); ++it) { const KisMetaData::Entry& entry = *it; // Check whether the prefix and namespace are know to exiv2 std::string prefix = exiv2Prefix(entry.schema()); dbgMetaData << "Saving " << entry.name(); const KisMetaData::Value& value = entry.value(); const KisMetaData::TypeInfo* typeInfo = entry.schema()->propertyType(entry.name()); if (value.type() == KisMetaData::Value::Structure) { QMap structure = value.asStructure(); const KisMetaData::Schema* structureSchema = 0; if (typeInfo) { structureSchema = typeInfo->structureSchema(); } if (!structureSchema) { dbgMetaData << "Unknown schema for " << entry.name(); structureSchema = entry.schema(); } Q_ASSERT(structureSchema); saveStructure(xmpData_, entry.name(), prefix, structure, structureSchema); } else { Exiv2::XmpKey key(prefix, entry.name().toLatin1().constData()); if (typeInfo && (typeInfo->propertyType() == KisMetaData::TypeInfo::OrderedArrayType || typeInfo->propertyType() == KisMetaData::TypeInfo::UnorderedArrayType || typeInfo->propertyType() == KisMetaData::TypeInfo::AlternativeArrayType) && typeInfo->embeddedPropertyType()->propertyType() == KisMetaData::TypeInfo::StructureType) { // Here is the bad part, again we need to do it by hand Exiv2::XmpTextValue tv; switch (typeInfo->propertyType()) { case KisMetaData::TypeInfo::OrderedArrayType: tv.setXmpArrayType(Exiv2::XmpValue::xaSeq); break; case KisMetaData::TypeInfo::UnorderedArrayType: tv.setXmpArrayType(Exiv2::XmpValue::xaBag); break; case KisMetaData::TypeInfo::AlternativeArrayType: tv.setXmpArrayType(Exiv2::XmpValue::xaAlt); break; default: // Cannot happen ; } xmpData_.add(key, &tv); // set the arrya type const KisMetaData::TypeInfo* stuctureTypeInfo = typeInfo->embeddedPropertyType(); const KisMetaData::Schema* structureSchema = 0; if (stuctureTypeInfo) { structureSchema = stuctureTypeInfo->structureSchema(); } if (!structureSchema) { dbgMetaData << "Unknown schema for " << entry.name(); structureSchema = entry.schema(); } Q_ASSERT(structureSchema); QList array = value.asArray(); for (int idx = 0; idx < array.size(); ++idx) { saveStructure(xmpData_, QString("%1[%2]").arg(entry.name()).arg(idx + 1), prefix, array[idx].asStructure(), structureSchema); } } else { dbgMetaData << ppVar(key.key().c_str()); Exiv2::Value *v = kmdValueToExivXmpValue(value); if (v) { xmpData_.add(key, v); } } } // TODO property qualifier } // Serialize data std::string xmpPacket_; Exiv2::XmpParser::encode(xmpPacket_, xmpData_); // Save data into the IO device ioDevice->open(QIODevice::WriteOnly); if (headerType == KisMetaData::IOBackend::JpegHeader) { xmpPacket_ = "http://ns.adobe.com/xap/1.0/\0" + xmpPacket_; } ioDevice->write(xmpPacket_.c_str(), xmpPacket_.length()); return true; } bool parseTagName(const QString &tagString, QString &structName, int &arrayIndex, QString &tagName, const KisMetaData::TypeInfo** typeInfo, const KisMetaData::Schema *schema) { arrayIndex = -1; *typeInfo = 0; int numSubNames = tagString.count('/') + 1; if (numSubNames == 1) { structName.clear(); tagName = tagString; *typeInfo = schema->propertyType(tagName); return true; } if (numSubNames == 2) { QRegExp regexp("([A-Za-z]\\w+)/([A-Za-z]\\w+):([A-Za-z]\\w+)"); if (regexp.indexIn(tagString) != -1) { structName = regexp.capturedTexts()[1]; tagName = regexp.capturedTexts()[3]; *typeInfo = schema->propertyType(structName); if (*typeInfo && (*typeInfo)->propertyType() == KisMetaData::TypeInfo::StructureType) { *typeInfo = (*typeInfo)->structureSchema()->propertyType(tagName); } return true; } QRegExp regexp2("([A-Za-z]\\w+)\\[(\\d+)\\]/([A-Za-z]\\w+):([A-Za-z]\\w+)"); if (regexp2.indexIn(tagString) != -1) { structName = regexp2.capturedTexts()[1]; arrayIndex = regexp2.capturedTexts()[2].toInt() - 1; tagName = regexp2.capturedTexts()[4]; if (schema->propertyType(structName)) { *typeInfo = schema->propertyType(structName)->embeddedPropertyType(); Q_ASSERT(*typeInfo); if ((*typeInfo)->propertyType() == KisMetaData::TypeInfo::StructureType) { *typeInfo = (*typeInfo)->structureSchema()->propertyType(tagName); } } return true; } } warnKrita << "WARNING: Unsupported tag. We do not yet support nested tags. The tag will be dropped!"; warnKrita << " Failing tag:" << tagString; return false; } bool KisXMPIO::loadFrom(KisMetaData::Store* store, QIODevice* ioDevice) const { ioDevice->open(QIODevice::ReadOnly); dbgMetaData << "Load XMP Data"; std::string xmpPacket_; QByteArray arr = ioDevice->readAll(); xmpPacket_.assign(arr.data(), arr.length()); dbgMetaData << xmpPacket_.length(); // dbgMetaData << xmpPacket_.c_str(); Exiv2::XmpData xmpData_; Exiv2::XmpParser::decode(xmpData_, xmpPacket_); QMap< const KisMetaData::Schema*, QMap > > structures; QMap< const KisMetaData::Schema*, QMap > > > arraysOfStructures; for (Exiv2::XmpData::iterator it = xmpData_.begin(); it != xmpData_.end(); ++it) { dbgMetaData << "Start iteration" << it->key().c_str(); Exiv2::XmpKey key(it->key()); dbgMetaData << key.groupName().c_str() << " " << key.tagName().c_str() << " " << key.ns().c_str(); if ((key.groupName() == "exif" || key.groupName() == "tiff") && key.tagName() == "NativeDigest") { // TODO: someone who has time to lose can look in adding support for NativeDigest, it's undocumented use by the XMP SDK to check if exif data has been changed while XMP hasn't been updated dbgMetaData << "dropped"; } else { const KisMetaData::Schema* schema = KisMetaData::SchemaRegistry::instance()->schemaFromPrefix(key.groupName().c_str()); if (!schema) { schema = KisMetaData::SchemaRegistry::instance()->schemaFromUri(key.ns().c_str()); if (!schema) { schema = KisMetaData::SchemaRegistry::instance()->create(key.ns().c_str(), key.groupName().c_str()); Q_ASSERT(schema); } } const Exiv2::Value::AutoPtr value = it->getValue(); QString structName; int arrayIndex = -1; QString tagName; const KisMetaData::TypeInfo* typeInfo = 0; if (!parseTagName(key.tagName().c_str(), structName, arrayIndex, tagName, &typeInfo, schema)) continue; bool isStructureEntry = !structName.isEmpty() && arrayIndex == -1; bool isStructureInArrayEntry = !structName.isEmpty() && arrayIndex != -1; Q_ASSERT(isStructureEntry != isStructureInArrayEntry || !isStructureEntry); KisMetaData::Value v; bool ignoreValue = false; // Compute the value if (value->typeId() == Exiv2::xmpBag || value->typeId() == Exiv2::xmpSeq || value->typeId() == Exiv2::xmpAlt) { const KisMetaData::TypeInfo* embeddedTypeInfo = 0; if (typeInfo) { embeddedTypeInfo = typeInfo->embeddedPropertyType(); } const KisMetaData::Parser* parser = 0; if (embeddedTypeInfo) { parser = embeddedTypeInfo->parser(); } const Exiv2::XmpArrayValue* xav = dynamic_cast(value.get()); Q_ASSERT(xav); QList array; for (int i = 0; i < xav->count(); ++i) { QString value = QString::fromStdString(xav->toString(i)); if (parser) { array.push_back(parser->parse(value)); } else { dbgImage << "No parser " << tagName; array.push_back(KisMetaData::Value(value)); } } KisMetaData::Value::ValueType vt = KisMetaData::Value::Invalid; switch (xav->xmpArrayType()) { case Exiv2::XmpValue::xaNone: warnKrita << "KisXMPIO: Unsupported array"; break; case Exiv2::XmpValue::xaAlt: vt = KisMetaData::Value::AlternativeArray; break; case Exiv2::XmpValue::xaBag: vt = KisMetaData::Value::UnorderedArray; break; case Exiv2::XmpValue::xaSeq: vt = KisMetaData::Value::OrderedArray; break; } v = KisMetaData::Value(array, vt); } else if (value->typeId() == Exiv2::langAlt) { const Exiv2::LangAltValue* xav = dynamic_cast(value.get()); QList alt; for (std::map< std::string, std::string>::const_iterator it = xav->value_.begin(); it != xav->value_.end(); ++it) { KisMetaData::Value valt(it->second.c_str()); valt.addPropertyQualifier("xml:lang", KisMetaData::Value(it->first.c_str())); alt.push_back(valt); } v = KisMetaData::Value(alt, KisMetaData::Value::LangArray); } else { QString valTxt = value->toString().c_str(); if (typeInfo && typeInfo->parser()) { v = typeInfo->parser()->parse(valTxt); } else { dbgMetaData << "No parser " << tagName; v = KisMetaData::Value(valTxt); } if (valTxt == "type=\"Struct\"") { if (!typeInfo || typeInfo->propertyType() == KisMetaData::TypeInfo::StructureType) { ignoreValue = true; } } } // set the value if (isStructureEntry) { structures[schema][structName][tagName] = v; } else if (isStructureInArrayEntry) { if (arraysOfStructures[schema][structName].size() <= arrayIndex) { arraysOfStructures[schema][structName].resize(arrayIndex + 1); } if (!arraysOfStructures[schema][structName][arrayIndex].contains(tagName)) { arraysOfStructures[schema][structName][arrayIndex][tagName] = v; } else { warnKrita << "WARNING: trying to overwrite tag" << tagName << "in" << structName << arrayIndex; } } else { if (!ignoreValue) { store->addEntry(KisMetaData::Entry(schema, tagName, v)); } else { dbgMetaData << "Ignoring value for " << tagName << " " << v; } } } } for (QMap< const KisMetaData::Schema*, QMap > >::iterator it = structures.begin(); it != structures.end(); ++it) { const KisMetaData::Schema* schema = it.key(); for (QMap >::iterator it2 = it.value().begin(); it2 != it.value().end(); ++it2) { store->addEntry(KisMetaData::Entry(schema, it2.key(), KisMetaData::Value(it2.value()))); } } for (QMap< const KisMetaData::Schema*, QMap > > >::iterator it = arraysOfStructures.begin(); it != arraysOfStructures.end(); ++it) { const KisMetaData::Schema* schema = it.key(); for (QMap > >::iterator it2 = it.value().begin(); it2 != it.value().end(); ++it2) { KisMetaData::Value::ValueType type = KisMetaData::Value::OrderedArray; QString entryName = it2.key(); if (schema->propertyType(entryName)) { switch (schema->propertyType(entryName)->propertyType()) { case KisMetaData::TypeInfo::OrderedArrayType: type = KisMetaData::Value::OrderedArray; break; case KisMetaData::TypeInfo::UnorderedArrayType: type = KisMetaData::Value::OrderedArray; break; case KisMetaData::TypeInfo::AlternativeArrayType: type = KisMetaData::Value::AlternativeArray; break; default: type = KisMetaData::Value::Invalid; break; } } else if (store->containsEntry(schema, entryName)) { KisMetaData::Value value = store->getEntry(schema, entryName).value(); if (value.isArray()) { type = value.type(); } } store->removeEntry(schema, entryName); if (type != KisMetaData::Value::Invalid) { QList< KisMetaData::Value > valueList; for (int i = 0; i < it2.value().size(); ++i) { valueList.append(it2.value()[i]); } store->addEntry(KisMetaData::Entry(schema, entryName, KisMetaData::Value(valueList, type))); } } } return true; } diff --git a/libs/ui/kisexiv2/kis_xmp_io.h b/libs/ui/kisexiv2/kis_xmp_io.h index e3d92004bc..32d95ac07b 100644 --- a/libs/ui/kisexiv2/kis_xmp_io.h +++ b/libs/ui/kisexiv2/kis_xmp_io.h @@ -1,53 +1,54 @@ /* * 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. + * the Free Software Foundation; 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 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_XMP_IO_H_ #define _KIS_XMP_IO_H_ #include #include class KisXMPIO : public KisMetaData::IOBackend { struct Private; public: KisXMPIO(); ~KisXMPIO() override; QString id() const override { return "xmp"; } QString name() const override { return i18n("XMP"); } BackendType type() const override { return Text; } bool supportSaving() const override { return true; } bool saveTo(KisMetaData::Store* store, QIODevice* ioDevice, HeaderType headerType = NoHeader) const override; bool canSaveAllEntries(KisMetaData::Store*) const override { return true; } bool supportLoading() const override { return true; } bool loadFrom(KisMetaData::Store* store, QIODevice* ioDevice) const override; }; #endif diff --git a/libs/ui/widgets/KisGamutMaskToolbar.cpp b/libs/ui/widgets/KisGamutMaskToolbar.cpp index ef8ca6cc06..6c007584cc 100644 --- a/libs/ui/widgets/KisGamutMaskToolbar.cpp +++ b/libs/ui/widgets/KisGamutMaskToolbar.cpp @@ -1,115 +1,116 @@ /* * Copyright (c) 2018 Anna Medonosova * * 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. + * the Free Software Foundation; 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 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 #include "KisGamutMaskToolbar.h" #include #include KisGamutMaskToolbar::KisGamutMaskToolbar(QWidget* parent) : QWidget(parent) , m_selectedMask(nullptr) { m_ui = new Ui_wdgGamutMaskToolbar(); m_ui->setupUi(this); m_iconMaskOff = KisIconUtils::loadIcon("gamut-mask-off"); m_iconMaskOn = KisIconUtils::loadIcon("gamut-mask-on"); m_textNoMask = i18n("Select a mask in \"Gamut Masks\" docker"); m_textMaskDisabled = i18n("Mask is disabled"); m_ui->bnToggleMask->setChecked(false); m_ui->bnToggleMask->setIcon(m_iconMaskOff); m_ui->rotationSlider->setRange(0, 360); m_ui->rotationSlider->setPrefix(i18n("Rotation: ")); m_ui->rotationSlider->setSuffix("°"); m_ui->rotationSlider->setFastSliderStep(30); // TODO: test for usability m_ui->rotationSlider->hide(); // gamut mask connections connect(m_ui->bnToggleMask, SIGNAL(toggled(bool)), SLOT(slotGamutMaskToggle(bool))); connect(m_ui->rotationSlider, SIGNAL(valueChanged(int)), SLOT(slotGamutMaskRotate(int))); } void KisGamutMaskToolbar::connectMaskSignals(KisCanvasResourceProvider* resourceProvider) { connect(resourceProvider, SIGNAL(sigGamutMaskChanged(KoGamutMask*)), this, SLOT(slotGamutMaskSet(KoGamutMask*)), Qt::UniqueConnection); connect(resourceProvider, SIGNAL(sigGamutMaskUnset()), this, SLOT(slotGamutMaskUnset()), Qt::UniqueConnection); connect(this, SIGNAL(sigGamutMaskChanged(KoGamutMask*)), resourceProvider, SLOT(slotGamutMaskActivated(KoGamutMask*)), Qt::UniqueConnection); } void KisGamutMaskToolbar::slotGamutMaskSet(KoGamutMask *mask) { if (!mask) { return; } m_selectedMask = mask; if (m_selectedMask) { slotGamutMaskToggle(true); } else { slotGamutMaskToggle(false); } } void KisGamutMaskToolbar::slotGamutMaskUnset() { m_ui->rotationSlider->hide(); m_ui->labelMaskName->show(); m_ui->labelMaskName->setText(m_textNoMask); } void KisGamutMaskToolbar::slotGamutMaskToggle(bool state) { bool b = (!m_selectedMask) ? false : state; m_ui->bnToggleMask->setChecked(b); if (b == true) { m_ui->bnToggleMask->setIcon(m_iconMaskOn); m_ui->labelMaskName->hide(); m_ui->rotationSlider->show(); m_ui->rotationSlider->blockSignals(true); m_ui->rotationSlider->setValue(m_selectedMask->rotation()); m_ui->rotationSlider->blockSignals(false); } else { m_ui->bnToggleMask->setIcon(m_iconMaskOff); m_ui->rotationSlider->hide(); m_ui->labelMaskName->show(); m_ui->labelMaskName->setText(m_textMaskDisabled); } emit sigGamutMaskToggle(state); } void KisGamutMaskToolbar::slotGamutMaskRotate(int angle) { if (!m_selectedMask) { return; } m_selectedMask->setRotation(angle); emit sigGamutMaskChanged(m_selectedMask); } diff --git a/libs/ui/widgets/KisGamutMaskToolbar.h b/libs/ui/widgets/KisGamutMaskToolbar.h index 45386705b2..c61792aa33 100644 --- a/libs/ui/widgets/KisGamutMaskToolbar.h +++ b/libs/ui/widgets/KisGamutMaskToolbar.h @@ -1,61 +1,62 @@ /* * Copyright (c) 2018 Anna Medonosova * * 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. + * the Free Software Foundation; 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 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 KISGAMUTMASKTOOLBAR_H #define KISGAMUTMASKTOOLBAR_H #include #include #include #include "kritaui_export.h" #include "ui_wdgGamutMaskToolbar.h" class KisCanvasResourceProvider; class KRITAUI_EXPORT KisGamutMaskToolbar : public QWidget { Q_OBJECT public: KisGamutMaskToolbar(QWidget* parent = nullptr); void connectMaskSignals(KisCanvasResourceProvider* resourceProvider); Q_SIGNALS: void sigGamutMaskToggle(bool state); void sigGamutMaskChanged(KoGamutMask*); public Q_SLOTS: void slotGamutMaskSet(KoGamutMask* mask); void slotGamutMaskUnset(); private Q_SLOTS: void slotGamutMaskToggle(bool state); void slotGamutMaskRotate(int angle); private: Ui_wdgGamutMaskToolbar* m_ui; KoGamutMask* m_selectedMask; QIcon m_iconMaskOff; QIcon m_iconMaskOn; QString m_textNoMask; QString m_textMaskDisabled; }; #endif // KISGAMUTMASKTOOLBAR_H diff --git a/libs/ui/widgets/KisLayerStyleAngleSelector.cpp b/libs/ui/widgets/KisLayerStyleAngleSelector.cpp index e576080b0a..87680a0203 100644 --- a/libs/ui/widgets/KisLayerStyleAngleSelector.cpp +++ b/libs/ui/widgets/KisLayerStyleAngleSelector.cpp @@ -1,117 +1,118 @@ /* * Copyright (c) 2018 Anna Medonosova * * 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. + * the Free Software Foundation; 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 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 "KisLayerStyleAngleSelector.h" #include #include #include KisLayerStyleAngleSelector::KisLayerStyleAngleSelector(QWidget *parent) : QWidget(parent) , m_enableGlobalLight(false) { ui = new Ui_WdgKisLayerStyleAngleSelector(); ui->setupUi(this); ui->chkUseGlobalLight->hide(); connect(ui->dialAngle, SIGNAL(valueChanged(int)), SLOT(slotDialAngleChanged(int))); connect(ui->intAngle, SIGNAL(valueChanged(int)), SLOT(slotIntAngleChanged(int))); } int KisLayerStyleAngleSelector::value() { return ui->intAngle->value(); } void KisLayerStyleAngleSelector::setValue(int value) { KisSignalsBlocker intB(ui->intAngle); KisSignalsBlocker dialB(ui->dialAngle); ui->intAngle->setValue(value); ui->dialAngle->setValue(value + m_dialValueShift); } void KisLayerStyleAngleSelector::enableGlobalLight(bool enable) { m_enableGlobalLight = enable; if (enable) { ui->chkUseGlobalLight->show(); connect(ui->chkUseGlobalLight, SIGNAL(toggled(bool)), SLOT(slotGlobalLightToggled())); } else { ui->chkUseGlobalLight->hide(); disconnect(ui->chkUseGlobalLight, SIGNAL(toggled(bool)), this, SLOT(slotGlobalLightToggled())); } } bool KisLayerStyleAngleSelector::useGlobalLight() { return m_enableGlobalLight && ui->chkUseGlobalLight->isChecked(); } void KisLayerStyleAngleSelector::setUseGlobalLight(bool state) { ui->chkUseGlobalLight->setChecked(state); } void KisLayerStyleAngleSelector::slotDialAngleChanged(int value) { KisSignalsBlocker b(ui->intAngle); int normalizedValue = 0; if (value >= 270 && value <= 360) { // Due to the mismatch between the domain of the dial (0°,360°) // and the spinbox (-179°,180°), the shift in the third quadrant // of the dial is different normalizedValue = value - 360 - m_dialValueShift; } else { normalizedValue = value - m_dialValueShift; } ui->intAngle->setValue(normalizedValue); emit valueChanged(normalizedValue); emitChangeSignals(); } void KisLayerStyleAngleSelector::slotIntAngleChanged(int value) { KisSignalsBlocker b(ui->dialAngle); int angleDialValue = value + m_dialValueShift; ui->dialAngle->setValue(angleDialValue); emit valueChanged(value); emitChangeSignals(); } void KisLayerStyleAngleSelector::slotGlobalLightToggled() { emitChangeSignals(); } void KisLayerStyleAngleSelector::emitChangeSignals() { if (useGlobalLight()) { emit globalAngleChanged(value()); } emit configChanged(); } diff --git a/libs/ui/widgets/KisLayerStyleAngleSelector.h b/libs/ui/widgets/KisLayerStyleAngleSelector.h index 35eb382641..970078beb0 100644 --- a/libs/ui/widgets/KisLayerStyleAngleSelector.h +++ b/libs/ui/widgets/KisLayerStyleAngleSelector.h @@ -1,68 +1,69 @@ /* * Copyright (c) 2018 Anna Medonosova * * 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. + * the Free Software Foundation; 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 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 KISLAYERSTYLEANGLESELECTOR_H #define KISLAYERSTYLEANGLESELECTOR_H #include #include #include #include class KisLayerStyleAngleSelector : public QWidget { Q_OBJECT public: KisLayerStyleAngleSelector(QWidget* parent); int value(); void setValue(int value); void enableGlobalLight(bool enable); bool useGlobalLight(); void setUseGlobalLight(bool state); Q_SIGNALS: void valueChanged(int); void configChanged(); void globalAngleChanged(int); private Q_SLOTS: void slotDialAngleChanged(int value); void slotIntAngleChanged(int value); void slotGlobalLightToggled(); private: void emitChangeSignals(); Ui_WdgKisLayerStyleAngleSelector* ui; // BUG: 372169 // Adobe's dial widget differs from QDial by 90 degrees, // therefore we need to apply this magic constant // to this widget's QDial for consistency between // the settings dialogs and on-canvas effects. // Wrapping is handled by QDial itself. const static int m_dialValueShift = 90; bool m_enableGlobalLight; }; #endif // KISLAYERSTYLEANGLESELECTOR_H diff --git a/libs/widgets/kis_color_input.cpp b/libs/widgets/kis_color_input.cpp index 0ff533e202..4bbd8e02f3 100644 --- a/libs/widgets/kis_color_input.cpp +++ b/libs/widgets/kis_color_input.cpp @@ -1,416 +1,417 @@ /* * 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. + * the Free Software Foundation; 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 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, bool usePercentage) : QWidget(parent), m_channelInfo(channelInfo), m_color(color), m_displayRenderer(displayRenderer), m_usePercentage(usePercentage) { } 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, bool usePercentage) : KisColorInput(parent, channelInfo, color, displayRenderer, usePercentage) { 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(); m_intNumInput->blockSignals(true); m_colorSlider->blockSignals(true); switch (m_channelInfo->channelValueType()) { case KoChannelInfo::UINT8: if (m_usePercentage) { m_intNumInput->setMaximum(100); m_intNumInput->setValue(round(*(reinterpret_cast(data))*1.0 / 255.0 * 100.0)); } else { m_intNumInput->setMaximum(0xFF); m_intNumInput->setValue(*(reinterpret_cast(data))); } m_colorSlider->setValue(*(reinterpret_cast(data))); *(reinterpret_cast(dataMin)) = 0x0; *(reinterpret_cast(dataMax)) = 0xFF; break; case KoChannelInfo::UINT16: if (m_usePercentage) { m_intNumInput->setMaximum(100); m_intNumInput->setValue(round(*(reinterpret_cast(data))*1.0 / 65535.0 * 100.0)); } else { m_intNumInput->setMaximum(0xFFFF); m_intNumInput->setValue(*(reinterpret_cast(data))); } m_colorSlider->setValue(*(reinterpret_cast(data))); *(reinterpret_cast(dataMin)) = 0x0; *(reinterpret_cast(dataMax)) = 0xFFFF; break; case KoChannelInfo::UINT32: if (m_usePercentage) { m_intNumInput->setMaximum(100); m_intNumInput->setValue(round(*(reinterpret_cast(data))*1.0 / 4294967295.0 * 100.0)); } else { m_intNumInput->setMaximum(0xFFFF); 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); m_intNumInput->blockSignals(false); m_colorSlider->blockSignals(false); } QWidget* KisIntegerColorInput::createInput() { m_intNumInput = new KisIntParseSpinBox(this); m_intNumInput->setMinimum(0); m_colorSlider->setMinimum(0); if (m_usePercentage) { m_intNumInput->setSuffix("%"); } else { m_intNumInput->setSuffix(""); } switch (m_channelInfo->channelValueType()) { case KoChannelInfo::UINT8: if (m_usePercentage) { m_intNumInput->setMaximum(100); } else { m_intNumInput->setMaximum(0xFF); } m_colorSlider->setMaximum(0xFF); break; case KoChannelInfo::UINT16: if (m_usePercentage) { m_intNumInput->setMaximum(100); } else { m_intNumInput->setMaximum(0xFFFF); } m_colorSlider->setMaximum(0xFFFF); break; case KoChannelInfo::UINT32: if (m_usePercentage) { m_intNumInput->setMaximum(100); } else { m_intNumInput->setMaximum(0xFFFFFFFF); } m_colorSlider->setMaximum(0xFFFFFFFF); break; default: Q_ASSERT(false); } connect(m_colorSlider, SIGNAL(valueChanged(int)), this, SLOT(onColorSliderChanged(int))); connect(m_intNumInput, SIGNAL(valueChanged(int)), this, SLOT(onNumInputChanged(int))); return m_intNumInput; } void KisIntegerColorInput::setPercentageWise(bool val) { m_usePercentage = val; if (m_usePercentage) { m_intNumInput->setSuffix("%"); } else { m_intNumInput->setSuffix(""); } } void KisIntegerColorInput::onColorSliderChanged(int val) { m_intNumInput->blockSignals(true); if (m_usePercentage) { switch (m_channelInfo->channelValueType()) { case KoChannelInfo::UINT8: m_intNumInput->setValue(round((val*1.0) / 255.0 * 100.0)); break; case KoChannelInfo::UINT16: m_intNumInput->setValue(round((val*1.0) / 65535.0 * 100.0)); break; case KoChannelInfo::UINT32: m_intNumInput->setValue(round((val*1.0) / 4294967295.0 * 100.0)); break; default: Q_ASSERT(false); } } else { m_intNumInput->setValue(val); } m_intNumInput->blockSignals(false); setValue(val); } void KisIntegerColorInput::onNumInputChanged(int val) { m_colorSlider->blockSignals(true); if (m_usePercentage) { switch (m_channelInfo->channelValueType()) { case KoChannelInfo::UINT8: m_colorSlider->setValue((val*1.0)/100.0 * 255.0); m_colorSlider->blockSignals(false); setValue((val*1.0)/100.0 * 255.0); break; case KoChannelInfo::UINT16: m_colorSlider->setValue((val*1.0)/100.0 * 65535.0); m_colorSlider->blockSignals(false); setValue((val*1.0)/100.0 * 65535.0); break; case KoChannelInfo::UINT32: m_colorSlider->setValue((val*1.0)/100.0 * 4294967295.0); m_colorSlider->blockSignals(false); setValue((val*1.0)/100.0 * 4294967295.0); break; default: Q_ASSERT(false); } } else { m_colorSlider->setValue(val); m_colorSlider->blockSignals(false); setValue(val); } } KisFloatColorInput::KisFloatColorInput(QWidget* parent, const KoChannelInfo* channelInfo, KoColor* color, KoColorDisplayRendererInterface *displayRenderer, bool usePercentage) : KisColorInput(parent, channelInfo, color, displayRenderer, usePercentage) { 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 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, bool usePercentage) : KisColorInput(parent, 0, color, displayRenderer, usePercentage) { 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); m_hexInput->setAlignment(Qt::AlignRight); 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/libs/widgets/kis_color_input.h b/libs/widgets/kis_color_input.h index 51d910be68..0a3ffcb276 100644 --- a/libs/widgets/kis_color_input.h +++ b/libs/widgets/kis_color_input.h @@ -1,111 +1,112 @@ /* * 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. + * the Free Software Foundation; 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 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 #include "kritawidgets_export.h" class KRITAWIDGETS_EXPORT KisColorInput : public QWidget { Q_OBJECT public: KisColorInput(QWidget* parent, const KoChannelInfo*, KoColor* color, KoColorDisplayRendererInterface *displayRenderer = KoDumbColorDisplayRenderer::instance(), bool usePercentage = false); inline bool usePercentage() const { return m_usePercentage; } virtual inline void setPercentageWise(bool val) { m_usePercentage = val; } 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; bool m_usePercentage; }; class KRITAWIDGETS_EXPORT KisIntegerColorInput : public KisColorInput { Q_OBJECT public: KisIntegerColorInput(QWidget* parent, const KoChannelInfo*, KoColor* color, KoColorDisplayRendererInterface *displayRenderer = KoDumbColorDisplayRenderer::instance(), bool usePercentage = false); protected: QWidget* createInput() override; void setPercentageWise(bool val) override; public Q_SLOTS: void setValue(int); void update(); private Q_SLOTS: void onColorSliderChanged(int); void onNumInputChanged(int); private: KisIntParseSpinBox* m_intNumInput; }; class KRITAWIDGETS_EXPORT KisFloatColorInput : public KisColorInput { Q_OBJECT public: KisFloatColorInput(QWidget* parent, const KoChannelInfo*, KoColor* color, KoColorDisplayRendererInterface *displayRenderer = KoDumbColorDisplayRenderer::instance(), bool usePercentage = false); protected: QWidget* createInput() override; public Q_SLOTS: void setValue(double); void sliderChanged(int); void update(); private: KisDoubleParseSpinBox* m_dblNumInput; qreal m_minValue; qreal m_maxValue; }; class KRITAWIDGETS_EXPORT KisHexColorInput : public KisColorInput { Q_OBJECT public: KisHexColorInput(QWidget* parent, KoColor* color, KoColorDisplayRendererInterface *displayRenderer = KoDumbColorDisplayRenderer::instance(), bool usePercentage = false); protected: QWidget* createInput() override; public Q_SLOTS: void setValue(); void update(); private: QLineEdit* m_hexInput; }; #endif diff --git a/plugins/assistants/Assistants/ConcentricEllipseAssistant.cc b/plugins/assistants/Assistants/ConcentricEllipseAssistant.cc index bf84366def..3fd53bd449 100644 --- a/plugins/assistants/Assistants/ConcentricEllipseAssistant.cc +++ b/plugins/assistants/Assistants/ConcentricEllipseAssistant.cc @@ -1,207 +1,208 @@ /* * Copyright (c) 2008 Cyrille Berger * Copyright (c) 2010 Geoffry Song * Copyright (c) 2017 Scott Petrovic * * 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. + * the Free Software Foundation; 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 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 "ConcentricEllipseAssistant.h" #include #include "kis_debug.h" #include #include #include #include #include #include #include ConcentricEllipseAssistant::ConcentricEllipseAssistant() : KisPaintingAssistant("concentric ellipse", i18n("Concentric Ellipse assistant")) { } KisPaintingAssistantSP ConcentricEllipseAssistant::clone(QMap &handleMap) const { return KisPaintingAssistantSP(new ConcentricEllipseAssistant(*this, handleMap)); } ConcentricEllipseAssistant::ConcentricEllipseAssistant(const ConcentricEllipseAssistant &rhs, QMap &handleMap) : KisPaintingAssistant(rhs, handleMap) , m_ellipse(rhs.m_ellipse) , m_extraEllipse(rhs.m_extraEllipse) { } QPointF ConcentricEllipseAssistant::project(const QPointF& pt, const QPointF& strokeBegin) const { Q_ASSERT(isAssistantComplete()); m_ellipse.set(*handles()[0], *handles()[1], *handles()[2]); qreal dx = pt.x() - strokeBegin.x(), dy = pt.y() - strokeBegin.y(); if (dx * dx + dy * dy < 4.0) { // allow some movement before snapping return strokeBegin; } //calculate ratio QPointF initial = m_ellipse.project(strokeBegin); QPointF center = m_ellipse.boundingRect().center(); qreal Ratio = QLineF(center, strokeBegin).length() /QLineF(center, initial).length(); //calculate the points of the extrapolated ellipse. QLineF extrapolate0 = QLineF(center, *handles()[0]); extrapolate0.setLength(extrapolate0.length()*Ratio); QLineF extrapolate1 = QLineF(center, *handles()[1]); extrapolate1.setLength(extrapolate1.length()*Ratio); QLineF extrapolate2 = QLineF(center, *handles()[2]); extrapolate2.setLength(extrapolate2.length()*Ratio); //set the extrapolation ellipse. m_extraEllipse.set(extrapolate0.p2(), extrapolate1.p2(), extrapolate2.p2()); return m_extraEllipse.project(pt); } QPointF ConcentricEllipseAssistant::adjustPosition(const QPointF& pt, const QPointF& strokeBegin) { return project(pt, strokeBegin); } void ConcentricEllipseAssistant::drawAssistant(QPainter& gc, const QRectF& updateRect, const KisCoordinatesConverter* converter, bool cached, KisCanvas2* canvas, bool assistantVisible, bool previewVisible) { gc.save(); gc.resetTransform(); QPointF mousePos; if (canvas){ //simplest, cheapest way to get the mouse-position// mousePos= canvas->canvasWidget()->mapFromGlobal(QCursor::pos()); } else { //...of course, you need to have access to a canvas-widget for that.// mousePos = QCursor::pos();//this'll give an offset// dbgFile<<"canvas does not exist in the ellipse assistant, you may have passed arguments incorrectly:"<documentToWidgetTransform(); if (isSnappingActive() && previewVisible == true){ if (isAssistantComplete()){ if (m_ellipse.set(*handles()[0], *handles()[1], *handles()[2])) { QPointF initial = m_ellipse.project(initialTransform.inverted().map(mousePos)); QPointF center = m_ellipse.boundingRect().center(); qreal Ratio = QLineF(center, initialTransform.inverted().map(mousePos)).length() /QLineF(center, initial).length(); //line from center to handle 1 * difference. //set handle1 translated to // valid ellipse gc.setTransform(initialTransform); gc.setTransform(m_ellipse.getInverse(), true); QPainterPath path; // Draw the ellipse path.addEllipse(QPointF(0, 0), m_ellipse.semiMajor()*Ratio, m_ellipse.semiMinor()*Ratio); drawPreview(gc, path); } } } gc.restore(); KisPaintingAssistant::drawAssistant(gc, updateRect, converter, cached, canvas, assistantVisible, previewVisible); } void ConcentricEllipseAssistant::drawCache(QPainter& gc, const KisCoordinatesConverter *converter, bool assistantVisible) { if (assistantVisible == false || handles().size() < 2) { // 2 points means a line, so we can continue after 1 point return; } QTransform initialTransform = converter->documentToWidgetTransform(); if (handles().size() == 2) { // just draw the axis gc.setTransform(initialTransform); QPainterPath path; path.moveTo(*handles()[0]); path.lineTo(*handles()[1]); drawPath(gc, path, isSnappingActive()); return; } if (m_ellipse.set(*handles()[0], *handles()[1], *handles()[2])) { // valid ellipse gc.setTransform(initialTransform); gc.setTransform(m_ellipse.getInverse(), true); QPainterPath path; path.moveTo(QPointF(-m_ellipse.semiMajor(), 0)); path.lineTo(QPointF(m_ellipse.semiMajor(), 0)); path.moveTo(QPointF(0, -m_ellipse.semiMinor())); path.lineTo(QPointF(0, m_ellipse.semiMinor())); // Draw the ellipse path.addEllipse(QPointF(0, 0), m_ellipse.semiMajor(), m_ellipse.semiMinor()); drawPath(gc, path, isSnappingActive()); } } QRect ConcentricEllipseAssistant::boundingRect() const { if (!isAssistantComplete()) { return KisPaintingAssistant::boundingRect(); } if (m_ellipse.set(*handles()[0], *handles()[1], *handles()[2])) { return m_ellipse.boundingRect().adjusted(-2, -2, 2, 2).toAlignedRect(); } else { return QRect(); } } QPointF ConcentricEllipseAssistant::buttonPosition() const { return (*handles()[0] + *handles()[1]) * 0.5; } bool ConcentricEllipseAssistant::isAssistantComplete() const { return handles().size() >= 3; } ConcentricEllipseAssistantFactory::ConcentricEllipseAssistantFactory() { } ConcentricEllipseAssistantFactory::~ConcentricEllipseAssistantFactory() { } QString ConcentricEllipseAssistantFactory::id() const { return "concentric ellipse"; } QString ConcentricEllipseAssistantFactory::name() const { return i18n("Concentric Ellipse"); } KisPaintingAssistant* ConcentricEllipseAssistantFactory::createPaintingAssistant() const { return new ConcentricEllipseAssistant; } diff --git a/plugins/assistants/Assistants/ConcentricEllipseAssistant.h b/plugins/assistants/Assistants/ConcentricEllipseAssistant.h index 1a0680eb38..55200afa59 100644 --- a/plugins/assistants/Assistants/ConcentricEllipseAssistant.h +++ b/plugins/assistants/Assistants/ConcentricEllipseAssistant.h @@ -1,59 +1,60 @@ /* * Copyright (c) 2008 Cyrille Berger * Copyright (c) 2010 Geoffry Song * Copyright (c) 2017 Scott Petrovic * * 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. + * the Free Software Foundation; 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 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 _CONCENTRIC_ELLIPSE_ASSISTANT_H_ #define _CONCENTRIC_ELLIPSE_ASSISTANT_H_ #include "kis_painting_assistant.h" #include "Ellipse.h" #include #include class ConcentricEllipseAssistant : public KisPaintingAssistant { public: ConcentricEllipseAssistant(); KisPaintingAssistantSP clone(QMap &handleMap) const override; QPointF adjustPosition(const QPointF& point, const QPointF& strokeBegin) override; QPointF buttonPosition() const override; int numHandles() const override { return 3; } bool isAssistantComplete() const override; protected: QRect boundingRect() const override; void drawAssistant(QPainter& gc, const QRectF& updateRect, const KisCoordinatesConverter* converter, bool cached, KisCanvas2* canvas, bool assistantVisible=true, bool previewVisible=true) override; void drawCache(QPainter& gc, const KisCoordinatesConverter *converter, bool assistantVisible=true) override; private: QPointF project(const QPointF& pt, const QPointF& strokeBegin) const; mutable Ellipse m_ellipse; mutable Ellipse m_extraEllipse; explicit ConcentricEllipseAssistant(const ConcentricEllipseAssistant &rhs, QMap &handleMap); }; class ConcentricEllipseAssistantFactory : public KisPaintingAssistantFactory { public: ConcentricEllipseAssistantFactory(); ~ConcentricEllipseAssistantFactory() override; QString id() const override; QString name() const override; KisPaintingAssistant* createPaintingAssistant() const override; }; #endif diff --git a/plugins/assistants/Assistants/Ellipse.cc b/plugins/assistants/Assistants/Ellipse.cc index 1acdd7aedf..5ad1f7d12b 100644 --- a/plugins/assistants/Assistants/Ellipse.cc +++ b/plugins/assistants/Assistants/Ellipse.cc @@ -1,192 +1,193 @@ /* * Copyright (c) 2010 Geoffry Song * * 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. + * the Free Software Foundation; 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 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 "Ellipse.h" #include #include Ellipse::Ellipse() : a(-1), b(-1) { } Ellipse::Ellipse(const QPointF& _p1, const QPointF& _p2, const QPointF& _p3) : p1(_p1), p2(_p2), p3(_p3) { changeMajor(); } Ellipse::~Ellipse() { } bool Ellipse::set(const QPointF& m1, const QPointF& m2, const QPointF& p) { bool changedMajor = m1 != p1 || m2 != p2, changedMinor = !changedMajor && p != p3; p1 = m1; p2 = m2; p3 = p; if (changedMajor) { return changeMajor(); } else if (changedMinor) { return changeMinor(); } else { return a > 0 && b > 0; } } QPointF Ellipse::project(const QPointF& pt) const { if (a <= 0 || b <= 0) return pt; // not a valid ellipse QPointF p = matrix.map(pt); /* * intersect line from (0,0) to p with the ellipse in canonical position * the equation of the line is y = py/px x * the equation of the ellipse is x^2/a^2 + y^2/b^2 = 1 * x=(a*b*px)/sqrt(a^2*py^2+b^2*px^2) * y=(a*b*py)/sqrt(a^2*py^2+b^2*px^2) */ const qreal divisor = sqrt(a * a * p.y() * p.y() + b * b * p.x() * p.x()); if (divisor <= 0) return inverse.map(QPointF(a, 0)); // give up const qreal ab = a * b, factor = 1.0 / divisor; QPointF ep(ab * p.x() * factor, ab * p.y() * factor); return inverse.map(ep); /* return inverse.map(closest(matrix.map(pt)));*/ } inline QPointF rotate90(const QPointF& p) { return QPointF(p.y(), -p.x()); } QRectF Ellipse::boundingRect() const { const QPointF d = rotate90((p2 - p1) * 0.5 * b / a); const QPointF pts[4] = { p1 + d, p1 - d, p2 + d, p2 - d }; QRectF ret; for (int i = 0; i < 4; ++i) { ret = ret.united(QRectF(pts[i], QSizeF(0.0001, 0.0001))); } return ret; } inline qreal sqrlength(const QPointF& vec) { return vec.x() * vec.x() + vec.y() * vec.y(); } inline qreal length(const QPointF& vec) { return sqrt(vec.x() * vec.x() + vec.y() * vec.y()); } bool Ellipse::changeMajor() { a = length(p1 - p2) * 0.5; /* * calculate transformation matrix * x' = m11*x + m21*y + dx * y' = m22*y + m12*x + dy * m11 = m22, m12 = -m21 (rotations and translations only) * x' = m11*x - m12*y + dx * y' = m11*y + m12*x + dy * * then, transforming (x1, y1) to (x1', y1') and (x2, y2) to (x2', y2'): * * m11 = (y2*y2' + y1 * (y1'-y2') - y2*y1' + x2*x'2 - x1*x'2 + (x1-x2)*x1') * ------------------------------------------------------------------ * (y2^2 - 2*y1*y2 + y1^2 + x2^2 - 2*x1*x2 + x1^2) * m12 = -(x1*(y2'-y1') - x2*y2' + x2*y1' + x2'*y2 - x1'*y2 + (x1'-x2')*y1) * ------------------------------------------------------------------ * (y2^2 - 2*y1*y2 + y1^2 + x2^2 - 2*x1*x2 + x1^2) * dx = (x1*(-y2*y2' + y2*y1' - x2*x2') + y1*( x2*y2' - x2*y1' - x2'*y2 - x1'*y2) + x2'*y1^2 + x1^2*x2' + x1'*(y2^2 + x2^2 - x1*x2)) * ---------------------------------------------------------------------------------------------------------------------------- * (y2^2 - 2*y1*y2 + y1^2 + x2^2 - 2*x1*x2 + x1^2) * dy = (x1*(-x2*y2' - x2*y1' + x2'*y2) + y1*(-y2*y2' - y2*y1' - x2*x2' + x2*x1') + y2'*y1^2 + x1^2*y2' + y1'(y2^2 + x2^2) - x1*x1'*y2) * ------------------------------------------------------------------------------------------------------------------------------- * (y2^2 - 2*y1*y2 + y1^2 + x2^2 - 2*x1*x2 + x1^2) * * in our usage, to move the ellipse into canonical position: * * (x1, y1) = p1 * (x2, y2) = p2 * (x1', y1') = (-a, 0) * (x2', y2') = (a, 0) */ const qreal x1 = p1.x(), x2 = p2.x(), y1 = p1.y(), y2 = p2.y(), x1p = -a, x2p = a, x1sqr = x1 * x1, x2sqr = x2 * x2, y1sqr = y1 * y1, y2sqr = y2 * y2, factor = 1.0 / (x1sqr + y1sqr + x2sqr + y2sqr - 2.0 * y1 * y2 - 2.0 * x1 * x2), m11 = (x2*x2p - x1*x2p + (x1-x2)*x1p) * factor, m12 = -(x2p*y2 - x1p*y2 + (x1p-x2p)*y1) * factor, dx = (x1*(-x2*x2p) + y1*(-x2p*y2 - x1p*y2) + x2p*y1sqr + x1sqr*x2p + x1p*(y2sqr + x2sqr - x1*x2)) * factor, dy = (x1*(x2p*y2) + y1*(-x2*x2p + x2*x1p) - x1*x1p*y2) * factor; matrix = QTransform(m11, m12, -m12, m11, dx, dy); inverse = matrix.inverted(); return changeMinor(); } bool Ellipse::changeMinor() { QPointF p = matrix.map(p3); /* * ellipse formula: * x^2/a^2 + y^2/b^2 = 1 * b = sqrt(y^2 / (1 - x^2/a^2)) */ const qreal asqr = a * a, xsqr = p.x() * p.x(), ysqr = p.y() * p.y(), divisor = (1.0 - xsqr / asqr); if (divisor <= 0) { // division by zero! b = -1; return false; } b = sqrt(ysqr / divisor); return true; } bool Ellipse::setMajor1(const QPointF& p) { p1 = p; return changeMajor(); } bool Ellipse::setMajor2(const QPointF& p) { p2 = p; return changeMajor(); } bool Ellipse::setPoint(const QPointF& p) { p3 = p; return changeMinor(); } diff --git a/plugins/assistants/Assistants/Ellipse.h b/plugins/assistants/Assistants/Ellipse.h index 24dcecdeb2..843616e2e7 100644 --- a/plugins/assistants/Assistants/Ellipse.h +++ b/plugins/assistants/Assistants/Ellipse.h @@ -1,62 +1,63 @@ /* * Copyright (c) 2010 Geoffry Song * * 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. + * the Free Software Foundation; 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 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 _ELLIPSE_H_ #define _ELLIPSE_H_ #include #include class Ellipse { public: Ellipse(); Ellipse(const QPointF& p1, const QPointF& p2, const QPointF& p3); ~Ellipse(); QPointF project(const QPointF&) const; // find a close point on the ellipse QRectF boundingRect() const; // find an axis-aligned box bounding this ellipse (inexact) bool set(const QPointF& m1, const QPointF& m2, const QPointF& p); // set all points const QPointF& major1() const { return p1; } bool setMajor1(const QPointF& p); const QPointF& major2() const { return p2; } bool setMajor2(const QPointF& p); const QPointF& point() const { return p3; } bool setPoint(const QPointF& p); const QTransform& getTransform() const { return matrix; } const QTransform& getInverse() const { return inverse; } qreal semiMajor() const { return a; } qreal semiMinor() const { return b; } private: bool changeMajor(); // determine 'a', 'b', 'matrix' and 'inverse' bool changeMinor(); // determine 'b' QTransform matrix; // transformation turning p1, p2 and p3 into their corresponding points on the ellipse in canonical position QTransform inverse; // inverse transformation qreal a; // semi-major axis: half the distance between p1 and p2 (horizontal axis) qreal b; // semi-minor axis (vertical axis) // a may not actually be larger than b, but we don't care that much QPointF p1; QPointF p2; QPointF p3; }; #endif diff --git a/plugins/assistants/Assistants/EllipseAssistant.cc b/plugins/assistants/Assistants/EllipseAssistant.cc index afee5c713b..4431886c15 100644 --- a/plugins/assistants/Assistants/EllipseAssistant.cc +++ b/plugins/assistants/Assistants/EllipseAssistant.cc @@ -1,180 +1,181 @@ /* * Copyright (c) 2008 Cyrille Berger * Copyright (c) 2010 Geoffry Song * Copyright (c) 2017 Scott Petrovic * * 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. + * the Free Software Foundation; 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 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 "EllipseAssistant.h" #include #include "kis_debug.h" #include #include #include #include #include #include EllipseAssistant::EllipseAssistant() : KisPaintingAssistant("ellipse", i18n("Ellipse assistant")) { } EllipseAssistant::EllipseAssistant(const EllipseAssistant &rhs, QMap &handleMap) : KisPaintingAssistant(rhs, handleMap) , e(rhs.e) { } KisPaintingAssistantSP EllipseAssistant::clone(QMap &handleMap) const { return KisPaintingAssistantSP(new EllipseAssistant(*this, handleMap)); } QPointF EllipseAssistant::project(const QPointF& pt) const { Q_ASSERT(isAssistantComplete()); e.set(*handles()[0], *handles()[1], *handles()[2]); return e.project(pt); } QPointF EllipseAssistant::adjustPosition(const QPointF& pt, const QPointF& /*strokeBegin*/) { return project(pt); } void EllipseAssistant::drawAssistant(QPainter& gc, const QRectF& updateRect, const KisCoordinatesConverter* converter, bool cached, KisCanvas2* canvas, bool assistantVisible, bool previewVisible) { gc.save(); gc.resetTransform(); QPoint mousePos; if (canvas){ //simplest, cheapest way to get the mouse-position// mousePos= canvas->canvasWidget()->mapFromGlobal(QCursor::pos()); } else { //...of course, you need to have access to a canvas-widget for that.// mousePos = QCursor::pos();//this'll give an offset// dbgFile<<"canvas does not exist in the ellipse assistant, you may have passed arguments incorrectly:"<documentToWidgetTransform(); if (isSnappingActive() && boundingRect().contains(initialTransform.inverted().map(mousePos), false) && previewVisible==true){ if (isAssistantComplete()){ if (e.set(*handles()[0], *handles()[1], *handles()[2])) { // valid ellipse gc.setTransform(initialTransform); gc.setTransform(e.getInverse(), true); QPainterPath path; //path.moveTo(QPointF(-e.semiMajor(), 0)); path.lineTo(QPointF(e.semiMajor(), 0)); //path.moveTo(QPointF(0, -e.semiMinor())); path.lineTo(QPointF(0, e.semiMinor())); // Draw the ellipse path.addEllipse(QPointF(0, 0), e.semiMajor(), e.semiMinor()); drawPreview(gc, path); } } } gc.restore(); KisPaintingAssistant::drawAssistant(gc, updateRect, converter, cached, canvas, assistantVisible, previewVisible); } void EllipseAssistant::drawCache(QPainter& gc, const KisCoordinatesConverter *converter, bool assistantVisible) { if (assistantVisible == false || handles().size() < 2){ return; } QTransform initialTransform = converter->documentToWidgetTransform(); if (handles().size() == 2) { // just draw the axis gc.setTransform(initialTransform); QPainterPath path; path.moveTo(*handles()[0]); path.lineTo(*handles()[1]); drawPath(gc, path, isSnappingActive()); return; } if (e.set(*handles()[0], *handles()[1], *handles()[2])) { // valid ellipse gc.setTransform(initialTransform); gc.setTransform(e.getInverse(), true); QPainterPath path; path.moveTo(QPointF(-e.semiMajor(), 0)); path.lineTo(QPointF(e.semiMajor(), 0)); path.moveTo(QPointF(0, -e.semiMinor())); path.lineTo(QPointF(0, e.semiMinor())); // Draw the ellipse path.addEllipse(QPointF(0, 0), e.semiMajor(), e.semiMinor()); drawPath(gc, path, isSnappingActive()); } } QRect EllipseAssistant::boundingRect() const { if (!isAssistantComplete()) { return KisPaintingAssistant::boundingRect(); } if (e.set(*handles()[0], *handles()[1], *handles()[2])) { return e.boundingRect().adjusted(-2, -2, 2, 2).toAlignedRect(); } else { return QRect(); } } QPointF EllipseAssistant::buttonPosition() const { return (*handles()[0] + *handles()[1]) * 0.5; } bool EllipseAssistant::isAssistantComplete() const { return handles().size() >= 3; } EllipseAssistantFactory::EllipseAssistantFactory() { } EllipseAssistantFactory::~EllipseAssistantFactory() { } QString EllipseAssistantFactory::id() const { return "ellipse"; } QString EllipseAssistantFactory::name() const { return i18n("Ellipse"); } KisPaintingAssistant* EllipseAssistantFactory::createPaintingAssistant() const { return new EllipseAssistant; } diff --git a/plugins/assistants/Assistants/EllipseAssistant.h b/plugins/assistants/Assistants/EllipseAssistant.h index 71283ef046..6e3b6b02aa 100644 --- a/plugins/assistants/Assistants/EllipseAssistant.h +++ b/plugins/assistants/Assistants/EllipseAssistant.h @@ -1,57 +1,58 @@ /* * Copyright (c) 2008 Cyrille Berger * Copyright (c) 2010 Geoffry Song * Copyright (c) 2017 Scott Petrovic * * 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. + * the Free Software Foundation; 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 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 _ELLIPSE_ASSISTANT_H_ #define _ELLIPSE_ASSISTANT_H_ #include "kis_painting_assistant.h" #include "Ellipse.h" #include class EllipseAssistant : public KisPaintingAssistant { public: EllipseAssistant(); KisPaintingAssistantSP clone(QMap &handleMap) const override; QPointF adjustPosition(const QPointF& point, const QPointF& strokeBegin) override; QPointF buttonPosition() const override; int numHandles() const override { return 3; } bool isAssistantComplete() const override; protected: QRect boundingRect() const override; void drawAssistant(QPainter& gc, const QRectF& updateRect, const KisCoordinatesConverter* converter, bool cached, KisCanvas2* canvas, bool assistantVisible=true, bool previewVisible=true) override; void drawCache(QPainter& gc, const KisCoordinatesConverter *converter, bool assistantVisible=true) override; private: QPointF project(const QPointF& pt) const; explicit EllipseAssistant(const EllipseAssistant &rhs, QMap &handleMap); mutable Ellipse e; }; class EllipseAssistantFactory : public KisPaintingAssistantFactory { public: EllipseAssistantFactory(); ~EllipseAssistantFactory() override; QString id() const override; QString name() const override; KisPaintingAssistant* createPaintingAssistant() const override; }; #endif diff --git a/plugins/assistants/Assistants/FisheyePointAssistant.cc b/plugins/assistants/Assistants/FisheyePointAssistant.cc index f97c8a59d9..610f2664fa 100644 --- a/plugins/assistants/Assistants/FisheyePointAssistant.cc +++ b/plugins/assistants/Assistants/FisheyePointAssistant.cc @@ -1,237 +1,238 @@ /* * Copyright (c) 2008 Cyrille Berger * Copyright (c) 2010 Geoffry Song * Copyright (c) 2014 Wolthera van Hövell tot Westerflier * Copyright (c) 2017 Scott Petrovic * * 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. + * the Free Software Foundation; 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 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 "FisheyePointAssistant.h" #include "kis_debug.h" #include #include #include #include #include #include #include #include #include FisheyePointAssistant::FisheyePointAssistant() : KisPaintingAssistant("fisheye-point", i18n("Fish Eye Point assistant")) { } FisheyePointAssistant::FisheyePointAssistant(const FisheyePointAssistant &rhs, QMap &handleMap) : KisPaintingAssistant(rhs, handleMap) , e(rhs.e) , extraE(rhs.extraE) { } KisPaintingAssistantSP FisheyePointAssistant::clone(QMap &handleMap) const { return KisPaintingAssistantSP(new FisheyePointAssistant(*this, handleMap)); } QPointF FisheyePointAssistant::project(const QPointF& pt, const QPointF& strokeBegin) { const static QPointF nullPoint(std::numeric_limits::quiet_NaN(), std::numeric_limits::quiet_NaN()); Q_ASSERT(isAssistantComplete()); e.set(*handles()[0], *handles()[1], *handles()[2]); qreal dx = pt.x() - strokeBegin.x(), dy = pt.y() - strokeBegin.y(); if (dx * dx + dy * dy < 4.0) { // allow some movement before snapping return strokeBegin; } //set the extrapolation ellipse. if (e.set(*handles()[0], *handles()[1], *handles()[2])){ QLineF radius(*handles()[1], *handles()[0]); radius.setAngle(fmod(radius.angle()+180.0,360.0)); QLineF radius2(*handles()[0], *handles()[1]); radius2.setAngle(fmod(radius2.angle()+180.0,360.0)); if ( extraE.set(*handles()[0], *handles()[1],strokeBegin ) ) { return extraE.project(pt); } else if (extraE.set(radius.p1(), radius.p2(),strokeBegin)) { return extraE.project(pt); } else if (extraE.set(radius2.p1(), radius2.p2(),strokeBegin)){ return extraE.project(pt); } } return nullPoint; } QPointF FisheyePointAssistant::adjustPosition(const QPointF& pt, const QPointF& strokeBegin) { return project(pt, strokeBegin); } void FisheyePointAssistant::drawAssistant(QPainter& gc, const QRectF& updateRect, const KisCoordinatesConverter* converter, bool cached, KisCanvas2* canvas, bool assistantVisible, bool previewVisible) { gc.save(); gc.resetTransform(); QPointF mousePos(0,0); if (canvas){ //simplest, cheapest way to get the mouse-position// mousePos= canvas->canvasWidget()->mapFromGlobal(QCursor::pos()); } else { //...of course, you need to have access to a canvas-widget for that.// mousePos = QCursor::pos();//this'll give an offset// dbgFile<<"canvas does not exist in ruler, you may have passed arguments incorrectly:"<documentToWidgetTransform(); if (isSnappingActive() && previewVisible == true ) { if (isAssistantComplete()){ if (e.set(*handles()[0], *handles()[1], *handles()[2])) { if (extraE.set(*handles()[0], *handles()[1], initialTransform.inverted().map(mousePos))){ gc.setTransform(initialTransform); gc.setTransform(e.getInverse(), true); QPainterPath path; // Draw the ellipse path.addEllipse(QPointF(0, 0), extraE.semiMajor(), extraE.semiMinor()); drawPreview(gc, path); } QLineF radius(*handles()[1], *handles()[0]); radius.setAngle(fmod(radius.angle()+180.0,360.0)); if (extraE.set(radius.p1(), radius.p2(), initialTransform.inverted().map(mousePos))){ gc.setTransform(initialTransform); gc.setTransform(extraE.getInverse(), true); QPainterPath path; // Draw the ellipse path.addEllipse(QPointF(0, 0), extraE.semiMajor(), extraE.semiMinor()); drawPreview(gc, path); } QLineF radius2(*handles()[0], *handles()[1]); radius2.setAngle(fmod(radius2.angle()+180.0,360.0)); if (extraE.set(radius2.p1(), radius2.p2(), initialTransform.inverted().map(mousePos))){ gc.setTransform(initialTransform); gc.setTransform(extraE.getInverse(), true); QPainterPath path; // Draw the ellipse path.addEllipse(QPointF(0, 0), extraE.semiMajor(), extraE.semiMinor()); drawPreview(gc, path); } } } } gc.restore(); KisPaintingAssistant::drawAssistant(gc, updateRect, converter, cached, canvas, assistantVisible, previewVisible); } void FisheyePointAssistant::drawCache(QPainter& gc, const KisCoordinatesConverter *converter, bool assistantVisible) { if (assistantVisible == false){ return; } QTransform initialTransform = converter->documentToWidgetTransform(); if (handles().size() == 2) { // just draw the axis gc.setTransform(initialTransform); QPainterPath path; path.moveTo(*handles()[0]); path.lineTo(*handles()[1]); drawPath(gc, path, isSnappingActive()); return; } if (e.set(*handles()[0], *handles()[1], *handles()[2])) { // valid ellipse gc.setTransform(initialTransform); gc.setTransform(e.getInverse(), true); QPainterPath path; //path.moveTo(QPointF(-e.semiMajor(), -e.semiMinor())); path.lineTo(QPointF(e.semiMajor(), -e.semiMinor())); path.moveTo(QPointF(-e.semiMajor(), -e.semiMinor())); path.lineTo(QPointF(-e.semiMajor(), e.semiMinor())); //path.moveTo(QPointF(-e.semiMajor(), e.semiMinor())); path.lineTo(QPointF(e.semiMajor(), e.semiMinor())); path.moveTo(QPointF(e.semiMajor(), -e.semiMinor())); path.lineTo(QPointF(e.semiMajor(), e.semiMinor())); path.moveTo(QPointF(-(e.semiMajor()*3), -e.semiMinor())); path.lineTo(QPointF(-(e.semiMajor()*3), e.semiMinor())); path.moveTo(QPointF((e.semiMajor()*3), -e.semiMinor())); path.lineTo(QPointF((e.semiMajor()*3), e.semiMinor())); path.moveTo(QPointF(-e.semiMajor(), 0)); path.lineTo(QPointF(e.semiMajor(), 0)); //path.moveTo(QPointF(0, -e.semiMinor())); path.lineTo(QPointF(0, e.semiMinor())); // Draw the ellipse path.addEllipse(QPointF(0, 0), e.semiMajor(), e.semiMinor()); drawPath(gc, path, isSnappingActive()); } } QRect FisheyePointAssistant::boundingRect() const { if (!isAssistantComplete()) { return KisPaintingAssistant::boundingRect(); } if (e.set(*handles()[0], *handles()[1], *handles()[2])) { return e.boundingRect().adjusted(-(e.semiMajor()*2), -2, (e.semiMajor()*2), 2).toAlignedRect(); } else { return QRect(); } } QPointF FisheyePointAssistant::buttonPosition() const { return (*handles()[0] + *handles()[1]) * 0.5; } bool FisheyePointAssistant::isAssistantComplete() const { return handles().size() >= 3; } FisheyePointAssistantFactory::FisheyePointAssistantFactory() { } FisheyePointAssistantFactory::~FisheyePointAssistantFactory() { } QString FisheyePointAssistantFactory::id() const { return "fisheye-point"; } QString FisheyePointAssistantFactory::name() const { return i18n("Fish Eye Point"); } KisPaintingAssistant* FisheyePointAssistantFactory::createPaintingAssistant() const { return new FisheyePointAssistant; } diff --git a/plugins/assistants/Assistants/FisheyePointAssistant.h b/plugins/assistants/Assistants/FisheyePointAssistant.h index 606d5b107d..f2a27d5a48 100644 --- a/plugins/assistants/Assistants/FisheyePointAssistant.h +++ b/plugins/assistants/Assistants/FisheyePointAssistant.h @@ -1,65 +1,66 @@ /* * Copyright (c) 2008 Cyrille Berger * Copyright (c) 2010 Geoffry Song * Copyright (c) 2014 Wolthera van Hövell tot Westerflier * Copyright (c) 2017 Scott Petrovic * * 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. + * the Free Software Foundation; 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 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 _FISHEYEPOINT_ASSISTANT_H_ #define _FISHEYEPOINT_ASSISTANT_H_ #include "kis_painting_assistant.h" #include "Ellipse.h" #include #include #include #include //class FisheyePoint; class FisheyePointAssistant : public KisPaintingAssistant { public: FisheyePointAssistant(); KisPaintingAssistantSP clone(QMap &handleMap) const override; QPointF adjustPosition(const QPointF& point, const QPointF& strokeBegin) override; //virtual void endStroke(); QPointF buttonPosition() const override; int numHandles() const override { return 3; } bool isAssistantComplete() const override; protected: QRect boundingRect() const override; void drawAssistant(QPainter& gc, const QRectF& updateRect, const KisCoordinatesConverter* converter, bool cached = true,KisCanvas2* canvas=0, bool assistantVisible=true, bool previewVisible=true) override; void drawCache(QPainter& gc, const KisCoordinatesConverter *converter, bool assistantVisible=true) override; private: QPointF project(const QPointF& pt, const QPointF& strokeBegin); explicit FisheyePointAssistant(const FisheyePointAssistant &rhs, QMap &handleMap); mutable Ellipse e; mutable Ellipse extraE; }; class FisheyePointAssistantFactory : public KisPaintingAssistantFactory { public: FisheyePointAssistantFactory(); ~FisheyePointAssistantFactory() override; QString id() const override; QString name() const override; KisPaintingAssistant* createPaintingAssistant() const override; }; #endif diff --git a/plugins/assistants/Assistants/InfiniteRulerAssistant.cc b/plugins/assistants/Assistants/InfiniteRulerAssistant.cc index 4ce58eedff..f85a188367 100644 --- a/plugins/assistants/Assistants/InfiniteRulerAssistant.cc +++ b/plugins/assistants/Assistants/InfiniteRulerAssistant.cc @@ -1,170 +1,171 @@ /* * Copyright (c) 2008 Cyrille Berger * Copyright (c) 2010 Geoffry Song * Copyright (c) 2014 Wolthera van Hövell tot Westerflier * Copyright (c) 2017 Scott Petrovic * * 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. + * the Free Software Foundation; 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 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 "InfiniteRulerAssistant.h" #include "kis_debug.h" #include #include #include #include #include #include #include #include InfiniteRulerAssistant::InfiniteRulerAssistant() : KisPaintingAssistant("infinite ruler", i18n("Infinite Ruler assistant")) { } InfiniteRulerAssistant::InfiniteRulerAssistant(const InfiniteRulerAssistant &rhs, QMap &handleMap) : KisPaintingAssistant(rhs, handleMap) { } KisPaintingAssistantSP InfiniteRulerAssistant::clone(QMap &handleMap) const { return KisPaintingAssistantSP(new InfiniteRulerAssistant(*this, handleMap)); } QPointF InfiniteRulerAssistant::project(const QPointF& pt, const QPointF& strokeBegin) { Q_ASSERT(isAssistantComplete()); //code nicked from the perspective ruler. qreal dx = pt.x() - strokeBegin.x(), dy = pt.y() - strokeBegin.y(); if (dx * dx + dy * dy < 4.0) { // allow some movement before snapping return strokeBegin; } //dbgKrita<canvasWidget()->mapFromGlobal(QCursor::pos()); } else { //...of course, you need to have access to a canvas-widget for that.// mousePos = QCursor::pos();//this'll give an offset// dbgFile<<"canvas does not exist in ruler, you may have passed arguments incorrectly:"<documentToWidgetTransform(); QLineF snapLine= QLineF(initialTransform.map(*handles()[0]), initialTransform.map(*handles()[1])); QRect viewport= gc.viewport(); KisAlgebra2D::intersectLineRect(snapLine, viewport); QPainterPath path; path.moveTo(snapLine.p1()); path.lineTo(snapLine.p2()); drawPreview(gc, path);//and we draw the preview. } gc.restore(); KisPaintingAssistant::drawAssistant(gc, updateRect, converter, cached, canvas, assistantVisible, previewVisible); } void InfiniteRulerAssistant::drawCache(QPainter& gc, const KisCoordinatesConverter *converter, bool assistantVisible) { if (assistantVisible == false || !isAssistantComplete()){ return; } QTransform initialTransform = converter->documentToWidgetTransform(); // Draw the line QPointF p1 = *handles()[0]; QPointF p2 = *handles()[1]; gc.setTransform(initialTransform); QPainterPath path; path.moveTo(p1); path.lineTo(p2); drawPath(gc, path, isSnappingActive()); } QPointF InfiniteRulerAssistant::buttonPosition() const { return (*handles()[0]); } bool InfiniteRulerAssistant::isAssistantComplete() const { return handles().size() >= 2; } InfiniteRulerAssistantFactory::InfiniteRulerAssistantFactory() { } InfiniteRulerAssistantFactory::~InfiniteRulerAssistantFactory() { } QString InfiniteRulerAssistantFactory::id() const { return "infinite ruler"; } QString InfiniteRulerAssistantFactory::name() const { return i18n("Infinite Ruler"); } KisPaintingAssistant* InfiniteRulerAssistantFactory::createPaintingAssistant() const { return new InfiniteRulerAssistant; } diff --git a/plugins/assistants/Assistants/InfiniteRulerAssistant.h b/plugins/assistants/Assistants/InfiniteRulerAssistant.h index 3e069635d1..db639da29c 100644 --- a/plugins/assistants/Assistants/InfiniteRulerAssistant.h +++ b/plugins/assistants/Assistants/InfiniteRulerAssistant.h @@ -1,62 +1,63 @@ /* * Copyright (c) 2008 Cyrille Berger * Copyright (c) 2010 Geoffry Song * Copyright (c) 2014 Wolthera van Hövell tot Westerflier * Copyright (c) 2017 Scott Petrovic * * 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. + * the Free Software Foundation; 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 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 _INFINITERULER_ASSISTANT_H_ #define _INFINITERULER_ASSISTANT_H_ #include "kis_painting_assistant.h" #include #include #include #include /* Design: */ class InfiniteRuler; class InfiniteRulerAssistant : public KisPaintingAssistant { public: InfiniteRulerAssistant(); KisPaintingAssistantSP clone(QMap &handleMap) const override; QPointF adjustPosition(const QPointF& point, const QPointF& strokeBegin) override; //virtual void endStroke(); QPointF buttonPosition() const override; int numHandles() const override { return 2; } bool isAssistantComplete() const override; protected: void drawAssistant(QPainter& gc, const QRectF& updateRect, const KisCoordinatesConverter* converter, bool cached = true,KisCanvas2* canvas=0, bool assistantVisible=true, bool previewVisible=true) override; void drawCache(QPainter& gc, const KisCoordinatesConverter *converter, bool assistantVisible=true) override; private: QPointF project(const QPointF& pt, const QPointF& strokeBegin); explicit InfiniteRulerAssistant(const InfiniteRulerAssistant &rhs, QMap &handleMap); }; class InfiniteRulerAssistantFactory : public KisPaintingAssistantFactory { public: InfiniteRulerAssistantFactory(); ~InfiniteRulerAssistantFactory() override; QString id() const override; QString name() const override; KisPaintingAssistant* createPaintingAssistant() const override; }; #endif diff --git a/plugins/assistants/Assistants/ParallelRulerAssistant.cc b/plugins/assistants/Assistants/ParallelRulerAssistant.cc index 766da9b21e..2d1fa2a943 100644 --- a/plugins/assistants/Assistants/ParallelRulerAssistant.cc +++ b/plugins/assistants/Assistants/ParallelRulerAssistant.cc @@ -1,177 +1,178 @@ /* * Copyright (c) 2008 Cyrille Berger * Copyright (c) 2010 Geoffry Song * Copyright (c) 2014 Wolthera van Hövell tot Westerflier * Copyright (c) 2017 Scott Petrovic * * 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. + * the Free Software Foundation; 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 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 "ParallelRulerAssistant.h" #include "kis_debug.h" #include #include #include #include #include #include #include #include ParallelRulerAssistant::ParallelRulerAssistant() : KisPaintingAssistant("parallel ruler", i18n("Parallel Ruler assistant")) { } KisPaintingAssistantSP ParallelRulerAssistant::clone(QMap &handleMap) const { return KisPaintingAssistantSP(new ParallelRulerAssistant(*this, handleMap)); } ParallelRulerAssistant::ParallelRulerAssistant(const ParallelRulerAssistant &rhs, QMap &handleMap) : KisPaintingAssistant(rhs, handleMap) { } QPointF ParallelRulerAssistant::project(const QPointF& pt, const QPointF& strokeBegin) { Q_ASSERT(isAssistantComplete()); //code nicked from the perspective ruler. qreal dx = pt.x() - strokeBegin.x(); qreal dy = pt.y() - strokeBegin.y(); if (dx * dx + dy * dy < 4.0) { return strokeBegin; // allow some movement before snapping } //dbgKrita<canvasWidget()->mapFromGlobal(QCursor::pos()); } else { //...of course, you need to have access to a canvas-widget for that.// mousePos = QCursor::pos();//this'll give an offset// dbgFile<<"canvas does not exist in ruler, you may have passed arguments incorrectly:"<documentToWidgetTransform(); QLineF snapLine= QLineF(initialTransform.map(*handles()[0]), initialTransform.map(*handles()[1])); QPointF translation = (initialTransform.map(*handles()[0])-mousePos)*-1.0; snapLine= snapLine.translated(translation); QRect viewport= gc.viewport(); KisAlgebra2D::intersectLineRect(snapLine, viewport); QPainterPath path; path.moveTo(snapLine.p1()); path.lineTo(snapLine.p2()); drawPreview(gc, path);//and we draw the preview. } gc.restore(); KisPaintingAssistant::drawAssistant(gc, updateRect, converter, cached, canvas, assistantVisible, previewVisible); } void ParallelRulerAssistant::drawCache(QPainter& gc, const KisCoordinatesConverter *converter, bool assistantVisible) { if (assistantVisible == false || !isAssistantComplete()){ return; } QTransform initialTransform = converter->documentToWidgetTransform(); // Draw the line QPointF p1 = *handles()[0]; QPointF p2 = *handles()[1]; gc.setTransform(initialTransform); QPainterPath path; path.moveTo(p1); path.lineTo(p2); drawPath(gc, path, isSnappingActive()); } QPointF ParallelRulerAssistant::buttonPosition() const { return (*handles()[0] + *handles()[1]) * 0.5; } bool ParallelRulerAssistant::isAssistantComplete() const { return handles().size() >= 2; } ParallelRulerAssistantFactory::ParallelRulerAssistantFactory() { } ParallelRulerAssistantFactory::~ParallelRulerAssistantFactory() { } QString ParallelRulerAssistantFactory::id() const { return "parallel ruler"; } QString ParallelRulerAssistantFactory::name() const { return i18n("Parallel Ruler"); } KisPaintingAssistant* ParallelRulerAssistantFactory::createPaintingAssistant() const { return new ParallelRulerAssistant; } diff --git a/plugins/assistants/Assistants/ParallelRulerAssistant.h b/plugins/assistants/Assistants/ParallelRulerAssistant.h index ece6cf38a7..5c82ad7246 100644 --- a/plugins/assistants/Assistants/ParallelRulerAssistant.h +++ b/plugins/assistants/Assistants/ParallelRulerAssistant.h @@ -1,62 +1,63 @@ /* * Copyright (c) 2008 Cyrille Berger * Copyright (c) 2010 Geoffry Song * Copyright (c) 2014 Wolthera van Hövell tot Westerflier * Copyright (c) 2017 Scott Petrovic * * 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. + * the Free Software Foundation; 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 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 _PARALLELRULER_ASSISTANT_H_ #define _PARALLELRULER_ASSISTANT_H_ #include "kis_painting_assistant.h" #include #include #include #include /* Design: */ class ParallelRuler; class ParallelRulerAssistant : public KisPaintingAssistant { public: ParallelRulerAssistant(); KisPaintingAssistantSP clone(QMap &handleMap) const override; QPointF adjustPosition(const QPointF& point, const QPointF& strokeBegin) override; //virtual void endStroke(); QPointF buttonPosition() const override; int numHandles() const override { return 2; } bool isAssistantComplete() const override; protected: void drawAssistant(QPainter& gc, const QRectF& updateRect, const KisCoordinatesConverter* converter, bool cached = true,KisCanvas2* canvas=0, bool assistantVisible=true, bool previewVisible=true) override; void drawCache(QPainter& gc, const KisCoordinatesConverter *converter, bool assistantVisible=true) override; private: QPointF project(const QPointF& pt, const QPointF& strokeBegin); explicit ParallelRulerAssistant(const ParallelRulerAssistant &rhs, QMap &handleMap); }; class ParallelRulerAssistantFactory : public KisPaintingAssistantFactory { public: ParallelRulerAssistantFactory(); ~ParallelRulerAssistantFactory() override; QString id() const override; QString name() const override; KisPaintingAssistant* createPaintingAssistant() const override; }; #endif diff --git a/plugins/assistants/Assistants/PerspectiveAssistant.cc b/plugins/assistants/Assistants/PerspectiveAssistant.cc index 4d920ecf7f..8e0c327e16 100644 --- a/plugins/assistants/Assistants/PerspectiveAssistant.cc +++ b/plugins/assistants/Assistants/PerspectiveAssistant.cc @@ -1,480 +1,481 @@ /* * Copyright (c) 2008 Cyrille Berger * Copyright (c) 2010 Geoffry Song * Copyright (c) 2017 Scott Petrovic * * 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. + * the Free Software Foundation; 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 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 "PerspectiveAssistant.h" #include "kis_debug.h" #include #include #include #include #include #include #include #include #include PerspectiveAssistant::PerspectiveAssistant(QObject *parent) : KisAbstractPerspectiveGrid(parent) , KisPaintingAssistant("perspective", i18n("Perspective assistant")) { } PerspectiveAssistant::PerspectiveAssistant(const PerspectiveAssistant &rhs, QMap &handleMap) : KisAbstractPerspectiveGrid(rhs.parent()) , KisPaintingAssistant(rhs, handleMap) , m_snapLine(rhs.m_snapLine) , m_cachedTransform(rhs.m_cachedTransform) , m_cachedPolygon(rhs.m_cachedPolygon) , m_cacheValid(rhs.m_cacheValid) { for (int i = 0; i < 4; ++i) { m_cachedPoints[i] = rhs.m_cachedPoints[i]; } } KisPaintingAssistantSP PerspectiveAssistant::clone(QMap &handleMap) const { return KisPaintingAssistantSP(new PerspectiveAssistant(*this, handleMap)); } // squared distance from a point to a line inline qreal distsqr(const QPointF& pt, const QLineF& line) { // distance = |(p2 - p1) x (p1 - pt)| / |p2 - p1| // magnitude of (p2 - p1) x (p1 - pt) const qreal cross = (line.dx() * (line.y1() - pt.y()) - line.dy() * (line.x1() - pt.x())); return cross * cross / (line.dx() * line.dx() + line.dy() * line.dy()); } QPointF PerspectiveAssistant::project(const QPointF& pt, const QPointF& strokeBegin) { const static QPointF nullPoint(std::numeric_limits::quiet_NaN(), std::numeric_limits::quiet_NaN()); Q_ASSERT(isAssistantComplete()); if (m_snapLine.isNull()) { QPolygonF poly; QTransform transform; if (!getTransform(poly, transform)) { return nullPoint; } if (!poly.containsPoint(strokeBegin, Qt::OddEvenFill)) { return nullPoint; // avoid problems with multiple assistants: only snap if starting in the grid } const qreal dx = pt.x() - strokeBegin.x(); const qreal dy = pt.y() - strokeBegin.y(); if (dx * dx + dy * dy < 4.0) { return strokeBegin; // allow some movement before snapping } // construct transformation bool invertible; const QTransform inverse = transform.inverted(&invertible); if (!invertible) { return nullPoint; // shouldn't happen } // figure out which direction to go const QPointF start = inverse.map(strokeBegin); const QLineF verticalLine = QLineF(strokeBegin, transform.map(start + QPointF(0, 1))); const QLineF horizontalLine = QLineF(strokeBegin, transform.map(start + QPointF(1, 0))); // determine whether the horizontal or vertical line is closer to the point m_snapLine = distsqr(pt, verticalLine) < distsqr(pt, horizontalLine) ? verticalLine : horizontalLine; } // snap to line const qreal dx = m_snapLine.dx(), dy = m_snapLine.dy(), dx2 = dx * dx, dy2 = dy * dy, invsqrlen = 1.0 / (dx2 + dy2); QPointF r(dx2 * pt.x() + dy2 * m_snapLine.x1() + dx * dy * (pt.y() - m_snapLine.y1()), dx2 * m_snapLine.y1() + dy2 * pt.y() + dx * dy * (pt.x() - m_snapLine.x1())); r *= invsqrlen; return r; } QPointF PerspectiveAssistant::adjustPosition(const QPointF& pt, const QPointF& strokeBegin) { return project(pt, strokeBegin); } void PerspectiveAssistant::endStroke() { m_snapLine = QLineF(); } bool PerspectiveAssistant::contains(const QPointF& pt) const { QPolygonF poly; if (!quad(poly)) return false; return poly.containsPoint(pt, Qt::OddEvenFill); } inline qreal lengthSquared(const QPointF& vector) { return vector.x() * vector.x() + vector.y() * vector.y(); } inline qreal localScale(const QTransform& transform, QPointF pt) { // const qreal epsilon = 1e-5, epsilonSquared = epsilon * epsilon; // qreal xSizeSquared = lengthSquared(transform.map(pt + QPointF(epsilon, 0.0)) - orig) / epsilonSquared; // qreal ySizeSquared = lengthSquared(transform.map(pt + QPointF(0.0, epsilon)) - orig) / epsilonSquared; // xSizeSquared /= lengthSquared(transform.map(QPointF(0.0, pt.y())) - transform.map(QPointF(1.0, pt.y()))); // ySizeSquared /= lengthSquared(transform.map(QPointF(pt.x(), 0.0)) - transform.map(QPointF(pt.x(), 1.0))); // when taking the limit epsilon->0: // xSizeSquared=((m23*y+m33)^2*(m23*y+m33+m13)^2)/(m23*y+m13*x+m33)^4 // ySizeSquared=((m23*y+m33)^2*(m23*y+m33+m13)^2)/(m23*y+m13*x+m33)^4 // xSize*ySize=(abs(m13*x+m33)*abs(m13*x+m33+m23)*abs(m23*y+m33)*abs(m23*y+m33+m13))/(m23*y+m13*x+m33)^4 const qreal x = transform.m13() * pt.x(), y = transform.m23() * pt.y(), a = x + transform.m33(), b = y + transform.m33(), c = x + y + transform.m33(), d = c * c; return fabs(a*(a + transform.m23())*b*(b + transform.m13()))/(d * d); } // returns the reciprocal of the maximum local scale at the points (0,0),(0,1),(1,0),(1,1) inline qreal inverseMaxLocalScale(const QTransform& transform) { const qreal a = fabs((transform.m33() + transform.m13()) * (transform.m33() + transform.m23())), b = fabs((transform.m33()) * (transform.m13() + transform.m33() + transform.m23())), d00 = transform.m33() * transform.m33(), d11 = (transform.m33() + transform.m23() + transform.m13())*(transform.m33() + transform.m23() + transform.m13()), s0011 = qMin(d00, d11) / a, d10 = (transform.m33() + transform.m13()) * (transform.m33() + transform.m13()), d01 = (transform.m33() + transform.m23()) * (transform.m33() + transform.m23()), s1001 = qMin(d10, d01) / b; return qMin(s0011, s1001); } qreal PerspectiveAssistant::distance(const QPointF& pt) const { QPolygonF poly; QTransform transform; if (!getTransform(poly, transform)) { return 1.0; } bool invertible; QTransform inverse = transform.inverted(&invertible); if (!invertible) { return 1.0; } if (inverse.m13() * pt.x() + inverse.m23() * pt.y() + inverse.m33() == 0.0) { return 0.0; // point at infinity } return localScale(transform, inverse.map(pt)) * inverseMaxLocalScale(transform); } // draw a vanishing point marker inline QPainterPath drawX(const QPointF& pt) { QPainterPath path; path.moveTo(QPointF(pt.x() - 5.0, pt.y() - 5.0)); path.lineTo(QPointF(pt.x() + 5.0, pt.y() + 5.0)); path.moveTo(QPointF(pt.x() - 5.0, pt.y() + 5.0)); path.lineTo(QPointF(pt.x() + 5.0, pt.y() - 5.0)); return path; } void PerspectiveAssistant::drawAssistant(QPainter& gc, const QRectF& updateRect, const KisCoordinatesConverter* converter, bool cached, KisCanvas2* canvas, bool assistantVisible, bool previewVisible) { gc.save(); gc.resetTransform(); QTransform initialTransform = converter->documentToWidgetTransform(); //QTransform reverseTransform = converter->widgetToDocument(); QPolygonF poly; QTransform transform; // unused, but computed for caching purposes if (getTransform(poly, transform) && assistantVisible==true) { // draw vanishing points QPointF intersection(0, 0); if (fmod(QLineF(poly[0], poly[1]).angle(), 180.0)>=fmod(QLineF(poly[2], poly[3]).angle(), 180.0)+2.0 || fmod(QLineF(poly[0], poly[1]).angle(), 180.0)<=fmod(QLineF(poly[2], poly[3]).angle(), 180.0)-2.0) { if (QLineF(poly[0], poly[1]).intersect(QLineF(poly[2], poly[3]), &intersection) != QLineF::NoIntersection) { drawPath(gc, drawX(initialTransform.map(intersection))); } } if (fmod(QLineF(poly[1], poly[2]).angle(), 180.0)>=fmod(QLineF(poly[3], poly[0]).angle(), 180.0)+2.0 || fmod(QLineF(poly[1], poly[2]).angle(), 180.0)<=fmod(QLineF(poly[3], poly[0]).angle(), 180.0)-2.0){ if (QLineF(poly[1], poly[2]).intersect(QLineF(poly[3], poly[0]), &intersection) != QLineF::NoIntersection) { drawPath(gc, drawX(initialTransform.map(intersection))); } } } if (isSnappingActive() && getTransform(poly, transform) && previewVisible==true){ //find vanishing point, find mouse, draw line between both. QPainterPath path2; QPointF intersection(0, 0);//this is the position of the vanishing point. QPointF mousePos(0,0); QLineF snapLine; QRect viewport= gc.viewport(); QRect bounds; if (canvas){ //simplest, cheapest way to get the mouse-position mousePos= canvas->canvasWidget()->mapFromGlobal(QCursor::pos()); } else { //...of course, you need to have access to a canvas-widget for that. mousePos = QCursor::pos(); // this'll give an offset dbgFile<<"canvas does not exist, you may have passed arguments incorrectly:"<=fmod(QLineF(poly[2], poly[3]).angle(), 180.0)+2.0 || fmod(QLineF(poly[0], poly[1]).angle(), 180.0)<=fmod(QLineF(poly[2], poly[3]).angle(), 180.0)-2.0) { if (QLineF(poly[0], poly[1]).intersect(QLineF(poly[2], poly[3]), &intersection) != QLineF::NoIntersection) { intersectTransformed = initialTransform.map(intersection); snapLine = QLineF(intersectTransformed, mousePos); KisAlgebra2D::intersectLineRect(snapLine, viewport); bounds= QRect(snapLine.p1().toPoint(), snapLine.p2().toPoint()); QPainterPath path; if (bounds.contains(intersectTransformed.toPoint())){ path2.moveTo(intersectTransformed); path2.lineTo(snapLine.p1()); } else { path2.moveTo(snapLine.p1()); path2.lineTo(snapLine.p2()); } } } if (fmod(QLineF(poly[1], poly[2]).angle(), 180.0)>=fmod(QLineF(poly[3], poly[0]).angle(), 180.0)+2.0 || fmod(QLineF(poly[1], poly[2]).angle(), 180.0)<=fmod(QLineF(poly[3], poly[0]).angle(), 180.0)-2.0){ if (QLineF(poly[1], poly[2]).intersect(QLineF(poly[3], poly[0]), &intersection) != QLineF::NoIntersection) { intersectTransformed = initialTransform.map(intersection); snapLine = QLineF(intersectTransformed, mousePos); KisAlgebra2D::intersectLineRect(snapLine, viewport); bounds= QRect(snapLine.p1().toPoint(), snapLine.p2().toPoint()); QPainterPath path; if (bounds.contains(intersectTransformed.toPoint())){ path2.moveTo(intersectTransformed); path2.lineTo(snapLine.p1()); } else { path2.moveTo(snapLine.p1()); path2.lineTo(snapLine.p2()); } } } drawPreview(gc, path2); } } gc.restore(); KisPaintingAssistant::drawAssistant(gc, updateRect, converter, cached,canvas, assistantVisible, previewVisible); } void PerspectiveAssistant::drawCache(QPainter& gc, const KisCoordinatesConverter *converter, bool assistantVisible) { if (assistantVisible == false) { return; } gc.setTransform(converter->documentToWidgetTransform()); QPolygonF poly; QTransform transform; if (!getTransform(poly, transform)) { // color red for an invalid transform, but not for an incomplete one if(isAssistantComplete()) { gc.setPen(QColor(255, 0, 0, 125)); gc.drawPolygon(poly); } else { QPainterPath path; path.addPolygon(poly); drawPath(gc, path, isSnappingActive()); } } else { gc.setPen(QColor(0, 0, 0, 125)); gc.setTransform(transform, true); QPainterPath path; for (int y = 0; y <= 8; ++y) { path.moveTo(QPointF(0.0, y * 0.125)); path.lineTo(QPointF(1.0, y * 0.125)); } for (int x = 0; x <= 8; ++x) { path.moveTo(QPointF(x * 0.125, 0.0)); path.lineTo(QPointF(x * 0.125, 1.0)); } drawPath(gc, path, isSnappingActive()); } } QPointF PerspectiveAssistant::buttonPosition() const { QPointF centroid(0, 0); for (int i = 0; i < 4; ++i) { centroid += *handles()[i]; } return centroid * 0.25; } template int sign(T a) { return (a > 0) - (a < 0); } // perpendicular dot product inline qreal pdot(const QPointF& a, const QPointF& b) { return a.x() * b.y() - a.y() * b.x(); } bool PerspectiveAssistant::quad(QPolygonF& poly) const { for (int i = 0; i < handles().size(); ++i) { poly.push_back(*handles()[i]); } if (!isAssistantComplete()) { return false; } int sum = 0; int signs[4]; for (int i = 0; i < 4; ++i) { int j = (i == 3) ? 0 : (i + 1); int k = (j == 3) ? 0 : (j + 1); signs[i] = sign(pdot(poly[j] - poly[i], poly[k] - poly[j])); sum += signs[i]; } if (sum == 0) { // complex (crossed) for (int i = 0; i < 4; ++i) { int j = (i == 3) ? 0 : (i + 1); if (signs[i] * signs[j] == -1) { // opposite signs: uncross std::swap(poly[i], poly[j]); return true; } } // okay, maybe it's just a line return false; } else if (sum != 4 && sum != -4) { // concave, or a triangle if (sum == 2 || sum == -2) { // concave, let's return a triangle instead for (int i = 0; i < 4; ++i) { int j = (i == 3) ? 0 : (i + 1); if (signs[i] != sign(sum)) { // wrong sign: drop the inside node poly.remove(j); return false; } } } return false; } // convex return true; } bool PerspectiveAssistant::getTransform(QPolygonF& poly, QTransform& transform) const { if (m_cachedPolygon.size() != 0 && isAssistantComplete()) { for (int i = 0; i <= 4; ++i) { if (i == 4) { poly = m_cachedPolygon; transform = m_cachedTransform; return m_cacheValid; } if (m_cachedPoints[i] != *handles()[i]) break; } } m_cachedPolygon.clear(); m_cacheValid = false; if (!quad(poly)) { m_cachedPolygon = poly; return false; } if (!QTransform::squareToQuad(poly, transform)) { qWarning("Failed to create perspective mapping"); return false; } for (int i = 0; i < 4; ++i) { m_cachedPoints[i] = *handles()[i]; } m_cachedPolygon = poly; m_cachedTransform = transform; m_cacheValid = true; return true; } bool PerspectiveAssistant::isAssistantComplete() const { return handles().size() >= 4; // specify 4 corners to make assistant complete } PerspectiveAssistantFactory::PerspectiveAssistantFactory() { } PerspectiveAssistantFactory::~PerspectiveAssistantFactory() { } QString PerspectiveAssistantFactory::id() const { return "perspective"; } QString PerspectiveAssistantFactory::name() const { return i18n("Perspective"); } KisPaintingAssistant* PerspectiveAssistantFactory::createPaintingAssistant() const { return new PerspectiveAssistant; } diff --git a/plugins/assistants/Assistants/PerspectiveAssistant.h b/plugins/assistants/Assistants/PerspectiveAssistant.h index e53ce1b411..7d4ccac50f 100644 --- a/plugins/assistants/Assistants/PerspectiveAssistant.h +++ b/plugins/assistants/Assistants/PerspectiveAssistant.h @@ -1,77 +1,78 @@ /* * Copyright (c) 2008 Cyrille Berger * Copyright (c) 2010 Geoffry Song * Copyright (c) 2017 Scott Petrovic * * 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. + * the Free Software Foundation; 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 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 _PERSPECTIVE_ASSISTANT_H_ #define _PERSPECTIVE_ASSISTANT_H_ #include "kis_abstract_perspective_grid.h" #include "kis_painting_assistant.h" #include #include #include #include class PerspectiveAssistant : public KisAbstractPerspectiveGrid, public KisPaintingAssistant { Q_OBJECT public: PerspectiveAssistant(QObject * parent = 0); KisPaintingAssistantSP clone(QMap &handleMap) const override; QPointF adjustPosition(const QPointF& point, const QPointF& strokeBegin) override; void endStroke() override; QPointF buttonPosition() const override; int numHandles() const override { return 4; } void drawAssistant(QPainter& gc, const QRectF& updateRect, const KisCoordinatesConverter* converter, bool cached = true,KisCanvas2* canvas=0, bool assistantVisible=true, bool previewVisible=true) override; bool contains(const QPointF& point) const override; qreal distance(const QPointF& point) const override; bool isAssistantComplete() const override; protected: void drawCache(QPainter& gc, const KisCoordinatesConverter *converter, bool assistantVisible=true) override; private: QPointF project(const QPointF& pt, const QPointF& strokeBegin); // creates the convex hull, returns false if it's not a quadrilateral bool quad(QPolygonF& out) const; // finds the transform from perspective coordinates (a unit square) to the document bool getTransform(QPolygonF& polyOut, QTransform& transformOut) const; explicit PerspectiveAssistant(const PerspectiveAssistant &rhs, QMap &handleMap); // which direction to snap to (in transformed coordinates) QLineF m_snapLine; // cached information mutable QTransform m_cachedTransform; mutable QPolygonF m_cachedPolygon; mutable QPointF m_cachedPoints[4]; mutable bool m_cacheValid; }; class PerspectiveAssistantFactory : public KisPaintingAssistantFactory { public: PerspectiveAssistantFactory(); ~PerspectiveAssistantFactory() override; QString id() const override; QString name() const override; KisPaintingAssistant* createPaintingAssistant() const override; }; #endif diff --git a/plugins/assistants/Assistants/Ruler.cc b/plugins/assistants/Assistants/Ruler.cc index 696b6f3d45..d8513a0304 100644 --- a/plugins/assistants/Assistants/Ruler.cc +++ b/plugins/assistants/Assistants/Ruler.cc @@ -1,50 +1,51 @@ /* * 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. + * the Free Software Foundation; 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 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 "Ruler.h" Ruler::Ruler() : p1(QPointF(10, 10)), p2(QPointF(100, 190)) { } Ruler::~Ruler() { } QPointF Ruler::project(const QPointF& pt) { double x1 = p1.x(); double y1 = p1.y(); double x2 = p2.x(); double y2 = p2.y(); double a1 = (y2 - y1) / (x2 - x1); double b1 = y1 - x1 * a1; double a2 = (x2 - x1) / (y1 - y2); double b2 = pt.y() - a2 * pt.x(); double xm = (b2 - b1) / (a1 - a2); return QPointF(xm, xm * a1 + b1); } const QPointF& Ruler::point1() const { return p1; } const QPointF& Ruler::point2() const { return p2; } diff --git a/plugins/assistants/Assistants/Ruler.h b/plugins/assistants/Assistants/Ruler.h index c629a6a0af..8fc032e6bb 100644 --- a/plugins/assistants/Assistants/Ruler.h +++ b/plugins/assistants/Assistants/Ruler.h @@ -1,42 +1,43 @@ /* * 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. + * the Free Software Foundation; 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 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 _RULER_H_ #define _RULER_H_ #include class Ruler { public: Ruler(); ~Ruler(); QPointF project(const QPointF&); const QPointF& point1() const; void setPoint1(const QPointF& p) { p1 = p; } const QPointF& point2() const; void setPoint2(const QPointF& p) { p2 = p; } private: QPointF p1; QPointF p2; }; #endif diff --git a/plugins/assistants/Assistants/RulerAssistant.cc b/plugins/assistants/Assistants/RulerAssistant.cc index 13f64eff7b..ab03b906cb 100644 --- a/plugins/assistants/Assistants/RulerAssistant.cc +++ b/plugins/assistants/Assistants/RulerAssistant.cc @@ -1,176 +1,177 @@ /* * Copyright (c) 2008 Cyrille Berger * Copyright (c) 2017 Scott Petrovic * * 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. + * the Free Software Foundation; 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 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 "RulerAssistant.h" #include "kis_debug.h" #include #include #include #include #include #include #include RulerAssistant::RulerAssistant() : KisPaintingAssistant("ruler", i18n("Ruler assistant")) { } KisPaintingAssistantSP RulerAssistant::clone(QMap &handleMap) const { return KisPaintingAssistantSP(new RulerAssistant(*this, handleMap)); } RulerAssistant::RulerAssistant(const RulerAssistant &rhs, QMap &handleMap) : KisPaintingAssistant(rhs, handleMap) { } QPointF RulerAssistant::project(const QPointF& pt) const { Q_ASSERT(isAssistantComplete()); QPointF pt1 = *handles()[0]; QPointF pt2 = *handles()[1]; QPointF a = pt - pt1; QPointF u = pt2 - pt1; qreal u_norm = sqrt(u.x() * u.x() + u.y() * u.y()); if(u_norm == 0) return pt; u /= u_norm; double t = a.x() * u.x() + a.y() * u.y(); if(t < 0.0) return pt1; if(t > u_norm) return pt2; return t * u + pt1; } QPointF RulerAssistant::adjustPosition(const QPointF& pt, const QPointF& /*strokeBegin*/) { return project(pt); } inline double angle(const QPointF& p1, const QPointF& p2) { return atan2(p2.y() - p1.y(), p2.x() - p1.x()); } inline double norm2(const QPointF& p) { return sqrt(p.x() * p.x() + p.y() * p.y()); } void RulerAssistant::drawAssistant(QPainter& gc, const QRectF& updateRect, const KisCoordinatesConverter* converter, bool cached, KisCanvas2* canvas, bool assistantVisible, bool previewVisible) { gc.save(); gc.resetTransform(); QPointF mousePos; if (canvas){ //simplest, cheapest way to get the mouse-position// mousePos= canvas->canvasWidget()->mapFromGlobal(QCursor::pos()); } else { //...of course, you need to have access to a canvas-widget for that.// mousePos = QCursor::pos();//this'll give an offset// dbgFile<<"canvas does not exist in ruler, you may have passed arguments incorrectly:"<documentToWidgetTransform(); // first we find the path that our point create. QPointF p1 = *handles()[0]; QPointF p2 = *handles()[1]; gc.setTransform(initialTransform); QPainterPath path; path.moveTo(p1); path.lineTo(p2); //then we use this path to check the bounding rectangle// if (isSnappingActive() && path.boundingRect().contains(initialTransform.inverted().map(mousePos)) && previewVisible==true){ drawPreview(gc, path);//and we draw the preview. } } gc.restore(); KisPaintingAssistant::drawAssistant(gc, updateRect, converter, cached, canvas, assistantVisible, previewVisible); } void RulerAssistant::drawCache(QPainter& gc, const KisCoordinatesConverter *converter, bool assistantVisible) { if (assistantVisible == false || !isAssistantComplete()){ return; } QTransform initialTransform = converter->documentToWidgetTransform(); // Draw the line QPointF p1 = *handles()[0]; QPointF p2 = *handles()[1]; gc.setTransform(initialTransform); QPainterPath path; path.moveTo(p1); path.lineTo(p2); drawPath(gc, path, isSnappingActive()); } QPointF RulerAssistant::buttonPosition() const { return (*handles()[0] + *handles()[1]) * 0.5; } bool RulerAssistant::isAssistantComplete() const { return handles().size() >= 2; } RulerAssistantFactory::RulerAssistantFactory() { } RulerAssistantFactory::~RulerAssistantFactory() { } QString RulerAssistantFactory::id() const { return "ruler"; } QString RulerAssistantFactory::name() const { return i18n("Ruler"); } KisPaintingAssistant* RulerAssistantFactory::createPaintingAssistant() const { return new RulerAssistant; } diff --git a/plugins/assistants/Assistants/RulerAssistant.h b/plugins/assistants/Assistants/RulerAssistant.h index 36fcdf5eb1..5211c69b90 100644 --- a/plugins/assistants/Assistants/RulerAssistant.h +++ b/plugins/assistants/Assistants/RulerAssistant.h @@ -1,56 +1,57 @@ /* * Copyright (c) 2008 Cyrille Berger * Copyright (c) 2017 Scott Petrovic * * 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. + * the Free Software Foundation; 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 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 _RULER_ASSISTANT_H_ #define _RULER_ASSISTANT_H_ #include #include "kis_painting_assistant.h" class Ruler; class RulerAssistant : public KisPaintingAssistant { public: RulerAssistant(); KisPaintingAssistantSP clone(QMap &handleMap) const override; QPointF adjustPosition(const QPointF& point, const QPointF& strokeBegin) override; QPointF buttonPosition() const override; int numHandles() const override { return 2; } bool isAssistantComplete() const override; protected: void drawAssistant(QPainter& gc, const QRectF& updateRect, const KisCoordinatesConverter* converter, bool cached, KisCanvas2* canvas, bool assistantVisible=true, bool previewVisible=true) override; void drawCache(QPainter& gc, const KisCoordinatesConverter *converter, bool assistantVisible=true) override; private: QPointF project(const QPointF& pt) const; explicit RulerAssistant(const RulerAssistant &rhs, QMap &handleMap); }; class RulerAssistantFactory : public KisPaintingAssistantFactory { public: RulerAssistantFactory(); ~RulerAssistantFactory() override; QString id() const override; QString name() const override; KisPaintingAssistant* createPaintingAssistant() const override; }; #endif diff --git a/plugins/assistants/Assistants/SplineAssistant.cc b/plugins/assistants/Assistants/SplineAssistant.cc index 3ad566d5b3..7755f38b2e 100644 --- a/plugins/assistants/Assistants/SplineAssistant.cc +++ b/plugins/assistants/Assistants/SplineAssistant.cc @@ -1,238 +1,239 @@ /* * Copyright (c) 2008 Cyrille Berger * Copyright (c) 2010 Geoffry Song * Copyright (c) 2017 Scott Petrovic * * 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. + * the Free Software Foundation; 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 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 "SplineAssistant.h" #include #include #include #include #include #include #include "kis_debug.h" #include #include #include SplineAssistant::SplineAssistant() : KisPaintingAssistant("spline", i18n("Spline assistant")) { } SplineAssistant::SplineAssistant(const SplineAssistant &rhs, QMap &handleMap) : KisPaintingAssistant(rhs, handleMap) , m_canvas(rhs.m_canvas) { } KisPaintingAssistantSP SplineAssistant::clone(QMap &handleMap) const { return KisPaintingAssistantSP(new SplineAssistant(*this, handleMap)); } // parametric form of a cubic spline (B(t) = (1-t)^3 P0 + 3 (1-t)^2 t P1 + 3 (1-t) t^2 P2 + t^3 P3) inline QPointF B(qreal t, const QPointF& P0, const QPointF& P1, const QPointF& P2, const QPointF& P3) { const qreal tp = 1 - t; const qreal tp2 = tp * tp; const qreal t2 = t * t; return ( tp2 * tp) * P0 + (3 * tp2 * t ) * P1 + (3 * tp * t2) * P2 + ( t * t2) * P3; } // squared distance from a point on the spline to given point: we want to minimize this inline qreal D(qreal t, const QPointF& P0, const QPointF& P1, const QPointF& P2, const QPointF& P3, const QPointF& p) { const qreal tp = 1 - t, tp2 = tp * tp, t2 = t * t, a = tp2 * tp, b = 3 * tp2 * t, c = 3 * tp * t2, d = t * t2, x_dist = a*P0.x() + b*P1.x() + c*P2.x() + d*P3.x() - p.x(), y_dist = a*P0.y() + b*P1.y() + c*P2.y() + d*P3.y() - p.y(); return x_dist * x_dist + y_dist * y_dist; } QPointF SplineAssistant::project(const QPointF& pt) const { Q_ASSERT(isAssistantComplete()); // minimize d(t), but keep t in the same neighbourhood as before (unless starting a new stroke) // (this is a rather inefficient method) qreal min_t = std::numeric_limits::max(); qreal d_min_t = std::numeric_limits::max(); for (qreal t = 0; t <= 1; t += 1e-3) { qreal d_t = D(t, *handles()[0], *handles()[2], *handles()[3], *handles()[1], pt); if (d_t < d_min_t) { d_min_t = d_t; min_t = t; } } return B(min_t, *handles()[0], *handles()[2], *handles()[3], *handles()[1]); } QPointF SplineAssistant::adjustPosition(const QPointF& pt, const QPointF& /*strokeBegin*/) { return project(pt); } void SplineAssistant::drawAssistant(QPainter& gc, const QRectF& updateRect, const KisCoordinatesConverter* converter, bool cached, KisCanvas2* canvas, bool assistantVisible, bool previewVisible) { gc.save(); gc.resetTransform(); QPoint mousePos; if (canvas){ //simplest, cheapest way to get the mouse-position// mousePos= canvas->canvasWidget()->mapFromGlobal(QCursor::pos()); m_canvas = canvas; } else { //...of course, you need to have access to a canvas-widget for that.// mousePos = QCursor::pos();//this'll give an offset// dbgFile<<"canvas does not exist in spline, you may have passed arguments incorrectly:"< 1) { QTransform initialTransform = converter->documentToWidgetTransform(); // first we find the path that our point create. QPointF pts[4]; pts[0] = *handles()[0]; pts[1] = *handles()[1]; pts[2] = (handles().size() >= 3) ? (*handles()[2]) : (*handles()[0]); pts[3] = (handles().size() >= 4) ? (*handles()[3]) : (handles().size() >= 3) ? (*handles()[2]) : (*handles()[1]); gc.setTransform(initialTransform); // Draw the spline QPainterPath path; path.moveTo(pts[0]); path.cubicTo(pts[2], pts[3], pts[1]); //then we use this path to check the bounding rectangle// if (isSnappingActive() && path.boundingRect().contains(initialTransform.inverted().map(mousePos)) && previewVisible==true){ drawPreview(gc, path);//and we draw the preview. } } gc.restore(); // there is some odd rectangle that is getting rendered when there is only one point, so don't start rendering the line until after 2 // this issue only exists with this spline assistant...none of the others if (handles().size() > 2) { KisPaintingAssistant::drawAssistant(gc, updateRect, converter, cached, canvas, assistantVisible, previewVisible); } } void SplineAssistant::drawCache(QPainter& gc, const KisCoordinatesConverter *converter, bool assistantVisible) { if (assistantVisible == false || handles().size() < 2 ){ return; } QTransform initialTransform = converter->documentToWidgetTransform(); QPointF pts[4]; pts[0] = *handles()[0]; pts[1] = *handles()[1]; pts[2] = (handles().size() >= 3) ? (*handles()[2]) : (*handles()[0]); pts[3] = (handles().size() >= 4) ? (*handles()[3]) : (handles().size() >= 3) ? (*handles()[2]) : (*handles()[1]); gc.setTransform(initialTransform); { // Draw bezier handles control lines only if we are editing the assistant gc.save(); QColor assistantColor = effectiveAssistantColor(); QPen bezierlinePen(assistantColor); bezierlinePen.setStyle(Qt::DotLine); bezierlinePen.setWidth(1); if (m_canvas->paintingAssistantsDecoration()->isEditingAssistants()) { if (!isSnappingActive()) { QColor snappingColor = assistantColor; snappingColor.setAlpha(snappingColor.alpha() * 0.2); bezierlinePen.setColor(snappingColor); } gc.setPen(bezierlinePen); gc.drawLine(pts[0], pts[2]); if (isAssistantComplete()) { gc.drawLine(pts[1], pts[3]); } gc.setPen(QColor(0, 0, 0, 125)); } gc.restore(); } // Draw the spline QPainterPath path; path.moveTo(pts[0]); path.cubicTo(pts[2], pts[3], pts[1]); drawPath(gc, path, isSnappingActive()); } QPointF SplineAssistant::buttonPosition() const { return B(0.5, *handles()[0], *handles()[2], *handles()[3], *handles()[1]); } bool SplineAssistant::isAssistantComplete() const { return handles().size() >= 4; // specify 4 corners to make assistant complete } SplineAssistantFactory::SplineAssistantFactory() { } SplineAssistantFactory::~SplineAssistantFactory() { } QString SplineAssistantFactory::id() const { return "spline"; } QString SplineAssistantFactory::name() const { return i18n("Spline"); } KisPaintingAssistant* SplineAssistantFactory::createPaintingAssistant() const { return new SplineAssistant; } diff --git a/plugins/assistants/Assistants/SplineAssistant.h b/plugins/assistants/Assistants/SplineAssistant.h index bda76ac790..0084a3be80 100644 --- a/plugins/assistants/Assistants/SplineAssistant.h +++ b/plugins/assistants/Assistants/SplineAssistant.h @@ -1,57 +1,58 @@ /* * Copyright (c) 2008 Cyrille Berger * Copyright (c) 2010 Geoffry Song * Copyright (c) 2017 Scott Petrovic * * 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. + * the Free Software Foundation; 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 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 _SPLINE_ASSISTANT_H_ #define _SPLINE_ASSISTANT_H_ #include "kis_painting_assistant.h" #include class SplineAssistant : public KisPaintingAssistant { public: SplineAssistant(); KisPaintingAssistantSP clone(QMap &handleMap) const override; QPointF adjustPosition(const QPointF& point, const QPointF& strokeBegin) override; QPointF buttonPosition() const override; int numHandles() const override { return 4; } bool isAssistantComplete() const override; protected: void drawAssistant(QPainter& gc, const QRectF& updateRect, const KisCoordinatesConverter* converter, bool cached, KisCanvas2* canvas, bool assistantVisible=true, bool previewVisible=true) override; void drawCache(QPainter& gc, const KisCoordinatesConverter *converter, bool assistantVisible=true) override; private: QPointF project(const QPointF& pt) const; explicit SplineAssistant(const SplineAssistant &rhs, QMap &handleMap); /// used for getting the decoration so the bezier handles aren't drawn while editing KisCanvas2* m_canvas; }; class SplineAssistantFactory : public KisPaintingAssistantFactory { public: SplineAssistantFactory(); ~SplineAssistantFactory() override; QString id() const override; QString name() const override; KisPaintingAssistant* createPaintingAssistant() const override; }; #endif diff --git a/plugins/assistants/Assistants/VanishingPointAssistant.cc b/plugins/assistants/Assistants/VanishingPointAssistant.cc index 31f91b9637..d3af88d14c 100644 --- a/plugins/assistants/Assistants/VanishingPointAssistant.cc +++ b/plugins/assistants/Assistants/VanishingPointAssistant.cc @@ -1,317 +1,318 @@ /* * Copyright (c) 2008 Cyrille Berger * Copyright (c) 2010 Geoffry Song * Copyright (c) 2014 Wolthera van Hövell tot Westerflier * Copyright (c) 2017 Scott Petrovic * * 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. + * the Free Software Foundation; 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 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 "VanishingPointAssistant.h" #include "kis_debug.h" #include #include #include #include #include #include #include #include #include VanishingPointAssistant::VanishingPointAssistant() : KisPaintingAssistant("vanishing point", i18n("Vanishing Point assistant")) { } VanishingPointAssistant::VanishingPointAssistant(const VanishingPointAssistant &rhs, QMap &handleMap) : KisPaintingAssistant(rhs, handleMap) , m_canvas(rhs.m_canvas) , m_referenceLineDensity(rhs.m_referenceLineDensity) { } KisPaintingAssistantSP VanishingPointAssistant::clone(QMap &handleMap) const { return KisPaintingAssistantSP(new VanishingPointAssistant(*this, handleMap)); } QPointF VanishingPointAssistant::project(const QPointF& pt, const QPointF& strokeBegin) { //Q_ASSERT(handles().size() == 1 || handles().size() == 5); //code nicked from the perspective ruler. qreal dx = pt.x() - strokeBegin.x(); qreal dy = pt.y() - strokeBegin.y(); if (dx * dx + dy * dy < 4.0) { // allow some movement before snapping return strokeBegin; } //dbgKrita<canvasWidget()->mapFromGlobal(QCursor::pos()); m_canvas = canvas; } else { //...of course, you need to have access to a canvas-widget for that.// mousePos = QCursor::pos();//this'll give an offset// dbgFile<<"canvas does not exist in ruler, you may have passed arguments incorrectly:"<paintingAssistantsDecoration()->isEditingAssistants() == false && isAssistantComplete()) { if (isSnappingActive() && previewVisible == true) { //don't draw if invalid. QTransform initialTransform = converter->documentToWidgetTransform(); QPointF startPoint = initialTransform.map(*handles()[0]); QLineF snapLine= QLineF(startPoint, mousePos); QRect viewport= gc.viewport(); KisAlgebra2D::intersectLineRect(snapLine, viewport); QRect bounds= QRect(snapLine.p1().toPoint(), snapLine.p2().toPoint()); QPainterPath path; if (bounds.contains(startPoint.toPoint())){ path.moveTo(startPoint); path.lineTo(snapLine.p1()); } else { path.moveTo(snapLine.p1()); path.lineTo(snapLine.p2()); } drawPreview(gc, path);//and we draw the preview. } } // editor specific controls display if (canvas->paintingAssistantsDecoration()->isEditingAssistants()) { // draws a circle around the vanishing point node while editing QTransform initialTransform = converter->documentToWidgetTransform(); QPointF p0 = initialTransform.map(*handles()[0]); // main vanishing point QPointF p1 = initialTransform.map(*sideHandles()[0]); QPointF p2 = initialTransform.map(*sideHandles()[1]); QPointF p3 = initialTransform.map(*sideHandles()[2]); QPointF p4 = initialTransform.map(*sideHandles()[3]); QRectF ellipse = QRectF(QPointF(p0.x() -15, p0.y() -15), QSizeF(30, 30)); QPainterPath pathCenter; pathCenter.addEllipse(ellipse); drawPath(gc, pathCenter, isSnappingActive()); QColor paintingColor = effectiveAssistantColor(); // draw the lines connecting the different nodes QPen penStyle(paintingColor, 2.0, Qt::SolidLine); if (!isSnappingActive()) { QColor snappingColor = paintingColor; snappingColor.setAlpha(snappingColor.alpha() * 0.2); penStyle.setColor(snappingColor); } gc.save(); gc.setPen(penStyle); gc.drawLine(p0, p1); gc.drawLine(p0, p3); gc.drawLine(p1, p2); gc.drawLine(p3, p4); gc.restore(); } // draw references guide for vanishing points at specified density // this is shown as part of the preview, so don't show if preview is off if( canvas->paintingAssistantsDecoration()->outlineVisibility() && this->isSnappingActive() ) { // cycle through degrees from 0 to 180. We are doing an infinite line, so we don't need to go 360 QTransform initialTransform = converter->documentToWidgetTransform(); QPointF p0 = initialTransform.map(*handles()[0]); // main vanishing point for (int currentAngle=0; currentAngle <= 180; currentAngle = currentAngle + m_referenceLineDensity ) { // determine the correct angle based on the iteration float xPos = cos(currentAngle * M_PI / 180); float yPos = sin(currentAngle * M_PI / 180); QPointF unitAngle; unitAngle.setX(p0.x() + xPos); unitAngle.setY(p0.y() + yPos); // find point QLineF snapLine= QLineF(p0, unitAngle); QRect viewport= gc.viewport(); KisAlgebra2D::intersectLineRect(snapLine, viewport); // make a line from VP center to edge of canvas with that angle QPainterPath path; path.moveTo(snapLine.p1()); path.lineTo(snapLine.p2()); drawPreview(gc, path);//and we draw the preview. } } gc.restore(); KisPaintingAssistant::drawAssistant(gc, updateRect, converter, cached, canvas, assistantVisible, previewVisible); } void VanishingPointAssistant::drawCache(QPainter& gc, const KisCoordinatesConverter *converter, bool assistantVisible) { if (!m_canvas || !isAssistantComplete()) { return; } if (assistantVisible == false || m_canvas->paintingAssistantsDecoration()->isEditingAssistants()) { return; } QTransform initialTransform = converter->documentToWidgetTransform(); QPointF p0 = initialTransform.map(*handles()[0]); // draws an "X" QPainterPath path; path.moveTo(QPointF(p0.x() - 10.0, p0.y() - 10.0)); path.lineTo(QPointF(p0.x() + 10.0, p0.y() + 10.0)); path.moveTo(QPointF(p0.x() - 10.0, p0.y() + 10.0)); path.lineTo(QPointF(p0.x() + 10.0, p0.y() - 10.0)); drawPath(gc, path, isSnappingActive()); } QPointF VanishingPointAssistant::buttonPosition() const { return (*handles()[0]); } void VanishingPointAssistant::setReferenceLineDensity(float value) { // cannot have less than 1 degree value if (value < 1.0) { value = 1.0; } m_referenceLineDensity = value; } float VanishingPointAssistant::referenceLineDensity() { return m_referenceLineDensity; } bool VanishingPointAssistant::isAssistantComplete() const { return handles().size() > 0; // only need one point to be ready } void VanishingPointAssistant::saveCustomXml(QXmlStreamWriter* xml) { xml->writeStartElement("angleDensity"); xml->writeAttribute("value", KisDomUtils::toString( this->referenceLineDensity())); xml->writeEndElement(); } bool VanishingPointAssistant::loadCustomXml(QXmlStreamReader* xml) { if (xml && xml->name() == "angleDensity") { this->setReferenceLineDensity((float)KisDomUtils::toDouble(xml->attributes().value("value").toString())); } return true; } VanishingPointAssistantFactory::VanishingPointAssistantFactory() { } VanishingPointAssistantFactory::~VanishingPointAssistantFactory() { } QString VanishingPointAssistantFactory::id() const { return "vanishing point"; } QString VanishingPointAssistantFactory::name() const { return i18n("Vanishing Point"); } KisPaintingAssistant* VanishingPointAssistantFactory::createPaintingAssistant() const { return new VanishingPointAssistant; } diff --git a/plugins/assistants/Assistants/VanishingPointAssistant.h b/plugins/assistants/Assistants/VanishingPointAssistant.h index 48e2802aa1..3710e602bf 100644 --- a/plugins/assistants/Assistants/VanishingPointAssistant.h +++ b/plugins/assistants/Assistants/VanishingPointAssistant.h @@ -1,84 +1,85 @@ /* * Copyright (c) 2008 Cyrille Berger * Copyright (c) 2010 Geoffry Song * Copyright (c) 2014 Wolthera van Hövell tot Westerflier * Copyright (c) 2017 Scott Petrovic * * 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. + * the Free Software Foundation; 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 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 _VANISHINGPOINT_ASSISTANT_H_ #define _VANISHINGPOINT_ASSISTANT_H_ #include "kis_painting_assistant.h" #include #include #include #include /* Design: *The idea behind the vanishing point ruler is that in a perspective deformed landscape, a set of parallel *lines al share a single vanishing point. *Therefore, a perspective can contain an theoretical infinite of vanishing points. *It's a pity if we only allowed an artist to access 1, 2 or 3 of these at any given time, as other *solutions for perspective tools do. *Hence a vanishing point ruler. * *This ruler is relatively simple compared to the other perspective ruler: *It has only one vanishing point that is required to draw. *However, it does have it's own weaknesses in how to determine onto which of these infinite rulers to snap. *Furthermore, it has four extra handles for adding a perspective ruler to a preexisting perspective. */ //class VanishingPoint; class VanishingPointAssistant : public KisPaintingAssistant { public: VanishingPointAssistant(); KisPaintingAssistantSP clone(QMap &handleMap) const override; QPointF adjustPosition(const QPointF& point, const QPointF& strokeBegin) override; //virtual void endStroke(); QPointF buttonPosition() const override; int numHandles() const override { return 1; } float referenceLineDensity(); void setReferenceLineDensity(float value); bool isAssistantComplete() const override; void saveCustomXml(QXmlStreamWriter* xml) override; bool loadCustomXml(QXmlStreamReader* xml) override; protected: void drawAssistant(QPainter& gc, const QRectF& updateRect, const KisCoordinatesConverter* converter, bool cached = true,KisCanvas2* canvas=0, bool assistantVisible=true, bool previewVisible=true) override; void drawCache(QPainter& gc, const KisCoordinatesConverter *converter, bool assistantVisible=true) override; private: QPointF project(const QPointF& pt, const QPointF& strokeBegin); explicit VanishingPointAssistant(const VanishingPointAssistant &rhs, QMap &handleMap); KisCanvas2 *m_canvas; float m_referenceLineDensity = 15.0; }; class VanishingPointAssistantFactory : public KisPaintingAssistantFactory { public: VanishingPointAssistantFactory(); ~VanishingPointAssistantFactory() override; QString id() const override; QString name() const override; KisPaintingAssistant* createPaintingAssistant() const override; }; #endif diff --git a/plugins/assistants/Assistants/assistant_tool.cc b/plugins/assistants/Assistants/assistant_tool.cc index 430421d45b..69d87c8ffe 100644 --- a/plugins/assistants/Assistants/assistant_tool.cc +++ b/plugins/assistants/Assistants/assistant_tool.cc @@ -1,60 +1,61 @@ /* * 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. + * the Free Software Foundation; 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 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 "assistant_tool.h" #include "kis_assistant_tool.h" #include #include #include #include #include #include "RulerAssistant.h" #include "EllipseAssistant.h" #include "SplineAssistant.h" #include "PerspectiveAssistant.h" #include "VanishingPointAssistant.h" #include "InfiniteRulerAssistant.h" #include "ParallelRulerAssistant.h" #include "ConcentricEllipseAssistant.h" #include "FisheyePointAssistant.h" //#include "mesh_assistant.h" K_PLUGIN_FACTORY_WITH_JSON(AssistantToolFactory, "kritaassistanttool.json", registerPlugin();) AssistantToolPlugin::AssistantToolPlugin(QObject *parent, const QVariantList &) : QObject(parent) { KoToolRegistry::instance()->add(new KisAssistantToolFactory()); KisPaintingAssistantFactoryRegistry::instance()->add(new RulerAssistantFactory); KisPaintingAssistantFactoryRegistry::instance()->add(new EllipseAssistantFactory); KisPaintingAssistantFactoryRegistry::instance()->add(new SplineAssistantFactory); KisPaintingAssistantFactoryRegistry::instance()->add(new PerspectiveAssistantFactory); KisPaintingAssistantFactoryRegistry::instance()->add(new VanishingPointAssistantFactory); KisPaintingAssistantFactoryRegistry::instance()->add(new InfiniteRulerAssistantFactory); KisPaintingAssistantFactoryRegistry::instance()->add(new ParallelRulerAssistantFactory); KisPaintingAssistantFactoryRegistry::instance()->add(new ConcentricEllipseAssistantFactory); KisPaintingAssistantFactoryRegistry::instance()->add(new FisheyePointAssistantFactory); // KisPaintingAssistantFactoryRegistry::instance()->add(new MeshAssistantFactory); } AssistantToolPlugin::~AssistantToolPlugin() { } #include "assistant_tool.moc" diff --git a/plugins/assistants/Assistants/assistant_tool.h b/plugins/assistants/Assistants/assistant_tool.h index ef76fb0925..739f2a8ce2 100644 --- a/plugins/assistants/Assistants/assistant_tool.h +++ b/plugins/assistants/Assistants/assistant_tool.h @@ -1,34 +1,35 @@ /* * 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. + * the Free Software Foundation; 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 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 _RULERASSISTANTTOOL_H_ #define _RULERASSISTANTTOOL_H_ #include #include class AssistantToolPlugin : public QObject { Q_OBJECT public: AssistantToolPlugin(QObject *parent, const QVariantList &); ~AssistantToolPlugin() override; }; #endif diff --git a/plugins/assistants/Assistants/kis_assistant_tool.cc b/plugins/assistants/Assistants/kis_assistant_tool.cc index 7cd15bec72..e371b6a87b 100644 --- a/plugins/assistants/Assistants/kis_assistant_tool.cc +++ b/plugins/assistants/Assistants/kis_assistant_tool.cc @@ -1,1061 +1,1062 @@ /* * Copyright (c) 2008 Cyrille Berger * Copyright (c) 2010 Geoffry Song * Copyright (c) 2017 Scott Petrovic * * 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. + * the Free Software Foundation; 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 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 #include #include #include #include #include #include #include #include #include #include "kis_dom_utils.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "kis_global.h" #include "VanishingPointAssistant.h" #include "EditAssistantsCommand.h" #include #include KisAssistantTool::KisAssistantTool(KoCanvasBase * canvas) : KisTool(canvas, KisCursor::arrowCursor()), m_canvas(dynamic_cast(canvas)), m_assistantDrag(0), m_newAssistant(0), m_optionsWidget(0) { Q_ASSERT(m_canvas); setObjectName("tool_assistanttool"); } KisAssistantTool::~KisAssistantTool() { } void KisAssistantTool::activate(ToolActivation toolActivation, const QSet &shapes) { KisTool::activate(toolActivation, shapes); m_canvas->paintingAssistantsDecoration()->activateAssistantsEditor(); m_handles = m_canvas->paintingAssistantsDecoration()->handles(); m_handleDrag = 0; m_internalMode = MODE_CREATION; m_assistantHelperYOffset = 10; m_handleSize = 17; m_canvas->paintingAssistantsDecoration()->setHandleSize(m_handleSize); if (m_optionsWidget) { m_canvas->paintingAssistantsDecoration()->deselectAssistant(); updateToolOptionsUI(); } m_canvas->updateCanvas(); } void KisAssistantTool::deactivate() { m_canvas->paintingAssistantsDecoration()->deactivateAssistantsEditor(); m_canvas->updateCanvas(); KisTool::deactivate(); } void KisAssistantTool::beginPrimaryAction(KoPointerEvent *event) { setMode(KisTool::PAINT_MODE); m_origAssistantList = KisPaintingAssistant::cloneAssistantList(m_canvas->paintingAssistantsDecoration()->assistants()); bool newAssistantAllowed = true; KisPaintingAssistantsDecorationSP canvasDecoration = m_canvas->paintingAssistantsDecoration(); if (m_newAssistant) { m_internalMode = MODE_CREATION; *m_newAssistant->handles().back() = canvasDecoration->snapToGuide(event, QPointF(), false); if (m_newAssistant->handles().size() == m_newAssistant->numHandles()) { addAssistant(); } else { m_newAssistant->addHandle(new KisPaintingAssistantHandle(canvasDecoration->snapToGuide(event, QPointF(), false)), HandleType::NORMAL); } m_canvas->updateCanvas(); return; } m_handleDrag = 0; double minDist = 81.0; QPointF mousePos = m_canvas->viewConverter()->documentToView(canvasDecoration->snapToGuide(event, QPointF(), false));//m_canvas->viewConverter()->documentToView(event->point); // syncs the assistant handles to the handles reference we store in this tool // they can get out of sync with the way the actions and paintevents occur // we probably need to stop storing a reference in m_handles and call the assistants directly m_handles = m_canvas->paintingAssistantsDecoration()->handles(); Q_FOREACH (KisPaintingAssistantSP assistant, m_canvas->paintingAssistantsDecoration()->assistants()) { // find out which handle on all assistants is closest to the mouse position // vanishing points have "side handles", so make sure to include that { QList allAssistantHandles; allAssistantHandles.append(assistant->handles()); allAssistantHandles.append(assistant->sideHandles()); Q_FOREACH (const KisPaintingAssistantHandleSP handle, allAssistantHandles) { double dist = KisPaintingAssistant::norm2(mousePos - m_canvas->viewConverter()->documentToView(*handle)); if (dist < minDist) { minDist = dist; m_handleDrag = handle; assistantSelected(assistant); // whatever handle is the closest contains the selected assistant } } } if(m_handleDrag && assistant->id() == "perspective") { // Look for the handle which was pressed if (m_handleDrag == assistant->topLeft()) { double dist = KisPaintingAssistant::norm2(mousePos - m_canvas->viewConverter()->documentToView(*m_handleDrag)); if (dist < minDist) { minDist = dist; } m_dragStart = QPointF(assistant->topRight().data()->x(),assistant->topRight().data()->y()); m_internalMode = MODE_DRAGGING_NODE; } else if (m_handleDrag == assistant->topRight()) { double dist = KisPaintingAssistant::norm2(mousePos - m_canvas->viewConverter()->documentToView(*m_handleDrag)); if (dist < minDist) { minDist = dist; } m_internalMode = MODE_DRAGGING_NODE; m_dragStart = QPointF(assistant->topLeft().data()->x(),assistant->topLeft().data()->y()); } else if (m_handleDrag == assistant->bottomLeft()) { double dist = KisPaintingAssistant::norm2(mousePos - m_canvas->viewConverter()->documentToView(*m_handleDrag)); if (dist < minDist) { minDist = dist; } m_internalMode = MODE_DRAGGING_NODE; m_dragStart = QPointF(assistant->bottomRight().data()->x(),assistant->bottomRight().data()->y()); } else if (m_handleDrag == assistant->bottomRight()) { double dist = KisPaintingAssistant::norm2(mousePos - m_canvas->viewConverter()->documentToView(*m_handleDrag)); if (dist < minDist) { minDist = dist; } m_internalMode = MODE_DRAGGING_NODE; m_dragStart = QPointF(assistant->bottomLeft().data()->x(),assistant->bottomLeft().data()->y()); } else if (m_handleDrag == assistant->leftMiddle()) { m_internalMode = MODE_DRAGGING_TRANSLATING_TWONODES; m_dragStart = QPointF((assistant->bottomLeft().data()->x()+assistant->topLeft().data()->x())*0.5, (assistant->bottomLeft().data()->y()+assistant->topLeft().data()->y())*0.5); m_selectedNode1 = new KisPaintingAssistantHandle(assistant->topLeft().data()->x(),assistant->topLeft().data()->y()); m_selectedNode2 = new KisPaintingAssistantHandle(assistant->bottomLeft().data()->x(),assistant->bottomLeft().data()->y()); m_newAssistant = toQShared(KisPaintingAssistantFactoryRegistry::instance()->get("perspective")->createPaintingAssistant()); m_newAssistant->addHandle(assistant->topLeft(), HandleType::NORMAL ); m_newAssistant->addHandle(m_selectedNode1, HandleType::NORMAL); m_newAssistant->addHandle(m_selectedNode2, HandleType::NORMAL); m_newAssistant->addHandle(assistant->bottomLeft(), HandleType::NORMAL); m_dragEnd = event->point; m_handleDrag = 0; m_canvas->updateCanvas(); // TODO update only the relevant part of the canvas return; } else if (m_handleDrag == assistant->rightMiddle()) { m_dragStart = QPointF((assistant->topRight().data()->x()+assistant->bottomRight().data()->x())*0.5, (assistant->topRight().data()->y()+assistant->bottomRight().data()->y())*0.5); m_internalMode = MODE_DRAGGING_TRANSLATING_TWONODES; m_selectedNode1 = new KisPaintingAssistantHandle(assistant->topRight().data()->x(),assistant->topRight().data()->y()); m_selectedNode2 = new KisPaintingAssistantHandle(assistant->bottomRight().data()->x(),assistant->bottomRight().data()->y()); m_newAssistant = toQShared(KisPaintingAssistantFactoryRegistry::instance()->get("perspective")->createPaintingAssistant()); m_newAssistant->addHandle(assistant->topRight(), HandleType::NORMAL); m_newAssistant->addHandle(m_selectedNode1, HandleType::NORMAL); m_newAssistant->addHandle(m_selectedNode2, HandleType::NORMAL); m_newAssistant->addHandle(assistant->bottomRight(), HandleType::NORMAL); m_dragEnd = event->point; m_handleDrag = 0; m_canvas->updateCanvas(); // TODO update only the relevant part of the canvas return; } else if (m_handleDrag == assistant->topMiddle()) { m_dragStart = QPointF((assistant->topLeft().data()->x()+assistant->topRight().data()->x())*0.5, (assistant->topLeft().data()->y()+assistant->topRight().data()->y())*0.5); m_internalMode = MODE_DRAGGING_TRANSLATING_TWONODES; m_selectedNode1 = new KisPaintingAssistantHandle(assistant->topLeft().data()->x(),assistant->topLeft().data()->y()); m_selectedNode2 = new KisPaintingAssistantHandle(assistant->topRight().data()->x(),assistant->topRight().data()->y()); m_newAssistant = toQShared(KisPaintingAssistantFactoryRegistry::instance()->get("perspective")->createPaintingAssistant()); m_newAssistant->addHandle(m_selectedNode1, HandleType::NORMAL); m_newAssistant->addHandle(m_selectedNode2, HandleType::NORMAL); m_newAssistant->addHandle(assistant->topRight(), HandleType::NORMAL); m_newAssistant->addHandle(assistant->topLeft(), HandleType::NORMAL); m_dragEnd = event->point; m_handleDrag = 0; m_canvas->updateCanvas(); // TODO update only the relevant part of the canvas return; } else if (m_handleDrag == assistant->bottomMiddle()) { m_dragStart = QPointF((assistant->bottomLeft().data()->x()+assistant->bottomRight().data()->x())*0.5, (assistant->bottomLeft().data()->y()+assistant->bottomRight().data()->y())*0.5); m_internalMode = MODE_DRAGGING_TRANSLATING_TWONODES; m_selectedNode1 = new KisPaintingAssistantHandle(assistant->bottomLeft().data()->x(),assistant->bottomLeft().data()->y()); m_selectedNode2 = new KisPaintingAssistantHandle(assistant->bottomRight().data()->x(),assistant->bottomRight().data()->y()); m_newAssistant = toQShared(KisPaintingAssistantFactoryRegistry::instance()->get("perspective")->createPaintingAssistant()); m_newAssistant->addHandle(assistant->bottomLeft(), HandleType::NORMAL); m_newAssistant->addHandle(assistant->bottomRight(), HandleType::NORMAL); m_newAssistant->addHandle(m_selectedNode2, HandleType::NORMAL); m_newAssistant->addHandle(m_selectedNode1, HandleType::NORMAL); m_dragEnd = event->point; m_handleDrag = 0; m_canvas->updateCanvas(); // TODO update only the relevant part of the canvas return; } m_snapIsRadial = false; } else if (m_handleDrag && assistant->handles().size()>1 && (assistant->id() == "ruler" || assistant->id() == "parallel ruler" || assistant->id() == "infinite ruler" || assistant->id() == "spline")){ if (m_handleDrag == assistant->handles()[0]) { m_dragStart = *assistant->handles()[1]; } else if (m_handleDrag == assistant->handles()[1]) { m_dragStart = *assistant->handles()[0]; } else if(assistant->handles().size()==4){ if (m_handleDrag == assistant->handles()[2]) { m_dragStart = *assistant->handles()[0]; } else if (m_handleDrag == assistant->handles()[3]) { m_dragStart = *assistant->handles()[1]; } } m_snapIsRadial = false; } else if (m_handleDrag && assistant->handles().size()>2 && (assistant->id() == "ellipse" || assistant->id() == "concentric ellipse" || assistant->id() == "fisheye-point")){ m_snapIsRadial = false; if (m_handleDrag == assistant->handles()[0]) { m_dragStart = *assistant->handles()[1]; } else if (m_handleDrag == assistant->handles()[1]) { m_dragStart = *assistant->handles()[0]; } else if (m_handleDrag == assistant->handles()[2]) { m_dragStart = assistant->buttonPosition(); m_radius = QLineF(m_dragStart, *assistant->handles()[0]); m_snapIsRadial = true; } } else { m_dragStart = assistant->buttonPosition(); m_snapIsRadial = false; } } if (m_handleDrag) { // TODO: Shift-press should now be handled using the alternate actions // if (event->modifiers() & Qt::ShiftModifier) { // m_handleDrag->uncache(); // m_handleDrag = m_handleDrag->split()[0]; // m_handles = m_canvas->view()->paintingAssistantsDecoration()->handles(); // } m_canvas->updateCanvas(); // TODO update only the relevant part of the canvas return; } m_assistantDrag.clear(); Q_FOREACH (KisPaintingAssistantSP assistant, m_canvas->paintingAssistantsDecoration()->assistants()) { // This code contains the click event behavior. QTransform initialTransform = m_canvas->coordinatesConverter()->documentToWidgetTransform(); QPointF actionsPosition = initialTransform.map(assistant->buttonPosition()); // for UI editor widget controls with move, show, and delete -- disregard document transforms like rotating and mirroring. // otherwise the UI controls get awkward to use when they are at 45 degree angles or the order of controls gets flipped backwards QPointF uiMousePosition = initialTransform.map( canvasDecoration->snapToGuide(event, QPointF(), false)); AssistantEditorData editorShared; // shared position data between assistant tool and decoration QPointF iconMovePosition(actionsPosition + editorShared.moveIconPosition); QPointF iconSnapPosition(actionsPosition + editorShared.snapIconPosition); QPointF iconDeletePosition(actionsPosition + editorShared.deleteIconPosition); QRectF deleteRect(iconDeletePosition, QSizeF(editorShared.deleteIconSize, editorShared.deleteIconSize)); QRectF visibleRect(iconSnapPosition, QSizeF(editorShared.snapIconSize, editorShared.snapIconSize)); QRectF moveRect(iconMovePosition, QSizeF(editorShared.moveIconSize, editorShared.moveIconSize)); if (moveRect.contains(uiMousePosition)) { m_assistantDrag = assistant; m_cursorStart = event->point; m_currentAdjustment = QPointF(); m_internalMode = MODE_EDITING; assistantSelected(assistant); // whatever handle is the closest contains the selected assistant return; } if (deleteRect.contains(uiMousePosition)) { removeAssistant(assistant); if(m_canvas->paintingAssistantsDecoration()->assistants().isEmpty()) { m_internalMode = MODE_CREATION; } else m_internalMode = MODE_EDITING; m_canvas->updateCanvas(); return; } if (visibleRect.contains(uiMousePosition)) { newAssistantAllowed = false; assistant->setSnappingActive(!assistant->isSnappingActive()); // toggle assistant->uncache();//this updates the chache of the assistant, very important. assistantSelected(assistant); // whatever handle is the closest contains the selected assistant } } if (newAssistantAllowed==true){//don't make a new assistant when I'm just toogling visibility// QString key = m_options.availableAssistantsComboBox->model()->index( m_options.availableAssistantsComboBox->currentIndex(), 0 ).data(Qt::UserRole).toString(); m_newAssistant = toQShared(KisPaintingAssistantFactoryRegistry::instance()->get(key)->createPaintingAssistant()); m_internalMode = MODE_CREATION; m_newAssistant->addHandle(new KisPaintingAssistantHandle(canvasDecoration->snapToGuide(event, QPointF(), false)), HandleType::NORMAL); if (m_newAssistant->numHandles() <= 1) { addAssistant(); } else { m_newAssistant->addHandle(new KisPaintingAssistantHandle(canvasDecoration->snapToGuide(event, QPointF(), false)), HandleType::NORMAL); } } if (m_newAssistant) { m_newAssistant->setAssistantGlobalColorCache(m_canvas->paintingAssistantsDecoration()->globalAssistantsColor()); } m_canvas->updateCanvas(); } void KisAssistantTool::continuePrimaryAction(KoPointerEvent *event) { KisPaintingAssistantsDecorationSP canvasDecoration = m_canvas->paintingAssistantsDecoration(); if (m_handleDrag) { *m_handleDrag = event->point; //ported from the gradient tool... we need to think about this more in the future. if (event->modifiers() == Qt::ShiftModifier && m_snapIsRadial) { QLineF dragRadius = QLineF(m_dragStart, event->point); dragRadius.setLength(m_radius.length()); *m_handleDrag = dragRadius.p2(); } else if (event->modifiers() == Qt::ShiftModifier ) { QPointF move = snapToClosestAxis(event->point - m_dragStart); *m_handleDrag = m_dragStart + move; } else { *m_handleDrag = canvasDecoration->snapToGuide(event, QPointF(), false); } m_handleDrag->uncache(); m_handleCombine = 0; if (!(event->modifiers() & Qt::ShiftModifier)) { double minDist = 49.0; QPointF mousePos = m_canvas->viewConverter()->documentToView(event->point); Q_FOREACH (const KisPaintingAssistantHandleSP handle, m_handles) { if (handle == m_handleDrag) continue; double dist = KisPaintingAssistant::norm2(mousePos - m_canvas->viewConverter()->documentToView(*handle)); if (dist < minDist) { minDist = dist; m_handleCombine = handle; } } } m_canvas->updateCanvas(); } else if (m_assistantDrag) { QPointF newAdjustment = canvasDecoration->snapToGuide(event, QPointF(), false) - m_cursorStart; if (event->modifiers() == Qt::ShiftModifier ) { newAdjustment = snapToClosestAxis(newAdjustment); } Q_FOREACH (KisPaintingAssistantHandleSP handle, m_assistantDrag->handles()) { *handle += (newAdjustment - m_currentAdjustment); } if (m_assistantDrag->id()== "vanishing point"){ Q_FOREACH (KisPaintingAssistantHandleSP handle, m_assistantDrag->sideHandles()) { *handle += (newAdjustment - m_currentAdjustment); } } m_currentAdjustment = newAdjustment; m_canvas->updateCanvas(); } else { event->ignore(); } bool wasHiglightedNode = m_higlightedNode != 0; QPointF mousep = m_canvas->viewConverter()->documentToView(event->point); QList pAssistant= m_canvas->paintingAssistantsDecoration()->assistants(); Q_FOREACH (KisPaintingAssistantSP assistant, pAssistant) { if(assistant->id() == "perspective") { if ((m_higlightedNode = assistant->closestCornerHandleFromPoint(mousep))) { if (m_higlightedNode == m_selectedNode1 || m_higlightedNode == m_selectedNode2) { m_higlightedNode = 0; } else { m_canvas->updateCanvas(); // TODO update only the relevant part of the canvas break; } } } //this following bit sets the translations for the vanishing-point handles. if(m_handleDrag && assistant->id() == "vanishing point" && assistant->sideHandles().size()==4) { //for inner handles, the outer handle gets translated. if (m_handleDrag == assistant->sideHandles()[0]) { QLineF perspectiveline = QLineF(*assistant->handles()[0], *assistant->sideHandles()[0]); qreal length = QLineF(*assistant->sideHandles()[0], *assistant->sideHandles()[1]).length(); if (length < 2.0){ length = 2.0; } length += perspectiveline.length(); perspectiveline.setLength(length); *assistant->sideHandles()[1] = perspectiveline.p2(); } else if (m_handleDrag == assistant->sideHandles()[2]){ QLineF perspectiveline = QLineF(*assistant->handles()[0], *assistant->sideHandles()[2]); qreal length = QLineF(*assistant->sideHandles()[2], *assistant->sideHandles()[3]).length(); if (length<2.0){ length=2.0; } length += perspectiveline.length(); perspectiveline.setLength(length); *assistant->sideHandles()[3] = perspectiveline.p2(); } // for outer handles, only the vanishing point is translated, but only if there's an intersection. else if (m_handleDrag == assistant->sideHandles()[1]|| m_handleDrag == assistant->sideHandles()[3]){ QPointF vanishingpoint(0,0); QLineF perspectiveline = QLineF(*assistant->sideHandles()[0], *assistant->sideHandles()[1]); QLineF perspectiveline2 = QLineF(*assistant->sideHandles()[2], *assistant->sideHandles()[3]); if (QLineF(perspectiveline2).intersect(QLineF(perspectiveline), &vanishingpoint) != QLineF::NoIntersection){ *assistant->handles()[0] = vanishingpoint; } }// and for the vanishing point itself, only the outer handles get translated. else if (m_handleDrag == assistant->handles()[0]){ QLineF perspectiveline = QLineF(*assistant->handles()[0], *assistant->sideHandles()[0]); QLineF perspectiveline2 = QLineF(*assistant->handles()[0], *assistant->sideHandles()[2]); qreal length = QLineF(*assistant->sideHandles()[0], *assistant->sideHandles()[1]).length(); qreal length2 = QLineF(*assistant->sideHandles()[2], *assistant->sideHandles()[3]).length(); if (length < 2.0) { length = 2.0; } if (length2 < 2.0) { length2=2.0; } length += perspectiveline.length(); length2 += perspectiveline2.length(); perspectiveline.setLength(length); perspectiveline2.setLength(length2); *assistant->sideHandles()[1] = perspectiveline.p2(); *assistant->sideHandles()[3] = perspectiveline2.p2(); } } } if (wasHiglightedNode && !m_higlightedNode) { m_canvas->updateCanvas(); // TODO update only the relevant part of the canvas } } void KisAssistantTool::endPrimaryAction(KoPointerEvent *event) { setMode(KisTool::HOVER_MODE); if (m_handleDrag || m_assistantDrag) { if (m_handleDrag) { if (!(event->modifiers() & Qt::ShiftModifier) && m_handleCombine) { m_handleCombine->mergeWith(m_handleDrag); m_handleCombine->uncache(); m_handles = m_canvas->paintingAssistantsDecoration()->handles(); } m_handleDrag = m_handleCombine = 0; } else { m_assistantDrag.clear(); } dbgUI << "creating undo command..."; KUndo2Command *command = new EditAssistantsCommand(m_canvas, m_origAssistantList, KisPaintingAssistant::cloneAssistantList(m_canvas->paintingAssistantsDecoration()->assistants())); m_canvas->viewManager()->undoAdapter()->addCommand(command); dbgUI << "done"; } else if(m_internalMode == MODE_DRAGGING_TRANSLATING_TWONODES) { addAssistant(); m_internalMode = MODE_CREATION; } else { event->ignore(); } m_canvas->updateCanvas(); // TODO update only the relevant part of the canvas } void KisAssistantTool::addAssistant() { m_canvas->paintingAssistantsDecoration()->addAssistant(m_newAssistant); KisAbstractPerspectiveGrid* grid = dynamic_cast(m_newAssistant.data()); if (grid) { m_canvas->viewManager()->canvasResourceProvider()->addPerspectiveGrid(grid); } QList assistants = m_canvas->paintingAssistantsDecoration()->assistants(); KUndo2Command *addAssistantCmd = new EditAssistantsCommand(m_canvas, m_origAssistantList, KisPaintingAssistant::cloneAssistantList(assistants), EditAssistantsCommand::ADD, assistants.indexOf(m_newAssistant)); m_canvas->viewManager()->undoAdapter()->addCommand(addAssistantCmd); m_handles = m_canvas->paintingAssistantsDecoration()->handles(); m_canvas->paintingAssistantsDecoration()->setSelectedAssistant(m_newAssistant); updateToolOptionsUI(); // vanishing point assistant will get an extra option m_newAssistant.clear(); } void KisAssistantTool::removeAssistant(KisPaintingAssistantSP assistant) { QList assistants = m_canvas->paintingAssistantsDecoration()->assistants(); KisAbstractPerspectiveGrid* grid = dynamic_cast(assistant.data()); if (grid) { m_canvas->viewManager()->canvasResourceProvider()->removePerspectiveGrid(grid); } m_canvas->paintingAssistantsDecoration()->removeAssistant(assistant); KUndo2Command *removeAssistantCmd = new EditAssistantsCommand(m_canvas, m_origAssistantList, KisPaintingAssistant::cloneAssistantList(m_canvas->paintingAssistantsDecoration()->assistants()), EditAssistantsCommand::REMOVE, assistants.indexOf(assistant)); m_canvas->viewManager()->undoAdapter()->addCommand(removeAssistantCmd); m_handles = m_canvas->paintingAssistantsDecoration()->handles(); m_canvas->paintingAssistantsDecoration()->deselectAssistant(); updateToolOptionsUI(); } void KisAssistantTool::assistantSelected(KisPaintingAssistantSP assistant) { m_canvas->paintingAssistantsDecoration()->setSelectedAssistant(assistant); updateToolOptionsUI(); } void KisAssistantTool::updateToolOptionsUI() { KisPaintingAssistantSP m_selectedAssistant = m_canvas->paintingAssistantsDecoration()->selectedAssistant(); bool hasActiveAssistant = m_selectedAssistant ? true : false; if (m_selectedAssistant) { bool isVanishingPointAssistant = m_selectedAssistant->id() == "vanishing point"; m_options.vanishingPointAngleSpinbox->setVisible(isVanishingPointAssistant); if (isVanishingPointAssistant) { QSharedPointer assis = qSharedPointerCast(m_selectedAssistant); m_options.vanishingPointAngleSpinbox->setValue(assis->referenceLineDensity()); } // load custom color settings from assistant (this happens when changing assistant m_options.useCustomAssistantColor->setChecked(m_selectedAssistant->useCustomColor()); m_options.customAssistantColorButton->setColor(m_selectedAssistant->assistantCustomColor()); float opacity = (float)m_selectedAssistant->assistantCustomColor().alpha()/255.0 * 100.0 ; m_options.customColorOpacitySlider->setValue(opacity); } else { m_options.vanishingPointAngleSpinbox->setVisible(false); // } // show/hide elements if an assistant is selected or not m_options.assistantsGlobalOpacitySlider->setVisible(hasActiveAssistant); m_options.assistantsColor->setVisible(hasActiveAssistant); m_options.globalColorLabel->setVisible(hasActiveAssistant); m_options.useCustomAssistantColor->setVisible(hasActiveAssistant); // hide custom color options if use custom color is not selected bool showCustomColorSettings = m_options.useCustomAssistantColor->isChecked() && hasActiveAssistant; m_options.customColorOpacitySlider->setVisible(showCustomColorSettings); m_options.customAssistantColorButton->setVisible(showCustomColorSettings); // disable global color settings if we are using the custom color m_options.assistantsGlobalOpacitySlider->setEnabled(!showCustomColorSettings); m_options.assistantsColor->setEnabled(!showCustomColorSettings); m_options.globalColorLabel->setEnabled(!showCustomColorSettings); } void KisAssistantTool::slotChangeVanishingPointAngle(double value) { if ( m_canvas->paintingAssistantsDecoration()->assistants().length() == 0) { return; } // get the selected assistant and change the angle value KisPaintingAssistantSP m_selectedAssistant = m_canvas->paintingAssistantsDecoration()->selectedAssistant(); if (m_selectedAssistant) { bool isVanishingPointAssistant = m_selectedAssistant->id() == "vanishing point"; if (isVanishingPointAssistant) { QSharedPointer assis = qSharedPointerCast(m_selectedAssistant); assis->setReferenceLineDensity((float)value); } } m_canvas->canvasWidget()->update(); } void KisAssistantTool::mouseMoveEvent(KoPointerEvent *event) { if (m_newAssistant && m_internalMode == MODE_CREATION) { *m_newAssistant->handles().back() = event->point; } else if (m_newAssistant && m_internalMode == MODE_DRAGGING_TRANSLATING_TWONODES) { QPointF translate = event->point - m_dragEnd; m_dragEnd = event->point; m_selectedNode1.data()->operator = (QPointF(m_selectedNode1.data()->x(),m_selectedNode1.data()->y()) + translate); m_selectedNode2.data()->operator = (QPointF(m_selectedNode2.data()->x(),m_selectedNode2.data()->y()) + translate); } m_canvas->updateCanvas(); } void KisAssistantTool::paint(QPainter& _gc, const KoViewConverter &_converter) { QRectF canvasSize = QRectF(QPointF(0, 0), QSizeF(m_canvas->image()->size())); // show special display while a new assistant is in the process of being created if (m_newAssistant) { QColor assistantColor = m_newAssistant->effectiveAssistantColor(); assistantColor.setAlpha(80); m_newAssistant->drawAssistant(_gc, canvasSize, m_canvas->coordinatesConverter(), false, m_canvas, true, false); Q_FOREACH (const KisPaintingAssistantHandleSP handle, m_newAssistant->handles()) { QPainterPath path; path.addEllipse(QRectF(_converter.documentToView(*handle) - QPointF(m_handleSize * 0.5, m_handleSize * 0.5), QSizeF(m_handleSize, m_handleSize))); _gc.save(); _gc.setPen(Qt::NoPen); _gc.setBrush(assistantColor); _gc.drawPath(path); _gc.restore(); } } Q_FOREACH (KisPaintingAssistantSP assistant, m_canvas->paintingAssistantsDecoration()->assistants()) { QColor assistantColor = assistant->effectiveAssistantColor(); assistantColor.setAlpha(80); Q_FOREACH (const KisPaintingAssistantHandleSP handle, m_handles) { QRectF ellipse(_converter.documentToView(*handle) - QPointF(m_handleSize * 0.5, m_handleSize * 0.5), QSizeF(m_handleSize, m_handleSize)); // render handles differently if it is the one being dragged. if (handle == m_handleDrag || handle == m_handleCombine) { QPen stroke(assistantColor, 4); _gc.save(); _gc.setPen(stroke); _gc.setBrush(Qt::NoBrush); _gc.drawEllipse(ellipse); _gc.restore(); } } } } void KisAssistantTool::removeAllAssistants() { m_canvas->viewManager()->canvasResourceProvider()->clearPerspectiveGrids(); m_canvas->paintingAssistantsDecoration()->removeAll(); m_handles = m_canvas->paintingAssistantsDecoration()->handles(); m_canvas->updateCanvas(); m_canvas->paintingAssistantsDecoration()->deselectAssistant(); updateToolOptionsUI(); } void KisAssistantTool::loadAssistants() { KoFileDialog dialog(m_canvas->viewManager()->mainWindow(), KoFileDialog::OpenFile, "OpenAssistant"); dialog.setCaption(i18n("Select an Assistant")); dialog.setDefaultDir(QStandardPaths::writableLocation(QStandardPaths::PicturesLocation)); dialog.setMimeTypeFilters(QStringList() << "application/x-krita-assistant", "application/x-krita-assistant"); QString filename = dialog.filename(); if (filename.isEmpty()) return; if (!QFileInfo(filename).exists()) return; QFile file(filename); file.open(QIODevice::ReadOnly); QByteArray data = file.readAll(); QXmlStreamReader xml(data); QMap handleMap; KisPaintingAssistantSP assistant; bool errors = false; while (!xml.atEnd()) { switch (xml.readNext()) { case QXmlStreamReader::StartElement: if (xml.name() == "handle") { if (assistant && !xml.attributes().value("ref").isEmpty()) { KisPaintingAssistantHandleSP handle = handleMap.value(xml.attributes().value("ref").toString().toInt()); if (handle) { assistant->addHandle(handle, HandleType::NORMAL); } else { errors = true; } } else { QString strId = xml.attributes().value("id").toString(), strX = xml.attributes().value("x").toString(), strY = xml.attributes().value("y").toString(); if (!strId.isEmpty() && !strX.isEmpty() && !strY.isEmpty()) { int id = strId.toInt(); double x = strX.toDouble(), y = strY.toDouble(); if (!handleMap.contains(id)) { handleMap.insert(id, new KisPaintingAssistantHandle(x, y)); } else { errors = true; } } else { errors = true; } } } else if (xml.name() == "assistant") { const KisPaintingAssistantFactory* factory = KisPaintingAssistantFactoryRegistry::instance()->get(xml.attributes().value("type").toString()); if (factory) { if (assistant) { errors = true; assistant.clear(); } assistant = toQShared(factory->createPaintingAssistant()); } else { errors = true; } // load custom shared assistant properties if ( xml.attributes().hasAttribute("useCustomColor")) { QStringRef useCustomColor = xml.attributes().value("useCustomColor"); bool usingColor = false; if (useCustomColor.toString() == "1") { usingColor = true; } assistant->setUseCustomColor(usingColor); } if ( xml.attributes().hasAttribute("useCustomColor")) { QStringRef customColor = xml.attributes().value("customColor"); assistant->setAssistantCustomColor( KisDomUtils::qStringToQColor(customColor.toString()) ); } } if (assistant) { assistant->loadCustomXml(&xml); } break; case QXmlStreamReader::EndElement: if (xml.name() == "assistant") { if (assistant) { if (assistant->handles().size() == assistant->numHandles()) { if (assistant->id() == "vanishing point"){ //ideally we'd save and load side-handles as well, but this is all I've got// QPointF pos = *assistant->handles()[0]; assistant->addHandle(new KisPaintingAssistantHandle(pos+QPointF(-70,0)), HandleType::SIDE); assistant->addHandle(new KisPaintingAssistantHandle(pos+QPointF(-140,0)), HandleType::SIDE); assistant->addHandle(new KisPaintingAssistantHandle(pos+QPointF(70,0)), HandleType::SIDE); assistant->addHandle(new KisPaintingAssistantHandle(pos+QPointF(140,0)), HandleType::SIDE); } m_canvas->paintingAssistantsDecoration()->addAssistant(assistant); KisAbstractPerspectiveGrid* grid = dynamic_cast(assistant.data()); if (grid) { m_canvas->viewManager()->canvasResourceProvider()->addPerspectiveGrid(grid); } } else { errors = true; } assistant.clear(); } } break; default: break; } } if (assistant) { errors = true; assistant.clear(); } if (xml.hasError()) { QMessageBox::warning(0, i18nc("@title:window", "Krita"), xml.errorString()); } if (errors) { QMessageBox::warning(0, i18nc("@title:window", "Krita"), i18n("Errors were encountered. Not all assistants were successfully loaded.")); } m_handles = m_canvas->paintingAssistantsDecoration()->handles(); m_canvas->updateCanvas(); } void KisAssistantTool::saveAssistants() { if (m_handles.isEmpty()) return; QByteArray data; QXmlStreamWriter xml(&data); xml.writeStartDocument(); xml.writeStartElement("paintingassistant"); xml.writeAttribute("color", KisDomUtils::qColorToQString( m_canvas->paintingAssistantsDecoration()->globalAssistantsColor())); // global color if no custom color used xml.writeStartElement("handles"); QMap handleMap; Q_FOREACH (const KisPaintingAssistantHandleSP handle, m_handles) { int id = handleMap.size(); handleMap.insert(handle, id); xml.writeStartElement("handle"); //xml.writeAttribute("type", handle->handleType()); xml.writeAttribute("id", QString::number(id)); xml.writeAttribute("x", QString::number(double(handle->x()), 'f', 3)); xml.writeAttribute("y", QString::number(double(handle->y()), 'f', 3)); xml.writeEndElement(); } xml.writeEndElement(); xml.writeStartElement("assistants"); Q_FOREACH (const KisPaintingAssistantSP assistant, m_canvas->paintingAssistantsDecoration()->assistants()) { xml.writeStartElement("assistant"); xml.writeAttribute("type", assistant->id()); xml.writeAttribute("useCustomColor", QString::number(assistant->useCustomColor())); xml.writeAttribute("customColor", KisDomUtils::qColorToQString(assistant->assistantCustomColor())); // custom assistant properties like angle density on vanishing point assistant->saveCustomXml(&xml); // handle information xml.writeStartElement("handles"); Q_FOREACH (const KisPaintingAssistantHandleSP handle, assistant->handles()) { xml.writeStartElement("handle"); xml.writeAttribute("ref", QString::number(handleMap.value(handle))); xml.writeEndElement(); } xml.writeEndElement(); xml.writeEndElement(); } xml.writeEndElement(); xml.writeEndElement(); xml.writeEndDocument(); KoFileDialog dialog(m_canvas->viewManager()->mainWindow(), KoFileDialog::SaveFile, "OpenAssistant"); dialog.setCaption(i18n("Save Assistant")); dialog.setDefaultDir(QStandardPaths::writableLocation(QStandardPaths::PicturesLocation)); dialog.setMimeTypeFilters(QStringList() << "application/x-krita-assistant", "application/x-krita-assistant"); QString filename = dialog.filename(); if (filename.isEmpty()) return; QFile file(filename); file.open(QIODevice::WriteOnly); file.write(data); } QWidget *KisAssistantTool::createOptionWidget() { if (!m_optionsWidget) { m_optionsWidget = new QWidget; m_options.setupUi(m_optionsWidget); // See https://bugs.kde.org/show_bug.cgi?id=316896 QWidget *specialSpacer = new QWidget(m_optionsWidget); specialSpacer->setObjectName("SpecialSpacer"); specialSpacer->setFixedSize(0, 0); m_optionsWidget->layout()->addWidget(specialSpacer); m_options.loadAssistantButton->setIcon(KisIconUtils::loadIcon("document-open")); m_options.saveAssistantButton->setIcon(KisIconUtils::loadIcon("document-save")); m_options.deleteAllAssistantsButton->setIcon(KisIconUtils::loadIcon("edit-delete")); QList assistants; Q_FOREACH (const QString& key, KisPaintingAssistantFactoryRegistry::instance()->keys()) { QString name = KisPaintingAssistantFactoryRegistry::instance()->get(key)->name(); assistants << KoID(key, name); } std::sort(assistants.begin(), assistants.end(), KoID::compareNames); Q_FOREACH(const KoID &id, assistants) { m_options.availableAssistantsComboBox->addItem(id.name(), id.id()); } connect(m_options.saveAssistantButton, SIGNAL(clicked()), SLOT(saveAssistants())); connect(m_options.loadAssistantButton, SIGNAL(clicked()), SLOT(loadAssistants())); connect(m_options.deleteAllAssistantsButton, SIGNAL(clicked()), SLOT(removeAllAssistants())); connect(m_options.assistantsColor, SIGNAL(changed(QColor)), SLOT(slotGlobalAssistantsColorChanged(QColor))); connect(m_options.assistantsGlobalOpacitySlider, SIGNAL(valueChanged(int)), SLOT(slotGlobalAssistantOpacityChanged())); connect(m_options.vanishingPointAngleSpinbox, SIGNAL(valueChanged(double)), this, SLOT(slotChangeVanishingPointAngle(double))); //ENTER_FUNCTION() << ppVar(m_canvas) << ppVar(m_canvas && m_canvas->paintingAssistantsDecoration()); // initialize UI elements with existing data if possible if (m_canvas && m_canvas->paintingAssistantsDecoration()) { const QColor color = m_canvas->paintingAssistantsDecoration()->globalAssistantsColor(); QColor opaqueColor = color; opaqueColor.setAlpha(255); //ENTER_FUNCTION() << ppVar(opaqueColor); m_options.assistantsColor->setColor(opaqueColor); m_options.customAssistantColorButton->setColor(opaqueColor); m_options.assistantsGlobalOpacitySlider->setValue(color.alphaF() * 100.0); } else { m_options.assistantsColor->setColor(QColor(176, 176, 176, 255)); // grey default for all assistants m_options.assistantsGlobalOpacitySlider->setValue(100); // 100% } m_options.assistantsGlobalOpacitySlider->setPrefix(i18n("Opacity: ")); m_options.assistantsGlobalOpacitySlider->setSuffix(" %"); // custom color of selected assistant m_options.customColorOpacitySlider->setValue(100); // 100% m_options.customColorOpacitySlider->setPrefix(i18n("Opacity: ")); m_options.customColorOpacitySlider->setSuffix(" %"); connect(m_options.useCustomAssistantColor, SIGNAL(clicked(bool)), this, SLOT(slotUpdateCustomColor())); connect(m_options.customAssistantColorButton, SIGNAL(changed(QColor)), this, SLOT(slotUpdateCustomColor())); connect(m_options.customColorOpacitySlider, SIGNAL(valueChanged(int)), SLOT(slotCustomOpacityChanged())); m_options.vanishingPointAngleSpinbox->setPrefix(i18n("Density: ")); m_options.vanishingPointAngleSpinbox->setSuffix(QChar(Qt::Key_degree)); m_options.vanishingPointAngleSpinbox->setRange(1.0, 180.0); m_options.vanishingPointAngleSpinbox->setSingleStep(0.5); m_options.vanishingPointAngleSpinbox->setVisible(false); } updateToolOptionsUI(); return m_optionsWidget; } void KisAssistantTool::slotGlobalAssistantsColorChanged(const QColor& setColor) { // color and alpha are stored separately, so we need to merge the values before sending it on int oldAlpha = m_canvas->paintingAssistantsDecoration()->globalAssistantsColor().alpha(); QColor newColor = setColor; newColor.setAlpha(oldAlpha); m_canvas->paintingAssistantsDecoration()->setGlobalAssistantsColor(newColor); m_canvas->paintingAssistantsDecoration()->uncache(); m_canvas->canvasWidget()->update(); } void KisAssistantTool::slotGlobalAssistantOpacityChanged() { QColor newColor = m_canvas->paintingAssistantsDecoration()->globalAssistantsColor(); qreal newOpacity = m_options.assistantsGlobalOpacitySlider->value() * 0.01 * 255.0; newColor.setAlpha(int(newOpacity)); m_canvas->paintingAssistantsDecoration()->setGlobalAssistantsColor(newColor); m_canvas->paintingAssistantsDecoration()->uncache(); m_canvas->canvasWidget()->update(); } void KisAssistantTool::slotUpdateCustomColor() { // get the selected assistant and change the angle value KisPaintingAssistantSP m_selectedAssistant = m_canvas->paintingAssistantsDecoration()->selectedAssistant(); if (m_selectedAssistant) { m_selectedAssistant->setUseCustomColor(m_options.useCustomAssistantColor->isChecked()); // changing color doesn't keep alpha, so update that before we send it on QColor newColor = m_options.customAssistantColorButton->color(); newColor.setAlpha(m_selectedAssistant->assistantCustomColor().alpha()); m_selectedAssistant->setAssistantCustomColor(newColor); m_selectedAssistant->uncache(); } updateToolOptionsUI(); m_canvas->canvasWidget()->update(); } void KisAssistantTool::slotCustomOpacityChanged() { KisPaintingAssistantSP m_selectedAssistant = m_canvas->paintingAssistantsDecoration()->selectedAssistant(); if (m_selectedAssistant) { QColor newColor = m_selectedAssistant->assistantCustomColor(); qreal newOpacity = m_options.customColorOpacitySlider->value() * 0.01 * 255.0; newColor.setAlpha(int(newOpacity)); m_selectedAssistant->setAssistantCustomColor(newColor); m_selectedAssistant->uncache(); } // this forces the canvas to refresh to see the changes immediately m_canvas->paintingAssistantsDecoration()->uncache(); m_canvas->canvasWidget()->update(); } diff --git a/plugins/assistants/Assistants/kis_assistant_tool.h b/plugins/assistants/Assistants/kis_assistant_tool.h index 0ef7512325..71c4ca524c 100644 --- a/plugins/assistants/Assistants/kis_assistant_tool.h +++ b/plugins/assistants/Assistants/kis_assistant_tool.h @@ -1,176 +1,177 @@ /* * Copyright (c) 2008 Cyrille Berger * Copyright (c) 2017 Scott Petrovic * * 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. + * the Free Software Foundation; 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 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_ASSISTANT_TOOL_H_ #define _KIS_ASSISTANT_TOOL_H_ #include #include #include #include #include "kis_painting_assistant.h" #include #include #include "ui_AssistantsToolOptions.h" /* The assistant tool allows artists to create special guides on the canvas * to help them with things like perspective and parallel lines * This tool has its own canvas decoration on it that only appears when the tool * is active. This decoration allows people to edit assistant points as well as delete assistants * Many of the operations here are forwarded on to another class (kis_painting_assistant_decoration) * that stores the assistant information as well as the decoration information with lines * * Drawing in two separate classes creates an issue where the editor controls in this class * are covered by the kis_painting_assistant_decoration class. In the future, we probably need to * do all the drawing in one class so we have better control of what is in front */ class KisAssistantTool : public KisTool { Q_OBJECT enum PerspectiveAssistantEditionMode { MODE_CREATION, // This is the mode when there is not yet a perspective grid MODE_EDITING, // This is the mode when the grid has been created, and we are waiting for the user to click on a control box MODE_DRAGGING_NODE, // In this mode one node is translated MODE_DRAGGING_TRANSLATING_TWONODES // This mode is used when creating a new sub perspective grid }; public: KisAssistantTool(KoCanvasBase * canvas); ~KisAssistantTool() override; virtual quint32 priority() { return 3; } /* this is a very big function that has to figure out if we are adding a new assistant, * or editing an existing one when we click on the canvas. There is also a lot of logic * in here that is specific to certain assistants and how they should be handled. * The editor widget is not a UI file, so the move, delete, preview areas have manual * hitbox regions specified to know if a click is doing any of those actions. */ void beginPrimaryAction(KoPointerEvent *event) override; void continuePrimaryAction(KoPointerEvent *event) override; void endPrimaryAction(KoPointerEvent *event) override; void mouseMoveEvent(KoPointerEvent *event) override; QWidget *createOptionWidget() override; private: // adds and removes assistant. // this is event is forwarded to the kis_painting_decoration class // perspective grids seem to be managed in two places with these calls void addAssistant(); void removeAssistant(KisPaintingAssistantSP assistant); void assistantSelected(KisPaintingAssistantSP assistant); public Q_SLOTS: void activate(ToolActivation toolActivation, const QSet &shapes) override; void deactivate() override; void slotChangeVanishingPointAngle(double value); private Q_SLOTS: void removeAllAssistants(); void saveAssistants(); void loadAssistants(); void updateToolOptionsUI(); /// send the color and opacity information from the UI to the kis_painting_decoration /// which manages the assistants void slotGlobalAssistantsColorChanged(const QColor&); void slotGlobalAssistantOpacityChanged(); void slotUpdateCustomColor(); void slotCustomOpacityChanged(); protected: /// Draws the editor widget controls with move, activate, and delete /// This also creates a lot of assistant specific stuff for vanishing points and perspective grids /// Whatever is painted here will be underneath the content painted in the kis_painting_assistant_decoration /// The kis_painting_assistant_decoration paints the final assistant, so this is more of just editor controls void paint(QPainter& gc, const KoViewConverter &converter) override; protected: /// this class manipulates the kis_painting_assistant_decorations a lot, so this class is a helper /// to get a reference to it and call "updateCanvas" which refreshes the display QPointer m_canvas; /// the handles are retrieved from the kis_painting_decoration originally /// They are used here to generate and manipulate editor handles with the tool's primary action QList m_handles; QList m_sideHandles; KisPaintingAssistantHandleSP m_handleDrag; KisPaintingAssistantHandleSP m_handleCombine; KisPaintingAssistantSP m_assistantDrag; /// Used while a new assistant is being created. Most assistants need multiple points to exist /// so this helps manage the visual state while this creation process is going on KisPaintingAssistantSP m_newAssistant; QPointF m_cursorStart; QPointF m_currentAdjustment; Ui::AssistantsToolOptions m_options; QWidget* m_optionsWidget; QPointF m_dragStart; QLineF m_radius; bool m_snapIsRadial; QPointF m_dragEnd; int m_handleSize; // how large the editor handles will appear private: void drawEditorWidget(KisPaintingAssistantSP assistant, QPainter& _gc); PerspectiveAssistantEditionMode m_internalMode; KisPaintingAssistantHandleSP m_selectedNode1, m_selectedNode2, m_higlightedNode; int m_assistantHelperYOffset; // used by the assistant editor icons for placement on the canvas. QList m_origAssistantList; }; class KisAssistantToolFactory : public KoToolFactoryBase { public: KisAssistantToolFactory() : KoToolFactoryBase("KisAssistantTool") { setToolTip(i18n("Assistant Tool")); setSection(TOOL_TYPE_VIEW); setIconName(koIconNameCStr("krita_tool_assistant")); setPriority(0); setActivationShapeId(KRITA_TOOL_ACTIVATION_ID); } ~KisAssistantToolFactory() override {} KoToolBase * createTool(KoCanvasBase * canvas) override { return new KisAssistantTool(canvas); } }; #endif diff --git a/plugins/dockers/advancedcolorselector/colorselectorng.cpp b/plugins/dockers/advancedcolorselector/colorselectorng.cpp index 3cec60c825..b4ce2ade0f 100644 --- a/plugins/dockers/advancedcolorselector/colorselectorng.cpp +++ b/plugins/dockers/advancedcolorselector/colorselectorng.cpp @@ -1,86 +1,87 @@ /* * Copyright (c) 2008 Cyrille Berger * Copyright (c) 2010 Adam Celarek * * 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. + * the Free Software Foundation; 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 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 "colorselectorng.h" #include #include #include #include "kis_color_selector_ng_dock.h" #include "kis_color_selector_settings.h" #include "kis_preference_set_registry.h" K_PLUGIN_FACTORY_WITH_JSON(ColorSelectorNgPluginFactory, "krita_colorselectorng.json", registerPlugin();) class ColorSelectorNgDockFactory : public KoDockFactoryBase { public: ColorSelectorNgDockFactory() { } QString id() const override { return QString("ColorSelectorNg"); } virtual Qt::DockWidgetArea defaultDockWidgetArea() const { return Qt::RightDockWidgetArea; } QDockWidget* createDockWidget() override { KisColorSelectorNgDock * dockWidget = new KisColorSelectorNgDock(); dockWidget->setObjectName(id()); return dockWidget; } DockPosition defaultDockPosition() const override { return DockRight; } }; ColorSelectorNgPlugin::ColorSelectorNgPlugin(QObject *parent, const QVariantList &) : QObject(parent) { KoDockRegistry::instance()->add(new ColorSelectorNgDockFactory()); KisPreferenceSetRegistry *preferenceSetRegistry = KisPreferenceSetRegistry::instance(); KisColorSelectorSettingsFactory* settingsFactory = new KisColorSelectorSettingsFactory(); //load and save preferences //if something in kritarc is missing, then the default from this load function will be used and saved back to kconfig. //this way, cfg.readEntry() in any part won't be able to set its own default KisPreferenceSet* settings = settingsFactory->createPreferenceSet(); Q_ASSERT(settings); settings->loadPreferences(); settings->savePreferences(); delete settings; preferenceSetRegistry->add("KisColorSelectorSettingsFactory", settingsFactory); } ColorSelectorNgPlugin::~ColorSelectorNgPlugin() { } #include "colorselectorng.moc" diff --git a/plugins/dockers/advancedcolorselector/colorselectorng.h b/plugins/dockers/advancedcolorselector/colorselectorng.h index 08da99cf15..32a93bbb8b 100644 --- a/plugins/dockers/advancedcolorselector/colorselectorng.h +++ b/plugins/dockers/advancedcolorselector/colorselectorng.h @@ -1,37 +1,38 @@ /* * Copyright (c) 2008 Cyrille Berger * Copyright (c) 2010 Adam Celarek * * 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. + * the Free Software Foundation; 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 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 _COLORSELECTORNG_H_ #define _COLORSELECTORNG_H_ #include #include /** * Template of view plugin */ class ColorSelectorNgPlugin : public QObject { Q_OBJECT public: ColorSelectorNgPlugin(QObject *parent, const QVariantList &); ~ColorSelectorNgPlugin() override; }; #endif diff --git a/plugins/dockers/advancedcolorselector/kis_color_history.cpp b/plugins/dockers/advancedcolorselector/kis_color_history.cpp index f4312b67a6..0dfdc0a3b0 100644 --- a/plugins/dockers/advancedcolorselector/kis_color_history.cpp +++ b/plugins/dockers/advancedcolorselector/kis_color_history.cpp @@ -1,80 +1,81 @@ /* * Copyright (c) 2010 Adam Celarek * * 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. + * the Free Software Foundation; 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 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_history.h" #include "kis_canvas2.h" #include "KisViewManager.h" #include "KisView.h" #include "kis_canvas_resource_provider.h" #include #include KisColorHistory::KisColorHistory(QWidget *parent) : KisColorPatches("lastUsedColors", parent) , m_resourceProvider(0) { } void KisColorHistory::unsetCanvas() { KisColorPatches::unsetCanvas(); m_resourceProvider = 0; } void KisColorHistory::setCanvas(KisCanvas2 *canvas) { if (!canvas) return; KisColorPatches::setCanvas(canvas); if (m_resourceProvider) { m_resourceProvider->disconnect(this); } m_resourceProvider = canvas->imageView()->resourceProvider(); connect(canvas->imageView()->resourceProvider(), SIGNAL(sigFGColorUsed(KoColor)), this, SLOT(addColorToHistory(KoColor)), Qt::UniqueConnection); } KisColorSelectorBase* KisColorHistory::createPopup() const { KisColorHistory* ret = new KisColorHistory(); ret->setCanvas(m_canvas); ret->setColors(colors()); ret->m_colorHistory=m_colorHistory; return ret; } void KisColorHistory::addColorToHistory(const KoColor& color) { // don't add color in erase mode. See https://bugs.kde.org/show_bug.cgi?id=298940 if (m_resourceProvider && m_resourceProvider->currentCompositeOp() == COMPOSITE_ERASE) return; m_colorHistory.removeAll(color); m_colorHistory.prepend(color); //the history holds 200 colors, but not all are displayed if (m_colorHistory.size()>200) { m_colorHistory.removeLast(); } setColors(m_colorHistory); } diff --git a/plugins/dockers/advancedcolorselector/kis_color_history.h b/plugins/dockers/advancedcolorselector/kis_color_history.h index f6055fe0ab..630e3cf2f8 100644 --- a/plugins/dockers/advancedcolorselector/kis_color_history.h +++ b/plugins/dockers/advancedcolorselector/kis_color_history.h @@ -1,45 +1,46 @@ /* * Copyright (c) 2010 Adam Celarek * * 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. + * the Free Software Foundation; 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 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_HISTORY_H #define KIS_COLOR_HISTORY_H #include "kis_color_patches.h" class KisCanvasResourceProvider; class KisColorHistory : public KisColorPatches { Q_OBJECT public: explicit KisColorHistory(QWidget *parent = 0); void setCanvas(KisCanvas2 *canvas) override; void unsetCanvas() override; protected: KisColorSelectorBase* createPopup() const override; public Q_SLOTS: void addColorToHistory(const KoColor& color); private: QList m_colorHistory; KisCanvasResourceProvider *m_resourceProvider; // to disconnect... }; #endif // KIS_COLOR_HISTORY_H diff --git a/plugins/dockers/advancedcolorselector/kis_color_patches.cpp b/plugins/dockers/advancedcolorselector/kis_color_patches.cpp index f54557494c..260a70872d 100644 --- a/plugins/dockers/advancedcolorselector/kis_color_patches.cpp +++ b/plugins/dockers/advancedcolorselector/kis_color_patches.cpp @@ -1,352 +1,353 @@ /* * Copyright (c) 2010 Adam Celarek * * 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. + * the Free Software Foundation; 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 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_patches.h" #include #include #include #include #include #include #include #include #include #include "kis_canvas2.h" #include "KoCanvasResourceProvider.h" #include "kis_display_color_converter.h" KisColorPatches::KisColorPatches(QString configPrefix, QWidget *parent) : KisColorSelectorBase(parent), m_allowColorListChangeGuard(true), m_scrollValue(0), m_configPrefix(configPrefix) { resize(1, 1); updateSettings(); } void KisColorPatches::setColors(QListcolors) { if (m_allowColorListChangeGuard) { m_colors = colors; m_allowColorListChangeGuard=false; KisColorPatches* parent = dynamic_cast(m_parent); if (parent) parent->setColors(colors); KisColorPatches* popup = dynamic_cast(m_popup); if (popup) popup->setColors(colors); m_allowColorListChangeGuard=true; update(); } } void KisColorPatches::paintEvent(QPaintEvent* e) { QPainter painter(this); if(m_allowScrolling) { if(m_direction == Vertical) painter.translate(0, m_scrollValue); else painter.translate(m_scrollValue, 0); } int widgetWidth = width(); int numPatchesInARow = qMax(widgetWidth/m_patchWidth, 1); int widgetHeight = height(); int numPatchesInACol = qMax(widgetHeight/m_patchHeight, 1); for(int i = m_buttonList.size(); i < qMin(fieldCount(), m_colors.size() + m_buttonList.size()); i++) { int row; int col; if(m_direction == Vertical) { row = i /numPatchesInARow; col = i % numPatchesInARow; } else { row= i % numPatchesInACol; col = i / numPatchesInACol; } QColor qcolor = converter()->toQColor(m_colors.at(i - m_buttonList.size())); painter.fillRect(col*m_patchWidth, row*m_patchHeight, m_patchWidth, m_patchHeight, qcolor); } QWidget::paintEvent(e); } void KisColorPatches::wheelEvent(QWheelEvent* event) { m_scrollValue+=event->delta()/2; if(m_direction == Vertical) { if(m_scrollValue < -1*(heightOfAllPatches()-height())) m_scrollValue = -1*(heightOfAllPatches()-height()); } else { if(m_scrollValue < -1*(widthOfAllPatches()-width())) m_scrollValue = -1*(widthOfAllPatches()-width()); } if(m_scrollValue>0) m_scrollValue=0; update(); } void KisColorPatches::resizeEvent(QResizeEvent* event) { if(size()==QSize(1, 1)) return; QWheelEvent dummyWheelEvent(QPoint(), 0, Qt::NoButton, Qt::NoModifier); wheelEvent(&dummyWheelEvent); if(parentWidget()==0) { // this instance is a popup setMinimumWidth(m_patchWidth*(m_patchCount/4)); setMaximumWidth(minimumWidth()); } if (m_allowScrolling == false && event->oldSize() != event->size()) { if(m_direction == Horizontal) { setMaximumHeight(heightForWidth(width())); setMinimumHeight(heightForWidth(width())); } else { setMaximumWidth(widthForHeight(height())); setMinimumWidth(widthForHeight(height())); } } } void KisColorPatches::mouseReleaseEvent(QMouseEvent* event) { KisColorSelectorBase::mouseReleaseEvent(event); event->setAccepted(false); KisColorSelectorBase::mouseReleaseEvent(event); if (event->isAccepted() || !rect().contains(event->pos())) return; if (!m_canvas) return; KoColor color; if(colorAt(event->pos(), &color)) { if (event->button()==Qt::LeftButton) m_canvas->resourceManager()->setForegroundColor(color); else if (event->button()==Qt::RightButton) m_canvas->resourceManager()->setBackgroundColor(color); } } void KisColorPatches::mousePressEvent(QMouseEvent *event) { KoColor koColor; if(!colorAt(event->pos(), &koColor)) return; KisColorSelectorBase::mousePressEvent(event); if(event->isAccepted()) return; updateColorPreview(koColor); if (event->button() == Qt::LeftButton) m_dragStartPos = event->pos(); } void KisColorPatches::mouseMoveEvent(QMouseEvent *event) { event->ignore(); KisColorSelectorBase::mouseMoveEvent(event); if(event->isAccepted()) return; if (!(event->buttons() & Qt::LeftButton)) return; if ((event->pos() - m_dragStartPos).manhattanLength() < QApplication::startDragDistance()) return; KoColor koColor; if(!colorAt(m_dragStartPos, &koColor)) return; QDrag *drag = new QDrag(this); QMimeData *mimeData = new QMimeData; QColor color = converter()->toQColor(koColor); mimeData->setColorData(color); mimeData->setText(color.name()); drag->setMimeData(mimeData); drag->exec(Qt::CopyAction); event->accept(); } int KisColorPatches::patchCount() const { return m_patchCount; } bool KisColorPatches::colorAt(const QPoint &pos, KoColor *result) const { if(!rect().contains(pos)) return false; int scrollX = m_direction==Horizontal?m_scrollValue:0; int scrollY = m_direction==Vertical?m_scrollValue:0; int column = (pos.x()-scrollX)/m_patchWidth; int row = (pos.y()-scrollY)/m_patchHeight; int patchNr; if(m_direction == Vertical) { int patchesInARow = width()/m_patchWidth; patchNr=row*patchesInARow+column; } else { // Vertical int patchesInAColumn = height()/m_patchHeight; patchNr=column*patchesInAColumn+row; } patchNr-=m_buttonList.size(); if(patchNr>=0 && patchNr buttonList) { for(int i=0; isetParent(this); } m_buttonList = buttonList; } void KisColorPatches::updateSettings() { KisColorSelectorBase::updateSettings(); KConfigGroup cfg = KSharedConfig::openConfig()->group("advancedColorSelector"); if(cfg.readEntry(m_configPrefix+"Alignment", false)) m_direction=Vertical; else m_direction=Horizontal; m_allowScrolling=cfg.readEntry(m_configPrefix+"Scrolling", true); m_numCols=cfg.readEntry(m_configPrefix+"NumCols", 1); m_numRows=cfg.readEntry(m_configPrefix+"NumRows", 1); m_patchCount=cfg.readEntry(m_configPrefix+"Count", 15); m_patchWidth=cfg.readEntry(m_configPrefix+"Width", 20); m_patchHeight=cfg.readEntry(m_configPrefix+"Height", 20); if(m_patchHeight == 0) { m_patchHeight = 1; } if(parentWidget()==0) { // this instance is a popup m_allowScrolling = false; m_direction = Horizontal; m_patchWidth*=2; m_patchHeight*=2; } for(int i=0; isetGeometry(0, i*m_patchHeight, m_patchWidth, m_patchHeight); } setMaximumWidth(QWIDGETSIZE_MAX); setMinimumWidth(1); setMaximumHeight(QWIDGETSIZE_MAX); setMinimumHeight(1); if(m_allowScrolling && m_direction == Horizontal) { setMaximumHeight(m_numRows*m_patchHeight); setMinimumHeight(m_numRows*m_patchHeight); } if(m_allowScrolling && m_direction == Vertical) { setMaximumWidth(m_numCols*m_patchWidth); setMinimumWidth(m_numCols*m_patchWidth); } if(m_allowScrolling == false) { m_scrollValue = 0; } QResizeEvent dummy(size(), QSize(-1,-1)); resizeEvent(&dummy); setPopupBehaviour(false, false); update(); } int KisColorPatches::widthOfAllPatches() { return (fieldCount()/m_numRows)*m_patchWidth; } int KisColorPatches::heightOfAllPatches() { return (fieldCount()/m_numCols)*m_patchHeight; } int KisColorPatches::heightForWidth(int width) const { int numPatchesInARow = width / m_patchWidth; int numRows = qMax((fieldCount() - 1), 1) / qMax(numPatchesInARow + 1, 1); return qMax(numRows * m_patchHeight, m_patchHeight); } int KisColorPatches::widthForHeight(int height) const { if (height == 0) { return 0; } if (m_patchHeight == 0) { return 0; } int numPatchesInACol = height / m_patchHeight; int numCols = (fieldCount() - 1) / (numPatchesInACol + 1); return qMax(numCols*m_patchWidth, m_patchWidth); } int KisColorPatches::fieldCount() const { return m_patchCount+m_buttonList.size(); } diff --git a/plugins/dockers/advancedcolorselector/kis_color_patches.h b/plugins/dockers/advancedcolorselector/kis_color_patches.h index 1905d4c102..e9bc5c1c0e 100644 --- a/plugins/dockers/advancedcolorselector/kis_color_patches.h +++ b/plugins/dockers/advancedcolorselector/kis_color_patches.h @@ -1,89 +1,90 @@ /* * Copyright (c) 2010 Adam Celarek * * 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. + * the Free Software Foundation; 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 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_PATCHES_H #define KIS_COLOR_PATCHES_H #include "kis_color_selector_base.h" #include "KoColor.h" class KoColor; class KisColorPatches : public KisColorSelectorBase { Q_OBJECT public: explicit KisColorPatches(QString configPrefix, QWidget *parent = 0); enum Direction { Horizontal, Vertical }; public Q_SLOTS: void updateSettings() override; protected: void setColors(QList colors); QList colors() const {return m_colors;} void paintEvent(QPaintEvent *) override; void wheelEvent(QWheelEvent *) override; void resizeEvent(QResizeEvent *) override; void mouseReleaseEvent(QMouseEvent *) override; void mousePressEvent(QMouseEvent *) override; void mouseMoveEvent(QMouseEvent *) override; int patchCount() const; bool colorAt(const QPoint &, KoColor *result) const; public: /// set buttons, that should be drawn additionally to the patches /// this class takes ownership of them and will delete them /// they will be resized to the patchsize void setAdditionalButtons(QList buttonList); private: int m_patchWidth; int m_patchHeight; int m_patchCount; QList m_colors; bool m_allowColorListChangeGuard; int m_scrollValue; Direction m_direction; bool m_allowScrolling; int m_numCols; int m_numRows; QList m_buttonList; /// returns width of the patchfield, if there are only m_numRows allowed int widthOfAllPatches(); /// returns height of the patchfield, if there are only m_numCols allowed int heightOfAllPatches(); /// returns height, that is needed to display all patches with the given width int heightForWidth(int width) const override; /// returns width, that is needed to display all patches with the given height int widthForHeight(int height) const; /// returns count of colors and buttons int fieldCount() const; QString m_configPrefix; QPoint m_dragStartPos; }; #endif diff --git a/plugins/dockers/advancedcolorselector/kis_color_selector.cpp b/plugins/dockers/advancedcolorselector/kis_color_selector.cpp index c90e1a5052..83c6a29aba 100644 --- a/plugins/dockers/advancedcolorselector/kis_color_selector.cpp +++ b/plugins/dockers/advancedcolorselector/kis_color_selector.cpp @@ -1,395 +1,396 @@ /* * Copyright (c) 2010 Adam Celarek * * 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. + * the Free Software Foundation; 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 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_selector.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "kis_color_selector_ring.h" #include "kis_color_selector_triangle.h" #include "kis_color_selector_simple.h" #include "kis_color_selector_wheel.h" #include "kis_color_selector_container.h" #include "kis_canvas2.h" #include "kis_signal_compressor.h" #include "KisViewManager.h" KisColorSelector::KisColorSelector(KisColorSelectorConfiguration conf, QWidget* parent) : KisColorSelectorBase(parent), m_ring(0), m_triangle(0), m_slider(0), m_square(0), m_wheel(0), m_mainComponent(0), m_subComponent(0), m_grabbingComponent(0), m_blipDisplay(true) { init(); updateSettings(); setConfiguration(conf); } KisColorSelector::KisColorSelector(QWidget* parent) : KisColorSelectorBase(parent), m_ring(0), m_triangle(0), m_slider(0), m_square(0), m_wheel(0), m_button(0), m_mainComponent(0), m_subComponent(0), m_grabbingComponent(0), m_blipDisplay(true) { init(); updateSettings(); } KisColorSelectorBase* KisColorSelector::createPopup() const { KisColorSelectorBase* popup = new KisColorSelector(0); popup->setColor(m_lastRealColor); return popup; } void KisColorSelector::setConfiguration(KisColorSelectorConfiguration conf) { m_configuration = conf; if(m_mainComponent!=0) { Q_ASSERT(m_subComponent!=0); m_mainComponent->setGeometry(0, 0, 0, 0); m_subComponent->setGeometry(0, 0, 0, 0); m_mainComponent->disconnect(); m_subComponent->disconnect(); } switch (m_configuration.mainType) { case KisColorSelectorConfiguration::Square: m_mainComponent=m_square; break; case KisColorSelectorConfiguration::Wheel: m_mainComponent=m_wheel; break; case KisColorSelectorConfiguration::Triangle: m_mainComponent=m_triangle; break; default: Q_ASSERT(false); } switch (m_configuration.subType) { case KisColorSelectorConfiguration::Ring: m_subComponent=m_ring; break; case KisColorSelectorConfiguration::Slider: m_subComponent=m_slider; break; default: Q_ASSERT(false); } connect(m_mainComponent, SIGNAL(paramChanged(qreal,qreal,qreal,qreal,qreal,qreal,qreal,qreal,qreal)), m_subComponent, SLOT(setParam(qreal,qreal,qreal,qreal,qreal,qreal,qreal,qreal,qreal)), Qt::UniqueConnection); connect(m_subComponent, SIGNAL(paramChanged(qreal,qreal,qreal,qreal,qreal,qreal,qreal,qreal,qreal)), m_mainComponent, SLOT(setParam(qreal,qreal,qreal,qreal,qreal,qreal,qreal,qreal,qreal)), Qt::UniqueConnection); connect(m_mainComponent, SIGNAL(update()), m_signalCompressor, SLOT(start()), Qt::UniqueConnection); connect(m_subComponent, SIGNAL(update()), m_signalCompressor, SLOT(start()), Qt::UniqueConnection); m_mainComponent->setConfiguration(m_configuration.mainTypeParameter, m_configuration.mainType); m_subComponent->setConfiguration(m_configuration.subTypeParameter, m_configuration.subType); QResizeEvent event(QSize(width(), height()), QSize()); resizeEvent(&event); } KisColorSelectorConfiguration KisColorSelector::configuration() const { return m_configuration; } void KisColorSelector::updateSettings() { KisColorSelectorBase::updateSettings(); KConfigGroup cfg = KSharedConfig::openConfig()->group("advancedColorSelector"); setConfiguration(KisColorSelectorConfiguration::fromString(cfg.readEntry("colorSelectorConfiguration", KisColorSelectorConfiguration().toString()))); } void KisColorSelector::slotGamutMaskSet(KoGamutMask *gamutMask) { m_mainComponent->setGamutMask(gamutMask); m_subComponent->setGamutMask(gamutMask); slotGamutMaskToggle(true); } void KisColorSelector::slotGamutMaskUnset() { m_mainComponent->unsetGamutMask(); m_subComponent->unsetGamutMask(); slotGamutMaskToggle(false); } void KisColorSelector::slotGamutMaskPreviewUpdate() { m_mainComponent->updateGamutMaskPreview(); m_subComponent->updateGamutMaskPreview(); } void KisColorSelector::slotGamutMaskToggle(bool state) { m_mainComponent->toggleGamutMask(state); m_subComponent->toggleGamutMask(state); } void KisColorSelector::updateIcons() { if (m_button) { m_button->setIcon(KisIconUtils::loadIcon("configure")); } } void KisColorSelector::hasAtLeastOneDocument(bool value) { m_hasAtLeastOneDocumentOpen = value; } void KisColorSelector::reset() { if (m_mainComponent) { m_mainComponent->setDirty(); } if (m_subComponent) { m_subComponent->setDirty(); } KisColorSelectorBase::reset(); } void KisColorSelector::paintEvent(QPaintEvent* e) { Q_UNUSED(e); QPainter p(this); p.fillRect(0,0,width(), height(), QColor(128,128,128)); p.setRenderHint(QPainter::Antialiasing); // this variable name isn't entirely accurate to what always happens. see definition in header file to understand it better if (!m_hasAtLeastOneDocumentOpen) { p.setOpacity(0.2); } m_mainComponent->paintEvent(&p); m_subComponent->paintEvent(&p); p.setOpacity(1.0); } inline int iconSize(qreal width, qreal height) { qreal radius = qMin(width, height)/2.; qreal xm = width/2.; qreal ym = height/2.; if(xm>=2*ym || ym>=2*xm) return qBound(5., radius, 32.); qreal a=-2; qreal b=2.*(xm+ym); qreal c=radius*radius-xm*xm-ym*ym; return qBound(5., ((-b+sqrt(b*b-4*a*c))/(2*a)), 32.); } void KisColorSelector::resizeEvent(QResizeEvent* e) { if (m_configuration.subType == KisColorSelectorConfiguration::Ring) { m_ring->setGeometry(0,0,width(), height()); if (displaySettingsButton()) { int size = iconSize(width(), height()); m_button->setGeometry(0, 0, size, size); } if (m_configuration.mainType == KisColorSelectorConfiguration::Triangle) { m_triangle->setGeometry(width()/2-m_ring->innerRadius(), height()/2-m_ring->innerRadius(), m_ring->innerRadius()*2, m_ring->innerRadius()*2); } else { int size = m_ring->innerRadius()*2/sqrt(2.); m_square->setGeometry(width()/2-size/2, height()/2-size/2, size, size); } } else { // type wheel and square if (m_configuration.mainType == KisColorSelectorConfiguration::Wheel) { if(displaySettingsButton()) { int size = iconSize(width(), height()*0.9); m_button->setGeometry(0, height()*0.1, size, size); } m_mainComponent->setGeometry(0, height()*0.1, width(), height()*0.9); m_subComponent->setGeometry( 0, 0, width(), height()*0.1); } else { int buttonSize = 0; if(displaySettingsButton()) { buttonSize = qBound(20, int(0.1*height()), 32); m_button->setGeometry(0, 0, buttonSize, buttonSize); } if(height()>width()) { int selectorHeight=height()-buttonSize; m_mainComponent->setGeometry(0, buttonSize+selectorHeight*0.1, width(), selectorHeight*0.9); m_subComponent->setGeometry( 0, buttonSize, width(), selectorHeight*0.1); } else { int selectorWidth=width()-buttonSize; m_mainComponent->setGeometry(buttonSize, height()*0.1, selectorWidth, height()*0.9); m_subComponent->setGeometry( buttonSize, 0, selectorWidth, height()*0.1); } } } // reset the correct color after resizing the widget setColor(m_lastRealColor); KisColorSelectorBase::resizeEvent(e); } void KisColorSelector::mousePressEvent(QMouseEvent* e) { e->setAccepted(false); KisColorSelectorBase::mousePressEvent(e); if(!e->isAccepted()) { if(m_mainComponent->wantsGrab(e->x(), e->y())) m_grabbingComponent=m_mainComponent; else if(m_subComponent->wantsGrab(e->x(), e->y())) m_grabbingComponent=m_subComponent; mouseEvent(e); updatePreviousColorPreview(); e->accept(); } } void KisColorSelector::mouseMoveEvent(QMouseEvent* e) { KisColorSelectorBase::mouseMoveEvent(e); mouseEvent(e); e->accept(); } void KisColorSelector::mouseReleaseEvent(QMouseEvent* e) { e->setAccepted(false); KisColorSelectorBase::mouseReleaseEvent(e); if(!e->isAccepted() && !(m_lastRealColor == m_currentRealColor)) { m_lastRealColor = m_currentRealColor; m_lastColorRole = Acs::buttonToRole(e->button()); updateColor(m_lastRealColor, m_lastColorRole, false); updateBaseColorPreview(m_currentRealColor); e->accept(); } m_grabbingComponent=0; } bool KisColorSelector::displaySettingsButton() { return dynamic_cast(parent()); } void KisColorSelector::setColor(const KoColor &color) { m_mainComponent->setColor(color); m_subComponent->setColor(color); m_lastRealColor = color; m_signalCompressor->start(); } void KisColorSelector::mouseEvent(QMouseEvent *e) { if (m_grabbingComponent && (e->buttons() & Qt::LeftButton || e->buttons() & Qt::RightButton)) { m_grabbingComponent->mouseEvent(e->x(), e->y()); KoColor color = m_mainComponent->currentColor(); Acs::ColorRole role = Acs::buttonsToRole(e->button(), e->buttons()); m_currentRealColor = color; requestUpdateColorAndPreview(color, role); } } void KisColorSelector::init() { setAcceptDrops(true); m_lastColorRole = Acs::Foreground; m_ring = new KisColorSelectorRing(this); m_triangle = new KisColorSelectorTriangle(this); m_slider = new KisColorSelectorSimple(this); m_square = new KisColorSelectorSimple(this); m_wheel = new KisColorSelectorWheel(this); if(displaySettingsButton()) { m_button = new QPushButton(this); m_button->setIcon(KisIconUtils::loadIcon("configure")); m_button->setFlat(true); connect(m_button, SIGNAL(clicked()), SIGNAL(settingsButtonClicked())); } // a tablet can send many more signals, than a mouse // this causes many repaints, if updating after every signal. m_signalCompressor = new KisSignalCompressor(20, KisSignalCompressor::FIRST_INACTIVE, this); connect(m_signalCompressor, SIGNAL(timeout()), SLOT(update())); setMinimumSize(40, 40); } diff --git a/plugins/dockers/advancedcolorselector/kis_color_selector.h b/plugins/dockers/advancedcolorselector/kis_color_selector.h index ef0f68ec7b..5d73ba5489 100644 --- a/plugins/dockers/advancedcolorselector/kis_color_selector.h +++ b/plugins/dockers/advancedcolorselector/kis_color_selector.h @@ -1,104 +1,105 @@ /* * Copyright (c) 2010 Adam Celarek * * 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. + * the Free Software Foundation; 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 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_SELECTOR_H #define KIS_COLOR_SELECTOR_H #include "kis_color_selector_base.h" #include class KisColorSelectorRing; class KisColorSelectorComponent; class KisColorSelectorSimple; class KisColorSelectorWheel; class QPushButton; class KisSignalCompressor; class KisColorSelector : public KisColorSelectorBase { Q_OBJECT public: KisColorSelector(KisColorSelectorConfiguration conf, QWidget* parent = 0); KisColorSelector(QWidget* parent=0); KisColorSelectorBase* createPopup() const override; void setConfiguration(KisColorSelectorConfiguration conf); KisColorSelectorConfiguration configuration() const; void setColor(const KoColor &color) override; /// update icons when a theme update happens void updateIcons(); void hasAtLeastOneDocument(bool value); public Q_SLOTS: void reset() override; void updateSettings() override; void slotGamutMaskSet(KoGamutMask* gamutMask); void slotGamutMaskUnset(); void slotGamutMaskPreviewUpdate(); void slotGamutMaskToggle(bool state); Q_SIGNALS: void settingsButtonClicked(); protected: void paintEvent(QPaintEvent*) override; void resizeEvent(QResizeEvent*) override; void mousePressEvent(QMouseEvent*) override; void mouseMoveEvent(QMouseEvent*) override; void mouseReleaseEvent(QMouseEvent*) override; bool displaySettingsButton(); private: void mouseEvent(QMouseEvent* e); void init(); KisColorSelectorRing* m_ring; KisColorSelectorComponent* m_triangle; KisColorSelectorSimple* m_slider; KisColorSelectorSimple* m_square; KisColorSelectorWheel* m_wheel; QPushButton* m_button; KisColorSelectorComponent* m_mainComponent; KisColorSelectorComponent* m_subComponent; KisColorSelectorComponent* m_grabbingComponent; KisSignalCompressor *m_signalCompressor; KisColorSelectorConfiguration m_configuration; KoColor m_lastRealColor; KoColor m_currentRealColor; bool m_blipDisplay; Acs::ColorRole m_lastColorRole; /// if Krita starts with a reference to this component that is attached to a canvas, it will call setCanvas() /// that check will be what ultimately decides whether this component will look enabled or disabled /// This color selector is sometimes not attached to the canvas, so we shouldn't disable it in that situation /// One instance of that is when you select the color wheel type from the settings. bool m_hasAtLeastOneDocumentOpen = true; public: void setDisplayBlip(bool disp) {m_blipDisplay = disp;} bool displayBlip() const {return m_blipDisplay;} }; #endif // KIS_COLSELNG_COLOR_SELECTOR_H diff --git a/plugins/dockers/advancedcolorselector/kis_color_selector_ng_dock.cpp b/plugins/dockers/advancedcolorselector/kis_color_selector_ng_dock.cpp index 93968eea1b..2080940e35 100644 --- a/plugins/dockers/advancedcolorselector/kis_color_selector_ng_dock.cpp +++ b/plugins/dockers/advancedcolorselector/kis_color_selector_ng_dock.cpp @@ -1,49 +1,50 @@ /* * Copyright (c) 2008 Cyrille Berger * Copyright (c) 2010 Adam Celarek * * 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. + * the Free Software Foundation; 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 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_selector_ng_dock.h" #include #include "kis_canvas2.h" #include "kis_color_selector_ng_docker_widget.h" KisColorSelectorNgDock::KisColorSelectorNgDock() : QDockWidget() { m_colorSelectorNgWidget = new KisColorSelectorNgDockerWidget(this); setWidget(m_colorSelectorNgWidget); m_colorSelectorNgWidget->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); setWindowTitle(i18n("Advanced Color Selector")); } void KisColorSelectorNgDock::setCanvas(KoCanvasBase * canvas) { setEnabled(canvas != 0); m_colorSelectorNgWidget->setCanvas(dynamic_cast(canvas)); } void KisColorSelectorNgDock::unsetCanvas() { setEnabled(false); m_colorSelectorNgWidget->unsetCanvas(); } diff --git a/plugins/dockers/advancedcolorselector/kis_color_selector_ng_dock.h b/plugins/dockers/advancedcolorselector/kis_color_selector_ng_dock.h index 7df03d9a10..21e8f69d82 100644 --- a/plugins/dockers/advancedcolorselector/kis_color_selector_ng_dock.h +++ b/plugins/dockers/advancedcolorselector/kis_color_selector_ng_dock.h @@ -1,41 +1,42 @@ /* * Copyright (c) 2008 Cyrille Berger * Copyright (c) 2010 Adam Celarek * * 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. + * the Free Software Foundation; 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 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_SELECTOR_NG_DOCKER_H #define KIS_COLOR_SELECTOR_NG_DOCKER_H #include #include class KisColorSelectorNgDockerWidget; class KisColorSelectorNgDock : public QDockWidget, public KoCanvasObserverBase { Q_OBJECT public: KisColorSelectorNgDock(); QString observerName() override { return "KisColorSelectorNgDock"; } /// reimplemented from KoCanvasObserverBase void setCanvas(KoCanvasBase *canvas) override; void unsetCanvas() override; private: KisColorSelectorNgDockerWidget *m_colorSelectorNgWidget; }; #endif diff --git a/plugins/dockers/advancedcolorselector/kis_color_selector_ng_docker_widget.cpp b/plugins/dockers/advancedcolorselector/kis_color_selector_ng_docker_widget.cpp index 511701c76a..494747a628 100644 --- a/plugins/dockers/advancedcolorselector/kis_color_selector_ng_docker_widget.cpp +++ b/plugins/dockers/advancedcolorselector/kis_color_selector_ng_docker_widget.cpp @@ -1,285 +1,286 @@ /* * Copyright (c) 2010 Adam Celarek * * 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. + * the Free Software Foundation; 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 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_selector_ng_docker_widget.h" #include "ui_wdg_color_selector_settings.h" #include #include #include #include #include #include #include #include #include #include "kis_canvas2.h" #include "KisViewManager.h" #include "kis_node_manager.h" #include "kis_canvas_resource_provider.h" #include "kis_color_space_selector.h" #include "kis_preference_set_registry.h" #include "kis_node.h" #include "kis_paint_device.h" #include "kis_color_history.h" #include "kis_common_colors.h" #include "kis_color_selector_settings.h" #include "kis_color_selector_container.h" #include "kis_action_registry.h" KisColorSelectorNgDockerWidget::KisColorSelectorNgDockerWidget(QWidget *parent) : QWidget(parent), m_colorHistoryAction(0), m_commonColorsAction(0), m_widgetLayout(0), m_mainLayout(0), m_horizontalPatchesContainer(0), m_sidebarLayout(0), m_verticalColorPatchesLayout(0), m_horizontalColorPatchesLayout(0), m_fallbackSettingsButton(new QToolButton(this)), m_canvas(0) { setAutoFillBackground(true); m_colorSelectorContainer = new KisColorSelectorContainer(this); m_colorHistoryWidget = new KisColorHistory(this); m_commonColorsWidget = new KisCommonColors(this); //default settings //remember to also change the default in the ui file //shade selector // fallback settings button when the color selector is disabled m_fallbackSettingsButton->setIcon(KisIconUtils::loadIcon("configure")); m_fallbackSettingsButton->setIconSize(QSize(22,22)); m_fallbackSettingsButton->setAutoRaise(true); m_fallbackSettingsButton->hide(); //layout m_widgetLayout = new QHBoxLayout(); m_widgetLayout->setSpacing(0); m_widgetLayout->setMargin(0); m_mainLayout = new QVBoxLayout(); m_mainLayout->setSpacing(0); m_mainLayout->setMargin(0); m_horizontalPatchesContainer = new QHBoxLayout(); m_horizontalPatchesContainer->setSpacing(0); m_horizontalPatchesContainer->setMargin(0); m_sidebarLayout = new QVBoxLayout(); m_sidebarLayout->setSpacing(0); m_sidebarLayout->setMargin(0); m_verticalColorPatchesLayout = new QHBoxLayout(); m_verticalColorPatchesLayout->setSpacing(0); m_verticalColorPatchesLayout->setMargin(0); m_horizontalColorPatchesLayout = new QVBoxLayout(); m_horizontalColorPatchesLayout->setSpacing(0); m_horizontalColorPatchesLayout->setMargin(0); m_horizontalPatchesContainer->addLayout(m_horizontalColorPatchesLayout); m_mainLayout->addWidget(m_colorSelectorContainer); m_mainLayout->addLayout(m_horizontalPatchesContainer); m_sidebarLayout->addLayout(m_verticalColorPatchesLayout); m_widgetLayout->addLayout(m_mainLayout); m_widgetLayout->addLayout(m_sidebarLayout); setLayout(m_widgetLayout); updateLayout(); connect(m_colorSelectorContainer, SIGNAL(openSettings()), this, SLOT(openSettings())); //emit settingsChanged() if the settings are changed in krita preferences KisPreferenceSetRegistry *preferenceSetRegistry = KisPreferenceSetRegistry::instance(); KisColorSelectorSettingsFactory* factory = dynamic_cast(preferenceSetRegistry->get("KisColorSelectorSettingsFactory")); Q_ASSERT(factory); connect(&(factory->repeater), SIGNAL(settingsUpdated()), this, SIGNAL(settingsChanged()), Qt::UniqueConnection); connect(this, SIGNAL(settingsChanged()), this, SLOT(updateLayout()), Qt::UniqueConnection); connect(this, SIGNAL(settingsChanged()), m_commonColorsWidget, SLOT(updateSettings()), Qt::UniqueConnection); connect(this, SIGNAL(settingsChanged()), m_colorHistoryWidget, SLOT(updateSettings()), Qt::UniqueConnection); connect(this, SIGNAL(settingsChanged()), m_colorSelectorContainer, SIGNAL(settingsChanged()), Qt::UniqueConnection); connect(this, SIGNAL(settingsChanged()), this, SLOT(update()), Qt::UniqueConnection); emit settingsChanged(); m_colorHistoryAction = KisActionRegistry::instance()->makeQAction("show_color_history", this); connect(m_colorHistoryAction, SIGNAL(triggered()), m_colorHistoryWidget, SLOT(showPopup()), Qt::UniqueConnection); m_commonColorsAction = KisActionRegistry::instance()->makeQAction("show_common_colors", this); connect(m_commonColorsAction, SIGNAL(triggered()), m_commonColorsWidget, SLOT(showPopup()), Qt::UniqueConnection); connect(m_fallbackSettingsButton, SIGNAL(clicked()), this, SLOT(openSettings())); } void KisColorSelectorNgDockerWidget::unsetCanvas() { m_canvas = 0; m_commonColorsWidget->unsetCanvas(); m_colorHistoryWidget->unsetCanvas(); m_colorSelectorContainer->unsetCanvas(); } void KisColorSelectorNgDockerWidget::setCanvas(KisCanvas2 *canvas) { if (m_canvas) { m_canvas->disconnect(this); KActionCollection *ac = m_canvas->viewManager()->actionCollection(); ac->takeAction(ac->action("show_color_history")); ac->takeAction(ac->action("show_common_colors")); } m_canvas = canvas; m_commonColorsWidget->setCanvas(canvas); m_colorHistoryWidget->setCanvas(canvas); m_colorSelectorContainer->setCanvas(canvas); if (m_canvas && m_canvas->viewManager()) { if (m_canvas->viewManager()->nodeManager()) { connect(m_canvas->viewManager()->nodeManager(), SIGNAL(sigLayerActivated(KisLayerSP)), SLOT(reactOnLayerChange()), Qt::UniqueConnection); } KActionCollection* actionCollection = canvas->viewManager()->actionCollection(); actionCollection->addAction("show_color_history", m_colorHistoryAction); actionCollection->addAction("show_common_colors", m_commonColorsAction); connect(m_canvas->viewManager()->mainWindow(), SIGNAL(themeChanged()), m_colorSelectorContainer, SLOT(slotUpdateIcons()), Qt::UniqueConnection); } reactOnLayerChange(); } void KisColorSelectorNgDockerWidget::openSettings() { if (!m_canvas) return; KisColorSelectorSettingsDialog settings; if(settings.exec()==QDialog::Accepted) { emit settingsChanged(); } } void KisColorSelectorNgDockerWidget::updateLayout() { KConfigGroup cfg = KSharedConfig::openConfig()->group("advancedColorSelector"); bool showColorSelector = (bool) cfg.readEntry("showColorSelector", true); //color patches bool m_lastColorsShow = cfg.readEntry("lastUsedColorsShow", true); KisColorPatches::Direction m_lastColorsDirection; if(cfg.readEntry("lastUsedColorsAlignment", false)) m_lastColorsDirection=KisColorPatches::Vertical; else m_lastColorsDirection=KisColorPatches::Horizontal; bool m_commonColorsShow = cfg.readEntry("commonColorsShow", true); KisColorPatches::Direction m_commonColorsDirection; if(cfg.readEntry("commonColorsAlignment", false)) m_commonColorsDirection=KisColorPatches::Vertical; else m_commonColorsDirection=KisColorPatches::Horizontal; m_verticalColorPatchesLayout->removeWidget(m_colorHistoryWidget); m_verticalColorPatchesLayout->removeWidget(m_commonColorsWidget); m_horizontalColorPatchesLayout->removeWidget(m_colorHistoryWidget); m_horizontalColorPatchesLayout->removeWidget(m_commonColorsWidget); m_sidebarLayout->removeWidget(m_fallbackSettingsButton); m_mainLayout->removeWidget(m_fallbackSettingsButton); if(m_lastColorsShow==false) m_colorHistoryWidget->hide(); else m_colorHistoryWidget->show(); if(m_commonColorsShow==false) { m_commonColorsWidget->hide(); } else { m_commonColorsWidget->show(); } bool fallbackSettingsButtonVertical = true; if(m_lastColorsShow && m_lastColorsDirection==KisColorPatches::Vertical) { m_verticalColorPatchesLayout->addWidget(m_colorHistoryWidget); } if(m_commonColorsShow && m_commonColorsDirection==KisColorPatches::Vertical) { m_verticalColorPatchesLayout->addWidget(m_commonColorsWidget); } if(m_lastColorsShow && m_lastColorsDirection==KisColorPatches::Horizontal) { m_horizontalColorPatchesLayout->addWidget(m_colorHistoryWidget); fallbackSettingsButtonVertical = false; } if(m_commonColorsShow && m_commonColorsDirection==KisColorPatches::Horizontal) { m_horizontalColorPatchesLayout->addWidget(m_commonColorsWidget); fallbackSettingsButtonVertical = false; } // prefer the vertical column, if patch components have different layout if (m_commonColorsDirection != m_lastColorsDirection) { fallbackSettingsButtonVertical = true; } if (!showColorSelector) { if (fallbackSettingsButtonVertical) { m_sidebarLayout->addWidget(m_fallbackSettingsButton); } else { m_horizontalPatchesContainer->addWidget(m_fallbackSettingsButton); } m_fallbackSettingsButton->show(); } else { m_fallbackSettingsButton->hide(); } updateGeometry(); } void KisColorSelectorNgDockerWidget::reactOnLayerChange() { /** * Trigger the update for the case if some legacy code needs it. * Now the node's color space is managed by the * KisDisplayColorConverter and KisColorSelectorBase objects, so * technically this call is not needed anymore. Please remove it * when you are totally sure this will not break something. */ emit settingsChanged(); } diff --git a/plugins/dockers/advancedcolorselector/kis_color_selector_ng_docker_widget.h b/plugins/dockers/advancedcolorselector/kis_color_selector_ng_docker_widget.h index 1b39587a4c..e9d51d3c06 100644 --- a/plugins/dockers/advancedcolorselector/kis_color_selector_ng_docker_widget.h +++ b/plugins/dockers/advancedcolorselector/kis_color_selector_ng_docker_widget.h @@ -1,75 +1,76 @@ /* * Copyright (c) 2010 Adam Celarek * * 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. + * the Free Software Foundation; 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 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_SELECTOR_NG_DOCKER_WIDGET_H #define KIS_COLOR_SELECTOR_NG_DOCKER_WIDGET_H #include #include #include #include class QAction; class KisCommonColors; class KisColorHistory; class KisColorSelectorContainer; class QVBoxLayout; class QHBoxLayout; class KisColorSelectorNgDockerWidget : public QWidget { Q_OBJECT public: explicit KisColorSelectorNgDockerWidget(QWidget *parent = 0); void setCanvas(KisCanvas2* canvas); void unsetCanvas(); public Q_SLOTS: void openSettings(); Q_SIGNALS: void settingsChanged(); protected Q_SLOTS: void updateLayout(); void reactOnLayerChange(); private: KisColorSelectorContainer* m_colorSelectorContainer; KisColorHistory* m_colorHistoryWidget; KisCommonColors* m_commonColorsWidget; QAction * m_colorHistoryAction; QAction * m_commonColorsAction; QHBoxLayout* m_widgetLayout; QVBoxLayout* m_mainLayout; QHBoxLayout* m_horizontalPatchesContainer; QVBoxLayout* m_sidebarLayout; QHBoxLayout* m_verticalColorPatchesLayout; // vertical color patches should be added here QVBoxLayout* m_horizontalColorPatchesLayout;//horizontal ----------"---------------------- QToolButton* m_fallbackSettingsButton; QPointer m_canvas; }; #endif diff --git a/plugins/dockers/advancedcolorselector/kis_common_colors.cpp b/plugins/dockers/advancedcolorselector/kis_common_colors.cpp index f8512ea1b3..6664ac6004 100644 --- a/plugins/dockers/advancedcolorselector/kis_common_colors.cpp +++ b/plugins/dockers/advancedcolorselector/kis_common_colors.cpp @@ -1,139 +1,140 @@ /* * Copyright (c) 2010 Adam Celarek * * 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. + * the Free Software Foundation; 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 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_common_colors.h" #include #include #include #include #include #include #include #include #include #include #include #include "KoColor.h" #include "kis_canvas2.h" #include "kis_image.h" #include "kis_paint_device.h" #include "kis_config.h" #include "kis_common_colors_recalculation_runner.h" KisCommonColors::KisCommonColors(QWidget *parent) : KisColorPatches("commonColors", parent) { m_reloadButton = new QPushButton(); m_reloadButton->setIcon(KisIconUtils::loadIcon("view-refresh")); m_reloadButton->setToolTip(i18n("Create a list of colors from the image")); connect(m_reloadButton, SIGNAL(clicked()), this, SLOT(recalculate())); QList tmpList; tmpList.append(m_reloadButton); setAdditionalButtons(tmpList); updateSettings(); m_recalculationTimer.setInterval(2000); m_recalculationTimer.setSingleShot(true); connect(&m_recalculationTimer, SIGNAL(timeout()), this, SLOT(recalculate())); } void KisCommonColors::setCanvas(KisCanvas2 *canvas) { KisColorPatches::setCanvas(canvas); KConfigGroup cfg = KSharedConfig::openConfig()->group("advancedColorSelector"); if (cfg.readEntry("commonColorsAutoUpdate", false)) { if (m_image) { m_image->disconnect(this); } if (m_canvas) { connect(m_canvas->image(), SIGNAL(sigImageUpdated(QRect)), &m_recalculationTimer, SLOT(start()), Qt::UniqueConnection); m_image = m_canvas->image(); } else { m_image = 0; } } } KisColorSelectorBase* KisCommonColors::createPopup() const { KisCommonColors* ret = new KisCommonColors(); ret->setCanvas(m_canvas); ret->setColors(colors()); return ret; } void KisCommonColors::updateSettings() { KisColorPatches::updateSettings(); if(!(m_canvas && m_canvas->image())) return; KConfigGroup cfg = KSharedConfig::openConfig()->group("advancedColorSelector"); if (cfg.readEntry("commonColorsAutoUpdate", false)) { connect(m_canvas->image(), SIGNAL(sigImageUpdated(QRect)), &m_recalculationTimer, SLOT(start()), Qt::UniqueConnection); } else { disconnect(m_canvas->image(), SIGNAL(sigImageUpdated(QRect)), &m_recalculationTimer, SLOT(start())); } m_reloadButton->setEnabled(true); } void KisCommonColors::setColors(QList colors) { QMutexLocker locker(&m_mutex); KisColorPatches::setColors(colors); m_reloadButton->setEnabled(true); m_calculatedColors = colors; } void KisCommonColors::recalculate() { if (!m_canvas) { return; } if(m_reloadButton->isEnabled()==false) { // on old computation is still running // try later to recalculate m_recalculationTimer.start(); return; } m_reloadButton->setEnabled(false); qApp->processEvents(); KisImageWSP kisImage = m_canvas->image(); QImage image = kisImage->projection()->createThumbnail(1024, 1024, kisImage->bounds(), 1, KoColorConversionTransformation::internalRenderingIntent(), KoColorConversionTransformation::internalConversionFlags()); KisCommonColorsRecalculationRunner* runner = new KisCommonColorsRecalculationRunner(image, patchCount(), this); QThreadPool::globalInstance()->start(runner); } diff --git a/plugins/dockers/advancedcolorselector/kis_common_colors.h b/plugins/dockers/advancedcolorselector/kis_common_colors.h index 47470af25e..77024a2569 100644 --- a/plugins/dockers/advancedcolorselector/kis_common_colors.h +++ b/plugins/dockers/advancedcolorselector/kis_common_colors.h @@ -1,50 +1,51 @@ /* * Copyright (c) 2010 Adam Celarek * * 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. + * the Free Software Foundation; 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 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_COMMON_COLORS_H #define KIS_COMMON_COLORS_H #include #include #include "kis_color_patches.h" #include class QPushButton; class KisCommonColors : public KisColorPatches { Q_OBJECT public: explicit KisCommonColors(QWidget *parent = 0); void setCanvas(KisCanvas2 *canvas) override; void unsetCanvas() override {} KisColorSelectorBase* createPopup() const override; public Q_SLOTS: void setColors(QList colors); void updateSettings() override; void recalculate(); private: QMutex m_mutex; QTimer m_recalculationTimer; QPushButton* m_reloadButton; QList m_calculatedColors; KisImageWSP m_image; }; #endif diff --git a/plugins/dockers/advancedcolorselector/kis_minimal_shade_selector.cpp b/plugins/dockers/advancedcolorselector/kis_minimal_shade_selector.cpp index f3fc6b6d30..b33c736e6a 100644 --- a/plugins/dockers/advancedcolorselector/kis_minimal_shade_selector.cpp +++ b/plugins/dockers/advancedcolorselector/kis_minimal_shade_selector.cpp @@ -1,182 +1,183 @@ /* * Copyright (c) 2010 Adam Celarek * * 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. + * the Free Software Foundation; 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 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_minimal_shade_selector.h" #include #include #include #include #include #include #include #include "KoCanvasResourceProvider.h" #include "kis_shade_selector_line.h" #include "kis_color_selector_base_proxy.h" KisMinimalShadeSelector::KisMinimalShadeSelector(QWidget *parent) : KisColorSelectorBase(parent) , m_canvas(0) , m_proxy(new KisColorSelectorBaseProxyObject(this)) { setAcceptDrops(true); QVBoxLayout* l = new QVBoxLayout(this); l->setSpacing(0); l->setMargin(0); updateSettings(); setMouseTracking(true); } KisMinimalShadeSelector::~KisMinimalShadeSelector() { } void KisMinimalShadeSelector::unsetCanvas() { KisColorSelectorBase::unsetCanvas(); m_canvas = 0; } void KisMinimalShadeSelector::setCanvas(KisCanvas2 *canvas) { KisColorSelectorBase::setCanvas(canvas); m_canvas = canvas; } void KisMinimalShadeSelector::setColor(const KoColor& color) { m_lastRealColor = color; for(int i=0; isetColor(color); } } void KisMinimalShadeSelector::updateSettings() { KisColorSelectorBase::updateSettings(); KConfigGroup cfg = KSharedConfig::openConfig()->group("advancedColorSelector"); QString stri = cfg.readEntry("minimalShadeSelectorLineConfig", "0|0.2|0|0"); QStringList strili = stri.split(';', QString::SkipEmptyParts); int lineCount = strili.size(); while(lineCount-m_shadingLines.size() > 0) { KisShadeSelectorLine *line = new KisShadeSelectorLine(m_proxy.data(), this); m_shadingLines.append(line); m_shadingLines.last()->setLineNumber(m_shadingLines.size()-1); layout()->addWidget(m_shadingLines.last()); } while(lineCount-m_shadingLines.size() < 0) { layout()->removeWidget(m_shadingLines.last()); delete m_shadingLines.takeLast(); } for(int i=0; ifromString(strili.at(i)); } int lineHeight = cfg.readEntry("minimalShadeSelectorLineHeight", 20); setMinimumHeight(lineCount*lineHeight+2*lineCount); setMaximumHeight(lineCount*lineHeight+2*lineCount); for(int i=0; iupdateSettings(); setPopupBehaviour(false, false); } void KisMinimalShadeSelector::mousePressEvent(QMouseEvent * e) { Q_FOREACH (KisShadeSelectorLine* line, m_shadingLines) { QMouseEvent newEvent(e->type(), line->mapFromGlobal(e->globalPos()), e->button(), e->buttons(), e->modifiers()); if(line->rect().contains(newEvent.pos())) line->mousePressEvent(&newEvent); } KisColorSelectorBase::mousePressEvent(e); } void KisMinimalShadeSelector::mouseMoveEvent(QMouseEvent * e) { Q_FOREACH (KisShadeSelectorLine* line, m_shadingLines) { QMouseEvent newEvent(e->type(), line->mapFromGlobal(e->globalPos()), e->button(), e->buttons(), e->modifiers()); if(line->rect().contains(newEvent.pos())) line->mouseMoveEvent(&newEvent); } KisColorSelectorBase::mouseMoveEvent(e); } void KisMinimalShadeSelector::mouseReleaseEvent(QMouseEvent * e) { Q_FOREACH (KisShadeSelectorLine* line, m_shadingLines) { QMouseEvent newEvent(e->type(), line->mapFromGlobal(e->globalPos()), e->button(), e->buttons(), e->modifiers()); if(line->rect().contains(newEvent.pos())) line->mouseReleaseEvent(&newEvent); } KisColorSelectorBase::mouseReleaseEvent(e); } void KisMinimalShadeSelector::canvasResourceChanged(int key, const QVariant &v) { if(m_colorUpdateAllowed==false) return; KConfigGroup cfg = KSharedConfig::openConfig()->group("advancedColorSelector"); bool onForeground = cfg.readEntry("shadeSelectorUpdateOnForeground", false); bool onBackground = cfg.readEntry("shadeSelectorUpdateOnBackground", true); if ((key == KoCanvasResourceProvider::ForegroundColor && onForeground) || (key == KoCanvasResourceProvider::BackgroundColor && onBackground)) { setColor(v.value()); } } void KisMinimalShadeSelector::paintEvent(QPaintEvent *) { QPainter painter(this); painter.fillRect(0,0,width(), height(), QColor(128,128,128)); } KisColorSelectorBase* KisMinimalShadeSelector::createPopup() const { KisMinimalShadeSelector* popup = new KisMinimalShadeSelector(0); popup->setColor(m_lastRealColor); return popup; } diff --git a/plugins/dockers/advancedcolorselector/kis_minimal_shade_selector.h b/plugins/dockers/advancedcolorselector/kis_minimal_shade_selector.h index 0b86c095e2..2d4aa38ba1 100644 --- a/plugins/dockers/advancedcolorselector/kis_minimal_shade_selector.h +++ b/plugins/dockers/advancedcolorselector/kis_minimal_shade_selector.h @@ -1,63 +1,64 @@ /* * Copyright (c) 2010 Adam Celarek * * 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. + * the Free Software Foundation; 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 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_MINIMAL_SHADE_SELECTOR_H #define KIS_MINIMAL_SHADE_SELECTOR_H #include #include #include "kis_color_selector_base.h" class KisShadeSelectorLine; class KisCanvas2; class KisColorSelectorBaseProxy; class KisMinimalShadeSelector : public KisColorSelectorBase { Q_OBJECT public: explicit KisMinimalShadeSelector(QWidget *parent = 0); ~KisMinimalShadeSelector() override; void unsetCanvas() override; void setCanvas(KisCanvas2* canvas) override; protected: void setColor(const KoColor& color) override; void mouseMoveEvent(QMouseEvent *) override; void mousePressEvent(QMouseEvent *) override; void mouseReleaseEvent(QMouseEvent *) override; public Q_SLOTS: void updateSettings() override; protected Q_SLOTS: void canvasResourceChanged(int key, const QVariant& v) override; protected: void paintEvent(QPaintEvent *) override; KisColorSelectorBase* createPopup() const override; private: QList m_shadingLines; KoColor m_lastRealColor; QPointer m_canvas; QScopedPointer m_proxy; }; #endif diff --git a/plugins/dockers/advancedcolorselector/kis_my_paint_shade_selector.cpp b/plugins/dockers/advancedcolorselector/kis_my_paint_shade_selector.cpp index b7083534a3..e5f1f36e55 100644 --- a/plugins/dockers/advancedcolorselector/kis_my_paint_shade_selector.cpp +++ b/plugins/dockers/advancedcolorselector/kis_my_paint_shade_selector.cpp @@ -1,303 +1,304 @@ /* * Copyright (c) 2010 Adam Celarek * Copyright (c) 2008 Martin Renold * Copyright (c) 2009 Ilya Portnov * * This class is based on "lib/colorchanger.hpp" from MyPaint (mypaint.intilinux.com) * * 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. + * the Free Software Foundation; 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 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_my_paint_shade_selector.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include "KoColorSpace.h" #include "KoColorSpaceRegistry.h" #include "KoColor.h" #include "KoCanvasResourceProvider.h" #include "kis_paint_device.h" #include "kis_painter.h" #include "kis_display_color_converter.h" inline int sqr(int x); inline qreal sqr2(qreal x); inline int signedSqr(int x); KisMyPaintShadeSelector::KisMyPaintShadeSelector(QWidget *parent) : KisColorSelectorBase(parent), m_updateTimer(new QTimer(this)) { setAcceptDrops(true); updateSettings(); setMinimumSize(80, 80); setColor(KoColor(Qt::red, colorSpace())); m_updateTimer->setInterval(1); m_updateTimer->setSingleShot(true); connect(m_updateTimer, SIGNAL(timeout()), this, SLOT(update())); } void KisMyPaintShadeSelector::paintEvent(QPaintEvent *) { // Hint to the casual reader: some of the calculation here do not // what Martin Renold originally intended. Not everything here will make sense. // It does not matter in the end, as long as the result looks good. // This selector was ported from MyPaint in 2010 if (m_cachedColorSpace != colorSpace()) { m_realPixelCache = new KisPaintDevice(colorSpace()); m_realCircleBorder = new KisPaintDevice(colorSpace()); m_cachedColorSpace = colorSpace(); } else { m_realPixelCache->clear(); m_realCircleBorder->clear(); } KConfigGroup cfg = KSharedConfig::openConfig()->group("advancedColorSelector"); QString shadeMyPaintType=cfg.readEntry("shadeMyPaintType", "HSV"); int size = qMin(width(), height()); int s_radius = size/2.6; for (int x=0; x 0) dxs = dx - stripe_width; else dxs = dx + stripe_width; if (dy > 0) dys = dy - stripe_width; else dys = dy + stripe_width; qreal r = std::sqrt(qreal(sqr(dxs)+sqr(dys))); if (qMin(abs(dx), abs(dy)) < stripe_width) { // horizontal and vertical lines dx = (dx/qreal(width()))*255; dy = (dy/qreal(height()))*255; h = 0; // x-axis = value, y-axis = saturation v = dx*v_factor + signedSqr(dx)*v_factor2; s = - (dy*s_factor + signedSqr(dy)*s_factor2); // but not both at once if (std::abs(dx) > std::abs(dy)) { // horizontal stripe s = 0.0; } else { // vertical stripe v = 0.0; } } else if (r < s_radius+1) { // hue if (dx > 0) h = 90*sqr2(r/s_radius); else h = 360 - 90*sqr2(r/s_radius); s = 256*(atan2f(std::abs(dxs),dys)/M_PI) - 128; if (r > s_radius) { // antialiasing boarder qreal aaFactor = r-floor(r); // part after the decimal point aaFactor = 1-aaFactor; qreal fh = m_colorH + h/360.0; qreal fs = m_colorS + s/255.0; qreal fv = m_colorV + v/255.0; fh -= floor(fh); fs = qBound(qreal(0.0), fs, qreal(1.0)); fv = qBound(qreal(0.01), fv, qreal(1.0)); KoColor color; //KoColor color = converter()->fromHsvF(fh, fs, fv); if(shadeMyPaintType=="HSV"){color = converter()->fromHsvF(fh, fs, fv);} else if(shadeMyPaintType=="HSL"){color = converter()->fromHslF(fh, fs, fv);} else if(shadeMyPaintType=="HSI"){color = converter()->fromHsiF(fh, fs, fv);} else if(shadeMyPaintType=="HSY"){color = converter()->fromHsyF(fh, fs, fv, R, G, B);} else{dbgKrita<<"MyPaint Color selector don't work right."; color = converter()->fromHsvF(fh, fs, fv);} //dbgKrita<toQcolor(); color.setOpacity(aaFactor); Acs::setColor(m_realCircleBorder, QPoint(x, y), color); h = 180 + 180*atan2f(dys,-dxs)/M_PI; v = 255*(r-s_radius)/(diag-s_radius) - 128; } } else { // background (hue+darkness gradient) h = 180 + 180*atan2f(dys,-dxs)/M_PI; v = 255*(r-s_radius)/(diag-s_radius) - 128; } qreal fh = m_colorH + h/360.0; qreal fs = m_colorS + s/255.0; qreal fv = m_colorV + v/255.0; fh -= floor(fh); fs = qBound(qreal(0.0), fs, qreal(1.0)); fv = qBound(qreal(0.01), fv, qreal(1.0)); KoColor color; //KoColor color = converter()->fromHsvF(fh, fs, fv); if(shadeMyPaintType=="HSV"){color = converter()->fromHsvF(fh, fs, fv);} else if(shadeMyPaintType=="HSL"){color = converter()->fromHslF(fh, fs, fv);} else if(shadeMyPaintType=="HSI"){color = converter()->fromHsiF(fh, fs, fv);} else if(shadeMyPaintType=="HSY"){color = converter()->fromHsyF(fh, fs, fv);} else{dbgKrita<<"MyPaint Color selector don't work right."; color = converter()->fromHsvF(fh, fs, fv);} Acs::setColor(m_realPixelCache, QPoint(x, y), color); } } KisPainter gc(m_realPixelCache); gc.bitBlt(QPoint(0,0), m_realCircleBorder, rect()); QPainter painter(this); QImage renderedImage = converter()->toQImage(m_realPixelCache); painter.drawImage(0, 0, renderedImage); } void KisMyPaintShadeSelector::mousePressEvent(QMouseEvent* e) { e->setAccepted(false); KisColorSelectorBase::mousePressEvent(e); } void KisMyPaintShadeSelector::mouseMoveEvent(QMouseEvent *e) { if(rect().contains(e->pos())) { KoColor color(Acs::pickColor(m_realPixelCache, e->pos())); this->updateColorPreview(color); } KisColorSelectorBase::mouseMoveEvent(e); } void KisMyPaintShadeSelector::mouseReleaseEvent(QMouseEvent *e) { e->setAccepted(false); KisColorSelectorBase::mouseReleaseEvent(e); if(!e->isAccepted()) { KoColor color(Acs::pickColor(m_realPixelCache, e->pos())); Acs::ColorRole role = Acs::buttonToRole(e->button()); KConfigGroup cfg = KSharedConfig::openConfig()->group("advancedColorSelector"); bool onRightClick = cfg.readEntry("shadeSelectorUpdateOnRightClick", false); bool onLeftClick = cfg.readEntry("shadeSelectorUpdateOnLeftClick", false); bool explicitColorReset = (e->button() == Qt::LeftButton && onLeftClick) || (e->button() == Qt::RightButton && onRightClick); this->updateColor(color, role, explicitColorReset); e->accept(); } } KisColorSelectorBase* KisMyPaintShadeSelector::createPopup() const { KisColorSelectorBase* popup = new KisMyPaintShadeSelector(0); popup->setColor(m_lastRealColor); return popup; } void KisMyPaintShadeSelector::setColor(const KoColor &color) { KConfigGroup cfg = KSharedConfig::openConfig()->group("advancedColorSelector"); QString shadeMyPaintType=cfg.readEntry("shadeMyPaintType", "HSV"); R = cfg.readEntry("lumaR", 0.2126); G = cfg.readEntry("lumaG", 0.7152); B = cfg.readEntry("lumaB", 0.0722); if(shadeMyPaintType=="HSV"){this->converter()->getHsvF(color, &m_colorH, &m_colorS, &m_colorV);} if(shadeMyPaintType=="HSL"){this->converter()->getHslF(color, &m_colorH, &m_colorS, &m_colorV);} if(shadeMyPaintType=="HSI"){this->converter()->getHsiF(color, &m_colorH, &m_colorS, &m_colorV);} if(shadeMyPaintType=="HSY"){this->converter()->getHsyF(color, &m_colorH, &m_colorS, &m_colorV, R, G, B);} m_lastRealColor = color; this->updateColorPreview(color); m_updateTimer->start(); } void KisMyPaintShadeSelector::canvasResourceChanged(int key, const QVariant &v) { if(m_colorUpdateAllowed==false) return; KConfigGroup cfg = KSharedConfig::openConfig()->group("advancedColorSelector"); bool onForeground = cfg.readEntry("shadeSelectorUpdateOnForeground", false); bool onBackground = cfg.readEntry("shadeSelectorUpdateOnBackground", true); if ((key == KoCanvasResourceProvider::ForegroundColor && onForeground) || (key == KoCanvasResourceProvider::BackgroundColor && onBackground)) { setColor(v.value()); } } inline int sqr(int x) { return x*x; } inline qreal sqr2(qreal x) { return (x*x)/2+x/2; } inline int signedSqr(int x) { int sign = x>0?1:-1; return x*x*sign; } diff --git a/plugins/dockers/advancedcolorselector/kis_my_paint_shade_selector.h b/plugins/dockers/advancedcolorselector/kis_my_paint_shade_selector.h index f0e5bab939..319551f460 100644 --- a/plugins/dockers/advancedcolorselector/kis_my_paint_shade_selector.h +++ b/plugins/dockers/advancedcolorselector/kis_my_paint_shade_selector.h @@ -1,64 +1,65 @@ /* * Copyright (c) 2010 Adam Celarek * Copyright (c) 2008 Martin Renold * Copyright (c) 2009 Ilya Portnov * * This class is based on "lib/colorchanger.hpp" from MyPaint (mypaint.intilinux.com) * * 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. + * the Free Software Foundation; 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 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_MY_PAINT_SHADE_SELECTOR_H #define KIS_MY_PAINT_SHADE_SELECTOR_H #include "kis_color_selector_base.h" #include #include #include class KoColorSpace; class QTimer; class KisMyPaintShadeSelector : public KisColorSelectorBase { Q_OBJECT public: KisMyPaintShadeSelector(QWidget *parent = 0); void mousePressEvent(QMouseEvent *) override; void mouseMoveEvent(QMouseEvent *) override; void mouseReleaseEvent(QMouseEvent *) override; public: void setColor(const KoColor &color) override; protected Q_SLOTS: void canvasResourceChanged(int key, const QVariant& v) override; protected: void paintEvent(QPaintEvent *) override; KisColorSelectorBase* createPopup() const override; private: qreal m_colorH, m_colorS, m_colorV; qreal R, G, B; QTimer* m_updateTimer; KoColor m_lastRealColor; KisPaintDeviceSP m_realPixelCache; KisPaintDeviceSP m_realCircleBorder; const KoColorSpace *m_cachedColorSpace; }; #endif // KIS_MY_PAINT_SHADE_SELECTOR_H diff --git a/plugins/dockers/advancedcolorselector/kis_shade_selector_line.cpp b/plugins/dockers/advancedcolorselector/kis_shade_selector_line.cpp index fa743d6bfd..03fa380c66 100644 --- a/plugins/dockers/advancedcolorselector/kis_shade_selector_line.cpp +++ b/plugins/dockers/advancedcolorselector/kis_shade_selector_line.cpp @@ -1,275 +1,276 @@ /* * Copyright (c) 2010 Adam Celarek * * 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. + * the Free Software Foundation; 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 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_shade_selector_line.h" #include #include #include #include #include #include #include #include #include "kis_canvas2.h" #include "kis_color_selector_base_proxy.h" #include "kis_display_color_converter.h" #include "kis_paint_device.h" KisShadeSelectorLine::KisShadeSelectorLine(KisColorSelectorBaseProxy *parentProxy, QWidget *parent) : KisShadeSelectorLineBase(parent), m_cachedColorSpace(0), m_displayHelpText(false), m_parentProxy(parentProxy) { setParam(0, 0, 0, 0, 0, 0); updateSettings(); setMouseTracking(true); m_mouseX=width()/2; m_isDown=false; } KisShadeSelectorLine::KisShadeSelectorLine(qreal hueDelta, qreal satDelta, qreal valDelta, KisColorSelectorBaseProxy *parentProxy, QWidget *parent, qreal hueShift, qreal satShift, qreal valShift) : KisShadeSelectorLineBase(parent), m_cachedColorSpace(0), m_displayHelpText(false), m_parentProxy(parentProxy) { setParam(hueDelta, satDelta, valDelta, hueShift, satShift, valShift); updateSettings(); m_mouseX=width()/2; m_isDown=false; } KisShadeSelectorLine::~KisShadeSelectorLine() { } void KisShadeSelectorLine::setParam(qreal hueDelta, qreal satDelta, qreal valDelta, qreal hueShift, qreal satShift, qreal valShift) { m_hueDelta = hueDelta; m_saturationDelta = satDelta; m_valueDelta = valDelta; m_hueShift = hueShift; m_saturationShift = satShift; m_valueShift = valShift; } void KisShadeSelectorLine::setColor(const KoColor &color) { m_realColor = color; m_realColor.convertTo(m_parentProxy->colorSpace()); m_mouseX=width()/2; update(); } void KisShadeSelectorLine::updateSettings() { KConfigGroup cfg = KSharedConfig::openConfig()->group("advancedColorSelector"); m_gradient = cfg.readEntry("minimalShadeSelectorAsGradient", false); m_patchCount = cfg.readEntry("minimalShadeSelectorPatchCount", 10); m_lineHeight = cfg.readEntry("minimalShadeSelectorLineHeight", 20); setMaximumHeight(m_lineHeight); setMinimumHeight(m_lineHeight); } QString KisShadeSelectorLine::toString() const { return QString("%1|%2|%3|%4|%5|%6|%7").arg(m_lineNumber).arg(m_hueDelta).arg(m_saturationDelta).arg(m_valueDelta).arg(m_hueShift).arg(m_saturationShift).arg(m_valueShift); } void KisShadeSelectorLine::fromString(const QString& string) { QStringList strili = string.split('|'); m_lineNumber = strili.at(0).toInt(); m_hueDelta = strili.at(1).toDouble(); m_saturationDelta = strili.at(2).toDouble(); m_valueDelta = strili.at(3).toDouble(); if(strili.size()==4) return; // don't crash, if reading old config files. m_hueShift = strili.at(4).toDouble(); m_saturationShift = strili.at(5).toDouble(); m_valueShift = strili.at(6).toDouble(); } void KisShadeSelectorLine::paintEvent(QPaintEvent *) { if (m_cachedColorSpace != m_parentProxy->colorSpace()) { m_realPixelCache = new KisPaintDevice(m_parentProxy->colorSpace()); m_cachedColorSpace = m_parentProxy->colorSpace(); } else { m_realPixelCache->clear(); } int patchCount; int patchSpacing; if(m_gradient) { patchCount = width(); patchSpacing = 0; } else { patchCount = m_patchCount; patchSpacing = 3; } qreal patchWidth = (width()-patchSpacing*patchCount)/qreal(patchCount); qreal hueStep; qreal saturationStep; qreal valueStep; if(m_gradient){ hueStep=m_hueDelta/qreal(patchCount-10); saturationStep=m_saturationDelta/qreal(patchCount-10); valueStep=m_valueDelta/qreal(patchCount-10); } else{ hueStep=m_hueDelta/qreal(patchCount); saturationStep=m_saturationDelta/qreal(patchCount); valueStep=m_valueDelta/qreal(patchCount); } qreal baseHue; qreal baseSaturation; qreal baseValue; m_parentProxy->converter()-> getHsvF(m_realColor, &baseHue, &baseSaturation, &baseValue); int z=0; for(int i=-patchCount/2; i<=patchCount/2; i++) { if(i==0 && patchCount%2==0) continue; qreal hue = baseHue + (i * hueStep) + m_hueShift; while (hue < 0.0) hue += 1.0; while (hue > 1.0) hue -= 1.0; qreal saturation = qBound(0., baseSaturation + (i * saturationStep) + m_saturationShift, 1.); qreal value = qBound(0., baseValue + (i * valueStep) + m_valueShift, 1.); if (qAbs(i) <= 5 && m_gradient) { hue = baseHue; saturation=baseSaturation; value=baseValue; } QRect patchRect(z * (patchWidth + patchSpacing), 0, patchWidth, m_lineHeight); KoColor patchColor = m_parentProxy->converter()->fromHsvF(hue, saturation, value); patchColor.convertTo(m_realPixelCache->colorSpace()); m_realPixelCache->fill(patchRect, patchColor); z++; } QPainter wpainter(this); QImage renderedImage = m_parentProxy->converter()->toQImage(m_realPixelCache); wpainter.drawImage(0, 0, renderedImage); if (m_gradient) { wpainter.setPen(QColor(175,175,175)); wpainter.drawRect(renderedImage.width()/2-5,0,10,renderedImage.height()-1); wpainter.setPen(QColor(75,75,75)); wpainter.drawRect(renderedImage.width()/2-4,0,8,renderedImage.height()-1); wpainter.setPen(QColor(175,175,175)); qreal mouseX = (qBound(5.0,m_mouseX,m_width-5)); wpainter.drawRect(mouseX-5,0,10,renderedImage.height()-1); wpainter.setPen(QColor(75,75,75)); wpainter.drawRect(mouseX-4,0,8,renderedImage.height()-1); } m_width=width(); if(m_displayHelpText) { QString helpText(i18n("delta h=%1 s=%2 v=%3 shift h=%4 s=%5 v=%6", m_hueDelta, m_saturationDelta, m_valueDelta, m_hueShift, m_saturationShift, m_valueShift)); wpainter.setPen(QColor(255,255,255)); wpainter.drawText(rect(), helpText); } } void KisShadeSelectorLine::resizeEvent(QResizeEvent *e) { QSize m_old = e->oldSize(); QSize m_new = e->size(); int m_nWidth = m_new.width(); int m_oWidth = m_old.width(); m_width = width(); m_mouseX = m_mouseX * m_nWidth / m_oWidth; } void KisShadeSelectorLine::mousePressEvent(QMouseEvent* e) { if(e->button()!=Qt::LeftButton && e->button()!=Qt::RightButton) { e->setAccepted(false); return; } if (e->y() > 0 && e->y() < height()) { m_parentProxy->showColorPreview(); e->accept(); m_mouseX = e->x(); m_isDown=true; update(); } } void KisShadeSelectorLine::mouseMoveEvent(QMouseEvent *e) { if ((m_isDown) && (e->buttons() & Qt::LeftButton)) { m_mouseX=e->x(); const QPoint mouseEv ((qBound(5.0,m_mouseX,m_width-5)),5); KoColor color(Acs::pickColor(m_realPixelCache, mouseEv)); m_parentProxy->updateColorPreview(color); update(); } } void KisShadeSelectorLine::mouseReleaseEvent(QMouseEvent * e) { if (e->button() != Qt::LeftButton && e->button() != Qt::RightButton) { e->ignore(); return; } m_mouseX=e->x(); const QPoint mouseEv ((qBound(5.0,m_mouseX,m_width-5)),5); KoColor color(Acs::pickColor(m_realPixelCache, mouseEv)); m_parentProxy->updateColorPreview(color); Acs::ColorRole role = Acs::buttonToRole(e->button()); KConfigGroup cfg = KSharedConfig::openConfig()->group("advancedColorSelector"); bool onRightClick = cfg.readEntry("shadeSelectorUpdateOnRightClick", false); bool onLeftClick = cfg.readEntry("shadeSelectorUpdateOnLeftClick", false); bool explicitColorReset = (e->button() == Qt::LeftButton && onLeftClick) || (e->button() == Qt::RightButton && onRightClick); m_parentProxy->updateColor(color, role, explicitColorReset); e->accept(); m_isDown=false; } diff --git a/plugins/dockers/advancedcolorselector/kis_shade_selector_line.h b/plugins/dockers/advancedcolorselector/kis_shade_selector_line.h index 2ac5ec8c7a..508d327672 100644 --- a/plugins/dockers/advancedcolorselector/kis_shade_selector_line.h +++ b/plugins/dockers/advancedcolorselector/kis_shade_selector_line.h @@ -1,96 +1,97 @@ /* * Copyright (c) 2010 Adam Celarek * * 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. + * the Free Software Foundation; 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 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_SHADE_SELECTOR_LINE_H #define KIS_SHADE_SELECTOR_LINE_H #include #include #include "kis_types.h" class KisCanvas2; class KisShadeSelectorLineComboBox; class KisColorSelectorBaseProxy; class KoColorSpace; class KisShadeSelectorLineBase : public QWidget { public: KisShadeSelectorLineBase(QWidget* parent) : QWidget(parent) {} void setLineNumber(int n) {m_lineNumber=n;} virtual QString toString() const = 0; virtual void fromString(const QString& string) = 0; protected: int m_lineNumber; }; class KisShadeSelectorLine : public KisShadeSelectorLineBase { Q_OBJECT public: explicit KisShadeSelectorLine(KisColorSelectorBaseProxy *parentProxy, QWidget *parent = 0); explicit KisShadeSelectorLine(qreal hueDelta, qreal satDelta, qreal valDelta, KisColorSelectorBaseProxy *parentProxy, QWidget *parent = 0, qreal hueShift = 0, qreal satShift = 0, qreal valShift = 0); ~KisShadeSelectorLine() override; void setParam(qreal hue, qreal sat, qreal val, qreal hueShift, qreal satShift, qreal shiftVal); void setColor(const KoColor& color); void updateSettings(); void setCanvas(KisCanvas2* canvas); void showHelpText() {m_displayHelpText=true;} QString toString() const override; void fromString(const QString& string) override; void paintEvent(QPaintEvent *) override; void resizeEvent(QResizeEvent *) override; void mousePressEvent(QMouseEvent *) override; void mouseMoveEvent(QMouseEvent *) override; void mouseReleaseEvent(QMouseEvent *) override; private: qreal m_hueDelta; qreal m_saturationDelta; qreal m_valueDelta; qreal m_hueShift; qreal m_saturationShift; qreal m_valueShift; KoColor m_realColor; KisPaintDeviceSP m_realPixelCache; const KoColorSpace *m_cachedColorSpace; bool m_gradient; int m_patchCount; int m_lineHeight; bool m_displayHelpText; qreal m_mouseX; QPoint m_ev; qreal m_width; bool m_isDown; friend class KisShadeSelectorLineComboBox; KisColorSelectorBaseProxy* m_parentProxy; }; #endif // KIS_SHADE_SELECTOR_LINE_H diff --git a/plugins/dockers/advancedcolorselector/kis_shade_selector_line_combo_box.cpp b/plugins/dockers/advancedcolorselector/kis_shade_selector_line_combo_box.cpp index 1e2ecb2367..f43ece889c 100644 --- a/plugins/dockers/advancedcolorselector/kis_shade_selector_line_combo_box.cpp +++ b/plugins/dockers/advancedcolorselector/kis_shade_selector_line_combo_box.cpp @@ -1,173 +1,174 @@ /* * Copyright (c) 2010 Adam Celarek * * 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. + * the Free Software Foundation; 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 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_shade_selector_line_combo_box.h" #include #include #include #include #include #include "kis_shade_selector_line.h" #include "kis_shade_selector_line_combo_box_popup.h" #include "kis_color_selector_base_proxy.h" #include "kis_global.h" KisShadeSelectorLineComboBox::KisShadeSelectorLineComboBox(QWidget *parent) : QComboBox(parent), m_popup(new KisShadeSelectorLineComboBoxPopup(this)), m_parentProxy(new KisColorSelectorBaseProxyNoop()), m_currentLine(new KisShadeSelectorLine(0,0,0, m_parentProxy.data(), this)) { QGridLayout* l = new QGridLayout(this); l->addWidget(m_currentLine); m_currentLine->setEnabled(false); KoColor color; color.fromQColor(QColor(190, 50, 50)); m_currentLine->setColor(color); updateSettings(); } KisShadeSelectorLineComboBox::~KisShadeSelectorLineComboBox() { } void KisShadeSelectorLineComboBox::hidePopup() { QComboBox::hidePopup(); m_popup->hide(); } void KisShadeSelectorLineComboBox::showPopup() { QComboBox::showPopup(); m_popup->show(); const int widgetMargin = 20; const QRect fitRect = kisGrowRect(QApplication::desktop()->screenGeometry(), -widgetMargin); QRect popupRect = m_popup->rect(); popupRect.moveTo(mapToGlobal(QPoint())); popupRect = kisEnsureInRect(popupRect, fitRect); m_popup->move(popupRect.topLeft()); m_popup->setConfiguration(m_currentLine->toString()); } void KisShadeSelectorLineComboBox::setConfiguration(const QString &stri) { m_currentLine->fromString(stri); update(); } QString KisShadeSelectorLineComboBox::configuration() const { return m_currentLine->toString(); } void KisShadeSelectorLineComboBox::setLineNumber(int n) { m_currentLine->setLineNumber(n); for(int i=0; ilayout()->count(); i++) { KisShadeSelectorLine* item = dynamic_cast(m_popup->layout()->itemAt(i)->widget()); if(item!=0) { item->setLineNumber(n); } } } void KisShadeSelectorLineComboBox::resizeEvent(QResizeEvent *e) { Q_UNUSED(e); m_currentLine->setMaximumWidth(width()-30-m_popup->spacing); m_popup->setMinimumWidth(qMax(280, width())); m_popup->setMaximumWidth(qMax(280, width())); } void KisShadeSelectorLineComboBox::updateSettings() { m_currentLine->updateSettings(); for(int i=0; ilayout()->count(); i++) { KisShadeSelectorLine* item = dynamic_cast(m_popup->layout()->itemAt(i)->widget()); if(item!=0) { item->updateSettings(); item->m_lineHeight=30; item->setMaximumHeight(30); item->setMinimumHeight(30); } } setLineHeight(m_currentLine->m_lineHeight); } void KisShadeSelectorLineComboBox::setGradient(bool b) { m_currentLine->m_gradient=b; for(int i=0; ilayout()->count(); i++) { KisShadeSelectorLine* item = dynamic_cast(m_popup->layout()->itemAt(i)->widget()); if(item!=0) { item->m_gradient=b; } } update(); } void KisShadeSelectorLineComboBox::setPatches(bool b) { m_currentLine->m_gradient=!b; for(int i=0; ilayout()->count(); i++) { KisShadeSelectorLine* item = dynamic_cast(m_popup->layout()->itemAt(i)->widget()); if(item!=0) { item->m_gradient=!b; } } update(); } void KisShadeSelectorLineComboBox::setPatchCount(int count) { m_currentLine->m_patchCount=count; for(int i=0; ilayout()->count(); i++) { KisShadeSelectorLine* item = dynamic_cast(m_popup->layout()->itemAt(i)->widget()); if(item!=0) { item->m_patchCount=count; } } update(); } void KisShadeSelectorLineComboBox::setLineHeight(int height) { m_currentLine->m_lineHeight=height; m_currentLine->setMinimumHeight(height); m_currentLine->setMaximumHeight(height); setMinimumHeight(height+m_popup->spacing); setMaximumHeight(height+m_popup->spacing); update(); } diff --git a/plugins/dockers/advancedcolorselector/kis_shade_selector_line_combo_box.h b/plugins/dockers/advancedcolorselector/kis_shade_selector_line_combo_box.h index 72e069a631..66f97ec525 100644 --- a/plugins/dockers/advancedcolorselector/kis_shade_selector_line_combo_box.h +++ b/plugins/dockers/advancedcolorselector/kis_shade_selector_line_combo_box.h @@ -1,56 +1,57 @@ /* * Copyright (c) 2010 Adam Celarek * * 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. + * the Free Software Foundation; 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 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_SHADE_SELECTOR_LINE_COMBO_BOX_H #define KIS_SHADE_SELECTOR_LINE_COMBO_BOX_H #include class KisShadeSelectorLineComboBoxPopup; class KisShadeSelectorLine; class KisColorSelectorBaseProxy; class KisShadeSelectorLineComboBox : public QComboBox { Q_OBJECT public: explicit KisShadeSelectorLineComboBox(QWidget *parent = 0); ~KisShadeSelectorLineComboBox() override; void hidePopup() override; void showPopup() override; QString configuration() const; void setLineNumber(int n); protected: void resizeEvent(QResizeEvent *e) override; public Q_SLOTS: void setConfiguration(const QString& stri); void updateSettings(); void setGradient(bool); void setPatches(bool); void setPatchCount(int count); void setLineHeight(int height); private: KisShadeSelectorLineComboBoxPopup* m_popup; QScopedPointer m_parentProxy; KisShadeSelectorLine* m_currentLine; }; #endif // KIS_SHADE_SELECTOR_LINE_COMBO_BOX_H diff --git a/plugins/dockers/advancedcolorselector/kis_shade_selector_lines_settings.cpp b/plugins/dockers/advancedcolorselector/kis_shade_selector_lines_settings.cpp index b998933527..81d173321d 100644 --- a/plugins/dockers/advancedcolorselector/kis_shade_selector_lines_settings.cpp +++ b/plugins/dockers/advancedcolorselector/kis_shade_selector_lines_settings.cpp @@ -1,88 +1,89 @@ /* * Copyright (c) 2010 Adam Celarek * * 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. + * the Free Software Foundation; 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 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_shade_selector_lines_settings.h" #include #include #include #include #include "kis_shade_selector_line_combo_box.h" KisShadeSelectorLinesSettings::KisShadeSelectorLinesSettings(QWidget *parent) : QWidget(parent) { QVBoxLayout* l = new QVBoxLayout(this); l->setSpacing(0); l->setMargin(0); } QString KisShadeSelectorLinesSettings::toString() const { QString result; for(int i=0; iconfiguration()); result.append(';'); } return result; } void KisShadeSelectorLinesSettings::fromString(const QString &stri) { QStringList strili = stri.split(';', QString::SkipEmptyParts); setLineCount(strili.size()); for(int i=0; isetConfiguration(strili.at(i)); } } void KisShadeSelectorLinesSettings::updateSettings() { KConfigGroup cfg = KSharedConfig::openConfig()->group("advancedColorSelector"); fromString(cfg.readEntry("minimalShadeSelectorLineConfig", "0|0.2|0|0")); for(int i=0; iupdateSettings(); } } void KisShadeSelectorLinesSettings::setLineCount(int count) { bool emitSignal = (m_lineList.size()!=count)?true:false; while(count-m_lineList.size() > 0) { m_lineList.append(new KisShadeSelectorLineComboBox(this)); m_lineList.last()->setLineNumber(m_lineList.size()-1); layout()->addWidget(m_lineList.last()); } while(count-m_lineList.size() < 0) { layout()->removeWidget(m_lineList.last()); delete m_lineList.takeLast(); } for(int i=0; i * * 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. + * the Free Software Foundation; 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 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_SHADE_SELECTOR_LINES_SETTINGS_H #define KIS_SHADE_SELECTOR_LINES_SETTINGS_H #include class KisShadeSelectorLineComboBox; class KisShadeSelectorLinesSettings : public QWidget { Q_OBJECT public: explicit KisShadeSelectorLinesSettings(QWidget *parent = 0); QString toString() const; void fromString(const QString& stri); public Q_SLOTS: void updateSettings(); void setLineCount(int count); Q_SIGNALS: void setGradient(bool); void setPatches(bool); void setPatchCount(int count); void setLineHeight(int height); Q_SIGNALS: void lineCountChanged(int newLineCount); private: QList m_lineList; }; #endif // KIS_SHADE_SELECTOR_LINES_SETTINGS_H diff --git a/plugins/dockers/arrangedocker/arrange_docker_widget.cpp b/plugins/dockers/arrangedocker/arrange_docker_widget.cpp index 760ff036da..bd133d385b 100644 --- a/plugins/dockers/arrangedocker/arrange_docker_widget.cpp +++ b/plugins/dockers/arrangedocker/arrange_docker_widget.cpp @@ -1,102 +1,103 @@ /* * 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. + * the Free Software Foundation; 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 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 "arrange_docker_widget.h" #include "ui_arrange_docker_widget.h" #include "kis_debug.h" #include "kactioncollection.h" #include #include struct ArrangeDockerWidget::Private { }; ArrangeDockerWidget::ArrangeDockerWidget(QWidget *parent) : QWidget(parent), ui(new Ui::ArrangeDockerWidget), m_d(new Private) { ui->setupUi(this); } ArrangeDockerWidget::~ArrangeDockerWidget() { } void replaceAction(QToolButton *button, QAction *newAction) { Q_FOREACH (QAction *action, button->actions()) { button->removeAction(action); } if (newAction) { button->setDefaultAction(newAction); } } void ArrangeDockerWidget::setActionCollection(KActionCollection *collection) { const bool enabled = collection->action("object_order_front"); if (enabled) { replaceAction(ui->bringToFront, collection->action("object_order_front")); replaceAction(ui->raiseLevel, collection->action("object_order_raise")); replaceAction(ui->lowerLevel, collection->action("object_order_lower")); replaceAction(ui->sendBack, collection->action("object_order_back")); replaceAction(ui->leftAlign, collection->action("object_align_horizontal_left")); replaceAction(ui->hCenterAlign, collection->action("object_align_horizontal_center")); replaceAction(ui->rightAlign, collection->action("object_align_horizontal_right")); replaceAction(ui->topAlign, collection->action("object_align_vertical_top")); replaceAction(ui->vCenterAlign, collection->action("object_align_vertical_center")); replaceAction(ui->bottomAlign, collection->action("object_align_vertical_bottom")); replaceAction(ui->hDistributeLeft, collection->action("object_distribute_horizontal_left")); replaceAction(ui->hDistributeCenter, collection->action("object_distribute_horizontal_center")); replaceAction(ui->hDistributeRight, collection->action("object_distribute_horizontal_right")); replaceAction(ui->hDistributeGaps, collection->action("object_distribute_horizontal_gaps")); replaceAction(ui->vDistributeTop, collection->action("object_distribute_vertical_top")); replaceAction(ui->vDistributeCenter, collection->action("object_distribute_vertical_center")); replaceAction(ui->vDistributeBottom, collection->action("object_distribute_vertical_bottom")); replaceAction(ui->vDistributeGaps, collection->action("object_distribute_vertical_gaps")); replaceAction(ui->group, collection->action("object_group")); replaceAction(ui->ungroup, collection->action("object_ungroup")); } setEnabled(enabled); } void ArrangeDockerWidget::switchState(bool enabled) { if (enabled) { ui->buttons->show(); ui->disabledLabel->hide(); } else { ui->buttons->hide(); ui->disabledLabel->show(); } } diff --git a/plugins/dockers/arrangedocker/arrange_docker_widget.h b/plugins/dockers/arrangedocker/arrange_docker_widget.h index 4054dbc5b9..17768cd0e7 100644 --- a/plugins/dockers/arrangedocker/arrange_docker_widget.h +++ b/plugins/dockers/arrangedocker/arrange_docker_widget.h @@ -1,49 +1,50 @@ /* * 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. + * the Free Software Foundation; 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 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 ARRANGE_DOCKER_WIDGET_H #define ARRANGE_DOCKER_WIDGET_H #include #include #include "kactioncollection.h" namespace Ui { class ArrangeDockerWidget; } class ArrangeDockerWidget : public QWidget { Q_OBJECT public: explicit ArrangeDockerWidget(QWidget *parent = 0); ~ArrangeDockerWidget() override; void setActionCollection(KActionCollection *collection); void switchState(bool enabled); private: Ui::ArrangeDockerWidget *ui; struct Private; const QScopedPointer m_d; }; #endif // ARRANGE_DOCKER_WIDGET_H diff --git a/plugins/dockers/arrangedocker/arrangedocker.cpp b/plugins/dockers/arrangedocker/arrangedocker.cpp index 63f5929832..b1fbb406cd 100644 --- a/plugins/dockers/arrangedocker/arrangedocker.cpp +++ b/plugins/dockers/arrangedocker/arrangedocker.cpp @@ -1,77 +1,78 @@ /* * 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. + * the Free Software Foundation; 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 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 "arrangedocker.h" #include #include #include #include #include #include "KisViewManager.h" #include "arrangedocker_dock.h" K_PLUGIN_FACTORY_WITH_JSON(ArrangeDockerPluginFactory, "krita_arrangedocker.json", registerPlugin();) class ArrangeDockerDockFactory : public KoDockFactoryBase { public: ArrangeDockerDockFactory() { } QString id() const override { return QString( "ArrangeDocker" ); } virtual Qt::DockWidgetArea defaultDockWidgetArea() const { return Qt::RightDockWidgetArea; } QDockWidget* createDockWidget() override { ArrangeDockerDock * dockWidget = new ArrangeDockerDock(); dockWidget->setObjectName(id()); return dockWidget; } DockPosition defaultDockPosition() const override { return DockMinimized; } private: }; ArrangeDockerPlugin::ArrangeDockerPlugin(QObject *parent, const QVariantList &) : QObject(parent) { KoDockRegistry::instance()->add(new ArrangeDockerDockFactory()); } ArrangeDockerPlugin::~ArrangeDockerPlugin() { m_view = 0; } #include "arrangedocker.moc" diff --git a/plugins/dockers/arrangedocker/arrangedocker.h b/plugins/dockers/arrangedocker/arrangedocker.h index 3e1880a238..dde0404187 100644 --- a/plugins/dockers/arrangedocker/arrangedocker.h +++ b/plugins/dockers/arrangedocker/arrangedocker.h @@ -1,39 +1,40 @@ /* * 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. + * the Free Software Foundation; 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 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 _ARRANGE_DOCKER_H_ #define _ARRANGE_DOCKER_H_ #include #include class KisViewManager; /** * Template of view plugin */ class ArrangeDockerPlugin : public QObject { Q_OBJECT public: ArrangeDockerPlugin(QObject *parent, const QVariantList &); ~ArrangeDockerPlugin() override; private: KisViewManager* m_view; }; #endif diff --git a/plugins/dockers/arrangedocker/arrangedocker_dock.cpp b/plugins/dockers/arrangedocker/arrangedocker_dock.cpp index 0208d8e25c..32c11c305f 100644 --- a/plugins/dockers/arrangedocker/arrangedocker_dock.cpp +++ b/plugins/dockers/arrangedocker/arrangedocker_dock.cpp @@ -1,90 +1,91 @@ /* * 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. + * the Free Software Foundation; 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 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 "arrangedocker_dock.h" #include #include "kis_canvas2.h" #include #include "arrange_docker_widget.h" #include #include ArrangeDockerDock::ArrangeDockerDock( ) : QDockWidget(i18n("Arrange")) , m_canvas(0) { m_configWidget = new ArrangeDockerWidget(this); m_configWidget->switchState(false); setWidget(m_configWidget); setEnabled(m_canvas); } ArrangeDockerDock::~ArrangeDockerDock() { } void ArrangeDockerDock::setCanvas(KoCanvasBase * canvas) { if(canvas && m_canvas == canvas) return; if (m_canvas) { m_canvasConnections.clear(); m_canvas->disconnectCanvasObserver(this); m_canvas->image()->disconnect(this); } m_canvas = canvas ? dynamic_cast(canvas) : 0; setEnabled(m_canvas); if (m_canvas) { m_canvasConnections.addConnection( m_canvas->toolProxy(), SIGNAL(toolChanged(QString)), this, SLOT(slotToolChanged(QString))); m_canvasConnections.addConnection( m_canvas->shapeManager(), SIGNAL(selectionChanged()), this, SLOT(slotToolChanged())); slotToolChanged(); } } void ArrangeDockerDock::unsetCanvas() { setCanvas(0); } void ArrangeDockerDock::slotToolChanged() { KActionCollection *collection = m_canvas->viewManager()->actionCollection(); m_configWidget->setActionCollection(collection); } void ArrangeDockerDock::slotToolChanged(QString toolId) { bool enableWidget = (toolId == "InteractionTool") ? true : false; m_configWidget->switchState(enableWidget); slotToolChanged(); } diff --git a/plugins/dockers/arrangedocker/arrangedocker_dock.h b/plugins/dockers/arrangedocker/arrangedocker_dock.h index ffcb2eac08..ff03550cd2 100644 --- a/plugins/dockers/arrangedocker/arrangedocker_dock.h +++ b/plugins/dockers/arrangedocker/arrangedocker_dock.h @@ -1,49 +1,50 @@ /* * 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. + * the Free Software Foundation; 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 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 _GRID_DOCK_H_ #define _GRID_DOCK_H_ #include #include #include "kis_signal_auto_connection.h" class KisCanvas2; class ArrangeDockerWidget; class KisSignalAutoConnection; class ArrangeDockerDock : public QDockWidget, public KoCanvasObserverBase { Q_OBJECT public: ArrangeDockerDock(); ~ArrangeDockerDock() override; QString observerName() override { return "ArrangeDockerDock"; } void setCanvas(KoCanvasBase *canvas) override; void unsetCanvas() override; private Q_SLOTS: void slotToolChanged(); void slotToolChanged(QString toolId); private: ArrangeDockerWidget *m_configWidget; QPointer m_canvas; KisSignalAutoConnectionsStore m_canvasConnections; }; #endif diff --git a/plugins/dockers/artisticcolorselector/artisticcolorselector_dock.cpp b/plugins/dockers/artisticcolorselector/artisticcolorselector_dock.cpp index 8b700a76c8..58c9788fe0 100644 --- a/plugins/dockers/artisticcolorselector/artisticcolorselector_dock.cpp +++ b/plugins/dockers/artisticcolorselector/artisticcolorselector_dock.cpp @@ -1,459 +1,460 @@ /* * Copyright (c) 2009 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. + * the Free Software Foundation; 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 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 #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 "artisticcolorselector_dock.h" #include #include #include #include #include "ui_wdgArtisticColorSelector.h" #include "ui_wdgARCSSettings.h" #include "ui_wdgWheelPreferencesPopup.h" class KisMainWindow; struct ArtisticColorSelectorUI: public QWidget, public Ui_wdgArtisticColorSelector { ArtisticColorSelectorUI() { setupUi(this); } }; struct ARCSSettingsUI: public QWidget, public Ui_wdgARCSSettings { ARCSSettingsUI() { setupUi(this); } }; struct WheelPreferencesPopupUI: public QWidget, public Ui_wdgWheelPreferencesPopup { WheelPreferencesPopupUI() { setupUi(this); } }; ArtisticColorSelectorDock::ArtisticColorSelectorDock() : QDockWidget(i18n("Artistic Color Selector")) , m_canvas(nullptr) , m_resourceProvider(0) , m_selectedMask(nullptr) { setEnabled(false); m_hsxButtons = new QButtonGroup(); m_preferencesUI = new ARCSSettingsUI(); m_wheelPrefsUI = new WheelPreferencesPopupUI(); m_selectorUI = new ArtisticColorSelectorUI(); QPixmap hueStepsPixmap = KisIconUtils::loadIcon("wheel-sectors").pixmap(16,16); QPixmap saturationStepsPixmap = KisIconUtils::loadIcon("wheel-rings").pixmap(16,16); QPixmap valueScaleStepsPixmap = KisIconUtils::loadIcon("wheel-light").pixmap(16,16); QIcon infinityIcon = KisIconUtils::loadIcon("infinity"); m_infinityPixmap = infinityIcon.pixmap(16,16); m_selectorUI->colorSelector->loadSettings(); m_selectorUI->bnWheelPrefs->setIcon(KisIconUtils::loadIcon("wheel-sectors")); m_selectorUI->bnWheelPrefs->setPopupWidget(m_wheelPrefsUI); m_selectorUI->bnDockerPrefs->setPopupWidget(m_preferencesUI); m_selectorUI->bnDockerPrefs->setIcon(KisIconUtils::loadIcon("configure")); //preferences m_hsxButtons->addButton(m_preferencesUI->bnHsy, KisColor::HSY); m_hsxButtons->addButton(m_preferencesUI->bnHsi, KisColor::HSI); m_hsxButtons->addButton(m_preferencesUI->bnHsl, KisColor::HSL); m_hsxButtons->addButton(m_preferencesUI->bnHsv, KisColor::HSV); m_wheelPrefsUI->bnInverseSat->setChecked(m_selectorUI->colorSelector->isSaturationInverted()); m_wheelPrefsUI->labelHueSteps->setPixmap(hueStepsPixmap); m_wheelPrefsUI->labelSaturationSteps->setPixmap(saturationStepsPixmap); m_wheelPrefsUI->labelValueScaleSteps->setPixmap(valueScaleStepsPixmap); m_wheelPrefsUI->numHueSteps->setRange(MIN_NUM_UI_HUE_PIECES, MAX_NUM_HUE_PIECES); m_wheelPrefsUI->numSaturationSteps->setRange(MIN_NUM_SATURATION_RINGS, MAX_NUM_SATURATION_RINGS); m_wheelPrefsUI->numValueScaleSteps->setRange(MIN_NUM_UI_LIGHT_PIECES, MAX_NUM_LIGHT_PIECES); m_wheelPrefsUI->bnInfHueSteps->setIcon(infinityIcon); m_wheelPrefsUI->bnInfValueScaleSteps->setIcon(infinityIcon); m_wheelPrefsUI->bnInfHueSteps->setToolTip(i18n("Continuous Mode")); m_wheelPrefsUI->bnInfValueScaleSteps->setToolTip(i18n("Continuous Mode")); int selectorHueSteps = m_selectorUI->colorSelector->getNumPieces(); if (selectorHueSteps == 1) { m_wheelPrefsUI->bnInfHueSteps->setChecked(true); } else { m_wheelPrefsUI->bnInfHueSteps->setChecked(false); } m_wheelPrefsUI->numHueSteps->setValue(selectorHueSteps); m_wheelPrefsUI->numSaturationSteps->setValue(m_selectorUI->colorSelector->getNumRings()); int selectorValueScaleSteps = m_selectorUI->colorSelector->getNumLightPieces(); if (selectorValueScaleSteps == 1) { m_wheelPrefsUI->bnInfValueScaleSteps->setChecked(true); } else { m_wheelPrefsUI->bnInfValueScaleSteps->setChecked(false); } m_wheelPrefsUI->numValueScaleSteps->setValue(m_selectorUI->colorSelector->getNumLightPieces()); m_preferencesUI->bnDefInfHueSteps->setIcon(infinityIcon); m_preferencesUI->bnDefInfValueScaleSteps->setIcon(infinityIcon); m_preferencesUI->labelDefHueSteps->setPixmap(hueStepsPixmap); m_preferencesUI->labelDefSaturationSteps->setPixmap(saturationStepsPixmap); m_preferencesUI->labelDefValueScaleSteps->setPixmap(valueScaleStepsPixmap); m_preferencesUI->defaultHueSteps->setRange(MIN_NUM_HUE_PIECES, MAX_NUM_HUE_PIECES); m_preferencesUI->defaultSaturationSteps->setRange(MIN_NUM_SATURATION_RINGS, MAX_NUM_SATURATION_RINGS); m_preferencesUI->defaultValueScaleSteps->setRange(MIN_NUM_LIGHT_PIECES, MAX_NUM_LIGHT_PIECES); m_preferencesUI->defaultHueSteps->setValue(m_selectorUI->colorSelector->getDefaultHueSteps()); m_preferencesUI->defaultSaturationSteps->setValue(m_selectorUI->colorSelector->getDefaultSaturationSteps()); m_preferencesUI->defaultValueScaleSteps->setValue(m_selectorUI->colorSelector->getDefaultValueScaleSteps()); m_preferencesUI->showBgColor->setChecked(m_selectorUI->colorSelector->getShowBgColor()); m_preferencesUI->showValueScaleNumbers->setChecked(m_selectorUI->colorSelector->getShowValueScaleNumbers()); m_preferencesUI->enforceGamutMask->setChecked(m_selectorUI->colorSelector->enforceGamutMask()); m_preferencesUI->permissiveGamutMask->setChecked(!m_selectorUI->colorSelector->enforceGamutMask()); m_preferencesUI->spLumaR->setValue(m_selectorUI->colorSelector->lumaR()); m_preferencesUI->spLumaG->setValue(m_selectorUI->colorSelector->lumaG()); m_preferencesUI->spLumaB->setValue(m_selectorUI->colorSelector->lumaB()); m_preferencesUI->spLumaGamma->setValue(m_selectorUI->colorSelector->lumaGamma()); switch(m_selectorUI->colorSelector->getColorSpace()) { case KisColor::HSV: { m_preferencesUI->bnHsv->setChecked(true); } break; case KisColor::HSI: { m_preferencesUI->bnHsi->setChecked(true); } break; case KisColor::HSL: { m_preferencesUI->bnHsl->setChecked(true); } break; case KisColor::HSY: { m_preferencesUI->bnHsy->setChecked(true); } break; } if (m_selectorUI->colorSelector->getColorSpace() == KisColor::HSY) { m_preferencesUI->lumaCoefficientBox->show(); } else { m_preferencesUI->lumaCoefficientBox->hide(); } connect(m_wheelPrefsUI->numValueScaleSteps , SIGNAL(valueChanged(int)) , SLOT(slotPreferenceChanged())); connect(m_wheelPrefsUI->numHueSteps , SIGNAL(valueChanged(int)) , SLOT(slotPreferenceChanged())); connect(m_wheelPrefsUI->numSaturationSteps , SIGNAL(valueChanged(int)) , SLOT(slotPreferenceChanged())); connect(m_wheelPrefsUI->bnInverseSat , SIGNAL(clicked(bool)) , SLOT(slotPreferenceChanged())); connect(m_wheelPrefsUI->bnInfHueSteps , SIGNAL(clicked(bool)) , SLOT(slotPreferenceChanged())); connect(m_wheelPrefsUI->bnInfValueScaleSteps, SIGNAL(clicked(bool)) , SLOT(slotPreferenceChanged())); connect(m_wheelPrefsUI->bnDefault , SIGNAL(clicked(bool)) , SLOT(slotResetDefaultSettings())); connect(m_preferencesUI->defaultHueSteps , SIGNAL(valueChanged(int)) , SLOT(slotPreferenceChanged())); connect(m_preferencesUI->defaultSaturationSteps, SIGNAL(valueChanged(int)) , SLOT(slotPreferenceChanged())); connect(m_preferencesUI->defaultValueScaleSteps, SIGNAL(valueChanged(int)) , SLOT(slotPreferenceChanged())); connect(m_preferencesUI->bnDefInfHueSteps , SIGNAL(clicked(bool)) , SLOT(slotPreferenceChanged())); connect(m_preferencesUI->bnDefInfValueScaleSteps, SIGNAL(clicked(bool)) , SLOT(slotPreferenceChanged())); connect(m_preferencesUI->showBgColor , SIGNAL(toggled(bool)) , SLOT(slotPreferenceChanged())); connect(m_preferencesUI->showValueScaleNumbers, SIGNAL(toggled(bool)) , SLOT(slotPreferenceChanged())); connect(m_preferencesUI->enforceGamutMask , SIGNAL(toggled(bool)) , SLOT(slotPreferenceChanged())); connect(m_preferencesUI->spLumaR , SIGNAL(valueChanged(qreal)), SLOT(slotColorSpaceSelected())); connect(m_preferencesUI->spLumaG , SIGNAL(valueChanged(qreal)), SLOT(slotColorSpaceSelected())); connect(m_preferencesUI->spLumaB , SIGNAL(valueChanged(qreal)), SLOT(slotColorSpaceSelected())); connect(m_preferencesUI->spLumaGamma , SIGNAL(valueChanged(qreal)), SLOT(slotColorSpaceSelected())); connect(m_selectorUI->colorSelector , SIGNAL(sigFgColorChanged(KisColor)) , SLOT(slotFgColorChanged(KisColor))); connect(m_selectorUI->colorSelector , SIGNAL(sigBgColorChanged(KisColor)) , SLOT(slotBgColorChanged(KisColor))); // gamut mask connections connect(m_selectorUI->gamutMaskToolbar, SIGNAL(sigGamutMaskToggle(bool)), SLOT(slotGamutMaskToggle(bool))); connect(m_hsxButtons , SIGNAL(buttonClicked(int)) , SLOT(slotColorSpaceSelected())); setWidget(m_selectorUI); } ArtisticColorSelectorDock::~ArtisticColorSelectorDock() { m_selectorUI->colorSelector->saveSettings(); delete m_hsxButtons; } void ArtisticColorSelectorDock::setViewManager(KisViewManager* kisview) { m_resourceProvider = kisview->canvasResourceProvider(); m_selectorUI->colorSelector->setFgColor(m_resourceProvider->resourceManager()->foregroundColor()); m_selectorUI->colorSelector->setBgColor(m_resourceProvider->resourceManager()->backgroundColor()); connect(m_resourceProvider, SIGNAL(sigGamutMaskChanged(KoGamutMask*)), this, SLOT(slotGamutMaskSet(KoGamutMask*)), Qt::UniqueConnection); connect(m_resourceProvider, SIGNAL(sigGamutMaskUnset()), this, SLOT(slotGamutMaskUnset()), Qt::UniqueConnection); connect(m_resourceProvider, SIGNAL(sigGamutMaskPreviewUpdate()), this, SLOT(slotGamutMaskPreviewUpdate()), Qt::UniqueConnection); m_selectorUI->gamutMaskToolbar->connectMaskSignals(m_resourceProvider); } void ArtisticColorSelectorDock::slotCanvasResourceChanged(int key, const QVariant& value) { if(key == KoCanvasResourceProvider::ForegroundColor) m_selectorUI->colorSelector->setFgColor(value.value()); if(key == KoCanvasResourceProvider::BackgroundColor) m_selectorUI->colorSelector->setBgColor(value.value()); } void ArtisticColorSelectorDock::slotFgColorChanged(const KisColor& color) { m_resourceProvider->resourceManager()->setForegroundColor( KoColor(color.toKoColor(), m_resourceProvider->resourceManager()->foregroundColor().colorSpace()) ); } void ArtisticColorSelectorDock::slotBgColorChanged(const KisColor& color) { m_resourceProvider->resourceManager()->setBackgroundColor( KoColor(color.toKoColor(), m_resourceProvider->resourceManager()->backgroundColor().colorSpace()) ); } void ArtisticColorSelectorDock::slotColorSpaceSelected() { KisColor::Type type = static_cast( m_hsxButtons->id(m_hsxButtons->checkedButton())); m_selectorUI->colorSelector->setColorSpace(type); if (type == KisColor::HSY) { m_preferencesUI->lumaCoefficientBox->show(); } else { m_preferencesUI->lumaCoefficientBox->hide(); } m_selectorUI->colorSelector->setLumaCoefficients( m_preferencesUI->spLumaR->value(), m_preferencesUI->spLumaG->value(), m_preferencesUI->spLumaB->value(), m_preferencesUI->spLumaGamma->value() ); } void ArtisticColorSelectorDock::slotPreferenceChanged() { int hueSteps = DEFAULT_HUE_STEPS; if (m_wheelPrefsUI->bnInfHueSteps->isChecked()) { m_wheelPrefsUI->numHueSteps->setEnabled(false); hueSteps = 1; } else { m_wheelPrefsUI->numHueSteps->setEnabled(true); hueSteps = m_wheelPrefsUI->numHueSteps->value(); } m_selectorUI->colorSelector->setNumPieces(hueSteps); m_selectorUI->colorSelector->setNumRings(m_wheelPrefsUI->numSaturationSteps->value()); int valueScaleSteps; if (m_wheelPrefsUI->bnInfValueScaleSteps->isChecked()) { m_wheelPrefsUI->numValueScaleSteps->setEnabled(false); valueScaleSteps = 1; } else { valueScaleSteps = m_wheelPrefsUI->numValueScaleSteps->value(); m_wheelPrefsUI->numValueScaleSteps->setEnabled(true); } m_selectorUI->colorSelector->setNumLightPieces(valueScaleSteps); int defHueSteps; if (m_preferencesUI->bnDefInfHueSteps->isChecked()) { m_preferencesUI->defaultHueSteps->setEnabled(false); defHueSteps = 1; } else { m_preferencesUI->defaultHueSteps->setEnabled(true); defHueSteps = m_preferencesUI->defaultHueSteps->value(); } m_selectorUI->colorSelector->setDefaultHueSteps(defHueSteps); m_selectorUI->colorSelector->setDefaultSaturationSteps(m_preferencesUI->defaultSaturationSteps->value()); int defValueScaleSteps; if (m_preferencesUI->bnDefInfValueScaleSteps->isChecked()) { m_preferencesUI->defaultValueScaleSteps->setEnabled(false); defValueScaleSteps = 1; } else { m_preferencesUI->defaultValueScaleSteps->setEnabled(true); defValueScaleSteps = m_preferencesUI->defaultValueScaleSteps->value(); } m_selectorUI->colorSelector->setDefaultValueScaleSteps(defValueScaleSteps); m_selectorUI->colorSelector->setShowBgColor(m_preferencesUI->showBgColor->isChecked()); m_selectorUI->colorSelector->setShowValueScaleNumbers(m_preferencesUI->showValueScaleNumbers->isChecked()); m_selectorUI->colorSelector->setEnforceGamutMask(m_preferencesUI->enforceGamutMask->isChecked()); m_selectorUI->colorSelector->setInverseSaturation(m_wheelPrefsUI->bnInverseSat->isChecked()); } void ArtisticColorSelectorDock::slotResetDefaultSettings() { quint32 hueSteps = m_selectorUI->colorSelector->getDefaultHueSteps(); quint32 saturationSteps = m_selectorUI->colorSelector->getDefaultSaturationSteps(); quint32 valueScaleSteps = m_selectorUI->colorSelector->getDefaultValueScaleSteps(); m_selectorUI->colorSelector->setNumRings(saturationSteps); m_wheelPrefsUI->numSaturationSteps->blockSignals(true); m_wheelPrefsUI->numSaturationSteps->setValue(saturationSteps); m_wheelPrefsUI->numSaturationSteps->blockSignals(false); m_selectorUI->colorSelector->setNumPieces(hueSteps); m_wheelPrefsUI->numHueSteps->blockSignals(true); m_wheelPrefsUI->numHueSteps->setValue(hueSteps); m_wheelPrefsUI->numHueSteps->blockSignals(false); if (hueSteps == 1) { m_wheelPrefsUI->numHueSteps->setEnabled(false); m_wheelPrefsUI->bnInfHueSteps->setChecked(true); } else { m_wheelPrefsUI->numHueSteps->setEnabled(true); m_wheelPrefsUI->bnInfHueSteps->setChecked(false); } m_selectorUI->colorSelector->setNumLightPieces(valueScaleSteps); m_wheelPrefsUI->numValueScaleSteps->blockSignals(true); m_wheelPrefsUI->numValueScaleSteps->setValue(valueScaleSteps); m_wheelPrefsUI->numValueScaleSteps->blockSignals(false); if (valueScaleSteps == 1) { m_wheelPrefsUI->numValueScaleSteps->setEnabled(false); m_wheelPrefsUI->bnInfValueScaleSteps->setChecked(true); } else { m_wheelPrefsUI->numValueScaleSteps->setEnabled(true); m_wheelPrefsUI->bnInfValueScaleSteps->setChecked(false); } } void ArtisticColorSelectorDock::slotGamutMaskToggle(bool checked) { bool b = (!m_selectedMask) ? false : checked; if (b == true) { m_selectorUI->colorSelector->setGamutMask(m_selectedMask); } m_selectorUI->colorSelector->setGamutMaskOn(b); } void ArtisticColorSelectorDock::setCanvas(KoCanvasBase *canvas) { if (!canvas) { return; } m_canvas = dynamic_cast(canvas); if (m_canvas) { m_canvas->disconnectCanvasObserver(this); } if (m_canvas) { connect(m_canvas->resourceManager(), SIGNAL(canvasResourceChanged(int,QVariant)), SLOT(slotCanvasResourceChanged(int,QVariant)), Qt::UniqueConnection); connect(m_canvas->displayColorConverter(), SIGNAL(displayConfigurationChanged()), SLOT(slotSelectorSettingsChanged()), Qt::UniqueConnection); m_selectorUI->colorSelector->setColorConverter(m_canvas->displayColorConverter()); setEnabled(true); } } void ArtisticColorSelectorDock::unsetCanvas() { setEnabled(false); m_canvas = nullptr; m_selectorUI->colorSelector->setColorConverter(KisDisplayColorConverter::dumbConverterInstance()); } void ArtisticColorSelectorDock::slotGamutMaskSet(KoGamutMask *mask) { if (!mask) { return; } m_selectedMask = mask; if (m_selectedMask) { m_selectorUI->colorSelector->setGamutMask(m_selectedMask); slotGamutMaskToggle(true); } else { slotGamutMaskToggle(false); } } void ArtisticColorSelectorDock::slotGamutMaskUnset() { if (!m_selectedMask) { return; } m_selectedMask = nullptr; slotGamutMaskToggle(false); m_selectorUI->colorSelector->setGamutMask(m_selectedMask); } void ArtisticColorSelectorDock::slotGamutMaskPreviewUpdate() { m_selectorUI->colorSelector->setDirty(); } void ArtisticColorSelectorDock::slotSelectorSettingsChanged() { m_selectorUI->colorSelector->setDirty(); } diff --git a/plugins/dockers/artisticcolorselector/artisticcolorselector_dock.h b/plugins/dockers/artisticcolorselector/artisticcolorselector_dock.h index 23112382c8..68172f0c43 100644 --- a/plugins/dockers/artisticcolorselector/artisticcolorselector_dock.h +++ b/plugins/dockers/artisticcolorselector/artisticcolorselector_dock.h @@ -1,86 +1,87 @@ /* * Copyright (c) 2009 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. + * the Free Software Foundation; 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 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 H_ARTISTIC_COLOR_SELECTOR_DOCK_H #define H_ARTISTIC_COLOR_SELECTOR_DOCK_H #include #include #include #include #include #include #include #include #include #include #include #include class KisCanvasResourceProvider; class KisColor; class QButtonGroup; class QMenu; struct ArtisticColorSelectorUI; struct ARCSSettingsUI; struct WheelPreferencesPopupUI; class ArtisticColorSelectorDock: public QDockWidget, public KisMainwindowObserver { Q_OBJECT public: ArtisticColorSelectorDock(); ~ArtisticColorSelectorDock() override; QString observerName() override { return "ArtisticColorSelectorDock"; } void setViewManager(KisViewManager* kisview) override; void setCanvas(KoCanvasBase* canvas) override; void unsetCanvas() override; private Q_SLOTS: void slotCanvasResourceChanged(int key, const QVariant& value); void slotFgColorChanged(const KisColor& color); void slotBgColorChanged(const KisColor& color); void slotColorSpaceSelected(); void slotPreferenceChanged(); void slotResetDefaultSettings(); void slotGamutMaskToggle(bool value); void slotGamutMaskSet(KoGamutMask* mask); void slotGamutMaskUnset(); void slotGamutMaskPreviewUpdate(); void slotSelectorSettingsChanged(); private: KisCanvas2* m_canvas; KisCanvasResourceProvider* m_resourceProvider; QButtonGroup* m_hsxButtons; ArtisticColorSelectorUI* m_selectorUI; ARCSSettingsUI* m_preferencesUI; WheelPreferencesPopupUI* m_wheelPrefsUI; KoGamutMask* m_selectedMask; QIcon m_iconMaskOff; QIcon m_iconMaskOn; QPixmap m_infinityPixmap; }; #endif // H_ARTISTIC_COLOR_SELECTOR_DOCK_H diff --git a/plugins/dockers/artisticcolorselector/artisticcolorselector_plugin.cpp b/plugins/dockers/artisticcolorselector/artisticcolorselector_plugin.cpp index 7051282cd8..be960ebc89 100644 --- a/plugins/dockers/artisticcolorselector/artisticcolorselector_plugin.cpp +++ b/plugins/dockers/artisticcolorselector/artisticcolorselector_plugin.cpp @@ -1,57 +1,58 @@ /* * Copyright (c) 2009 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. + * the Free Software Foundation; 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 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 "artisticcolorselector_plugin.h" #include "artisticcolorselector_dock.h" #include #include #include #include K_PLUGIN_FACTORY_WITH_JSON(PaletteDockPluginFactory, "krita_artisticcolorselector.json", registerPlugin();) class ArtisticColorSelectorDockFactory: public KoDockFactoryBase { public: QString id() const override { return QString("ArtisticColorSelector"); } virtual Qt::DockWidgetArea defaultDockWidgetArea() const { return Qt::RightDockWidgetArea; } QDockWidget* createDockWidget() override { ArtisticColorSelectorDock* dockWidget = new ArtisticColorSelectorDock(); dockWidget->setObjectName(id()); return dockWidget; } DockPosition defaultDockPosition() const override { return DockMinimized; } }; ArtisticColorSelectorPlugin::ArtisticColorSelectorPlugin(QObject* parent, const QVariantList &): QObject(parent) { KoDockRegistry::instance()->add(new ArtisticColorSelectorDockFactory()); } #include "artisticcolorselector_plugin.moc" diff --git a/plugins/dockers/artisticcolorselector/artisticcolorselector_plugin.h b/plugins/dockers/artisticcolorselector/artisticcolorselector_plugin.h index 808acba69c..98e0e2070d 100644 --- a/plugins/dockers/artisticcolorselector/artisticcolorselector_plugin.h +++ b/plugins/dockers/artisticcolorselector/artisticcolorselector_plugin.h @@ -1,30 +1,31 @@ /* * Copyright (c) 2009 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. + * the Free Software Foundation; 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 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 H_ARTISTIC_COLOR_SELECTOR_PLUGIN_H #define H_ARTISTIC_COLOR_SELECTOR_PLUGIN_H #include #include class ArtisticColorSelectorPlugin: public QObject { public: ArtisticColorSelectorPlugin(QObject *parent, const QVariantList &); }; #endif // H_ARTISTIC_COLOR_SELECTOR_PLUGIN_H diff --git a/plugins/dockers/artisticcolorselector/kis_arcs_constants.h b/plugins/dockers/artisticcolorselector/kis_arcs_constants.h index 4a40cbbfb4..c0421db5ef 100644 --- a/plugins/dockers/artisticcolorselector/kis_arcs_constants.h +++ b/plugins/dockers/artisticcolorselector/kis_arcs_constants.h @@ -1,54 +1,55 @@ /* * Copyright (c) 2018 Anna Medonosova * * 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. + * the Free Software Foundation; 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 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_ARCS_CONSTANTS_H #define KIS_ARCS_CONSTANTS_H #include #include static const int MIN_NUM_HUE_PIECES = 1; static const int MIN_NUM_UI_HUE_PIECES = 2; static const int MAX_NUM_HUE_PIECES = 48; static const int MIN_NUM_LIGHT_PIECES = 1; static const int MIN_NUM_UI_LIGHT_PIECES = 2; static const int MAX_NUM_LIGHT_PIECES = 30; static const int MIN_NUM_SATURATION_RINGS = 1; static const int MAX_NUM_SATURATION_RINGS = 20; static const int DEFAULT_HUE_STEPS = 12; static const int DEFAULT_SATURATION_STEPS = 7; static const int DEFAULT_VALUE_SCALE_STEPS = 11; static const qreal DEFAULT_LUMA_R = 0.2126; static const qreal DEFAULT_LUMA_G = 0.7152; static const qreal DEFAULT_LUMA_B = 0.0722; static const qreal DEFAULT_LUMA_GAMMA = 2.2; // color scheme for the selector static const QColor COLOR_MIDDLE_GRAY = QColor(128,128,128,255); static const QColor COLOR_DARK = QColor(50,50,50,255); static const QColor COLOR_LIGHT = QColor(200,200,200,255); static const QColor COLOR_SELECTED_DARK = QColor(30,30,30,255); static const QColor COLOR_SELECTED_LIGHT = QColor(220,220,220,255); static const QColor COLOR_MASK_FILL = COLOR_MIDDLE_GRAY; static const QColor COLOR_MASK_OUTLINE = COLOR_LIGHT; static const QColor COLOR_MASK_CLEAR = COLOR_LIGHT; static const QColor COLOR_NORMAL_OUTLINE = COLOR_MIDDLE_GRAY; #endif // KIS_ARCS_CONSTANTS_H diff --git a/plugins/dockers/channeldocker/channeldocker.cpp b/plugins/dockers/channeldocker/channeldocker.cpp index 0b8b0239b0..cb24487c99 100644 --- a/plugins/dockers/channeldocker/channeldocker.cpp +++ b/plugins/dockers/channeldocker/channeldocker.cpp @@ -1,87 +1,88 @@ /* * Copyright (c) 2011 Sven Langkamp * * 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. + * the Free Software Foundation; 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 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 "channeldocker.h" #include #include #include #include #include #include #include "kis_config.h" #include "kis_cursor.h" #include "kis_global.h" #include "kis_types.h" #include "KisViewManager.h" #include "channeldocker_dock.h" #include K_PLUGIN_FACTORY_WITH_JSON(ChannelDockerPluginFactory, "krita_channeldocker.json", registerPlugin();) class ChannelDockerDockFactory : public KoDockFactoryBase { public: ChannelDockerDockFactory() { } QString id() const override { return QString( "ChannelDocker" ); } virtual Qt::DockWidgetArea defaultDockWidgetArea() const { return Qt::RightDockWidgetArea; } QDockWidget* createDockWidget() override { ChannelDockerDock * dockWidget = new ChannelDockerDock(); dockWidget->setObjectName(id()); return dockWidget; } DockPosition defaultDockPosition() const override { return DockMinimized; } private: }; ChannelDockerPlugin::ChannelDockerPlugin(QObject *parent, const QVariantList &) : QObject(parent) { KoDockRegistry::instance()->add(new ChannelDockerDockFactory()); } ChannelDockerPlugin::~ChannelDockerPlugin() { } #include "channeldocker.moc" diff --git a/plugins/dockers/channeldocker/channeldocker.h b/plugins/dockers/channeldocker/channeldocker.h index bf374e8302..b68e493228 100644 --- a/plugins/dockers/channeldocker/channeldocker.h +++ b/plugins/dockers/channeldocker/channeldocker.h @@ -1,36 +1,37 @@ /* * Copyright (c) 2011 Sven Langkamp * * 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. + * the Free Software Foundation; 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 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 CHANNELDOCKER_H #define CHANNELDOCKER_H #include #include /** * Docker showing the channels of the current layer */ class ChannelDockerPlugin : public QObject { Q_OBJECT public: ChannelDockerPlugin(QObject *parent, const QVariantList &); ~ChannelDockerPlugin() override; }; #endif diff --git a/plugins/dockers/channeldocker/channeldocker_dock.cpp b/plugins/dockers/channeldocker/channeldocker_dock.cpp index 57f385b1d7..ea692a07ab 100644 --- a/plugins/dockers/channeldocker/channeldocker_dock.cpp +++ b/plugins/dockers/channeldocker/channeldocker_dock.cpp @@ -1,126 +1,127 @@ /* * Copyright (c) 2011 Sven Langkamp * * 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. + * the Free Software Foundation; 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 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 "channeldocker_dock.h" #include #include #include #include #include #include "channelmodel.h" #include #include #include #include #include #include #include #include "kis_signal_compressor.h" #include #include ChannelDockerDock::ChannelDockerDock( ) : QDockWidget(i18n("Channels")), m_imageIdleWatcher(new KisIdleWatcher(250, this)), m_canvas(0) { m_channelTable = new QTableView(this); m_model = new ChannelModel(this); m_channelTable->setModel(m_model); m_channelTable->setShowGrid(false); m_channelTable->horizontalHeader()->setStretchLastSection(true); m_channelTable->verticalHeader()->setVisible(false); m_channelTable->horizontalHeader()->setVisible(false); m_channelTable->setSelectionBehavior( QAbstractItemView::SelectRows ); QScroller *scroller = KisKineticScroller::createPreconfiguredScroller(m_channelTable); if (scroller){ connect(scroller, SIGNAL(stateChanged(QScroller::State)), this, SLOT(slotScrollerStateChanged(QScroller::State))); } setWidget(m_channelTable); connect(m_channelTable,&QTableView::activated, m_model, &ChannelModel::rowActivated); } void ChannelDockerDock::setCanvas(KoCanvasBase * canvas) { if(m_canvas == canvas) return; setEnabled(canvas != 0); if (m_canvas) { m_canvas->disconnectCanvasObserver(this); m_canvas->image()->disconnect(this); } if (!canvas) { m_canvas = 0; return; } m_canvas = dynamic_cast(canvas); if ( m_canvas && m_canvas->image() ) { m_model->slotSetCanvas(m_canvas); KisPaintDeviceSP dev = m_canvas->image()->projection(); m_imageIdleWatcher->setTrackedImage(m_canvas->image()); connect(m_imageIdleWatcher, &KisIdleWatcher::startedIdleMode, this, &ChannelDockerDock::updateChannelTable); connect(dev, SIGNAL(colorSpaceChanged(const KoColorSpace*)), m_model, SLOT(slotColorSpaceChanged(const KoColorSpace*))); connect(dev, SIGNAL(colorSpaceChanged(const KoColorSpace*)), m_canvas, SLOT(channelSelectionChanged())); connect(m_model, SIGNAL(channelFlagsChanged()), m_canvas, SLOT(channelSelectionChanged())); m_imageIdleWatcher->startCountdown(); } } void ChannelDockerDock::unsetCanvas() { setEnabled(false); m_canvas = 0; m_model->unsetCanvas(); } void ChannelDockerDock::showEvent(QShowEvent *event) { Q_UNUSED(event); m_imageIdleWatcher->startCountdown(); } void ChannelDockerDock::startUpdateCanvasProjection() { m_imageIdleWatcher->startCountdown(); } void ChannelDockerDock::updateChannelTable() { if (isVisible() && m_canvas && m_canvas->image()){ m_model->updateData(m_canvas); m_channelTable->resizeRowsToContents(); m_channelTable->resizeColumnsToContents(); } } diff --git a/plugins/dockers/channeldocker/channeldocker_dock.h b/plugins/dockers/channeldocker/channeldocker_dock.h index 57ba3531dd..9a295a33db 100644 --- a/plugins/dockers/channeldocker/channeldocker_dock.h +++ b/plugins/dockers/channeldocker/channeldocker_dock.h @@ -1,60 +1,61 @@ /* * Copyright (c) 2011 Sven Langkamp * * 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. + * the Free Software Foundation; 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 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 CHANNELDOCKER_DOCK_H #define CHANNELDOCKER_DOCK_H #include #include #include #include #include class ChannelModel; class QTableView; class KisSignalCompressor; class KisIdleWatcher; class ChannelDockerDock : public QDockWidget, public KoCanvasObserverBase { Q_OBJECT public: ChannelDockerDock(); QString observerName() override { return "ChannelDockerDock"; } void setCanvas(KoCanvasBase *canvas) override; void unsetCanvas() override; void showEvent(QShowEvent *event) override; public Q_SLOTS: void startUpdateCanvasProjection(); void slotScrollerStateChanged(QScroller::State state){KisKineticScroller::updateCursor(this, state);} private Q_SLOTS: void updateChannelTable(void); private: KisIdleWatcher* m_imageIdleWatcher; KisSignalCompressor *m_compressor; QPointer m_canvas; QTableView *m_channelTable; ChannelModel *m_model; }; #endif diff --git a/plugins/dockers/channeldocker/channelmodel.cpp b/plugins/dockers/channeldocker/channelmodel.cpp index 9b0f9b4f0b..23fa4bdcc4 100644 --- a/plugins/dockers/channeldocker/channelmodel.cpp +++ b/plugins/dockers/channeldocker/channelmodel.cpp @@ -1,263 +1,264 @@ /* * Copyright (c) 2011 Sven Langkamp * * 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. + * the Free Software Foundation; 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 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 "channelmodel.h" #include #include #include #include #include #include #include #include #include ChannelModel::ChannelModel(QObject* parent): QAbstractTableModel(parent), m_canvas(nullptr), m_oversampleRatio(2), m_channelCount(0) { setThumbnailSizeLimit(QSize(64, 64)); } ChannelModel::~ChannelModel() { } QVariant ChannelModel::data(const QModelIndex& index, int role) const { if (m_canvas && index.isValid()) { KisGroupLayerSP rootLayer = m_canvas->image()->rootLayer(); const KoColorSpace* cs = rootLayer->colorSpace(); QList channels = cs->channels(); int channelIndex = index.row(); switch (role) { case Qt::DisplayRole: { if (index.column() == 2) { return channels.at(channelIndex)->name(); } return QVariant(); } case Qt::DecorationRole: { if (index.column() == 1) { Q_ASSERT(m_thumbnails.count() > index.row()); return QVariant(m_thumbnails.at(index.row())); } return QVariant(); } case Qt::CheckStateRole: { Q_ASSERT(index.row() < rowCount()); Q_ASSERT(index.column() < columnCount()); if (index.column() == 0) { QBitArray flags = rootLayer->channelFlags(); return (flags.isEmpty() || flags.testBit(channelIndex)) ? Qt::Checked : Qt::Unchecked; } return QVariant(); } } } return QVariant(); } QVariant ChannelModel::headerData(int section, Qt::Orientation orientation, int role) const { Q_UNUSED(section); Q_UNUSED(orientation); Q_UNUSED(role); return QVariant(); } int ChannelModel::rowCount(const QModelIndex& /*parent*/) const { if (!m_canvas) return 0; return m_channelCount; } int ChannelModel::columnCount(const QModelIndex& /*parent*/) const { if (!m_canvas) return 0; //columns are: checkbox, thumbnail, channel name return 3; } bool ChannelModel::setData(const QModelIndex& index, const QVariant& value, int role) { if (m_canvas && m_canvas->image()) { KisGroupLayerSP rootLayer = m_canvas->image()->rootLayer(); const KoColorSpace* cs = rootLayer->colorSpace(); QList channels = cs->channels(); Q_ASSERT(index.row() <= channels.count()); int channelIndex = index.row(); if (role == Qt::CheckStateRole) { QBitArray flags = rootLayer->channelFlags(); flags = flags.isEmpty() ? cs->channelFlags(true, true) : flags; Q_ASSERT(!flags.isEmpty()); flags.setBit(channelIndex, value.toInt() == Qt::Checked); rootLayer->setChannelFlags(flags); emit channelFlagsChanged(); emit dataChanged(this->index(0, 0), this->index(channels.count(), 0)); return true; } } return false; } //User double clicked on a row (but on channel checkbox) //we select this channel, and deselect all other channels (except alpha, which we don't touch) //this makes it fast to select single color channel void ChannelModel::rowActivated(const QModelIndex &index) { if (m_canvas && m_canvas->image()) { KisGroupLayerWSP rootLayer = m_canvas->image()->rootLayer(); const KoColorSpace* cs = rootLayer->colorSpace(); QList channels = cs->channels(); Q_ASSERT(index.row() <= channels.count()); int channelIndex = index.row(); QBitArray flags = rootLayer->channelFlags(); flags = flags.isEmpty() ? cs->channelFlags(true, true) : flags; Q_ASSERT(!flags.isEmpty()); for (int i = 0; i < channels.count(); ++i) { if (channels[i]->channelType() != KoChannelInfo::ALPHA) { flags.setBit(i, (i == channelIndex)); } } rootLayer->setChannelFlags(flags); emit channelFlagsChanged(); emit dataChanged(this->index(0, 0), this->index(channels.count(), 0)); } } Qt::ItemFlags ChannelModel::flags(const QModelIndex& /*index*/) const { Qt::ItemFlags flags = Qt::ItemIsSelectable | Qt::ItemIsEnabled | Qt::ItemIsUserCheckable; return flags; } void ChannelModel::unsetCanvas() { m_canvas = 0; } void ChannelModel::setThumbnailSizeLimit(QSize size) { m_thumbnailSizeLimit = size; updateData(m_canvas); } void ChannelModel::slotSetCanvas(KisCanvas2 *canvas) { if (m_canvas != canvas) { beginResetModel(); m_canvas = canvas; if (m_canvas && m_canvas->image()) { m_channelCount = m_canvas->image()->colorSpace()->channelCount(); updateThumbnails(); } else { m_channelCount = 0; } endResetModel(); } } void ChannelModel::slotColorSpaceChanged(const KoColorSpace *colorSpace) { Q_UNUSED(colorSpace); beginResetModel(); updateThumbnails(); endResetModel(); } void ChannelModel::updateData(KisCanvas2 *canvas) { beginResetModel(); m_canvas = canvas; m_channelCount = (m_canvas) ? m_canvas->image()->colorSpace()->channelCount() : 0; updateThumbnails(); endResetModel(); } //Create thumbnails from full image. //Assumptions: thumbnail size is small compared to the original image and thumbnail quality //doesn't need to be high, so we use fast but not very accurate algorithm. void ChannelModel::updateThumbnails(void) { if (m_canvas && m_canvas->image()) { KisImageSP canvas_image = m_canvas->image(); const KoColorSpace* cs = canvas_image->colorSpace(); m_channelCount = cs->channelCount(); KisPaintDeviceSP dev = canvas_image->projection(); //make sure thumbnail maintains aspect ratio of the original image QSize thumbnailSize(canvas_image->bounds().size()); thumbnailSize.scale(m_thumbnailSizeLimit, Qt::KeepAspectRatio); KisPaintDeviceSP thumbnailDev = dev->createThumbnailDeviceOversampled(thumbnailSize.width(), thumbnailSize.height(), m_oversampleRatio, canvas_image->bounds()); m_thumbnails.resize(m_channelCount); for (quint32 i = 0; i < (quint32)m_channelCount; ++i) { #if QT_VERSION >= 0x050500 m_thumbnails[i] = QImage(thumbnailSize, QImage::Format_Grayscale8); #else m_thumbnails[i] = QImage(thumbnailSize, QImage::Format_ARGB32_Premultiplied); #endif } KisSequentialConstIterator it(thumbnailDev, QRect(0, 0, thumbnailSize.width(), thumbnailSize.height())); for (int y = 0; y < thumbnailSize.height(); y++) { for (int x = 0; x < thumbnailSize.width(); x++) { it.nextPixel(); const quint8* pixel = it.rawDataConst(); for (int chan = 0; chan < m_channelCount; ++chan) { QImage &img = m_thumbnails[chan]; #if QT_VERSION >= 0x050500 *(img.scanLine(y) + x) = cs->scaleToU8(pixel, chan); #else quint8 v = cs->scaleToU8(pixel, chan); img.setPixel(x, y, qRgb(v, v, v)); #endif } } } } else { m_channelCount = 0; } } #include "moc_channelmodel.cpp" diff --git a/plugins/dockers/channeldocker/channelmodel.h b/plugins/dockers/channeldocker/channelmodel.h index a05b73c068..992ae0a8e4 100644 --- a/plugins/dockers/channeldocker/channelmodel.h +++ b/plugins/dockers/channeldocker/channelmodel.h @@ -1,70 +1,71 @@ /* * Copyright (c) 2011 Sven Langkamp * * 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. + * the Free Software Foundation; 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 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 CHANNELMODEL_H #define CHANNELMODEL_H #include #include #include #include #include class KoColorSpace; class ChannelModel : public QAbstractTableModel { Q_OBJECT public: ChannelModel(QObject* parent = 0); ~ChannelModel() override; QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const override; QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const override; int rowCount(const QModelIndex& parent = QModelIndex()) const override; int columnCount(const QModelIndex& parent = QModelIndex()) const override; bool setData(const QModelIndex& index, const QVariant& value, int role = Qt::EditRole) override; Qt::ItemFlags flags(const QModelIndex& index) const override; void unsetCanvas( void ); //set maximum size of the thumbnail image. This should be set based on screen resolution, etc. void setThumbnailSizeLimit(QSize size); public Q_SLOTS: void slotSetCanvas(KisCanvas2* canvas); void slotColorSpaceChanged(const KoColorSpace *colorSpace); void updateData(KisCanvas2 *canvas); void rowActivated(const QModelIndex &index); Q_SIGNALS: void channelFlagsChanged(); private: void updateThumbnails(); private: QPointer m_canvas; QVector m_thumbnails; QSize m_thumbnailSizeLimit; int m_oversampleRatio; int m_channelCount; }; #endif // CHANNELMODEL_H diff --git a/plugins/dockers/compositiondocker/compositiondocker.cpp b/plugins/dockers/compositiondocker/compositiondocker.cpp index acd1324500..afa79677b6 100644 --- a/plugins/dockers/compositiondocker/compositiondocker.cpp +++ b/plugins/dockers/compositiondocker/compositiondocker.cpp @@ -1,86 +1,87 @@ /* * Copyright (c) 2011 Sven Langkamp * * 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. + * the Free Software Foundation; 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 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 "compositiondocker.h" #include #include #include #include #include #include #include "kis_config.h" #include "kis_cursor.h" #include "kis_global.h" #include "kis_types.h" #include "KisViewManager.h" #include "compositiondocker_dock.h" #include K_PLUGIN_FACTORY_WITH_JSON(CompositionDockerPluginFactory, "krita_compositiondocker.json", registerPlugin();) class CompositionDockerDockFactory : public KoDockFactoryBase { public: CompositionDockerDockFactory() { } QString id() const override { return QString( "CompositionDocker" ); } virtual Qt::DockWidgetArea defaultDockWidgetArea() const { return Qt::RightDockWidgetArea; } QDockWidget* createDockWidget() override { CompositionDockerDock * dockWidget = new CompositionDockerDock(); dockWidget->setObjectName(id()); return dockWidget; } DockPosition defaultDockPosition() const override { return DockMinimized; } private: }; CompositionDockerPlugin::CompositionDockerPlugin(QObject *parent, const QVariantList &) : QObject(parent) { KoDockRegistry::instance()->add(new CompositionDockerDockFactory()); } CompositionDockerPlugin::~CompositionDockerPlugin() { } #include "compositiondocker.moc" diff --git a/plugins/dockers/compositiondocker/compositiondocker.h b/plugins/dockers/compositiondocker/compositiondocker.h index d715d38316..247132944d 100644 --- a/plugins/dockers/compositiondocker/compositiondocker.h +++ b/plugins/dockers/compositiondocker/compositiondocker.h @@ -1,36 +1,37 @@ /* * Copyright (c) 2012 Sven Langkamp * * 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. + * the Free Software Foundation; 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 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 COMPOSITIONDOCKER_H #define COMPOSITIONDOCKER_H #include #include /** * Docker compositions of the image */ class CompositionDockerPlugin : public QObject { Q_OBJECT public: CompositionDockerPlugin(QObject *parent, const QVariantList &); ~CompositionDockerPlugin() override; }; #endif diff --git a/plugins/dockers/compositiondocker/compositiondocker_dock.cpp b/plugins/dockers/compositiondocker/compositiondocker_dock.cpp index 7b7eaacfa7..bfa840a8b7 100644 --- a/plugins/dockers/compositiondocker/compositiondocker_dock.cpp +++ b/plugins/dockers/compositiondocker/compositiondocker_dock.cpp @@ -1,309 +1,310 @@ /* * Copyright (c) 2012 Sven Langkamp * * 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. + * the Free Software Foundation; 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 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 "compositiondocker_dock.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 "compositionmodel.h" CompositionDockerDock::CompositionDockerDock( ) : QDockWidget(i18n("Compositions")), m_canvas(0) { QWidget* widget = new QWidget(this); setupUi(widget); m_model = new CompositionModel(this); compositionView->setModel(m_model); compositionView->installEventFilter(this); deleteButton->setIcon(KisIconUtils::loadIcon("edit-delete")); saveButton->setIcon(KisIconUtils::loadIcon("list-add")); exportButton->setIcon(KisIconUtils::loadIcon("document-export")); deleteButton->setToolTip(i18n("Delete Composition")); saveButton->setToolTip(i18n("New Composition")); exportButton->setToolTip(i18n("Export Composition")); setWidget(widget); connect( compositionView, SIGNAL(doubleClicked(QModelIndex)), this, SLOT(activated(QModelIndex)) ); compositionView->setContextMenuPolicy(Qt::CustomContextMenu); connect( compositionView, SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(customContextMenuRequested(QPoint))); connect( deleteButton, SIGNAL(clicked(bool)), this, SLOT(deleteClicked())); connect( saveButton, SIGNAL(clicked(bool)), this, SLOT(saveClicked())); connect( exportButton, SIGNAL(clicked(bool)), this, SLOT(exportClicked())); saveNameEdit->setPlaceholderText(i18n("Insert Name")); QScroller *scroller = KisKineticScroller::createPreconfiguredScroller(compositionView); if (scroller) { connect(scroller, SIGNAL(stateChanged(QScroller::State)), this, SLOT(slotScrollerStateChanged(QScroller::State))); } } CompositionDockerDock::~CompositionDockerDock() { } void CompositionDockerDock::setCanvas(KoCanvasBase * canvas) { if (m_canvas && m_canvas->viewManager()) { Q_FOREACH (KisAction *action, m_actions) { m_canvas->viewManager()->actionManager()->takeAction(action); } } unsetCanvas(); setEnabled(canvas != 0); m_canvas = dynamic_cast(canvas); if (m_canvas && m_canvas->viewManager()) { if (m_actions.isEmpty()) { KisAction *updateAction = m_canvas->viewManager()->actionManager()->createAction("update_composition"); connect(updateAction, SIGNAL(triggered()), this, SLOT(updateComposition())); m_actions.append(updateAction); KisAction *renameAction = m_canvas->viewManager()->actionManager()->createAction("rename_composition"); connect(renameAction, SIGNAL(triggered()), this, SLOT(renameComposition())); m_actions.append(renameAction); } else { Q_FOREACH (KisAction *action, m_actions) { m_canvas->viewManager()->actionManager()->addAction(action->objectName(), action); } } updateModel(); } } void CompositionDockerDock::unsetCanvas() { setEnabled(false); m_canvas = 0; m_model->setCompositions(QList()); } void CompositionDockerDock::activated(const QModelIndex& index) { KisLayerCompositionSP composition = m_model->compositionFromIndex(index); composition->apply(); } void CompositionDockerDock::deleteClicked() { QModelIndex index = compositionView->currentIndex(); if (m_canvas && m_canvas->viewManager() && m_canvas->viewManager()->image() && index.isValid()) { KisLayerCompositionSP composition = m_model->compositionFromIndex(index); m_canvas->viewManager()->image()->removeComposition(composition); updateModel(); } } void CompositionDockerDock::saveClicked() { KisImageWSP image = m_canvas->viewManager()->image(); if (!image) return; // format as 001, 002 ... QString name = saveNameEdit->text(); if (name.isEmpty()) { bool found = false; int i = 1; do { name = QString("%1").arg(i, 3, 10, QChar('0')); found = false; Q_FOREACH (KisLayerCompositionSP composition, m_canvas->viewManager()->image()->compositions()) { if (composition->name() == name) { found = true; break; } } i++; } while(found && i < 1000); } KisLayerCompositionSP composition(new KisLayerComposition(image, name)); composition->store(); image->addComposition(composition); saveNameEdit->clear(); updateModel(); compositionView->setCurrentIndex(m_model->index(image->compositions().count()-1, 0)); image->setModified(); } void CompositionDockerDock::updateModel() { if (m_model && m_canvas && m_canvas->viewManager() && m_canvas->viewManager()->image()) { m_model->setCompositions(m_canvas->viewManager()->image()->compositions()); } } void CompositionDockerDock::exportClicked() { if (m_canvas && m_canvas->viewManager() && m_canvas->viewManager()->image()) { QString path; KoFileDialog dialog(0, KoFileDialog::OpenDirectory, "compositiondockerdock"); dialog.setCaption(i18n("Select a Directory")); dialog.setDefaultDir(QStandardPaths::writableLocation(QStandardPaths::HomeLocation)); path = dialog.filename(); if (path.isNull()) return; if (!path.endsWith('/')) { path.append('/'); } KisImageWSP image = m_canvas->viewManager()->image(); QString filename = m_canvas->viewManager()->document()->localFilePath(); if (!filename.isEmpty()) { QFileInfo info(filename); path += info.baseName() + '_'; } Q_FOREACH (KisLayerCompositionSP composition, m_canvas->viewManager()->image()->compositions()) { if (!composition->isExportEnabled()) { continue; } composition->apply(); image->refreshGraph(); image->lock(); #if 0 image->rootLayer()->projection()->convertToQImage(0, 0, 0, image->width(), image->height()).save(path + composition->name() + ".png"); #else QRect r = image->bounds(); KisDocument *d = KisPart::instance()->createDocument(); KisImageSP dst = new KisImage(d->createUndoStore(), r.width(), r.height(), image->colorSpace(), composition->name()); dst->setResolution(image->xRes(), image->yRes()); d->setCurrentImage(dst); KisPaintLayer* paintLayer = new KisPaintLayer(dst, "projection", OPACITY_OPAQUE_U8); KisPainter gc(paintLayer->paintDevice()); gc.bitBlt(QPoint(0, 0), image->rootLayer()->projection(), r); dst->addNode(paintLayer, dst->rootLayer(), KisLayerSP(0)); dst->refreshGraph(); d->setFileBatchMode(true); const QByteArray outputFormat("image/png"); d->exportDocumentSync(QUrl::fromLocalFile(path + composition->name() + ".png"), outputFormat); delete d; #endif image->unlock(); } } } bool CompositionDockerDock::eventFilter(QObject* obj, QEvent* event) { if (event->type() == QEvent::KeyPress ) { QKeyEvent *keyEvent = static_cast(event); if (keyEvent->key() == Qt::Key_Up || keyEvent->key() == Qt::Key_Down) { // new index will be set after the method is called QTimer::singleShot(0, this, SLOT(activateCurrentIndex())); } return false; } else { return QObject::eventFilter(obj, event); } } void CompositionDockerDock::activateCurrentIndex() { QModelIndex index = compositionView->currentIndex(); if (index.isValid()) { activated(index); } } void CompositionDockerDock::customContextMenuRequested(QPoint pos) { if (m_actions.isEmpty()) return; QMenu menu; Q_FOREACH (KisAction *action, m_actions) { menu.addAction(action); } menu.exec(compositionView->mapToGlobal(pos)); } void CompositionDockerDock::updateComposition() { QModelIndex index = compositionView->currentIndex(); if (m_canvas && m_canvas->viewManager() && m_canvas->viewManager()->image() && index.isValid()) { KisLayerCompositionSP composition = m_model->compositionFromIndex(index); composition->store(); m_canvas->image()->setModified(); } } void CompositionDockerDock::renameComposition() { dbgKrita << "rename"; QModelIndex index = compositionView->currentIndex(); if (m_canvas && m_canvas->viewManager() && m_canvas->viewManager()->image() && index.isValid()) { KisLayerCompositionSP composition = m_model->compositionFromIndex(index); bool ok; QString name = QInputDialog::getText(this, i18n("Rename Composition"), i18n("New Name:"), QLineEdit::Normal, composition->name(), &ok); if (ok && !name.isEmpty()) { composition->setName(name); m_canvas->image()->setModified(); } } } diff --git a/plugins/dockers/compositiondocker/compositiondocker_dock.h b/plugins/dockers/compositiondocker/compositiondocker_dock.h index 853fe0ab99..41bcbe33db 100644 --- a/plugins/dockers/compositiondocker/compositiondocker_dock.h +++ b/plugins/dockers/compositiondocker/compositiondocker_dock.h @@ -1,70 +1,71 @@ /* * Copyright (c) 2012 Sven Langkamp * * 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. + * the Free Software Foundation; 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 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 COMPOSITIONDOCKER_DOCK_H #define COMPOSITIONDOCKER_DOCK_H #include #include #include #include #include #include "ui_wdgcompositiondocker.h" #include class CompositionModel; class KisAction; class CompositionDockerDock : public QDockWidget, public KoCanvasObserverBase, public Ui_WdgCompositionDocker { Q_OBJECT public: CompositionDockerDock(); ~CompositionDockerDock() override; QString observerName() override { return "CompositionDockerDock"; } void setCanvas(KoCanvasBase *canvas) override; void unsetCanvas() override; void updateModel(); protected: bool eventFilter(QObject *obj, QEvent *event) override; public Q_SLOTS: void slotScrollerStateChanged(QScroller::State state){ KisKineticScroller::updateCursor(this, state); } private Q_SLOTS: void activated (const QModelIndex& index); void deleteClicked(); void saveClicked(); void exportClicked(); void activateCurrentIndex(); void customContextMenuRequested(QPoint pos); void updateComposition(); void renameComposition(); private: QPointer m_canvas; CompositionModel *m_model; QVector m_actions; }; #endif diff --git a/plugins/dockers/compositiondocker/compositionmodel.cpp b/plugins/dockers/compositiondocker/compositionmodel.cpp index b8561b4aef..2a9f686a25 100644 --- a/plugins/dockers/compositiondocker/compositionmodel.cpp +++ b/plugins/dockers/compositiondocker/compositionmodel.cpp @@ -1,110 +1,111 @@ /* * Copyright (c) 2012 Sven Langkamp * * 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. + * the Free Software Foundation; 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 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 "compositionmodel.h" #include #include #include CompositionModel::CompositionModel(QObject* parent): QAbstractTableModel(parent) { } CompositionModel::~CompositionModel() { } QVariant CompositionModel::data(const QModelIndex& index, int role) const { if (index.isValid()) { switch (role) { case Qt::DisplayRole: { return m_compositions.at(index.row())->name(); } case Qt::DecorationRole: { return KisIconUtils::loadIcon("tools-wizard"); } case Qt::CheckStateRole: { return m_compositions.at(index.row())->isExportEnabled() ? Qt::Checked : Qt::Unchecked; } } } return QVariant(); } bool CompositionModel::setData ( const QModelIndex& index, const QVariant& value, int role ) { if (index.isValid()) { if (role == Qt::CheckStateRole) { Q_ASSERT(index.row() < rowCount()); Q_ASSERT(index.column() < columnCount()); if (index.column() == 0) { bool exportEnabled = value.toInt() == Qt::Checked; KisLayerCompositionSP layerComposition = m_compositions.at(index.row()); if (layerComposition) { layerComposition->setExportEnabled(exportEnabled); } } } return true; } return false; } QVariant CompositionModel::headerData(int /*section*/, Qt::Orientation /*orientation*/, int /*role*/) const { return i18n("Composition"); } int CompositionModel::rowCount(const QModelIndex& /*parent*/) const { return m_compositions.count(); } int CompositionModel::columnCount(const QModelIndex& /*parent*/) const { return 2; } Qt::ItemFlags CompositionModel::flags(const QModelIndex& /*index*/) const { Qt::ItemFlags flags = Qt::ItemIsSelectable | Qt::ItemIsEnabled | Qt::ItemIsUserCheckable; return flags; } KisLayerCompositionSP CompositionModel::compositionFromIndex(const QModelIndex& index) { if(index.isValid()) { return m_compositions.at(index.row()); } return KisLayerCompositionSP(); } void CompositionModel::setCompositions(QList< KisLayerCompositionSP > compositions) { m_compositions = compositions; beginResetModel(); endResetModel(); } diff --git a/plugins/dockers/compositiondocker/compositionmodel.h b/plugins/dockers/compositiondocker/compositionmodel.h index 637b6f8123..51061efb5c 100644 --- a/plugins/dockers/compositiondocker/compositionmodel.h +++ b/plugins/dockers/compositiondocker/compositionmodel.h @@ -1,49 +1,50 @@ /* * Copyright (c) 2012 Sven Langkamp * * 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. + * the Free Software Foundation; 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 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 COMPOSITIONMODEL_H #define COMPOSITIONMODEL_H #include #include #include class CompositionModel : public QAbstractTableModel { Q_OBJECT public: CompositionModel(QObject* parent = 0); ~CompositionModel() override; QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const override; bool setData ( const QModelIndex& index, const QVariant& value, int role = Qt::EditRole ) override; QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const override; int rowCount(const QModelIndex& parent = QModelIndex()) const override; int columnCount(const QModelIndex& parent = QModelIndex()) const override; Qt::ItemFlags flags(const QModelIndex& index) const override; KisLayerCompositionSP compositionFromIndex(const QModelIndex& index); void setCompositions(QList compositions); // public Q_SLOTS: // void clear(); private: QList m_compositions; }; #endif // TASKSETMODEL_H diff --git a/plugins/dockers/digitalmixer/digitalmixer.cc b/plugins/dockers/digitalmixer/digitalmixer.cc index 743b60ac99..0ba5eac3bc 100644 --- a/plugins/dockers/digitalmixer/digitalmixer.cc +++ b/plugins/dockers/digitalmixer/digitalmixer.cc @@ -1,88 +1,89 @@ /* * Copyright (c) 2009 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. + * the Free Software Foundation; 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 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 "digitalmixer.h" #include #include #include #include #include #include #include "kis_config.h" #include "kis_cursor.h" #include "kis_global.h" #include "kis_types.h" #include "KisViewManager.h" #include "digitalmixer_dock.h" #include K_PLUGIN_FACTORY_WITH_JSON(DigitalMixerPluginFactory, "krita_digitalmixer.json", registerPlugin();) class DigitalMixerDockFactory : public KoDockFactoryBase { public: DigitalMixerDockFactory() { } QString id() const override { return QString( "DigitalMixer" ); } virtual Qt::DockWidgetArea defaultDockWidgetArea() const { return Qt::RightDockWidgetArea; } QDockWidget* createDockWidget() override { DigitalMixerDock * dockWidget = new DigitalMixerDock(); dockWidget->setObjectName(id()); return dockWidget; } DockPosition defaultDockPosition() const override { return DockMinimized; } private: }; DigitalMixerPlugin::DigitalMixerPlugin(QObject *parent, const QVariantList &) : QObject(parent) { KoDockRegistry::instance()->add(new DigitalMixerDockFactory()); } DigitalMixerPlugin::~DigitalMixerPlugin() { m_view = 0; } #include "digitalmixer.moc" diff --git a/plugins/dockers/digitalmixer/digitalmixer.h b/plugins/dockers/digitalmixer/digitalmixer.h index c5b0510c40..8e0dbe726c 100644 --- a/plugins/dockers/digitalmixer/digitalmixer.h +++ b/plugins/dockers/digitalmixer/digitalmixer.h @@ -1,39 +1,40 @@ /* * Copyright (c) 2009 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. + * the Free Software Foundation; 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 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 _DIGITALMIXER_H_ #define _DIGITALMIXER_H_ #include #include class KisViewManager; /** * Template of view plugin */ class DigitalMixerPlugin : public QObject { Q_OBJECT public: DigitalMixerPlugin(QObject *parent, const QVariantList &); ~DigitalMixerPlugin() override; private: KisViewManager* m_view; }; #endif diff --git a/plugins/dockers/digitalmixer/digitalmixer_dock.cc b/plugins/dockers/digitalmixer/digitalmixer_dock.cc index eb8b955984..19f8c25b5e 100644 --- a/plugins/dockers/digitalmixer/digitalmixer_dock.cc +++ b/plugins/dockers/digitalmixer/digitalmixer_dock.cc @@ -1,167 +1,168 @@ /* * Copyright (c) 2009 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. + * the Free Software Foundation; 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 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 "digitalmixer_dock.h" #include #include #include #include #include #include #include #include #include #include #include class DigitalMixerPatch : public KoColorPatch { public: DigitalMixerPatch(QWidget* parent) : KoColorPatch(parent) {} QSize sizeHint() const override { return QSize(24,24); } }; DigitalMixerDock::DigitalMixerDock( ) : QDockWidget(i18n("Digital Colors Mixer")), m_canvas(0) , m_tellCanvas(true) { const KoColorSpace *sRGB = KoColorSpaceRegistry::instance()->rgb8(); KoColor initColors[6] = { KoColor(Qt::black, sRGB), KoColor(Qt::white, sRGB), KoColor(Qt::red, sRGB), KoColor(Qt::green, sRGB), KoColor(Qt::blue, sRGB), KoColor(Qt::yellow, sRGB) }; QWidget* widget = new QWidget(this); QGridLayout* layout = new QGridLayout( widget ); // Current Color m_currentColorPatch = new KoColorPatch(this); m_currentColorPatch->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); m_currentColorPatch->setMinimumWidth(48); layout->addWidget(m_currentColorPatch, 0, 0,3,1); // Create the sliders QSignalMapper* signalMapperSelectColor = new QSignalMapper(this); connect(signalMapperSelectColor, SIGNAL(mapped(int)), SLOT(popupColorChanged(int))); QSignalMapper* signalMapperColorSlider = new QSignalMapper(this); connect(signalMapperColorSlider, SIGNAL(mapped(int)), SLOT(colorSliderChanged(int))); QSignalMapper* signalMapperTargetColor = new QSignalMapper(this); connect(signalMapperTargetColor, SIGNAL(mapped(int)), SLOT(targetColorChanged(int))); for(int i = 0; i < 6; ++i) { Mixer mixer; mixer.targetColor = new DigitalMixerPatch(this); mixer.targetColor->setFixedSize(32, 22); layout->addWidget(mixer.targetColor, 0, i + 1); mixer.targetSlider = new KoColorSlider(Qt::Vertical, this); mixer.targetSlider->setFixedWidth(22); mixer.targetSlider->setMinimumHeight(66); layout->addWidget(mixer.targetSlider, 1, i + 1); mixer.actionColor = new KisColorButton( this ); mixer.actionColor->setColor(initColors[i]); mixer.actionColor->setFixedWidth(22); layout->addWidget(mixer.actionColor, 2, i + 1); m_mixers.push_back(mixer); connect(mixer.actionColor, SIGNAL(changed(KoColor)), signalMapperSelectColor, SLOT(map())); signalMapperSelectColor->setMapping(mixer.actionColor, i); connect(mixer.targetSlider, SIGNAL(valueChanged(int)), signalMapperColorSlider, SLOT(map())); signalMapperColorSlider->setMapping(mixer.targetSlider, i); mixer.targetSlider->setValue(125); connect(mixer.targetColor, SIGNAL(triggered(KoColorPatch*)), signalMapperTargetColor, SLOT(map())); signalMapperTargetColor->setMapping(mixer.targetColor, i); } setCurrentColor(KoColor(Qt::black, KoColorSpaceRegistry::instance()->rgb8())); setWidget( widget ); } void DigitalMixerDock::setCanvas(KoCanvasBase * canvas) { setEnabled(canvas != 0); if (m_canvas) { m_canvas->disconnectCanvasObserver(this); } m_canvas = canvas; if (m_canvas) { connect(m_canvas->resourceManager(), SIGNAL(canvasResourceChanged(int,QVariant)), this, SLOT(canvasResourceChanged(int,QVariant))); m_tellCanvas=false; setCurrentColor(m_canvas->resourceManager()->foregroundColor()); m_tellCanvas=true; } } void DigitalMixerDock::popupColorChanged(int i) { KoColor color = m_mixers[i].actionColor->color(); color.convertTo(m_currentColor.colorSpace()); m_mixers[i].targetSlider->setColors( color, m_currentColor); colorSliderChanged(i); } void DigitalMixerDock::colorSliderChanged(int i) { m_mixers[i].targetColor->setColor(m_mixers[i].targetSlider->currentColor()); } void DigitalMixerDock::targetColorChanged(int i) { setCurrentColor(m_mixers[i].targetColor->color()); } void DigitalMixerDock::setCurrentColor(const KoColor& color) { m_currentColor = color; m_currentColorPatch->setColor(color); for(int i = 0; i < m_mixers.size(); ++i) { popupColorChanged(i); colorSliderChanged(i); } if (m_canvas && m_tellCanvas) { m_canvas->resourceManager()->setForegroundColor(m_currentColor); } } void DigitalMixerDock::canvasResourceChanged(int key, const QVariant& v) { m_tellCanvas = false; if (key == KoCanvasResourceProvider::ForegroundColor) setCurrentColor(v.value()); m_tellCanvas = true; } diff --git a/plugins/dockers/digitalmixer/digitalmixer_dock.h b/plugins/dockers/digitalmixer/digitalmixer_dock.h index 251d83fa51..9552f7820b 100644 --- a/plugins/dockers/digitalmixer/digitalmixer_dock.h +++ b/plugins/dockers/digitalmixer/digitalmixer_dock.h @@ -1,63 +1,64 @@ /* * Copyright (c) 2009 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. + * the Free Software Foundation; 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 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 _DIGITALMIXER_DOCK_H_ #define _DIGITALMIXER_DOCK_H_ #include #include #include #include #include class KoColorPopupAction; class KoColorSlider; class KoColorPatch; class KisColorButton; class DigitalMixerDock : public QDockWidget, public KoCanvasObserverBase { Q_OBJECT public: DigitalMixerDock( ); QString observerName() override { return "DigitalMixerDock"; } /// reimplemented from KoCanvasObserverBase void setCanvas(KoCanvasBase *canvas) override; void unsetCanvas() override { m_canvas = 0; setEnabled(false);} public Q_SLOTS: void setCurrentColor(const KoColor& ); void canvasResourceChanged(int, const QVariant&); private Q_SLOTS: void popupColorChanged(int i); void colorSliderChanged(int i); void targetColorChanged(int); private: QPointer m_canvas; KoColor m_currentColor; KoColorPatch* m_currentColorPatch; struct Mixer { KoColorPatch* targetColor; KoColorSlider* targetSlider; KisColorButton* actionColor; }; QList m_mixers; bool m_tellCanvas; }; #endif diff --git a/plugins/dockers/gamutmask/KisGamutMaskChooser.cpp b/plugins/dockers/gamutmask/KisGamutMaskChooser.cpp index 19cf385cc7..f0dd21399a 100644 --- a/plugins/dockers/gamutmask/KisGamutMaskChooser.cpp +++ b/plugins/dockers/gamutmask/KisGamutMaskChooser.cpp @@ -1,251 +1,252 @@ /* * Copyright (c) 2018 Anna Medonosova * - * 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 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 library is distributed in the hope that it will be useful, + * 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 Lesser General Public License for more details. + * GNU General Public License for more details. * - * You should have received a copy of the GNU Lesser General Public License + * 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 "KisGamutMaskChooser.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include /// The resource item delegate for rendering the resource preview class KisGamutMaskDelegate: public QAbstractItemDelegate { public: KisGamutMaskDelegate(QObject * parent = 0) : QAbstractItemDelegate(parent) , m_mode(KisGamutMaskChooser::ViewMode::THUMBNAIL) {} ~KisGamutMaskDelegate() override {} /// reimplemented void paint(QPainter *, const QStyleOptionViewItem &, const QModelIndex &) const override; /// reimplemented QSize sizeHint(const QStyleOptionViewItem & option, const QModelIndex &) const override { return option.decorationSize; } void setViewMode(KisGamutMaskChooser::ViewMode mode) { m_mode = mode; } private: KisGamutMaskChooser::ViewMode m_mode; }; void KisGamutMaskDelegate::paint(QPainter * painter, const QStyleOptionViewItem & option, const QModelIndex & index) const { painter->save(); painter->setRenderHint(QPainter::SmoothPixmapTransform, true); if (!index.isValid()) return; KoResource* resource = static_cast(index.internalPointer()); KoGamutMask* mask = static_cast(resource); if (!mask) { return; } QImage preview = mask->image(); if(preview.isNull()) { return; } QRect paintRect = option.rect.adjusted(1, 1, -1, -1); if (m_mode == KisGamutMaskChooser::ViewMode::THUMBNAIL) { painter->drawImage(paintRect.x(), paintRect.y(), preview.scaled(paintRect.size(), Qt::IgnoreAspectRatio, Qt::SmoothTransformation)); if (option.state & QStyle::State_Selected) { painter->setCompositionMode(QPainter::CompositionMode_Overlay); painter->setOpacity(0.5); painter->fillRect(paintRect, Qt::white); painter->setCompositionMode(QPainter::CompositionMode_SourceOver); painter->setOpacity(1.0); painter->setPen(QPen(option.palette.highlight(), 2, Qt::SolidLine, Qt::FlatCap, Qt::MiterJoin)); QRect selectedBorder = option.rect.adjusted(1, 1, -1, -1); painter->drawRect(selectedBorder); } } else { QSize previewSize(paintRect.height(), paintRect.height()); painter->drawImage(paintRect.x(), paintRect.y(), preview.scaled(previewSize, Qt::IgnoreAspectRatio, Qt::SmoothTransformation)); int leftMargin = 8; int rightMargin = 7; int vertMargin = 4; int descOffset = 7; QFont font = option.font; font.setBold(true); painter->setFont(font); QRectF titleRect(QPointF(previewSize.width() + leftMargin, paintRect.y() + vertMargin), QPointF(paintRect.width() - rightMargin, paintRect.y() + descOffset + painter->fontMetrics().lineSpacing())); painter->drawText(titleRect, Qt::AlignLeft, painter->fontMetrics().elidedText( mask->title(), Qt::ElideRight, titleRect.width() ) ); if (!mask->description().isEmpty() && !mask->description().isNull()) { font.setPointSize(font.pointSize()-1); font.setBold(false); font.setStyle(QFont::StyleItalic); painter->setFont(font); QRectF descRect(QPointF(previewSize.width() + leftMargin, paintRect.y() + descOffset + painter->fontMetrics().lineSpacing()), QPointF(paintRect.right() - rightMargin, paintRect.bottom() - vertMargin)); int numLines = floor(((float)descRect.height() / (float)painter->fontMetrics().lineSpacing())); if (numLines > 0) { int elideWidth = 0; QTextLayout textLayout(mask->description()); textLayout.beginLayout(); for (int i = 0; i < numLines; i++) { QTextLine line = textLayout.createLine(); if (line.isValid()) { line.setLineWidth(descRect.width()); elideWidth += line.naturalTextWidth(); } } QString elidedText = painter->fontMetrics().elidedText(mask->description(), Qt::ElideRight, elideWidth); painter->drawText(descRect, Qt::AlignLeft|Qt::TextWordWrap, elidedText); } } } painter->restore(); } KisGamutMaskChooser::KisGamutMaskChooser(QWidget *parent) : QWidget(parent) { m_delegate = new KisGamutMaskDelegate(this); KoResourceServer* rServer = KoResourceServerProvider::instance()->gamutMaskServer(); QSharedPointer adapter(new KoResourceServerAdapter(rServer)); m_itemChooser = new KoResourceItemChooser(adapter, this); m_itemChooser->setItemDelegate(m_delegate); m_itemChooser->showTaggingBar(true); m_itemChooser->showButtons(false); m_itemChooser->setColumnCount(4); m_itemChooser->setSynced(true); QVBoxLayout* layout = new QVBoxLayout(this); layout->setContentsMargins(0,0,0,0); // TODO: menu for view mode change QMenu* menu = new QMenu(this); menu->setStyleSheet("margin: 6px"); menu->addSection(i18n("Display")); QActionGroup *actionGroup = new QActionGroup(this); KisConfig cfg(true); m_mode = KisGamutMaskChooser::ViewMode(cfg.readEntry("GamutMasks.viewMode", KisGamutMaskChooser::THUMBNAIL)); QAction* action = menu->addAction(KisIconUtils::loadIcon("view-preview"), i18n("Thumbnails"), this, SLOT(slotSetModeThumbnail())); action->setCheckable(true); action->setChecked(m_mode == KisGamutMaskChooser::THUMBNAIL); action->setActionGroup(actionGroup); action = menu->addAction(KisIconUtils::loadIcon("view-list-details"), i18n("Details"), this, SLOT(slotSetModeDetail())); action->setCheckable(true); action->setChecked(m_mode == KisGamutMaskChooser::DETAIL); action->setActionGroup(actionGroup); // setting the view mode setViewMode(m_mode); m_itemChooser->setViewModeButtonVisible(true); QToolButton* viewModeButton = m_itemChooser->viewModeButton(); viewModeButton->setMenu(menu); layout->addWidget(m_itemChooser); setLayout(layout); connect(m_itemChooser, SIGNAL(resourceSelected(KoResource*)), this, SLOT(resourceSelected(KoResource*))); } KisGamutMaskChooser::~KisGamutMaskChooser() { } void KisGamutMaskChooser::setCurrentResource(KoResource *resource) { m_itemChooser->setCurrentResource(resource); } void KisGamutMaskChooser::resizeEvent(QResizeEvent *event) { QWidget::resizeEvent(event); updateViewSettings(); } void KisGamutMaskChooser::setViewMode(KisGamutMaskChooser::ViewMode mode) { m_mode = mode; updateViewSettings(); } void KisGamutMaskChooser::updateViewSettings() { KisConfig cfg(false); cfg.writeEntry("GamutMasks.viewMode", qint32(m_mode)); if (m_mode == KisGamutMaskChooser::THUMBNAIL) { m_itemChooser->setSynced(true); m_delegate->setViewMode(m_mode); } else if (m_mode == KisGamutMaskChooser::DETAIL) { m_itemChooser->setSynced(false); m_itemChooser->setColumnCount(1); m_itemChooser->setRowHeight(this->fontMetrics().lineSpacing()*4); m_itemChooser->setColumnWidth(m_itemChooser->width()); m_delegate->setViewMode(m_mode); } } void KisGamutMaskChooser::resourceSelected(KoResource* resource) { emit sigGamutMaskSelected(static_cast(resource)); } void KisGamutMaskChooser::slotSetModeThumbnail() { setViewMode(KisGamutMaskChooser::THUMBNAIL); } void KisGamutMaskChooser::slotSetModeDetail() { setViewMode(KisGamutMaskChooser::DETAIL); } diff --git a/plugins/dockers/gamutmask/KisGamutMaskChooser.h b/plugins/dockers/gamutmask/KisGamutMaskChooser.h index 7ed187b96c..56865508e8 100644 --- a/plugins/dockers/gamutmask/KisGamutMaskChooser.h +++ b/plugins/dockers/gamutmask/KisGamutMaskChooser.h @@ -1,61 +1,63 @@ /* * Copyright (c) 2018 Anna Medonosova * - * 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 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 library is distributed in the hope that it will be useful, + * 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 Lesser General Public License for more details. + * GNU General Public License for more details. * - * You should have received a copy of the GNU Lesser General Public License + * 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 KISGAMUTMASKCHOOSER_H #define KISGAMUTMASKCHOOSER_H #include class KoResourceItemChooser; class KoResource; class KoGamutMask; class KisGamutMaskDelegate; class KisGamutMaskChooser : public QWidget { Q_OBJECT public: explicit KisGamutMaskChooser(QWidget *parent = nullptr); ~KisGamutMaskChooser() override; enum ViewMode { THUMBNAIL, // Shows thumbnails DETAIL // Shows thumbsnails with text next to it }; void setCurrentResource(KoResource* resource); protected: void resizeEvent(QResizeEvent* event) override; Q_SIGNALS: void sigGamutMaskSelected(KoGamutMask* mask); private Q_SLOTS: void resourceSelected(KoResource* resource); void slotSetModeThumbnail(); void slotSetModeDetail(); private: void setViewMode(ViewMode mode); void updateViewSettings(); KoResourceItemChooser* m_itemChooser; KisGamutMaskDelegate* m_delegate; ViewMode m_mode; }; #endif // KISGAMUTMASKCHOOSER_H diff --git a/plugins/dockers/gamutmask/gamutmask_dock.cpp b/plugins/dockers/gamutmask/gamutmask_dock.cpp index f6333ef32c..75385386ea 100644 --- a/plugins/dockers/gamutmask/gamutmask_dock.cpp +++ b/plugins/dockers/gamutmask/gamutmask_dock.cpp @@ -1,629 +1,630 @@ /* * Copyright (c) 2018 Anna Medonosova * - * 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 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 library is distributed in the hope that it will be useful, + * 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 Lesser General Public License for more details. + * GNU General Public License for more details. * - * You should have received a copy of the GNU Lesser General Public License + * 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 #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 "gamutmask_dock.h" #include #include #include #include #include #include "ui_wdgGamutMaskChooser.h" class KisMainWindow; struct GamutMaskChooserUI: public QWidget, public Ui_wdgGamutMaskChooser { GamutMaskChooserUI() { setupUi(this); } }; GamutMaskDock::GamutMaskDock() : QDockWidget(i18n("Gamut Masks")) , m_resourceProvider(0) , m_selfClosingTemplate(false) , m_externalTemplateClose(false) , m_creatingNewMask(false) , m_templatePrevSaved(false) , m_selfSelectingMask(false) , m_selectedMask(nullptr) , m_maskDocument(nullptr) , m_view(nullptr) { m_dockerUI = new GamutMaskChooserUI(); m_dockerUI->bnMaskEditor->setIcon(KisIconUtils::loadIcon("dirty-preset")); m_dockerUI->bnMaskDelete->setIcon(KisIconUtils::loadIcon("deletelayer")); m_dockerUI->bnMaskNew->setIcon(KisIconUtils::loadIcon("list-add")); m_dockerUI->bnMaskDuplicate->setIcon(KisIconUtils::loadIcon("duplicatelayer")); m_dockerUI->maskPropertiesBox->setVisible(false); m_dockerUI->bnSaveMask->setIcon(KisIconUtils::loadIcon("document-save")); m_dockerUI->bnCancelMaskEdit->setIcon(KisIconUtils::loadIcon("dialog-cancel")); m_dockerUI->bnPreviewMask->setIcon(KisIconUtils::loadIcon("visible")); QRegularExpression maskTitleRegex("^[-_\\(\\)\\sA-Za-z0-9]+$"); QRegularExpressionValidator* m_maskTitleValidator = new QRegularExpressionValidator(maskTitleRegex, this); m_dockerUI->maskTitleEdit->setValidator(m_maskTitleValidator); KoResourceServer* rServer = KoResourceServerProvider::instance()->gamutMaskServer(); rServer->addObserver(this); // gamut mask connections connect(m_dockerUI->bnSaveMask , SIGNAL(clicked()) , SLOT(slotGamutMaskSave())); connect(m_dockerUI->bnCancelMaskEdit , SIGNAL(clicked()) , SLOT(slotGamutMaskCancelEdit())); connect(m_dockerUI->bnPreviewMask , SIGNAL(clicked()) , SLOT(slotGamutMaskPreview())); connect(m_dockerUI->bnMaskEditor , SIGNAL(clicked()) , SLOT(slotGamutMaskEdit())); connect(m_dockerUI->maskChooser, SIGNAL(sigGamutMaskSelected(KoGamutMask*)), SLOT(slotGamutMaskSelected(KoGamutMask*))); connect(m_dockerUI->bnMaskNew , SIGNAL(clicked()) , SLOT(slotGamutMaskCreateNew())); connect(m_dockerUI->bnMaskDelete , SIGNAL(clicked()) , SLOT(slotGamutMaskDelete())); connect(m_dockerUI->bnMaskDuplicate , SIGNAL(clicked()) , SLOT(slotGamutMaskDuplicate())); setWidget(m_dockerUI); } GamutMaskDock::~GamutMaskDock() { KoResourceServer* rServer = KoResourceServerProvider::instance()->gamutMaskServer(); rServer->removeObserver(this); } void GamutMaskDock::setViewManager(KisViewManager* kisview) { m_resourceProvider = kisview->canvasResourceProvider(); selectMask(m_resourceProvider->currentGamutMask()); connect(this, SIGNAL(sigGamutMaskSet(KoGamutMask*)), m_resourceProvider, SLOT(slotGamutMaskActivated(KoGamutMask*)), Qt::UniqueConnection); connect(this, SIGNAL(sigGamutMaskChanged(KoGamutMask*)), m_resourceProvider, SLOT(slotGamutMaskActivated(KoGamutMask*)), Qt::UniqueConnection); connect(this, SIGNAL(sigGamutMaskUnset()), m_resourceProvider, SLOT(slotGamutMaskUnset()), Qt::UniqueConnection); connect(this, SIGNAL(sigGamutMaskPreviewUpdate()), m_resourceProvider, SLOT(slotGamutMaskPreviewUpdate()), Qt::UniqueConnection); connect(KisPart::instance(), SIGNAL(sigDocumentRemoved(QString)), this, SLOT(slotDocumentRemoved(QString)), Qt::UniqueConnection); } void GamutMaskDock::slotGamutMaskEdit() { if (!m_selectedMask) { return; } openMaskEditor(); } bool GamutMaskDock::openMaskEditor() { if (!m_selectedMask) { return false; } // find the template resource first, so we can abort the action early on QString maskTemplateFile = KoResourcePaths::findResource("ko_gamutmasks", "GamutMaskTemplate.kra"); if (maskTemplateFile.isEmpty() || maskTemplateFile.isNull() || !QFile::exists(maskTemplateFile)) { dbgPlugins << "GamutMaskDock::openMaskEditor(): maskTemplateFile (" << maskTemplateFile << ") was not found on the system"; getUserFeedback(i18n("Could not open gamut mask for editing."), i18n("The editor template was not found."), QMessageBox::Ok, QMessageBox::Ok, QMessageBox::Critical); return false; } m_dockerUI->maskPropertiesBox->setVisible(true); m_dockerUI->maskPropertiesBox->setEnabled(true); m_dockerUI->editControlsBox->setEnabled(false); m_dockerUI->editControlsBox->setVisible(false); m_dockerUI->maskTitleEdit->setText(m_selectedMask->title()); m_dockerUI->maskDescriptionEdit->setPlainText(m_selectedMask->description()); m_maskDocument = KisPart::instance()->createDocument(); KisPart::instance()->addDocument(m_maskDocument); m_maskDocument->openUrl(QUrl::fromLocalFile(maskTemplateFile), KisDocument::DontAddToRecent); // template document needs a proper autogenerated filename, // to avoid collision with other documents, // otherwise bugs happen when slotDocumentRemoved is called // (e.g. user closes another view, the template stays open, but the edit operation is canceled) m_maskDocument->setInfiniteAutoSaveInterval(); QString maskPath = QString("%1%2%3_%4.kra") .arg(QDir::tempPath()) .arg(QDir::separator()) .arg("GamutMaskTemplate") .arg(std::time(nullptr)); m_maskDocument->setUrl(QUrl::fromLocalFile(maskPath)); m_maskDocument->setLocalFilePath(maskPath); KisShapeLayerSP shapeLayer = getShapeLayer(); // pass only copies of shapes to the layer, // so the originals don't disappear from the mask later for (KoShape *shape: m_selectedMask->koShapes()) { KoShape* newShape = shape->cloneShape(); newShape->setStroke(KoShapeStrokeModelSP()); newShape->setBackground(QSharedPointer(new KoColorBackground(QColor(255,255,255)))); shapeLayer->addShape(newShape); } m_maskDocument->setPreActivatedNode(shapeLayer); // set document as active KisMainWindow* mainWindow = KisPart::instance()->currentMainwindow(); KIS_ASSERT(mainWindow); m_view = mainWindow->addViewAndNotifyLoadingCompleted(m_maskDocument); KIS_ASSERT(m_view); for(KisView *view: KisPart::instance()->views()) { if (view->document() == m_maskDocument) { view->activateWindow(); break; } } connect(m_view->viewManager(), SIGNAL(viewChanged()), this, SLOT(slotViewChanged())); connect(m_maskDocument, SIGNAL(completed()), this, SLOT(slotDocumentSaved())); return true; } void GamutMaskDock::cancelMaskEdit() { if (m_creatingNewMask) { deleteMask(); } if (m_selectedMask) { m_selectedMask->clearPreview(); if (m_resourceProvider->currentGamutMask() == m_selectedMask) { emit sigGamutMaskChanged(m_selectedMask); } } closeMaskDocument(); } void GamutMaskDock::selectMask(KoGamutMask *mask, bool notifyItemChooser) { if (!mask) { return; } m_selectedMask = mask; if (notifyItemChooser) { m_selfSelectingMask = true; m_dockerUI->maskChooser->setCurrentResource(m_selectedMask); m_selfSelectingMask = false; } emit sigGamutMaskSet(m_selectedMask); } bool GamutMaskDock::saveSelectedMaskResource() { if (!m_selectedMask || !m_maskDocument) { return false; } bool maskSaved = false; if (m_selectedMask) { QList shapes = getShapesFromLayer(); if (shapes.count() > 0) { m_selectedMask->setMaskShapes(shapes); m_selectedMask->setImage( m_maskDocument->image()->convertToQImage(m_maskDocument->image()->bounds() , m_maskDocument->image()->profile() ) ); m_selectedMask->setDescription(m_dockerUI->maskDescriptionEdit->toPlainText()); m_selectedMask->clearPreview(); m_selectedMask->save(); maskSaved = true; } else { getUserFeedback(i18n("Saving of gamut mask '%1' was aborted.", m_selectedMask->title()), i18n("

The mask template is invalid.

" "

Please check that:" "

    " "
  • your template contains a vector layer named 'maskShapesLayer'
  • " "
  • there are one or more vector shapes on the 'maskShapesLayer'
  • " "

" ), QMessageBox::Ok, QMessageBox::Ok); } } return maskSaved; } void GamutMaskDock::deleteMask() { KoResourceServer* rServer = KoResourceServerProvider::instance()->gamutMaskServer(); rServer->removeResourceAndBlacklist(m_selectedMask); m_selectedMask = nullptr; } int GamutMaskDock::getUserFeedback(QString text, QString informativeText, QMessageBox::StandardButtons buttons, QMessageBox::StandardButton defaultButton, QMessageBox::Icon severity) { QMessageBox msgBox; msgBox.setWindowTitle(i18nc("@title:window", "Krita")); msgBox.setText(QString("

%1

").arg(text)); msgBox.setInformativeText(informativeText); msgBox.setStandardButtons(buttons); msgBox.setDefaultButton(defaultButton); msgBox.setIcon(severity); int res = msgBox.exec(); return res; } int GamutMaskDock::saveOrCancel(QMessageBox::StandardButton defaultAction) { int response = 0; if (m_maskDocument->isModified()) { response = getUserFeedback(i18n("Gamut mask '%1' has been modified.", m_selectedMask->title()), i18n("Do you want to save it?"), QMessageBox::Cancel | QMessageBox::Close | QMessageBox::Save, defaultAction); } else if (m_templatePrevSaved && defaultAction != QMessageBox::Close) { response = QMessageBox::Save; } else if (!m_templatePrevSaved) { response = QMessageBox::Close; } else { response = defaultAction; } switch (response) { case QMessageBox::Save : { slotGamutMaskSave(); break; } case QMessageBox::Close : { cancelMaskEdit(); break; } } return response; } KoGamutMask *GamutMaskDock::createMaskResource(KoGamutMask* sourceMask, QString newTitle) { m_creatingNewMask = true; KoGamutMask* newMask = nullptr; if (sourceMask) { newMask = new KoGamutMask(sourceMask); newMask->setImage(sourceMask->image()); } else { newMask = new KoGamutMask(); QString defaultPreviewPath = KoResourcePaths::findResource("ko_gamutmasks", "empty_mask_preview.png"); KIS_SAFE_ASSERT_RECOVER_NOOP(!(defaultPreviewPath.isEmpty() || defaultPreviewPath.isNull() || !QFile::exists(defaultPreviewPath))); newMask->setImage(QImage(defaultPreviewPath, "PNG")); } QPair maskFile = resolveMaskTitle(newTitle); QString maskTitle = maskFile.first; QFileInfo fileInfo = maskFile.second; newMask->setTitle(maskTitle); newMask->setFilename(fileInfo.filePath()); newMask->setValid(true); KoResourceServer* rServer = KoResourceServerProvider::instance()->gamutMaskServer(); rServer->removeFromBlacklist(newMask); rServer->addResource(newMask, false); return newMask; } QPair GamutMaskDock::resolveMaskTitle(QString suggestedTitle) { KoResourceServer* rServer = KoResourceServerProvider::instance()->gamutMaskServer(); QString saveLocation = rServer->saveLocation(); QString processedTitle = suggestedTitle.trimmed(); QString resourceName = processedTitle; while (rServer->resourceByName(resourceName)) { resourceName = resourceName + QString(" (Copy)"); } QString maskTitle = resourceName; QString maskFile = maskTitle + ".kgm"; QString path = saveLocation + maskFile.replace(QRegularExpression("\\s+"), "_"); QFileInfo fileInfo(path); return QPair(maskTitle, fileInfo); } void GamutMaskDock::closeMaskDocument() { if (!m_externalTemplateClose) { if (m_maskDocument) { // set the document to not modified to bypass confirmation dialog // the close is already confirmed m_maskDocument->setModified(false); m_maskDocument->closeUrl(); m_view->closeView(); m_view->deleteLater(); // set a flag that we are doing it ourselves, so the docker does not react to // removing signal from KisPart m_selfClosingTemplate = true; KisPart::instance()->removeView(m_view); KisPart::instance()->removeDocument(m_maskDocument); m_selfClosingTemplate = false; } } m_dockerUI->maskPropertiesBox->setVisible(false); m_dockerUI->editControlsBox->setVisible(true); m_dockerUI->editControlsBox->setEnabled(true); disconnect(m_view->viewManager(), SIGNAL(viewChanged()), this, SLOT(slotViewChanged())); disconnect(m_maskDocument, SIGNAL(completed()), this, SLOT(slotDocumentSaved())); // the template file is meant as temporary, if the user saved it, delete now if (QFile::exists(m_maskDocument->localFilePath())) { QFile::remove(m_maskDocument->localFilePath()); } m_maskDocument = nullptr; m_view = nullptr; m_creatingNewMask = false; m_templatePrevSaved = false; } QList GamutMaskDock::getShapesFromLayer() { KisShapeLayerSP shapeLayer = getShapeLayer(); // create a deep copy of the shapes to save in the mask, // otherwise they vanish when the template closes QList newShapes; if (shapeLayer) { for (KoShape* sh: shapeLayer->shapes()) { KoShape* newShape = sh->cloneShape(); KoShapeStrokeSP border(new KoShapeStroke(0.5f, Qt::white)); newShape->setStroke(border); newShape->setBackground(QSharedPointer(new KoColorBackground(QColor(255,255,255,0)))); newShapes.append(newShape); } } return newShapes; } KisShapeLayerSP GamutMaskDock::getShapeLayer() { KisNodeSP node = m_maskDocument->image()->rootLayer()->findChildByName("maskShapesLayer"); return KisShapeLayerSP(dynamic_cast(node.data())); } void GamutMaskDock::slotGamutMaskSave() { if (!m_selectedMask || !m_maskDocument) { return; } QString newTitle = m_dockerUI->maskTitleEdit->text(); if (m_selectedMask->title() != newTitle) { // title has changed, rename KoGamutMask* newMask = createMaskResource(m_selectedMask, newTitle); // delete old mask and select new deleteMask(); selectMask(newMask); } bool maskSaved = saveSelectedMaskResource(); if (maskSaved) { emit sigGamutMaskSet(m_selectedMask); closeMaskDocument(); } } void GamutMaskDock::slotGamutMaskCancelEdit() { if (!m_selectedMask) { return; } saveOrCancel(QMessageBox::Close); } void GamutMaskDock::slotGamutMaskPreview() { if (!m_selectedMask) { return; } m_selectedMask->setPreviewMaskShapes(getShapesFromLayer()); emit sigGamutMaskPreviewUpdate(); } void GamutMaskDock::slotGamutMaskSelected(KoGamutMask *mask) { if (!m_selfSelectingMask) { if (m_maskDocument) { int res = saveOrCancel(); if (res == QMessageBox::Cancel) { return; } } selectMask(mask, false); } } void GamutMaskDock::setCanvas(KoCanvasBase *canvas) { setEnabled(canvas != 0); } void GamutMaskDock::unsetCanvas() { setEnabled(false); } void GamutMaskDock::unsetResourceServer() { KoResourceServer* rServer = KoResourceServerProvider::instance()->gamutMaskServer(); rServer->removeObserver(this); } void GamutMaskDock::removingResource(KoGamutMask *resource) { // if deleting previously set mask, notify selectors to unset their mask if (resource == m_resourceProvider->currentGamutMask()) { emit sigGamutMaskUnset(); m_selectedMask = nullptr; } } void GamutMaskDock::resourceChanged(KoGamutMask *resource) { // if currently set mask has been changed, notify selectors if (resource == m_resourceProvider->currentGamutMask()) { selectMask(resource); } } void GamutMaskDock::slotGamutMaskCreateNew() { KoGamutMask* newMask = createMaskResource(nullptr, "new mask"); selectMask(newMask); bool editorOpened = openMaskEditor(); if (!editorOpened) { deleteMask(); } } void GamutMaskDock::slotGamutMaskDuplicate() { if (!m_selectedMask) { return; } KoGamutMask* newMask = createMaskResource(m_selectedMask, m_selectedMask->title()); selectMask(newMask); bool editorOpened = openMaskEditor(); if (!editorOpened) { deleteMask(); } } void GamutMaskDock::slotGamutMaskDelete() { if (!m_selectedMask) { return; } int res = getUserFeedback(i18n("Are you sure you want to delete mask '%1'?" , m_selectedMask->title())); if (res == QMessageBox::Yes) { deleteMask(); } } void GamutMaskDock::slotDocumentRemoved(QString filename) { if (!m_maskDocument) { return; } m_externalTemplateClose = true; // we do not want to run this if it is we who close the file if (!m_selfClosingTemplate) { // KisPart called, that a document will be removed // if it's ours, cancel the mask edit operation if (m_maskDocument->url().toLocalFile() == filename) { m_maskDocument->waitForSavingToComplete(); saveOrCancel(); } } m_externalTemplateClose = false; } void GamutMaskDock::slotViewChanged() { if (!m_maskDocument || !m_view) { return; } if (m_view->viewManager()->document() == m_maskDocument) { m_dockerUI->maskPropertiesBox->setEnabled(true); } else { m_dockerUI->maskPropertiesBox->setEnabled(false); } } void GamutMaskDock::slotDocumentSaved() { m_templatePrevSaved = true; } diff --git a/plugins/dockers/gamutmask/gamutmask_dock.h b/plugins/dockers/gamutmask/gamutmask_dock.h index 43e14d0af7..023e0c036a 100644 --- a/plugins/dockers/gamutmask/gamutmask_dock.h +++ b/plugins/dockers/gamutmask/gamutmask_dock.h @@ -1,125 +1,126 @@ /* * Copyright (c) 2018 Anna Medonosova * - * 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 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 library is distributed in the hope that it will be useful, + * 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 Lesser General Public License for more details. + * GNU General Public License for more details. * - * You should have received a copy of the GNU Lesser General Public License + * 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 H_GAMUT_MASK_DOCK_H #define H_GAMUT_MASK_DOCK_H #include #include #include #include #include #include #include #include #include #include #include #include #include #include class KisCanvasResourceProvider; class QButtonGroup; class QMenu; struct GamutMaskChooserUI; class GamutMaskDock: public QDockWidget, public KisMainwindowObserver, public KoResourceServerObserver { Q_OBJECT public: GamutMaskDock(); ~GamutMaskDock() override; QString observerName() override { return "GamutMaskDock"; } void setViewManager(KisViewManager* kisview) override; void setCanvas(KoCanvasBase *canvas) override; void unsetCanvas() override; public: // KoResourceServerObserver void unsetResourceServer() override; void resourceAdded(KoGamutMask* /*resource*/) override {}; void removingResource(KoGamutMask* resource) override; void resourceChanged(KoGamutMask* resource) override; void syncTaggedResourceView() override {} void syncTagAddition(const QString&) override {} void syncTagRemoval(const QString&) override {} Q_SIGNALS: void sigGamutMaskSet(KoGamutMask* mask); void sigGamutMaskChanged(KoGamutMask* mask); void sigGamutMaskUnset(); void sigGamutMaskPreviewUpdate(); private Q_SLOTS: void slotGamutMaskEdit(); void slotGamutMaskSave(); void slotGamutMaskCancelEdit(); void slotGamutMaskSelected(KoGamutMask* mask); void slotGamutMaskPreview(); void slotGamutMaskCreateNew(); void slotGamutMaskDuplicate(); void slotGamutMaskDelete(); void slotDocumentRemoved(QString filename); void slotViewChanged(); void slotDocumentSaved(); private: void closeMaskDocument(); bool openMaskEditor(); void cancelMaskEdit(); void selectMask(KoGamutMask* mask, bool notifyItemChooser = true); bool saveSelectedMaskResource(); void deleteMask(); int getUserFeedback(QString text, QString informativeText = "", QMessageBox::StandardButtons buttons = QMessageBox::Yes | QMessageBox::No, QMessageBox::StandardButton defaultButton = QMessageBox::Yes, QMessageBox::Icon severity = QMessageBox::Warning); int saveOrCancel(QMessageBox::StandardButton defaultAction = QMessageBox::Save); KoGamutMask* createMaskResource(KoGamutMask* sourceMask, QString newTitle); QPair resolveMaskTitle(QString suggestedTitle); QList getShapesFromLayer(); KisShapeLayerSP getShapeLayer(); KisCanvasResourceProvider* m_resourceProvider; bool m_selfClosingTemplate; bool m_externalTemplateClose; bool m_creatingNewMask; bool m_templatePrevSaved; bool m_selfSelectingMask; GamutMaskChooserUI* m_dockerUI; KoResourceItemChooser* m_maskChooser; KoGamutMask* m_selectedMask; QRegExpValidator* m_maskTitleValidator; KisDocument* m_maskDocument; KisView* m_view; }; #endif // H_GAMUT_MASK_DOCK_H diff --git a/plugins/dockers/gamutmask/gamutmask_plugin.cpp b/plugins/dockers/gamutmask/gamutmask_plugin.cpp index 5c94818b63..cd5ca10d09 100644 --- a/plugins/dockers/gamutmask/gamutmask_plugin.cpp +++ b/plugins/dockers/gamutmask/gamutmask_plugin.cpp @@ -1,57 +1,58 @@ /* * Copyright (c) 2018 Anna Medonosova * - * 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 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 library is distributed in the hope that it will be useful, + * 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 Lesser General Public License for more details. + * GNU General Public License for more details. * - * You should have received a copy of the GNU Lesser General Public License + * 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 "gamutmask_plugin.h" #include "gamutmask_dock.h" #include #include #include #include K_PLUGIN_FACTORY_WITH_JSON(PaletteDockPluginFactory, "krita_gamutmask.json", registerPlugin();) class GamutMaskDockFactory: public KoDockFactoryBase { public: QString id() const override { return QString("GamutMask"); } virtual Qt::DockWidgetArea defaultDockWidgetArea() const { return Qt::RightDockWidgetArea; } QDockWidget* createDockWidget() override { GamutMaskDock* dockWidget = new GamutMaskDock(); dockWidget->setObjectName(id()); return dockWidget; } DockPosition defaultDockPosition() const override { return DockMinimized; } }; GamutMaskPlugin::GamutMaskPlugin(QObject* parent, const QVariantList &): QObject(parent) { KoDockRegistry::instance()->add(new GamutMaskDockFactory()); } #include "gamutmask_plugin.moc" diff --git a/plugins/dockers/gamutmask/gamutmask_plugin.h b/plugins/dockers/gamutmask/gamutmask_plugin.h index 005a3fdd25..e26ca0ea9e 100644 --- a/plugins/dockers/gamutmask/gamutmask_plugin.h +++ b/plugins/dockers/gamutmask/gamutmask_plugin.h @@ -1,30 +1,31 @@ /* * Copyright (c) 2018 Anna Medonosova * - * 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 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 library is distributed in the hope that it will be useful, + * 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 Lesser General Public License for more details. + * GNU General Public License for more details. * - * You should have received a copy of the GNU Lesser General Public License + * 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 H_GAMUT_MASK_PLUGIN_H #define H_GAMUT_MASK_PLUGIN_H #include #include class GamutMaskPlugin: public QObject { public: GamutMaskPlugin(QObject *parent, const QVariantList &); }; #endif // H_GAMUT_MASK_PLUGIN_H diff --git a/plugins/dockers/griddocker/grid_config_widget.cpp b/plugins/dockers/griddocker/grid_config_widget.cpp index f96b1400fa..198cd0e385 100644 --- a/plugins/dockers/griddocker/grid_config_widget.cpp +++ b/plugins/dockers/griddocker/grid_config_widget.cpp @@ -1,358 +1,359 @@ /* * 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. + * the Free Software Foundation; 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 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" #include #include #include #include struct GridConfigWidget::Private { Private() : guiSignalsBlocked(false) {} KisGridConfig gridConfig; KisGuidesConfig guidesConfig; bool guiSignalsBlocked {false}; }; 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); ui->angleLeftSpinbox->setSuffix(QChar(Qt::Key_degree)); ui->angleRightSpinbox->setSuffix(QChar(Qt::Key_degree)); ui->cellSpacingSpinbox->setSuffix(i18n(" px")); ui->gridTypeCombobox->addItem(i18n("Rectangle")); ui->gridTypeCombobox->addItem(i18n("Isometric")); ui->gridTypeCombobox->setCurrentIndex(0); // set to rectangle by default slotGridTypeChanged(); // update the UI to hide any elements we don't need connect(ui->gridTypeCombobox, SIGNAL(currentIndexChanged(int)), SLOT(slotGridTypeChanged())); setGridConfig(m_d->gridConfig); setGuidesConfig(m_d->guidesConfig); // hide offset UI elements if offset is disabled 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->angleLeftSpinbox, SIGNAL(valueChanged(int)), SLOT(slotGridGuiChanged())); connect(ui->angleRightSpinbox, SIGNAL(valueChanged(int)), SLOT(slotGridGuiChanged())); connect(ui->cellSpacingSpinbox, SIGNAL(valueChanged(int)), SLOT(slotGridGuiChanged())); connect(ui->selectMainStyle, SIGNAL(currentIndexChanged(int)), SLOT(slotGridGuiChanged())); connect(ui->colorMain, SIGNAL(changed(QColor)), SLOT(slotGridGuiChanged())); connect(ui->selectSubdivisionStyle, SIGNAL(currentIndexChanged(int)), SLOT(slotGridGuiChanged())); connect(ui->colorSubdivision, SIGNAL(changed(QColor)), SLOT(slotGridGuiChanged())); connect(ui->selectGuidesStyle, SIGNAL(currentIndexChanged(int)), SLOT(slotGuidesGuiChanged())); connect(ui->colorGuides, SIGNAL(changed(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())); connect(ui->chkShowRulers,SIGNAL(toggled(bool)),SIGNAL(showRulersChanged(bool))); connect(KisConfigNotifier::instance(), SIGNAL(configChanged()), SLOT(slotPreferencesUpdated())); } 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->intHSpacing->setValue(m_d->gridConfig.spacing().x()); ui->intHSpacing->setMaximum(std::numeric_limits::max()); ui->intVSpacing->setValue(m_d->gridConfig.spacing().y()); ui->intVSpacing->setMaximum(std::numeric_limits::max()); ui->intXOffset->setValue(m_d->gridConfig.offset().x()); ui->intYOffset->setValue(m_d->gridConfig.offset().y()); ui->intSubdivision->setValue(m_d->gridConfig.subdivision()); ui->chkSnapToGrid->setChecked(m_d->gridConfig.snapToGrid()); ui->angleLeftSpinbox->setValue(m_d->gridConfig.angleLeft()); ui->angleRightSpinbox->setValue(m_d->gridConfig.angleRight()); ui->cellSpacingSpinbox->setValue(m_d->gridConfig.cellSpacing()); ui->selectMainStyle->setCurrentIndex(int(m_d->gridConfig.lineTypeMain())); ui->selectSubdivisionStyle->setCurrentIndex(int(m_d->gridConfig.lineTypeSubdivision())); ui->gridTypeCombobox->setCurrentIndex(m_d->gridConfig.gridType()); 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; } 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.setAngleLeft(ui->angleLeftSpinbox->value()); config.setAngleRight(ui->angleRightSpinbox->value()); config.setCellSpacing(ui->cellSpacingSpinbox->value()); config.setGridType(ui->gridTypeCombobox->currentIndex()); 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::slotPreferencesUpdated() { KisConfig cfg(true); enableIsometricGrid(cfg.useOpenGL()); // Isometric view needs OpenGL } void GridConfigWidget::slotGuidesGuiChanged() { if (m_d->guiSignalsBlocked) return; KisGuidesConfig currentConfig = fetchGuiGuidesConfig(); if (currentConfig == m_d->guidesConfig) return; setGuidesConfigImpl(currentConfig); } void GridConfigWidget::slotGridTypeChanged() { bool showRectangleControls = ui->gridTypeCombobox->currentIndex() == 0; // specific rectangle UI controls ui->lblXSpacing->setVisible(showRectangleControls); ui->lblYSpacing->setVisible(showRectangleControls); ui->intHSpacing->setVisible(showRectangleControls); ui->intVSpacing->setVisible(showRectangleControls); ui->spacingAspectButton->setVisible(showRectangleControls); ui->lblSubdivision->setVisible(showRectangleControls); ui->intSubdivision->setVisible(showRectangleControls); ui->lblSubdivisionStyle->setVisible(showRectangleControls); ui->selectSubdivisionStyle->setVisible(showRectangleControls); ui->colorSubdivision->setVisible(showRectangleControls); // specific isometric UI controls ui->leftAngleLabel->setVisible(!showRectangleControls); ui->rightAngleLabel->setVisible(!showRectangleControls); ui->angleLeftSpinbox->setVisible(!showRectangleControls); ui->angleRightSpinbox->setVisible(!showRectangleControls); ui->cellSpacingLabel->setVisible(!showRectangleControls); ui->cellSpacingSpinbox->setVisible(!showRectangleControls); // disable snapping for isometric grid type for now // remember if we had snapping enabled if it was on the rectangule mode if (!showRectangleControls) { m_isGridEnabled = ui->chkSnapToGrid->isChecked(); ui->chkSnapToGrid->setEnabled(false); ui->chkSnapToGrid->setChecked(false); } else { ui->chkSnapToGrid->setEnabled(true); ui->chkSnapToGrid->setChecked(m_isGridEnabled); } slotGridGuiChanged(); } bool GridConfigWidget::showRulers() const { return ui->chkShowRulers->isChecked(); } void GridConfigWidget::enableIsometricGrid(bool value) { m_isIsometricGridEnabled = value; // Isometric grids disabled if OpenGL is disabled QStandardItemModel *model = qobject_cast(ui->gridTypeCombobox->model()); QStandardItem *item = model->item(1); // isometric option // item->setFlags(m_isIsometricGridEnabled ? item->flags() & ~Qt::ItemIsEnabled: // item->flags() | Qt::ItemIsEnabled); item->setEnabled(m_isIsometricGridEnabled); if (m_isIsometricGridEnabled) { item->setText(i18n("Isometric")); } else { item->setText(i18n("Isometric (requires OpenGL)")); // change drop down index to Rectangular in case it was previously set to isometric ui->gridTypeCombobox->setCurrentIndex(0); } } void GridConfigWidget::setShowRulers(bool value) { ui->chkShowRulers->setChecked(value); } diff --git a/plugins/dockers/griddocker/grid_config_widget.h b/plugins/dockers/griddocker/grid_config_widget.h index 1aa90828c0..e89bad031f 100644 --- a/plugins/dockers/griddocker/grid_config_widget.h +++ b/plugins/dockers/griddocker/grid_config_widget.h @@ -1,81 +1,82 @@ /* * 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. + * the Free Software Foundation; 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 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 GRID_CONFIG_WIDGET_H #define GRID_CONFIG_WIDGET_H #include #include namespace Ui { class GridConfigWidget; } class KisGridConfig; class KisGuidesConfig; class GridConfigWidget : public QWidget { Q_OBJECT public: explicit GridConfigWidget(QWidget *parent = 0); ~GridConfigWidget() override; void setGridConfig(const KisGridConfig &value); KisGridConfig gridConfig() const; void setGuidesConfig(const KisGuidesConfig &value); KisGuidesConfig guidesConfig() const; bool showRulers() const; void enableIsometricGrid(bool value); public Q_SLOTS: void setShowRulers(bool value); private Q_SLOTS: void slotGridGuiChanged(); void slotGuidesGuiChanged(); void slotGridTypeChanged(); void slotPreferencesUpdated(); Q_SIGNALS: void gridValueChanged(); void guidesValueChanged(); void showRulersChanged(bool); private: KisGridConfig fetchGuiGridConfig() const; void setGridConfigImpl(const KisGridConfig &value); KisGuidesConfig fetchGuiGuidesConfig() const; void setGuidesConfigImpl(const KisGuidesConfig &value); private: Ui::GridConfigWidget *ui; struct Private; const QScopedPointer m_d; bool m_isGridEnabled {false}; bool m_isIsometricGridEnabled {true}; }; #endif // GRID_CONFIG_WIDGET_H diff --git a/plugins/dockers/griddocker/griddocker.cpp b/plugins/dockers/griddocker/griddocker.cpp index 3dd6a87f7b..d5aeb698c7 100644 --- a/plugins/dockers/griddocker/griddocker.cpp +++ b/plugins/dockers/griddocker/griddocker.cpp @@ -1,87 +1,88 @@ /* * 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. + * the Free Software Foundation; 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 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 "griddocker.h" #include #include #include #include #include #include #include "kis_config.h" #include "kis_cursor.h" #include "kis_global.h" #include "kis_types.h" #include "KisViewManager.h" #include "griddocker_dock.h" #include K_PLUGIN_FACTORY_WITH_JSON(GridDockerPluginFactory, "krita_griddocker.json", registerPlugin();) class GridDockerDockFactory : public KoDockFactoryBase { public: GridDockerDockFactory() { } QString id() const override { return QString( "GridDocker" ); } virtual Qt::DockWidgetArea defaultDockWidgetArea() const { return Qt::RightDockWidgetArea; } QDockWidget* createDockWidget() override { GridDockerDock * dockWidget = new GridDockerDock(); dockWidget->setObjectName(id()); return dockWidget; } DockPosition defaultDockPosition() const override { return DockMinimized; } private: }; GridDockerPlugin::GridDockerPlugin(QObject *parent, const QVariantList &) : QObject(parent) { KoDockRegistry::instance()->add(new GridDockerDockFactory()); } GridDockerPlugin::~GridDockerPlugin() { m_view = 0; } #include "griddocker.moc" diff --git a/plugins/dockers/griddocker/griddocker.h b/plugins/dockers/griddocker/griddocker.h index fa7df907cf..9de7f52fe2 100644 --- a/plugins/dockers/griddocker/griddocker.h +++ b/plugins/dockers/griddocker/griddocker.h @@ -1,39 +1,40 @@ /* * 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. + * the Free Software Foundation; 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 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 _GRID_DOCKER_H_ #define _GRID_DOCKER_H_ #include #include class KisViewManager; /** * Template of view plugin */ class GridDockerPlugin : public QObject { Q_OBJECT public: GridDockerPlugin(QObject *parent, const QVariantList &); ~GridDockerPlugin() override; private: KisViewManager* m_view; }; #endif diff --git a/plugins/dockers/griddocker/griddocker_dock.cpp b/plugins/dockers/griddocker/griddocker_dock.cpp index 5615e8d23d..0c6a1be2e8 100644 --- a/plugins/dockers/griddocker/griddocker_dock.cpp +++ b/plugins/dockers/griddocker/griddocker_dock.cpp @@ -1,128 +1,129 @@ /* * 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. + * the Free Software Foundation; 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 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 "griddocker_dock.h" //#include "gridwidget.h" // #include // #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "grid_config_widget.h" GridDockerDock::GridDockerDock( ) : QDockWidget(i18n("Grid and Guides")) , m_canvas(0) { m_configWidget = new GridConfigWidget(this); connect(m_configWidget, SIGNAL(gridValueChanged()), SLOT(slotGuiGridConfigChanged())); connect(m_configWidget, SIGNAL(guidesValueChanged()), SLOT(slotGuiGuidesConfigChanged())); setWidget(m_configWidget); setEnabled(m_canvas); } GridDockerDock::~GridDockerDock() { } void GridDockerDock::setCanvas(KoCanvasBase * canvas) { if(canvas && m_canvas == canvas) return; if (m_canvas) { m_canvasConnections.clear(); m_canvas->disconnectCanvasObserver(this); m_canvas->image()->disconnect(this); } m_canvas = canvas ? dynamic_cast(canvas) : 0; setEnabled(m_canvas); if (m_canvas && m_canvas->viewManager() && m_canvas->viewManager()->document()) { m_canvasConnections.addConnection( m_canvas->viewManager()->gridManager(), SIGNAL(sigRequestUpdateGridConfig(KisGridConfig)), this, SLOT(slotGridConfigUpdateRequested(KisGridConfig))); slotGridConfigUpdateRequested(m_canvas->viewManager()->document()->gridConfig()); KisAction* action = m_canvas->viewManager()->actionManager()->actionByName("view_ruler"); m_canvasConnections.addConnection(m_configWidget,SIGNAL(showRulersChanged(bool)),action,SLOT(setChecked(bool))); m_canvasConnections.addConnection(action,SIGNAL(toggled(bool)),m_configWidget,SLOT(setShowRulers(bool))); m_configWidget->setShowRulers(action->isChecked()); m_canvasConnections.addConnection( m_canvas->viewManager()->guidesManager(), SIGNAL(sigRequestUpdateGuidesConfig(KisGuidesConfig)), this, SLOT(slotGuidesConfigUpdateRequested(KisGuidesConfig))); slotGuidesConfigUpdateRequested(m_canvas->viewManager()->document()->guidesConfig()); // isometric grid only available with OpenGL if (m_canvas->canvasIsOpenGL()) { m_configWidget->enableIsometricGrid(true); } else { m_configWidget->enableIsometricGrid(false); } } } void GridDockerDock::unsetCanvas() { setCanvas(0); } void GridDockerDock::slotGuiGridConfigChanged() { if (!m_canvas) return; m_canvas->viewManager()->gridManager()->setGridConfig(m_configWidget->gridConfig()); } void GridDockerDock::slotGridConfigUpdateRequested(const KisGridConfig &config) { m_configWidget->setGridConfig(config); } void GridDockerDock::slotGuiGuidesConfigChanged() { if (!m_canvas) return; m_canvas->viewManager()->guidesManager()->setGuidesConfig(m_configWidget->guidesConfig()); } void GridDockerDock::slotGuidesConfigUpdateRequested(const KisGuidesConfig &config) { m_configWidget->setGuidesConfig(config); } diff --git a/plugins/dockers/griddocker/griddocker_dock.h b/plugins/dockers/griddocker/griddocker_dock.h index d7d1a775d8..b156c23eab 100644 --- a/plugins/dockers/griddocker/griddocker_dock.h +++ b/plugins/dockers/griddocker/griddocker_dock.h @@ -1,55 +1,56 @@ /* * 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. + * the Free Software Foundation; 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 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 _GRID_DOCK_H_ #define _GRID_DOCK_H_ #include #include #include "kis_signal_auto_connection.h" class QVBoxLayout; class KisCanvas2; class GridConfigWidget; class KisSignalAutoConnection; class KisGridConfig; class KisGuidesConfig; class GridDockerDock : public QDockWidget, public KoCanvasObserverBase { Q_OBJECT public: GridDockerDock(); ~GridDockerDock() override; QString observerName() override { return "GridDockerDock"; } void setCanvas(KoCanvasBase *canvas) override; void unsetCanvas() override; public Q_SLOTS: void slotGuiGridConfigChanged(); void slotGridConfigUpdateRequested(const KisGridConfig &config); void slotGuiGuidesConfigChanged(); void slotGuidesConfigUpdateRequested(const KisGuidesConfig &config); private: GridConfigWidget *m_configWidget; QPointer m_canvas; KisSignalAutoConnectionsStore m_canvasConnections; }; #endif diff --git a/plugins/dockers/histogram/histogramdocker.cpp b/plugins/dockers/histogram/histogramdocker.cpp index 623bce5f92..93dd11349a 100644 --- a/plugins/dockers/histogram/histogramdocker.cpp +++ b/plugins/dockers/histogram/histogramdocker.cpp @@ -1,87 +1,88 @@ /* * Copyright (c) 2016 Eugene Ingerman * * 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. + * the Free Software Foundation; 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 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 "histogramdocker.h" #include #include #include #include #include #include #include "kis_config.h" #include "kis_cursor.h" #include "kis_global.h" #include "kis_types.h" #include "KisViewManager.h" #include "histogramdocker_dock.h" #include K_PLUGIN_FACTORY_WITH_JSON(HistogramDockerPluginFactory, "krita_histogramdocker.json", registerPlugin();) class HistogramDockerDockFactory : public KoDockFactoryBase { public: HistogramDockerDockFactory() { } QString id() const override { return QString( "HistogramDocker" ); } virtual Qt::DockWidgetArea defaultDockWidgetArea() const { return Qt::RightDockWidgetArea; } QDockWidget* createDockWidget() override { HistogramDockerDock * dockWidget = new HistogramDockerDock(); dockWidget->setObjectName(id()); return dockWidget; } DockPosition defaultDockPosition() const override { return DockRight; } private: }; HistogramDockerPlugin::HistogramDockerPlugin(QObject *parent, const QVariantList &) : QObject(parent) { KoDockRegistry::instance()->add(new HistogramDockerDockFactory()); } HistogramDockerPlugin::~HistogramDockerPlugin() { m_view = 0; } #include "histogramdocker.moc" diff --git a/plugins/dockers/histogram/histogramdocker.h b/plugins/dockers/histogram/histogramdocker.h index 0e73af0b5e..4bb0047f43 100644 --- a/plugins/dockers/histogram/histogramdocker.h +++ b/plugins/dockers/histogram/histogramdocker.h @@ -1,39 +1,40 @@ /* * Copyright (c) 2016 Eugene Ingerman * * 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. + * the Free Software Foundation; 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 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 _HISTOGRAM_DOCKER_H_ #define _HISTOGRAM_DOCKER_H_ #include #include class KisViewManager; /** * Template of view plugin */ class HistogramDockerPlugin : public QObject { Q_OBJECT public: HistogramDockerPlugin(QObject *parent, const QVariantList &); ~HistogramDockerPlugin() override; private: KisViewManager* m_view; }; #endif diff --git a/plugins/dockers/histogram/histogramdocker_dock.cpp b/plugins/dockers/histogram/histogramdocker_dock.cpp index 4028c25c7f..e537851c74 100644 --- a/plugins/dockers/histogram/histogramdocker_dock.cpp +++ b/plugins/dockers/histogram/histogramdocker_dock.cpp @@ -1,111 +1,112 @@ /* * Copyright (c) 2016 Eugene Ingerman * * 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. + * the Free Software Foundation; 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 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 "histogramdocker_dock.h" #include #include #include #include "kis_canvas2.h" #include #include #include "kis_image.h" #include "kis_paint_device.h" #include "kis_idle_watcher.h" #include "histogramdockerwidget.h" HistogramDockerDock::HistogramDockerDock() : QDockWidget(i18n("Histogram")), m_imageIdleWatcher(new KisIdleWatcher(250, this)), m_canvas(0) { QWidget *page = new QWidget(this); m_layout = new QVBoxLayout(page); m_histogramWidget = new HistogramDockerWidget(this); m_histogramWidget->setBackgroundRole(QPalette::AlternateBase); m_histogramWidget->setAutoFillBackground(true); // paints background role before paint() m_histogramWidget->setMinimumHeight(50); //m_histogramWidget->setSmoothHistogram(false); m_layout->addWidget(m_histogramWidget, 1); setWidget(page); connect(m_imageIdleWatcher, &KisIdleWatcher::startedIdleMode, this, &HistogramDockerDock::updateHistogram); } void HistogramDockerDock::setCanvas(KoCanvasBase * canvas) { if (m_canvas == canvas) return; setEnabled(canvas != 0); if (m_canvas) { m_canvas->disconnectCanvasObserver(this); m_canvas->image()->disconnect(this); } m_canvas = dynamic_cast(canvas); if (m_canvas) { m_histogramWidget->setPaintDevice(m_canvas); m_imageIdleWatcher->setTrackedImage(m_canvas->image()); connect(m_canvas->image(), SIGNAL(sigImageUpdated(QRect)), this, SLOT(startUpdateCanvasProjection()), Qt::UniqueConnection); connect(m_canvas->image(), SIGNAL(sigColorSpaceChanged(const KoColorSpace*)), this, SLOT(sigColorSpaceChanged(const KoColorSpace*)), Qt::UniqueConnection); m_imageIdleWatcher->startCountdown(); } } void HistogramDockerDock::unsetCanvas() { setEnabled(false); m_canvas = 0; m_histogramWidget->setPaintDevice(m_canvas); m_imageIdleWatcher->startCountdown(); } void HistogramDockerDock::startUpdateCanvasProjection() { if (isVisible()) { m_imageIdleWatcher->startCountdown(); } } void HistogramDockerDock::showEvent(QShowEvent *event) { Q_UNUSED(event); m_imageIdleWatcher->startCountdown(); } void HistogramDockerDock::sigColorSpaceChanged(const KoColorSpace */*cs*/) { if (isVisible()) { m_imageIdleWatcher->startCountdown(); } } void HistogramDockerDock::updateHistogram() { if (isVisible()) { m_histogramWidget->updateHistogram(); } } diff --git a/plugins/dockers/histogram/histogramdocker_dock.h b/plugins/dockers/histogram/histogramdocker_dock.h index 583a95e70c..53c074d26a 100644 --- a/plugins/dockers/histogram/histogramdocker_dock.h +++ b/plugins/dockers/histogram/histogramdocker_dock.h @@ -1,59 +1,60 @@ /* * Copyright (c) 2016 Eugene Ingerman * * 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. + * the Free Software Foundation; 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 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 _HISTOGRAM_DOCK_H_ #define _HISTOGRAM_DOCK_H_ #include #include #include #include #include class QVBoxLayout; class KisIdleWatcher; class KoHistogramProducer; class HistogramDockerWidget; class HistogramDockerDock : public QDockWidget, public KoCanvasObserverBase { Q_OBJECT public: HistogramDockerDock(); QString observerName() override { return "HistogramDockerDock"; } void setCanvas(KoCanvasBase *canvas) override; void unsetCanvas() override; public Q_SLOTS: void startUpdateCanvasProjection(); void sigColorSpaceChanged(const KoColorSpace* cs); void updateHistogram(); protected: void showEvent(QShowEvent *event) override; private: QVBoxLayout *m_layout; KisIdleWatcher *m_imageIdleWatcher; HistogramDockerWidget *m_histogramWidget; QPointer m_canvas; }; #endif diff --git a/plugins/dockers/histogram/histogramdockerwidget.cpp b/plugins/dockers/histogram/histogramdockerwidget.cpp index 30e51285ab..5c8e29d929 100644 --- a/plugins/dockers/histogram/histogramdockerwidget.cpp +++ b/plugins/dockers/histogram/histogramdockerwidget.cpp @@ -1,198 +1,199 @@ /* * Copyright (c) 2016 Eugene Ingerman * * 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. + * the Free Software Foundation; 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 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 "histogramdockerwidget.h" #include #include #include #include #include #include #include #include "KoChannelInfo.h" #include "kis_paint_device.h" #include "KoColorSpace.h" #include "kis_iterator_ng.h" #include "kis_canvas2.h" HistogramDockerWidget::HistogramDockerWidget(QWidget *parent, const char *name, Qt::WindowFlags f) : QLabel(parent, f), m_paintDevice(nullptr), m_smoothHistogram(true) { setObjectName(name); } HistogramDockerWidget::~HistogramDockerWidget() { } void HistogramDockerWidget::setPaintDevice(KisCanvas2* canvas) { if (canvas) { m_paintDevice = canvas->image()->projection(); m_bounds = canvas->image()->bounds(); } else { m_paintDevice.clear(); m_bounds = QRect(); m_histogramData.clear(); } } void HistogramDockerWidget::updateHistogram() { if (!m_paintDevice.isNull()) { KisPaintDeviceSP m_devClone = new KisPaintDevice(m_paintDevice->colorSpace()); m_devClone->makeCloneFrom(m_paintDevice, m_bounds); HistogramComputationThread *workerThread = new HistogramComputationThread(m_devClone, m_bounds); connect(workerThread, &HistogramComputationThread::resultReady, this, &HistogramDockerWidget::receiveNewHistogram); connect(workerThread, &HistogramComputationThread::finished, workerThread, &QObject::deleteLater); workerThread->start(); } else { m_histogramData.clear(); update(); } } void HistogramDockerWidget::receiveNewHistogram(HistVector *histogramData) { m_histogramData = *histogramData; update(); } void HistogramDockerWidget::paintEvent(QPaintEvent *event) { if (m_paintDevice && !m_histogramData.empty()) { int nBins = m_histogramData.at(0).size(); const KoColorSpace* cs = m_paintDevice->colorSpace(); QLabel::paintEvent(event); QPainter painter(this); painter.fillRect(0, 0, this->width(), this->height(), this->palette().dark().color()); painter.setPen(this->palette().light().color()); const int NGRID = 4; for (int i = 0; i <= NGRID; ++i) { painter.drawLine(this->width()*i / NGRID, 0., this->width()*i / NGRID, this->height()); painter.drawLine(0., this->height()*i / NGRID, this->width(), this->height()*i / NGRID); } unsigned int nChannels = cs->channelCount(); QList channels = cs->channels(); unsigned int highest = 0; //find the most populous bin in the histogram to scale it properly for (int chan = 0; chan < channels.size(); chan++) { if (channels.at(chan)->channelType() != KoChannelInfo::ALPHA) { std::vector histogramTemp = m_histogramData.at(chan); //use 98th percentile, rather than max for better visual appearance int nthPercentile = 2 * histogramTemp.size() / 100; //unsigned int max = *std::max_element(m_histogramData.at(chan).begin(),m_histogramData.at(chan).end()); std::nth_element(histogramTemp.begin(), histogramTemp.begin() + nthPercentile, histogramTemp.end(), std::greater()); unsigned int max = *(histogramTemp.begin() + nthPercentile); highest = std::max(max, highest); } } painter.setWindow(QRect(-1, 0, nBins + 1, highest)); painter.setCompositionMode(QPainter::CompositionMode_Plus); for (int chan = 0; chan < (int)nChannels; chan++) { if (channels.at(chan)->channelType() != KoChannelInfo::ALPHA) { QColor color = channels.at(chan)->color(); //special handling of grayscale color spaces. can't use color returned above. if(cs->colorChannelCount()==1){ color = QColor(Qt::gray); } QColor fill_color = color; fill_color.setAlphaF(.25); painter.setBrush(fill_color); QPen pen = QPen(color); pen.setWidth(0); painter.setPen(pen); if (m_smoothHistogram) { QPainterPath path; path.moveTo(QPointF(-1, highest)); for (qint32 i = 0; i < nBins; ++i) { float v = std::max((float)highest - m_histogramData[chan][i], 0.f); path.lineTo(QPointF(i, v)); } path.lineTo(QPointF(nBins + 1, highest)); path.closeSubpath(); painter.drawPath(path); } else { pen.setWidth(1); painter.setPen(pen); for (qint32 i = 0; i < nBins; ++i) { float v = std::max((float)highest - m_histogramData[chan][i], 0.f); painter.drawLine(QPointF(i, highest), QPointF(i, v)); } } } } } } void HistogramComputationThread::run() { const KoColorSpace *cs = m_dev->colorSpace(); quint32 channelCount = m_dev->channelCount(); quint32 pixelSize = m_dev->pixelSize(); quint32 imageSize = m_bounds.width() * m_bounds.height(); quint32 nSkip = 1 + (imageSize >> 20); //for speed use about 1M pixels for computing histograms //allocate space for the histogram data bins.resize((int)channelCount); for (auto &bin : bins) { bin.resize(std::numeric_limits::max() + 1); } QRect bounds = m_dev->exactBounds(); if (bounds.isEmpty()) return; quint32 toSkip = nSkip; KisSequentialConstIterator it(m_dev, m_dev->exactBounds()); int numConseqPixels = it.nConseqPixels(); while (it.nextPixels(numConseqPixels)) { numConseqPixels = it.nConseqPixels(); const quint8* pixel = it.rawDataConst(); for (int k = 0; k < numConseqPixels; ++k) { if (--toSkip == 0) { for (int chan = 0; chan < (int)channelCount; ++chan) { bins[chan][cs->scaleToU8(pixel, chan)]++; } toSkip = nSkip; } pixel += pixelSize; } } emit resultReady(&bins); } diff --git a/plugins/dockers/histogram/histogramdockerwidget.h b/plugins/dockers/histogram/histogramdockerwidget.h index a482583c11..156db1fad2 100644 --- a/plugins/dockers/histogram/histogramdockerwidget.h +++ b/plugins/dockers/histogram/histogramdockerwidget.h @@ -1,74 +1,75 @@ /* * Copyright (c) 2016 Eugene Ingerman * * 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. + * the Free Software Foundation; 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 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 HISTOGRAMDOCKERWIDGET_H #define HISTOGRAMDOCKERWIDGET_H #include #include #include #include #include "kis_types.h" #include class KisCanvas2; typedef std::vector > HistVector; //Don't use QVector here - it's too slow for this purpose class HistogramComputationThread : public QThread { Q_OBJECT public: HistogramComputationThread(KisPaintDeviceSP _dev, const QRect& _bounds) : m_dev(_dev), m_bounds(_bounds) {} void run() override; Q_SIGNALS: void resultReady(HistVector*); private: KisPaintDeviceSP m_dev; QRect m_bounds; HistVector bins; }; class HistogramDockerWidget : public QLabel { Q_OBJECT public: HistogramDockerWidget(QWidget *parent = 0, const char *name = 0, Qt::WindowFlags f = 0); ~HistogramDockerWidget() override; void setPaintDevice(KisCanvas2* canvas); void paintEvent(QPaintEvent *event) override; public Q_SLOTS: void updateHistogram(); void receiveNewHistogram(HistVector*); private: KisPaintDeviceSP m_paintDevice; HistVector m_histogramData; QRect m_bounds; bool m_smoothHistogram; }; #endif // HISTOGRAMDOCKERWIDGET_H diff --git a/plugins/dockers/layerdocker/LayerDocker.cpp b/plugins/dockers/layerdocker/LayerDocker.cpp index cbef015e08..ba5683c8e3 100644 --- a/plugins/dockers/layerdocker/LayerDocker.cpp +++ b/plugins/dockers/layerdocker/LayerDocker.cpp @@ -1,41 +1,42 @@ /* * Copyright (c) 2009 Boudewijn Rempt * * 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. + * the Free Software Foundation; 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 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 "LayerDocker.h" #include #include #include #include "kis_debug.h" #include "LayerBox.h" K_PLUGIN_FACTORY_WITH_JSON(KritaLayerDockerPluginFactory, "kritalayerdocker.json", registerPlugin();) KritaLayerDockerPlugin::KritaLayerDockerPlugin(QObject *parent, const QVariantList &) : QObject(parent) { KoDockRegistry::instance()->add(new LayerBoxFactory()); } KritaLayerDockerPlugin::~KritaLayerDockerPlugin() { } #include "LayerDocker.moc" diff --git a/plugins/dockers/layerdocker/LayerDocker.h b/plugins/dockers/layerdocker/LayerDocker.h index e7c0729930..be323bd581 100644 --- a/plugins/dockers/layerdocker/LayerDocker.h +++ b/plugins/dockers/layerdocker/LayerDocker.h @@ -1,37 +1,38 @@ /* * Copyright (c) 2009 Boudewijn Rempt * * 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. + * the Free Software Foundation; 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 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 _DEFAULT_DOCKERS_H #define _DEFAULT_DOCKERS_H #include #include /** * Template of view plugin */ class KritaLayerDockerPlugin : public QObject { Q_OBJECT public: KritaLayerDockerPlugin(QObject *parent, const QVariantList &); ~KritaLayerDockerPlugin() override; }; #endif diff --git a/plugins/dockers/logdocker/LogDocker.cpp b/plugins/dockers/logdocker/LogDocker.cpp index e65a9e4a3d..8146da5426 100644 --- a/plugins/dockers/logdocker/LogDocker.cpp +++ b/plugins/dockers/logdocker/LogDocker.cpp @@ -1,80 +1,80 @@ /* -* Copyright (c) 2018 Boudewijn Rempt + * Copyright (c) 2018 Boudewijn Rempt * - * 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 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 library is distributed in the hope that it will be useful, + * 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 Lesser General Public License for more details. + * GNU General Public License for more details. * - * You should have received a copy of the GNU Lesser General Public License + * 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 "LogDocker.h" #include #include #include #include #include "LogDockerDock.h" K_PLUGIN_FACTORY_WITH_JSON(LogDockerPluginFactory, "krita_logdocker.json", registerPlugin();) class LogDockerDockFactory : public KoDockFactoryBase { public: LogDockerDockFactory() { } virtual ~LogDockerDockFactory() { } QString id() const override { return QString( "LogDocker" ); } virtual Qt::DockWidgetArea defaultDockWidgetArea() const { return Qt::RightDockWidgetArea; } QDockWidget* createDockWidget() override { LogDockerDock * dockWidget = new LogDockerDock(); dockWidget->setObjectName(id()); return dockWidget; } DockPosition defaultDockPosition() const override { return DockMinimized; } private: }; LogDockerPlugin::LogDockerPlugin(QObject *parent, const QVariantList &) : QObject(parent) { KoDockRegistry::instance()->add(new LogDockerDockFactory()); } LogDockerPlugin::~LogDockerPlugin() { } #include "LogDocker.moc" diff --git a/plugins/dockers/logdocker/LogDocker.h b/plugins/dockers/logdocker/LogDocker.h index 40ac6a099e..07b4872f77 100644 --- a/plugins/dockers/logdocker/LogDocker.h +++ b/plugins/dockers/logdocker/LogDocker.h @@ -1,32 +1,34 @@ /* * Copyright (c) 2018 Boudewijn Rempt * - * 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 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 library is distributed in the hope that it will be useful, + * 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 Lesser General Public License for more details. + * GNU General Public License for more details. * - * You should have received a copy of the GNU Lesser General Public License + * 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 _LOG_DOCKER_H_ #define _LOG_DOCKER_H_ #include #include class LogDockerPlugin : public QObject { Q_OBJECT public: LogDockerPlugin(QObject *parent, const QVariantList &); ~LogDockerPlugin() override; }; #endif diff --git a/plugins/dockers/logdocker/LogDockerDock.cpp b/plugins/dockers/logdocker/LogDockerDock.cpp index dedbed5e6a..6271ab7156 100644 --- a/plugins/dockers/logdocker/LogDockerDock.cpp +++ b/plugins/dockers/logdocker/LogDockerDock.cpp @@ -1,336 +1,338 @@ /* * Copyright (c) 2018 Boudewijn Rempt * - * 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 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 library is distributed in the hope that it will be useful, + * 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 Lesser General Public License for more details. + * GNU General Public License for more details. * - * You should have received a copy of the GNU Lesser General Public License + * 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 "LogDockerDock.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "kis_canvas2.h" #include "KisViewManager.h" #include "kis_config.h" MessageSender *LogDockerDock::s_messageSender {new MessageSender()}; QTextCharFormat LogDockerDock::s_debug; QTextCharFormat LogDockerDock::s_info; QTextCharFormat LogDockerDock::s_warning; QTextCharFormat LogDockerDock::s_critical; QTextCharFormat LogDockerDock::s_fatal; LogDockerDock::LogDockerDock( ) : QDockWidget(i18n("Log Viewer")) { QWidget *page = new QWidget(this); setupUi(page); setWidget(page); bnToggle->setIcon(koIcon("view-list-text")); connect(bnToggle, SIGNAL(clicked(bool)), SLOT(toggleLogging(bool))); bnToggle->setChecked(KisConfig(true).readEntry("logviewer_enabled", false)); toggleLogging(KisConfig(true).readEntry("logviewer_enabled", false)); bnClear->setIcon(koIcon("edit-clear")); connect(bnClear, SIGNAL(clicked(bool)), SLOT(clearLog())); bnSave->setIcon(koIcon("document-save")); connect(bnSave, SIGNAL(clicked(bool)), SLOT(saveLog())); bnSettings->setIcon(koIcon("configure")); connect(bnSettings, SIGNAL(clicked(bool)), SLOT(settings())); qRegisterMetaType("QtMsgType"); connect(s_messageSender, SIGNAL(emitMessage(QtMsgType,QString)), this, SLOT(insertMessage(QtMsgType,QString)), Qt::AutoConnection); applyCategories(); changeTheme(); } void LogDockerDock::setCanvas(KoCanvasBase *) { setEnabled(true); } void LogDockerDock::setViewManager(KisViewManager *kisview) { connect(static_cast(kisview->mainWindow()), SIGNAL(themeChanged()), SLOT(changeTheme())); } void LogDockerDock::toggleLogging(bool toggle) { KisConfig(false).writeEntry("logviewer_enabled", toggle); if (toggle) { qInstallMessageHandler(messageHandler); applyCategories(); } else { qInstallMessageHandler(0); } } void LogDockerDock::clearLog() { txtLogViewer->document()->clear(); } void LogDockerDock::saveLog() { KoFileDialog fileDialog(this, KoFileDialog::SaveFile, "logfile"); fileDialog.setDefaultDir(QStandardPaths::writableLocation(QStandardPaths::DesktopLocation) + "/" + QString("krita_%1.log").arg(QDateTime::currentDateTime().toString())); QString filename = fileDialog.filename(); if (!filename.isEmpty()) { QFile f(filename); f.open(QFile::WriteOnly); f.write(txtLogViewer->document()->toPlainText().toUtf8()); f.close(); } } void LogDockerDock::settings() { KoDialog dlg(this); dlg.setButtons(KoDialog::Ok | KoDialog::Cancel); dlg.setCaption(i18n("Log Settings")); QWidget *page = new QWidget(&dlg); dlg.setMainWidget(page); QVBoxLayout *layout = new QVBoxLayout(page); KConfigGroup cfg( KSharedConfig::openConfig(), "LogDocker"); QCheckBox *chkKrita = new QCheckBox(i18n("General"), page); chkKrita->setChecked(cfg.readEntry("krita_41000", false)); layout->addWidget(chkKrita); QCheckBox *chkResources = new QCheckBox(i18n("Resource Management"), page); chkResources->setChecked(cfg.readEntry("resources_30009", false)); layout->addWidget(chkResources); QCheckBox *chkImage = new QCheckBox(i18n("Image Core"), page); chkImage->setChecked(cfg.readEntry("image_41001", false)); layout->addWidget(chkImage); QCheckBox *chkRegistry = new QCheckBox(i18n("Registries"), page); chkRegistry->setChecked(cfg.readEntry("registry_41002", false)); layout->addWidget(chkRegistry); QCheckBox *chkTools = new QCheckBox(i18n("Tools"), page); chkTools->setChecked(cfg.readEntry("tools_41003", false)); layout->addWidget(chkTools); QCheckBox *chkTiles = new QCheckBox(i18n("Tile Engine"), page); chkTiles->setChecked(cfg.readEntry("tiles_41004", false)); layout->addWidget(chkTiles); QCheckBox *chkFilters = new QCheckBox(i18n("Filters"), page); chkFilters->setChecked(cfg.readEntry("filters_41005", false)); layout->addWidget(chkFilters); QCheckBox *chkPlugins = new QCheckBox(i18n("Plugin Management"), page); chkPlugins->setChecked(cfg.readEntry("plugins_41006", false)); layout->addWidget(chkPlugins); QCheckBox *chkUi = new QCheckBox(i18n("User Interface"), page); chkUi->setChecked(cfg.readEntry("ui_41007", false)); layout->addWidget(chkUi); QCheckBox *chkFile = new QCheckBox(i18n("File loading and saving"), page); chkFile->setChecked(cfg.readEntry("file_41008", false)); layout->addWidget(chkFile); QCheckBox *chkMath = new QCheckBox(i18n("Mathematics and calculations"), page); chkMath->setChecked(cfg.readEntry("math_41009", false)); layout->addWidget(chkMath); QCheckBox *chkRender = new QCheckBox(i18n("Image Rendering"), page); chkRender->setChecked(cfg.readEntry("render_41010", false)); layout->addWidget(chkRender); QCheckBox *chkScript = new QCheckBox(i18n("Scripting"), page); chkScript->setChecked(cfg.readEntry("script_41011", false)); layout->addWidget(chkScript); QCheckBox *chkInput = new QCheckBox(i18n("Input handling"), page); chkInput->setChecked(cfg.readEntry("input_41012", false)); layout->addWidget(chkInput); QCheckBox *chkAction = new QCheckBox(i18n("Actions"), page); chkAction->setChecked(cfg.readEntry("action_41013", false)); layout->addWidget(chkAction); QCheckBox *chkTablet = new QCheckBox(i18n("Tablet Handling"), page); chkTablet->setChecked(cfg.readEntry("tablet_41014", false)); layout->addWidget(chkTablet); QCheckBox *chkOpenGL = new QCheckBox(i18n("GPU Canvas"), page); chkOpenGL->setChecked(cfg.readEntry("opengl_41015", false)); layout->addWidget(chkOpenGL); QCheckBox *chkMetaData = new QCheckBox(i18n("Metadata"), page); chkMetaData->setChecked(cfg.readEntry("metadata_41016", false)); layout->addWidget(chkMetaData); QCheckBox *chkPigment = new QCheckBox(i18n("Color Management"), page); chkPigment->setChecked(cfg.readEntry("pigment", false)); layout->addWidget(chkPigment); if (dlg.exec()) { // Apply the new settings cfg.writeEntry("resources_30009", chkResources->isChecked()); cfg.writeEntry("krita_41000", chkKrita->isChecked()); cfg.writeEntry("image_41001", chkImage->isChecked()); cfg.writeEntry("registry_41002", chkRegistry->isChecked()); cfg.writeEntry("tools_41003", chkTools->isChecked()); cfg.writeEntry("tiles_41004", chkTiles->isChecked()); cfg.writeEntry("filters_41005", chkFilters->isChecked()); cfg.writeEntry("plugins_41006", chkPlugins->isChecked()); cfg.writeEntry("ui_41007", chkUi->isChecked()); cfg.writeEntry("file_41008", chkFile->isChecked()); cfg.writeEntry("math_41009", chkMath->isChecked()); cfg.writeEntry("render_41010", chkRender->isChecked()); cfg.writeEntry("script_41011", chkScript->isChecked()); cfg.writeEntry("input_41012", chkInput->isChecked()); cfg.writeEntry("action_41013", chkAction->isChecked()); cfg.writeEntry("tablet_41014", chkTablet->isChecked()); cfg.writeEntry("opengl_41015", chkOpenGL->isChecked()); cfg.writeEntry("metadata_41016", chkMetaData->isChecked()); cfg.writeEntry("pigment", chkPigment->isChecked()); applyCategories(); } } QString cfgToString(QString tpl, bool cfg) { return tpl.arg(cfg ? "true" : "false"); } void LogDockerDock::applyCategories() { QStringList filters; KConfigGroup cfg( KSharedConfig::openConfig(), "LogDocker"); filters << cfgToString("krita.general=%1", cfg.readEntry("krita_41000", false)); filters << cfgToString("krita.lib.resources=%1", cfg.readEntry("resources_30009", false)); filters << cfgToString("krita.core=%1", cfg.readEntry("image_41001", false)); filters << cfgToString("krita.registry=%1", cfg.readEntry("registry_41002", false)); filters << cfgToString("krita.tools=%1", cfg.readEntry("tools_41003", false)); filters << cfgToString("krita.lib.flake=%1", cfg.readEntry("tools_41003", false)); filters << cfgToString("krita.tiles=%1", cfg.readEntry("tiles_41004", false)); filters << cfgToString("krita.filters=%1", cfg.readEntry("filters_41005", false)); filters << cfgToString("krita.plugins=%1", cfg.readEntry("plugins_41006", false)); filters << cfgToString("krita.lib.plugin=%1", cfg.readEntry("plugins_41006", false)); filters << cfgToString("krita.ui=%1", cfg.readEntry("ui_41007", false)); filters << cfgToString("krita.widgets=%1", cfg.readEntry("ui_41007", false)); filters << cfgToString("krita.widgetutils=%1", cfg.readEntry("ui_41007", false)); filters << cfgToString("krita.file=%1", cfg.readEntry("file_41008", false)); filters << cfgToString("krita.lib.store=%1", cfg.readEntry("file_41008", false)); filters << cfgToString("krita.lib.odf=%1", cfg.readEntry("file_41008", false)); filters << cfgToString("krita.math=%1", cfg.readEntry("math_41009", false)); filters << cfgToString("krita.grender=%1", cfg.readEntry("render_41010", false)); filters << cfgToString("krita.scripting=%1", cfg.readEntry("script_41011", false)); filters << cfgToString("krita.input=%1", cfg.readEntry("input_41012", false)); filters << cfgToString("krita.action=%1", cfg.readEntry("action_41013", false)); filters << cfgToString("krita.tablet=%1", cfg.readEntry("tablet_41014", false)); filters << cfgToString("krita.opengl=%1", cfg.readEntry("opengl_41015", false)); filters << cfgToString("krita.metadata=%1", cfg.readEntry("metadata_41016", false)); filters << cfgToString("krita.lib.pigment=%1", cfg.readEntry("pigment", false)); QLoggingCategory::setFilterRules(filters.join("\n")); } void LogDockerDock::messageHandler(QtMsgType type, const QMessageLogContext &/*context*/, const QString &msg) { s_messageSender->sendMessage(type, msg); } void LogDockerDock::insertMessage(QtMsgType type, const QString &msg) { QTextDocument *doc = txtLogViewer->document(); QTextCursor cursor(doc); cursor.movePosition(QTextCursor::End, QTextCursor::MoveAnchor); cursor.beginEditBlock(); switch (type) { case QtDebugMsg: cursor.insertText(msg + "\n", s_debug); break; case QtInfoMsg: cursor.insertText(msg + "\n", s_info); break; case QtWarningMsg: cursor.insertText(msg + "\n", s_warning); break; case QtCriticalMsg: cursor.insertText(msg + "\n", s_critical); break; case QtFatalMsg: cursor.insertText(msg + "\n", s_fatal); break; } cursor.endEditBlock(); txtLogViewer->verticalScrollBar()->setValue(txtLogViewer->verticalScrollBar()->maximum()); } void LogDockerDock::changeTheme() { clearLog(); QColor background = qApp->palette().background().color(); if (background.value() > 100) { s_debug.setForeground(Qt::black); s_info.setForeground(Qt::darkGreen); s_warning.setForeground(Qt::darkYellow); s_critical.setForeground(Qt::darkRed); s_fatal.setForeground(Qt::darkRed); } else { s_debug.setForeground(Qt::white); s_info.setForeground(Qt::green); s_warning.setForeground(Qt::yellow); s_critical.setForeground(Qt::red); s_fatal.setForeground(Qt::red); } s_fatal.setFontWeight(QFont::Bold); } void MessageSender::sendMessage(QtMsgType type, const QString &msg) { emit emitMessage(type, msg); } diff --git a/plugins/dockers/logdocker/LogDockerDock.h b/plugins/dockers/logdocker/LogDockerDock.h index 4bb749365a..75647661a5 100644 --- a/plugins/dockers/logdocker/LogDockerDock.h +++ b/plugins/dockers/logdocker/LogDockerDock.h @@ -1,75 +1,76 @@ /* * Copyright (c) 2018 Boudewijn Rempt * - * 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 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 library is distributed in the hope that it will be useful, + * 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 Lesser General Public License for more details. + * GNU General Public License for more details. * - * You should have received a copy of the GNU Lesser General Public License + * 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 _LOGDOCKER_DOCK_H_ #define _LOGDOCKER_DOCK_H_ #include #include #include "ui_WdgLogDocker.h" class MessageSender : public QObject { Q_OBJECT public: MessageSender() : QObject() {} ~MessageSender() override {} void sendMessage(QtMsgType type, const QString &msg); Q_SIGNALS: void emitMessage(QtMsgType type, const QString &msg); }; class LogDockerDock : public QDockWidget, public KisMainwindowObserver, public Ui_WdgLogDocker { Q_OBJECT public: LogDockerDock( ); QString observerName() override { return "LogDockerDock"; } void setCanvas(KoCanvasBase *canvas) override; void unsetCanvas() override {} void setViewManager(KisViewManager* kisview) override; private Q_SLOTS: void toggleLogging(bool toggle); void clearLog(); void saveLog(); void settings(); void insertMessage(QtMsgType type, const QString &msg); void changeTheme(); private: void applyCategories(); static MessageSender *s_messageSender; static QTextCharFormat s_debug; static QTextCharFormat s_info; static QTextCharFormat s_warning; static QTextCharFormat s_critical; static QTextCharFormat s_fatal; static void messageHandler(QtMsgType type, const QMessageLogContext &context, const QString &msg); }; #endif diff --git a/plugins/dockers/lut/lutdocker.cpp b/plugins/dockers/lut/lutdocker.cpp index 78cf0845ff..e00c5a1399 100644 --- a/plugins/dockers/lut/lutdocker.cpp +++ b/plugins/dockers/lut/lutdocker.cpp @@ -1,89 +1,90 @@ /* * Copyright (c) 2009 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. + * the Free Software Foundation; 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 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 "lutdocker.h" #include #include #include #include #include #include #include "kis_config.h" #include "kis_cursor.h" #include "kis_global.h" #include "kis_types.h" #include "lutdocker_dock.h" #include #include namespace OCIO = OCIO_NAMESPACE; K_PLUGIN_FACTORY_WITH_JSON(LutDockerPluginFactory, "krita_lutdocker.json", registerPlugin();) class LutDockerDockFactory : public KoDockFactoryBase { public: LutDockerDockFactory() { } QString id() const override { return QString( "LutDocker" ); } virtual Qt::DockWidgetArea defaultDockWidgetArea() const { return Qt::RightDockWidgetArea; } QDockWidget* createDockWidget() override { LutDockerDock * dockWidget = new LutDockerDock(); dockWidget->setObjectName(id()); return dockWidget; } DockPosition defaultDockPosition() const override { return DockMinimized; } private: OCIO::ConstConfigRcPtr m_config; }; LutDockerPlugin::LutDockerPlugin(QObject *parent, const QVariantList &) : QObject(parent) { KoDockRegistry::instance()->add(new LutDockerDockFactory()); } LutDockerPlugin::~LutDockerPlugin() { } #include "lutdocker.moc" diff --git a/plugins/dockers/lut/lutdocker.h b/plugins/dockers/lut/lutdocker.h index f51fe9edc3..b965e36ad3 100644 --- a/plugins/dockers/lut/lutdocker.h +++ b/plugins/dockers/lut/lutdocker.h @@ -1,36 +1,37 @@ /* * Copyright (c) 2009 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. + * the Free Software Foundation; 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 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 _LUT_DOCKER_H_ #define _LUT_DOCKER_H_ #include #include /** * Template of view plugin */ class LutDockerPlugin : public QObject { Q_OBJECT public: LutDockerPlugin(QObject *parent, const QVariantList &); virtual ~LutDockerPlugin(); }; #endif diff --git a/plugins/dockers/overview/overviewdocker.cpp b/plugins/dockers/overview/overviewdocker.cpp index 173730168c..cebe84a5cf 100644 --- a/plugins/dockers/overview/overviewdocker.cpp +++ b/plugins/dockers/overview/overviewdocker.cpp @@ -1,87 +1,88 @@ /* * Copyright (c) 2009 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. + * the Free Software Foundation; 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 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 "overviewdocker.h" #include #include #include #include #include #include #include "kis_config.h" #include "kis_cursor.h" #include "kis_global.h" #include "kis_types.h" #include "KisViewManager.h" #include "overviewdocker_dock.h" #include K_PLUGIN_FACTORY_WITH_JSON(OverviewDockerPluginFactory, "krita_overviewdocker.json", registerPlugin();) class OverviewDockerDockFactory : public KoDockFactoryBase { public: OverviewDockerDockFactory() { } QString id() const override { return QString( "OverviewDocker" ); } virtual Qt::DockWidgetArea defaultDockWidgetArea() const { return Qt::RightDockWidgetArea; } QDockWidget* createDockWidget() override { OverviewDockerDock * dockWidget = new OverviewDockerDock(); dockWidget->setObjectName(id()); return dockWidget; } DockPosition defaultDockPosition() const override { return DockMinimized; } private: }; OverviewDockerPlugin::OverviewDockerPlugin(QObject *parent, const QVariantList &) : QObject(parent) { KoDockRegistry::instance()->add(new OverviewDockerDockFactory()); } OverviewDockerPlugin::~OverviewDockerPlugin() { m_view = 0; } #include "overviewdocker.moc" diff --git a/plugins/dockers/overview/overviewdocker.h b/plugins/dockers/overview/overviewdocker.h index 3820926ddf..de453f6616 100644 --- a/plugins/dockers/overview/overviewdocker.h +++ b/plugins/dockers/overview/overviewdocker.h @@ -1,39 +1,40 @@ /* * Copyright (c) 2009 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. + * the Free Software Foundation; 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 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 _OVERVIEW_DOCKER_H_ #define _OVERVIEW_DOCKER_H_ #include #include class KisViewManager; /** * Template of view plugin */ class OverviewDockerPlugin : public QObject { Q_OBJECT public: OverviewDockerPlugin(QObject *parent, const QVariantList &); ~OverviewDockerPlugin() override; private: KisViewManager* m_view; }; #endif diff --git a/plugins/dockers/overview/overviewdocker_dock.cpp b/plugins/dockers/overview/overviewdocker_dock.cpp index 18d41ba05e..2cfa57a2bc 100644 --- a/plugins/dockers/overview/overviewdocker_dock.cpp +++ b/plugins/dockers/overview/overviewdocker_dock.cpp @@ -1,153 +1,154 @@ /* * Copyright (c) 2009 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. + * the Free Software Foundation; 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 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 "overviewdocker_dock.h" #include "overviewwidget.h" #include #include #include #include #include #include #include #include "kis_canvas2.h" #include #include #include #include #include "kis_image.h" #include "kis_paint_device.h" #include "kis_signal_compressor.h" #include "kis_canvas_controller.h" #include "kis_icon_utils.h" #include "kis_signals_blocker.h" OverviewDockerDock::OverviewDockerDock( ) : QDockWidget(i18n("Overview")) , m_zoomSlider(nullptr) , m_rotateSlider(nullptr) , m_mirrorCanvas(nullptr) , m_canvas(nullptr) { QWidget *page = new QWidget(this); m_layout = new QVBoxLayout(page); m_horizontalLayout = new QHBoxLayout(); m_overviewWidget = new OverviewWidget(this); m_overviewWidget->setMinimumHeight(50); m_overviewWidget->setBackgroundRole(QPalette::AlternateBase); m_overviewWidget->setAutoFillBackground(true); // paints background role before paint() m_layout->addWidget(m_overviewWidget, 1); setWidget(page); } void OverviewDockerDock::setCanvas(KoCanvasBase * canvas) { if(m_canvas == canvas) return; setEnabled(canvas != nullptr); if (m_canvas) { m_canvas->disconnectCanvasObserver(this); m_canvas->image()->disconnect(this); } if (m_zoomSlider) { m_layout->removeWidget(m_zoomSlider); delete m_zoomSlider; m_zoomSlider = nullptr; } if (m_rotateSlider) { m_horizontalLayout->removeWidget(m_rotateSlider); delete m_rotateSlider; m_rotateSlider = nullptr; } if (m_mirrorCanvas) { m_horizontalLayout->removeWidget(m_mirrorCanvas); delete m_mirrorCanvas; m_mirrorCanvas = nullptr; } m_layout->removeItem(m_horizontalLayout); m_canvas = dynamic_cast(canvas); m_overviewWidget->setCanvas(canvas); if (m_canvas && m_canvas->viewManager() && m_canvas->viewManager()->zoomController() && m_canvas->viewManager()->zoomController()->zoomAction()) { m_zoomSlider = m_canvas->viewManager()->zoomController()->zoomAction()->createWidget(m_canvas->imageView()->KisView::statusBar()); m_layout->addWidget(m_zoomSlider); m_rotateSlider = new KisDoubleSliderSpinBox(); m_rotateSlider->setRange(-180, 180, 2); m_rotateSlider->setValue(m_canvas->rotationAngle()); m_rotateSlider->setPrefix(i18n("Rotation: ")); m_rotateSlider->setSuffix("°"); connect(m_rotateSlider, SIGNAL(valueChanged(qreal)), this, SLOT(rotateCanvasView(qreal)), Qt::UniqueConnection); connect(m_canvas->canvasController()->proxyObject, SIGNAL(canvasOffsetXChanged(int)), this, SLOT(updateSlider())); m_mirrorCanvas = new QToolButton(); QList actions = m_canvas->viewManager()->actionCollection()->actions(); Q_FOREACH(QAction* action, actions) { if (action->objectName()=="mirror_canvas") { m_mirrorCanvas->setDefaultAction(action); } } m_horizontalLayout->addWidget(m_mirrorCanvas); m_horizontalLayout->addWidget(m_rotateSlider); m_layout->addLayout(m_horizontalLayout); } } void OverviewDockerDock::unsetCanvas() { setEnabled(false); m_canvas = nullptr; m_overviewWidget->unsetCanvas(); } void OverviewDockerDock::rotateCanvasView(qreal rotation) { KisCanvasController *canvasController = dynamic_cast(m_canvas->viewManager()->canvasBase()->canvasController()); if (canvasController) { canvasController->rotateCanvas(rotation-m_canvas->rotationAngle()); } } void OverviewDockerDock::updateSlider() { KisSignalsBlocker l(m_rotateSlider); qreal rotation = m_canvas->rotationAngle(); if (rotation > 180) { rotation = rotation - 360; } else if (rotation < -180) { rotation = rotation + 360; } if (m_rotateSlider->value() != rotation) { m_rotateSlider->setValue(rotation); } } diff --git a/plugins/dockers/overview/overviewdocker_dock.h b/plugins/dockers/overview/overviewdocker_dock.h index 0270b04478..2fbc1f6d2e 100644 --- a/plugins/dockers/overview/overviewdocker_dock.h +++ b/plugins/dockers/overview/overviewdocker_dock.h @@ -1,56 +1,57 @@ /* * Copyright (c) 2009 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. + * the Free Software Foundation; 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 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 _OVERVIEW_DOCK_H_ #define _OVERVIEW_DOCK_H_ #include #include #include #include #include class QVBoxLayout; class QHBoxLayout; class QToolButton; class OverviewWidget; class OverviewDockerDock : public QDockWidget, public KoCanvasObserverBase { Q_OBJECT public: OverviewDockerDock(); QString observerName() override { return "OverviewDockerDock"; } void setCanvas(KoCanvasBase *canvas) override; void unsetCanvas() override; public Q_SLOTS: void rotateCanvasView(qreal rotation); void updateSlider(); private: QVBoxLayout *m_layout; QHBoxLayout *m_horizontalLayout; OverviewWidget *m_overviewWidget; QWidget *m_zoomSlider; KisDoubleSliderSpinBox *m_rotateSlider; QToolButton *m_mirrorCanvas; QPointer m_canvas; }; #endif diff --git a/plugins/dockers/overview/overviewwidget.cc b/plugins/dockers/overview/overviewwidget.cc index 20c4bcf926..201c60a13e 100644 --- a/plugins/dockers/overview/overviewwidget.cc +++ b/plugins/dockers/overview/overviewwidget.cc @@ -1,381 +1,382 @@ /* * Copyright (c) 2009 Cyrille Berger * Copyright (c) 2014 Sven Langkamp * * 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. + * the Free Software Foundation; 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 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 "overviewwidget.h" #include #include #include #include #include #include #include #include #include #include #include #include #include "kis_idle_watcher.h" #include "krita_utils.h" #include "kis_painter.h" #include #include "kis_transform_worker.h" #include "kis_filter_strategy.h" #include #include const qreal oversample = 2.; const int thumbnailTileDim = 128; struct OverviewThumbnailStrokeStrategy::Private { class ProcessData : public KisStrokeJobData { public: ProcessData(KisPaintDeviceSP _dev, KisPaintDeviceSP _thumbDev, const QSize& _thumbnailSize, const QRect &_rect) : KisStrokeJobData(CONCURRENT), dev(_dev), thumbDev(_thumbDev), thumbnailSize(_thumbnailSize), tileRect(_rect) {} KisPaintDeviceSP dev; KisPaintDeviceSP thumbDev; QSize thumbnailSize; QRect tileRect; }; class FinishProcessing : public KisStrokeJobData { public: FinishProcessing(KisPaintDeviceSP _thumbDev, const QSize& _thumbnailSize) : KisStrokeJobData(SEQUENTIAL), thumbDev(_thumbDev), thumbnailSize(_thumbnailSize) {} KisPaintDeviceSP thumbDev; QSize thumbnailSize; }; }; OverviewWidget::OverviewWidget(QWidget * parent) : QWidget(parent) , m_canvas(0) , m_dragging(false) , m_imageIdleWatcher(250) { setMouseTracking(true); KisConfig cfg(true); slotThemeChanged(); } OverviewWidget::~OverviewWidget() { } void OverviewWidget::setCanvas(KoCanvasBase * canvas) { if (m_canvas) { m_canvas->image()->disconnect(this); } m_canvas = dynamic_cast(canvas); if (m_canvas) { m_imageIdleWatcher.setTrackedImage(m_canvas->image()); connect(&m_imageIdleWatcher, &KisIdleWatcher::startedIdleMode, this, &OverviewWidget::generateThumbnail); connect(m_canvas->image(), SIGNAL(sigImageUpdated(QRect)),SLOT(startUpdateCanvasProjection())); connect(m_canvas->image(), SIGNAL(sigSizeChanged(QPointF,QPointF)),SLOT(startUpdateCanvasProjection())); connect(m_canvas->canvasController()->proxyObject, SIGNAL(canvasOffsetXChanged(int)), this, SLOT(update()), Qt::UniqueConnection); connect(m_canvas->viewManager()->mainWindow(), SIGNAL(themeChanged()), this, SLOT(slotThemeChanged())); generateThumbnail(); } } QSize OverviewWidget::recalculatePreviewSize() { QSize imageSize(m_canvas->image()->bounds().size()); const qreal hScale = 1.0 * this->width() / imageSize.width(); const qreal vScale = 1.0 * this->height() / imageSize.height(); m_previewScale = qMin(hScale, vScale); return imageSize * m_previewScale; } QPointF OverviewWidget::previewOrigin() { const QSize previewSize = recalculatePreviewSize(); return QPointF((width() - previewSize.width()) / 2.0f, (height() - previewSize.height()) / 2.0f); } QPolygonF OverviewWidget::previewPolygon() { if (m_canvas) { const QRectF &canvasRect = QRectF(m_canvas->canvasWidget()->rect()); return canvasToPreviewTransform().map(canvasRect); } return QPolygonF(); } QTransform OverviewWidget::previewToCanvasTransform() { QTransform previewToImage = QTransform::fromTranslate(-this->width() / 2.0, -this->height() / 2.0) * QTransform::fromScale(1.0 / m_previewScale, 1.0 / m_previewScale) * QTransform::fromTranslate(m_canvas->image()->width() / 2.0, m_canvas->image()->height() / 2.0); return previewToImage * m_canvas->coordinatesConverter()->imageToWidgetTransform(); } QTransform OverviewWidget::canvasToPreviewTransform() { return previewToCanvasTransform().inverted(); } void OverviewWidget::startUpdateCanvasProjection() { m_imageIdleWatcher.startCountdown(); } void OverviewWidget::showEvent(QShowEvent *event) { Q_UNUSED(event); m_imageIdleWatcher.startCountdown(); } void OverviewWidget::resizeEvent(QResizeEvent *event) { Q_UNUSED(event); if (m_canvas) { if (!m_oldPixmap.isNull()) { QSize newSize = recalculatePreviewSize(); m_pixmap = m_oldPixmap.scaled(newSize, Qt::KeepAspectRatio, Qt::SmoothTransformation); } m_imageIdleWatcher.startCountdown(); } } void OverviewWidget::mousePressEvent(QMouseEvent* event) { if (m_canvas) { QPointF previewPos = event->pos(); if (!previewPolygon().containsPoint(previewPos, Qt::WindingFill)) { const QRect& canvasRect = m_canvas->canvasWidget()->rect(); const QPointF newCanvasPos = previewToCanvasTransform().map(previewPos) - QPointF(canvasRect.width() / 2.0f, canvasRect.height() / 2.0f); m_canvas->canvasController()->pan(newCanvasPos.toPoint()); } m_lastPos = previewPos; m_dragging = true; } event->accept(); update(); } void OverviewWidget::mouseMoveEvent(QMouseEvent* event) { if (m_dragging) { QPointF previewPos = event->pos(); const QPointF lastCanvasPos = previewToCanvasTransform().map(m_lastPos); const QPointF newCanvasPos = previewToCanvasTransform().map(event->pos()); QPointF diff = newCanvasPos - lastCanvasPos; m_canvas->canvasController()->pan(diff.toPoint()); m_lastPos = previewPos; } event->accept(); } void OverviewWidget::mouseReleaseEvent(QMouseEvent* event) { m_dragging = false; event->accept(); update(); } void OverviewWidget::wheelEvent(QWheelEvent* event) { float delta = event->delta(); if (delta > 0) { m_canvas->viewManager()->zoomController()->zoomAction()->zoomIn(); } else { m_canvas->viewManager()->zoomController()->zoomAction()->zoomOut(); } } void OverviewWidget::generateThumbnail() { if (isVisible()) { QMutexLocker locker(&mutex); if (m_canvas) { QSize previewSize = recalculatePreviewSize(); if(previewSize.isValid()){ KisImageSP image = m_canvas->image(); if (!strokeId.isNull()) { image->cancelStroke(strokeId); strokeId.clear(); } OverviewThumbnailStrokeStrategy* stroke = new OverviewThumbnailStrokeStrategy(image); connect(stroke, SIGNAL(thumbnailUpdated(QImage)), this, SLOT(updateThumbnail(QImage))); strokeId = image->startStroke(stroke); KisPaintDeviceSP dev = image->projection(); KisPaintDeviceSP thumbDev = new KisPaintDevice(dev->colorSpace()); //creating a special stroke that computes thumbnail image in small chunks that can be quickly interrupted //if user starts painting QList jobs = OverviewThumbnailStrokeStrategy::createJobsData(dev, image->bounds(), thumbDev, previewSize); Q_FOREACH (KisStrokeJobData *jd, jobs) { image->addJob(strokeId, jd); } image->endStroke(strokeId); } } } } void OverviewWidget::updateThumbnail(QImage pixmap) { m_pixmap = QPixmap::fromImage(pixmap); m_oldPixmap = m_pixmap.copy(); update(); } void OverviewWidget::slotThemeChanged() { m_outlineColor = qApp->palette().color(QPalette::Highlight); } void OverviewWidget::paintEvent(QPaintEvent* event) { QWidget::paintEvent(event); if (m_canvas) { QPainter p(this); const QSize previewSize = recalculatePreviewSize(); const QRectF previewRect = QRectF(previewOrigin(), previewSize); p.drawPixmap(previewRect.toRect(), m_pixmap); QRect r = rect(); QPolygonF outline; outline << r.topLeft() << r.topRight() << r.bottomRight() << r.bottomLeft(); QPen pen; pen.setColor(m_outlineColor); pen.setStyle(Qt::DashLine); p.setPen(pen); p.drawPolygon(outline.intersected(previewPolygon())); pen.setStyle(Qt::SolidLine); p.setPen(pen); p.drawPolygon(previewPolygon()); } } OverviewThumbnailStrokeStrategy::OverviewThumbnailStrokeStrategy(KisImageWSP image) : KisSimpleStrokeStrategy("OverviewThumbnail"), m_image(image) { enableJob(KisSimpleStrokeStrategy::JOB_INIT, true, KisStrokeJobData::BARRIER, KisStrokeJobData::EXCLUSIVE); enableJob(KisSimpleStrokeStrategy::JOB_DOSTROKE); //enableJob(KisSimpleStrokeStrategy::JOB_FINISH); enableJob(KisSimpleStrokeStrategy::JOB_CANCEL, true, KisStrokeJobData::SEQUENTIAL, KisStrokeJobData::EXCLUSIVE); setRequestsOtherStrokesToEnd(false); setClearsRedoOnStart(false); setCanForgetAboutMe(true); } QList OverviewThumbnailStrokeStrategy::createJobsData(KisPaintDeviceSP dev, const QRect& imageRect, KisPaintDeviceSP thumbDev, const QSize& thumbnailSize) { QSize thumbnailOversampledSize = oversample * thumbnailSize; if ((thumbnailOversampledSize.width() > imageRect.width()) || (thumbnailOversampledSize.height() > imageRect.height())) { thumbnailOversampledSize.scale(imageRect.size(), Qt::KeepAspectRatio); } QVector tileRects = KritaUtils::splitRectIntoPatches(QRect(QPoint(0, 0), thumbnailOversampledSize), QSize(thumbnailTileDim, thumbnailTileDim)); QList jobsData; Q_FOREACH (const QRect &tileRectangle, tileRects) { jobsData << new OverviewThumbnailStrokeStrategy::Private::ProcessData(dev, thumbDev, thumbnailOversampledSize, tileRectangle); } jobsData << new OverviewThumbnailStrokeStrategy::Private::FinishProcessing(thumbDev, thumbnailSize); return jobsData; } OverviewThumbnailStrokeStrategy::~OverviewThumbnailStrokeStrategy() { } void OverviewThumbnailStrokeStrategy::initStrokeCallback() { } void OverviewThumbnailStrokeStrategy::doStrokeCallback(KisStrokeJobData *data) { Private::ProcessData *d_pd = dynamic_cast(data); if (d_pd) { //we aren't going to use oversample capability of createThumbnailDevice because it recomputes exact bounds for each small patch, which is //slow. We'll handle scaling separately. KisPaintDeviceSP thumbnailTile = d_pd->dev->createThumbnailDeviceOversampled(d_pd->thumbnailSize.width(), d_pd->thumbnailSize.height(), 1, m_image->bounds(), d_pd->tileRect); { QMutexLocker locker(&m_thumbnailMergeMutex); KisPainter gc(d_pd->thumbDev); gc.bitBlt(QPoint(d_pd->tileRect.x(), d_pd->tileRect.y()), thumbnailTile, d_pd->tileRect); } return; } Private::FinishProcessing *d_fp = dynamic_cast(data); if (d_fp) { QImage overviewImage; KoDummyUpdater updater; KisTransformWorker worker(d_fp->thumbDev, 1 / oversample, 1 / oversample, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, &updater, KisFilterStrategyRegistry::instance()->value("Bilinear")); worker.run(); overviewImage = d_fp->thumbDev->convertToQImage(KoColorSpaceRegistry::instance()->rgb8()->profile(), QRect(QPoint(0,0), d_fp->thumbnailSize)); emit thumbnailUpdated(overviewImage); return; } } void OverviewThumbnailStrokeStrategy::finishStrokeCallback() { } void OverviewThumbnailStrokeStrategy::cancelStrokeCallback() { } diff --git a/plugins/dockers/overview/overviewwidget.h b/plugins/dockers/overview/overviewwidget.h index ff69aba503..b52c60d2d2 100644 --- a/plugins/dockers/overview/overviewwidget.h +++ b/plugins/dockers/overview/overviewwidget.h @@ -1,117 +1,118 @@ /* * Copyright (c) 2009 Cyrille Berger * Copyright (c) 2014 Sven Langkamp * * 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. + * the Free Software Foundation; 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 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 OVERVIEWWIDGET_H #define OVERVIEWWIDGET_H #include #include #include #include #include #include "kis_idle_watcher.h" #include "kis_simple_stroke_strategy.h" #include class KisSignalCompressor; class KoCanvasBase; class OverviewThumbnailStrokeStrategy : public QObject, public KisSimpleStrokeStrategy { Q_OBJECT public: OverviewThumbnailStrokeStrategy(KisImageWSP image); ~OverviewThumbnailStrokeStrategy() override; static QList createJobsData(KisPaintDeviceSP dev, const QRect& imageRect, KisPaintDeviceSP thumbDev, const QSize &thumbnailSize); private: void initStrokeCallback() override; void doStrokeCallback(KisStrokeJobData *data) override; void finishStrokeCallback() override; void cancelStrokeCallback() override; Q_SIGNALS: //Emitted when thumbnail is updated and overviewImage is fully generated. void thumbnailUpdated(QImage pixmap); private: struct Private; const QScopedPointer m_d; QMutex m_thumbnailMergeMutex; KisImageSP m_image; }; class OverviewWidget : public QWidget { Q_OBJECT public: OverviewWidget(QWidget * parent = 0); ~OverviewWidget() override; virtual void setCanvas(KoCanvasBase *canvas); virtual void unsetCanvas() { m_canvas = 0; } public Q_SLOTS: void startUpdateCanvasProjection(); void generateThumbnail(); void updateThumbnail(QImage pixmap); void slotThemeChanged(); protected: void resizeEvent(QResizeEvent *event) override; void showEvent(QShowEvent *event) override; void paintEvent(QPaintEvent *event) override; void mousePressEvent(QMouseEvent* event) override; void mouseMoveEvent(QMouseEvent* event) override; void mouseReleaseEvent(QMouseEvent* event) override; void wheelEvent(QWheelEvent* event) override; private: QSize recalculatePreviewSize(); QPointF previewOrigin(); QTransform canvasToPreviewTransform(); QTransform previewToCanvasTransform(); QPolygonF previewPolygon(); qreal m_previewScale; QPixmap m_oldPixmap; QPixmap m_pixmap; QPointer m_canvas; bool m_dragging; QPointF m_lastPos; QColor m_outlineColor; KisIdleWatcher m_imageIdleWatcher; KisStrokeId strokeId; QMutex mutex; }; #endif /* OVERVIEWWIDGET_H */ diff --git a/plugins/dockers/palettedocker/palettedocker.h b/plugins/dockers/palettedocker/palettedocker.h index 5b6c082b39..3d9745a8a0 100644 --- a/plugins/dockers/palettedocker/palettedocker.h +++ b/plugins/dockers/palettedocker/palettedocker.h @@ -1,36 +1,37 @@ /* * Copyright (c) 2013 Sven Langkamp * * 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. + * the Free Software Foundation; 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 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 PALETTEDOCKER_H #define PALETTEDOCKER_H #include #include /** * Docker showing the channels of the current layer */ class PaletteDockerPlugin : public QObject { Q_OBJECT public: PaletteDockerPlugin(QObject *parent, const QVariantList &); ~PaletteDockerPlugin() override; }; #endif diff --git a/plugins/dockers/patterndocker/patterndocker.cpp b/plugins/dockers/patterndocker/patterndocker.cpp index cb22ea5f96..ff7c59e587 100644 --- a/plugins/dockers/patterndocker/patterndocker.cpp +++ b/plugins/dockers/patterndocker/patterndocker.cpp @@ -1,87 +1,88 @@ /* * Copyright (c) 2009 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. + * the Free Software Foundation; 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 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 "patterndocker.h" #include #include #include #include #include #include #include "kis_config.h" #include "kis_cursor.h" #include "kis_global.h" #include "kis_types.h" #include "KisViewManager.h" #include "patterndocker_dock.h" #include K_PLUGIN_FACTORY_WITH_JSON(PatternDockerPluginFactory, "krita_patterndocker.json", registerPlugin();) class PatternDockerDockFactory : public KoDockFactoryBase { public: PatternDockerDockFactory() { } QString id() const override { return QString( "PatternDocker" ); } virtual Qt::DockWidgetArea defaultDockWidgetArea() const { return Qt::RightDockWidgetArea; } QDockWidget* createDockWidget() override { PatternDockerDock * dockWidget = new PatternDockerDock(); dockWidget->setObjectName(id()); return dockWidget; } DockPosition defaultDockPosition() const override { return DockMinimized; } private: }; PatternDockerPlugin::PatternDockerPlugin(QObject *parent, const QVariantList &) : QObject(parent) { KoDockRegistry::instance()->add(new PatternDockerDockFactory()); } PatternDockerPlugin::~PatternDockerPlugin() { m_view = 0; } #include "patterndocker.moc" diff --git a/plugins/dockers/patterndocker/patterndocker.h b/plugins/dockers/patterndocker/patterndocker.h index 1d4b908b10..0c440d052a 100644 --- a/plugins/dockers/patterndocker/patterndocker.h +++ b/plugins/dockers/patterndocker/patterndocker.h @@ -1,39 +1,40 @@ /* * Copyright (c) 2009 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. + * the Free Software Foundation; 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 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 _PATTERN_DOCKER_H_ #define _PATTERN_DOCKER_H_ #include #include class KisViewManager; /** * Template of view plugin */ class PatternDockerPlugin : public QObject { Q_OBJECT public: PatternDockerPlugin(QObject *parent, const QVariantList &); ~PatternDockerPlugin() override; private: KisViewManager* m_view; }; #endif diff --git a/plugins/dockers/patterndocker/patterndocker_dock.cpp b/plugins/dockers/patterndocker/patterndocker_dock.cpp index c30692885b..0b43d6b1fb 100644 --- a/plugins/dockers/patterndocker/patterndocker_dock.cpp +++ b/plugins/dockers/patterndocker/patterndocker_dock.cpp @@ -1,69 +1,70 @@ /* * Copyright (c) 2009 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. + * the Free Software Foundation; 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 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 "patterndocker_dock.h" #include #include #include #include #include #include #include PatternDockerDock::PatternDockerDock( ) : QDockWidget(i18n("Patterns")) { m_patternChooser = new KisPatternChooser(this); m_patternChooser->setPreviewOrientation(Qt::Vertical); m_patternChooser->setCurrentItem(0,0); m_patternChooser->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred); m_patternChooser->setMinimumHeight(160); setWidget(m_patternChooser); } void PatternDockerDock::setViewManager(KisViewManager* kisview) { KisCanvasResourceProvider* resourceProvider = kisview->canvasResourceProvider(); connect(resourceProvider, SIGNAL(sigPatternChanged(KoPattern*)), this, SLOT(patternChanged(KoPattern*))); connect(m_patternChooser, SIGNAL(resourceSelected(KoResource*)), resourceProvider, SLOT(slotPatternActivated(KoResource*))); } void PatternDockerDock::setCanvas(KoCanvasBase *canvas) { setEnabled(canvas != 0); } void PatternDockerDock::unsetCanvas() { setEnabled(false); } void PatternDockerDock::patternChanged(KoPattern *pattern) { m_patternChooser->setCurrentPattern(pattern); } diff --git a/plugins/dockers/patterndocker/patterndocker_dock.h b/plugins/dockers/patterndocker/patterndocker_dock.h index bc4113b6c5..29f40fd71a 100644 --- a/plugins/dockers/patterndocker/patterndocker_dock.h +++ b/plugins/dockers/patterndocker/patterndocker_dock.h @@ -1,46 +1,47 @@ /* * Copyright (c) 2009 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. + * the Free Software Foundation; 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 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 _PATTERN_DOCK_H_ #define _PATTERN_DOCK_H_ #include #include class KoPattern; class KisPatternChooser; class PatternDockerDock : public QDockWidget, public KisMainwindowObserver { Q_OBJECT public: PatternDockerDock( ); void setViewManager(KisViewManager* kisview) override; void setCanvas(KoCanvasBase *canvas) override; void unsetCanvas() override; QString observerName() override { return "PatternDockerDock"; } public Q_SLOTS: void patternChanged(KoPattern *pattern); private Q_SLOTS: private: KisPatternChooser* m_patternChooser; }; #endif diff --git a/plugins/dockers/presetdocker/presetdocker.cpp b/plugins/dockers/presetdocker/presetdocker.cpp index b6870de8d0..47547d0feb 100644 --- a/plugins/dockers/presetdocker/presetdocker.cpp +++ b/plugins/dockers/presetdocker/presetdocker.cpp @@ -1,87 +1,88 @@ /* * Copyright (c) 2009 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. + * the Free Software Foundation; 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 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 "presetdocker.h" #include #include #include #include #include #include #include "kis_config.h" #include "kis_cursor.h" #include "kis_global.h" #include "kis_types.h" #include "KisViewManager.h" #include "presetdocker_dock.h" #include K_PLUGIN_FACTORY_WITH_JSON(PresetDockerPluginFactory, "krita_presetdocker.json", registerPlugin();) class PresetDockerDockFactory : public KoDockFactoryBase { public: PresetDockerDockFactory() { } QString id() const override { return QString( "PresetDocker" ); } virtual Qt::DockWidgetArea defaultDockWidgetArea() const { return Qt::RightDockWidgetArea; } QDockWidget* createDockWidget() override { PresetDockerDock * dockWidget = new PresetDockerDock(); dockWidget->setObjectName(id()); return dockWidget; } DockPosition defaultDockPosition() const override { return DockMinimized; } private: }; PresetDockerPlugin::PresetDockerPlugin(QObject *parent, const QVariantList &) : QObject(parent) { KoDockRegistry::instance()->add(new PresetDockerDockFactory()); } PresetDockerPlugin::~PresetDockerPlugin() { m_view = 0; } #include "presetdocker.moc" diff --git a/plugins/dockers/presetdocker/presetdocker.h b/plugins/dockers/presetdocker/presetdocker.h index 0635425c62..ab8cf1ffa5 100644 --- a/plugins/dockers/presetdocker/presetdocker.h +++ b/plugins/dockers/presetdocker/presetdocker.h @@ -1,39 +1,40 @@ /* * Copyright (c) 2009 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. + * the Free Software Foundation; 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 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 _PRESET_DOCKER_H_ #define _PRESET_DOCKER_H_ #include #include class KisViewManager; /** * Template of view plugin */ class PresetDockerPlugin : public QObject { Q_OBJECT public: PresetDockerPlugin(QObject *parent, const QVariantList &); ~PresetDockerPlugin() override; private: KisViewManager* m_view; }; #endif diff --git a/plugins/dockers/presetdocker/presetdocker_dock.cpp b/plugins/dockers/presetdocker/presetdocker_dock.cpp index 9ee9c152d2..82322f09b5 100644 --- a/plugins/dockers/presetdocker/presetdocker_dock.cpp +++ b/plugins/dockers/presetdocker/presetdocker_dock.cpp @@ -1,85 +1,86 @@ /* * Copyright (c) 2009 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. + * the Free Software Foundation; 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 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 "presetdocker_dock.h" #include #include #include #include #include #include "kis_canvas2.h" #include "KisViewManager.h" #include "kis_paintop_box.h" #include "kis_paintop_presets_chooser_popup.h" #include "kis_canvas_resource_provider.h" #include PresetDockerDock::PresetDockerDock( ) : QDockWidget(i18n("Brush Presets")) , m_canvas(0) { m_presetChooser = new KisPaintOpPresetsChooserPopup(this); m_presetChooser->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred); m_presetChooser->showButtons(false); setWidget(m_presetChooser); } void PresetDockerDock::setCanvas(KoCanvasBase *canvas) { setEnabled(canvas != 0); if (m_canvas) { m_canvas->disconnectCanvasObserver(this); m_presetChooser->disconnect(m_canvas->viewManager()->paintOpBox()); } m_canvas = dynamic_cast(canvas); if (!m_canvas || !m_canvas->viewManager() || !m_canvas->resourceManager()) return; connect(m_presetChooser, SIGNAL(resourceSelected(KoResource*)), m_canvas->viewManager()->paintOpBox(), SLOT(resourceSelected(KoResource*))); connect(m_presetChooser, SIGNAL(resourceClicked(KoResource*)), m_canvas->viewManager()->paintOpBox(), SLOT(resourceSelected(KoResource*))); connect(canvas->resourceManager(), SIGNAL(canvasResourceChanged(int,QVariant)), this, SLOT(canvasResourceChanged(int,QVariant))); connect(m_canvas->viewManager()->mainWindow(), SIGNAL(themeChanged()), m_presetChooser, SLOT(slotThemeChanged())); canvasResourceChanged(); } void PresetDockerDock::canvasResourceChanged(int /*key*/, const QVariant& /*v*/) { if (m_canvas && m_canvas->resourceManager()) { if (sender()) sender()->blockSignals(true); KisPaintOpPresetSP preset = m_canvas->resourceManager()->resource(KisCanvasResourceProvider::CurrentPaintOpPreset).value(); if(preset) m_presetChooser->canvasResourceChanged(preset); if (sender()) sender()->blockSignals(false); m_presetChooser->updateViewSettings(); } } diff --git a/plugins/dockers/presetdocker/presetdocker_dock.h b/plugins/dockers/presetdocker/presetdocker_dock.h index 6d77ef2289..9ae08a239a 100644 --- a/plugins/dockers/presetdocker/presetdocker_dock.h +++ b/plugins/dockers/presetdocker/presetdocker_dock.h @@ -1,43 +1,44 @@ /* * Copyright (c) 2009 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. + * the Free Software Foundation; 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 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 _PRESETDOCKER_DOCK_H_ #define _PRESETDOCKER_DOCK_H_ #include #include #include #include class KisPaintOpPresetsChooserPopup; class PresetDockerDock : public QDockWidget, public KoCanvasObserverBase { Q_OBJECT public: PresetDockerDock( ); QString observerName() override { return "PresetDockerDock"; } void setCanvas(KoCanvasBase *canvas) override; void unsetCanvas() override { m_canvas = 0; setEnabled(false);} public Q_SLOTS: void canvasResourceChanged(int key = 0, const QVariant& v = QVariant()); private: QPointer m_canvas; KisPaintOpPresetsChooserPopup* m_presetChooser; }; #endif diff --git a/plugins/dockers/presethistory/presethistory.cpp b/plugins/dockers/presethistory/presethistory.cpp index b2e67bc232..0a40a024a1 100644 --- a/plugins/dockers/presethistory/presethistory.cpp +++ b/plugins/dockers/presethistory/presethistory.cpp @@ -1,70 +1,71 @@ /* * Copyright (c) 2015 Boudewijn Rempt * * 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. + * the Free Software Foundation; 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 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 "presethistory.h" #include #include #include #include "presethistory_dock.h" K_PLUGIN_FACTORY_WITH_JSON(PresetHistoryPluginFactory, "krita_presethistory.json", registerPlugin();) class PresetHistoryDockFactory : public KoDockFactoryBase { public: PresetHistoryDockFactory() { } QString id() const override { return QString( "PresetHistory" ); } virtual Qt::DockWidgetArea defaultDockWidgetArea() const { return Qt::RightDockWidgetArea; } QDockWidget* createDockWidget() override { PresetHistoryDock * dockWidget = new PresetHistoryDock(); dockWidget->setObjectName(id()); return dockWidget; } DockPosition defaultDockPosition() const override { return DockMinimized; } }; PresetHistoryPlugin::PresetHistoryPlugin(QObject *parent, const QVariantList &) : QObject(parent) { KoDockRegistry::instance()->add(new PresetHistoryDockFactory()); } PresetHistoryPlugin::~PresetHistoryPlugin() { } #include "presethistory.moc" diff --git a/plugins/dockers/presethistory/presethistory.h b/plugins/dockers/presethistory/presethistory.h index 41cfc3f59a..70c12efdbc 100644 --- a/plugins/dockers/presethistory/presethistory.h +++ b/plugins/dockers/presethistory/presethistory.h @@ -1,35 +1,36 @@ /* * Copyright (c) 2015 Boudewijn Rempt * * 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. + * the Free Software Foundation; 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 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 _PRESET_DOCKER_H_ #define _PRESET_DOCKER_H_ #include #include /** * Shows the last used presets */ class PresetHistoryPlugin : public QObject { Q_OBJECT public: PresetHistoryPlugin(QObject *parent, const QVariantList &); ~PresetHistoryPlugin() override; }; #endif diff --git a/plugins/dockers/presethistory/presethistory_dock.cpp b/plugins/dockers/presethistory/presethistory_dock.cpp index cb7023c848..d231b910db 100644 --- a/plugins/dockers/presethistory/presethistory_dock.cpp +++ b/plugins/dockers/presethistory/presethistory_dock.cpp @@ -1,150 +1,151 @@ /* * Copyright (c) 2015 Boudewijn Rempt * * 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. + * the Free Software Foundation; 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 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 "presethistory_dock.h" #include #include #include #include #include #include #include #include "kis_config.h" #include "kis_canvas2.h" #include "KisViewManager.h" #include "kis_paintop_box.h" #include "kis_paintop_presets_chooser_popup.h" #include "kis_canvas_resource_provider.h" #include "KisResourceServerProvider.h" #include #include #include #define ICON_SIZE 48 PresetHistoryDock::PresetHistoryDock( ) : QDockWidget(i18n("Brush Preset History")) , m_canvas(0) , m_block(false) , m_initialized(false) { m_presetHistory = new QListWidget(this); m_presetHistory->setIconSize(QSize(ICON_SIZE, ICON_SIZE)); m_presetHistory->setDragEnabled(false); m_presetHistory->setSelectionBehavior(QAbstractItemView::SelectRows); m_presetHistory->setSelectionMode(QAbstractItemView::SingleSelection); m_presetHistory->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred); setWidget(m_presetHistory); QScroller* scroller = KisKineticScroller::createPreconfiguredScroller(m_presetHistory); if( scroller ) { connect(scroller, SIGNAL(stateChanged(QScroller::State)), this, SLOT(slotScrollerStateChanged(QScroller::State))); } connect(m_presetHistory, SIGNAL(itemClicked(QListWidgetItem*)), SLOT(presetSelected(QListWidgetItem*))); } void PresetHistoryDock::setCanvas(KoCanvasBase * canvas) { setEnabled(canvas != 0); if (m_canvas) { m_canvas->disconnectCanvasObserver(this); disconnect(m_canvas->resourceManager()); } m_canvas = dynamic_cast(canvas); if (!m_canvas || !m_canvas->viewManager() || !m_canvas->resourceManager()) return; connect(canvas->resourceManager(), SIGNAL(canvasResourceChanged(int,QVariant)), SLOT(canvasResourceChanged(int,QVariant))); if (!m_initialized) { KisConfig cfg(true); QStringList presetHistory = cfg.readEntry("presethistory", "").split(",", QString::SkipEmptyParts); KisPaintOpPresetResourceServer * rserver = KisResourceServerProvider::instance()->paintOpPresetServer(); Q_FOREACH (const QString &p, presetHistory) { KisPaintOpPresetSP preset = rserver->resourceByName(p); addPreset(preset); } m_initialized = true; } } void PresetHistoryDock::unsetCanvas() { m_canvas = 0; setEnabled(false); QStringList presetHistory; for(int i = m_presetHistory->count() -1; i >=0; --i) { QListWidgetItem *item = m_presetHistory->item(i); QVariant v = item->data(Qt::UserRole); KisPaintOpPresetSP preset = v.value(); presetHistory << preset->name(); } KisConfig cfg(false); cfg.writeEntry("presethistory", presetHistory.join(",")); } void PresetHistoryDock::presetSelected(QListWidgetItem *item) { if (item) { QVariant v = item->data(Qt::UserRole); KisPaintOpPresetSP preset = v.value(); m_block = true; m_canvas->viewManager()->paintOpBox()->resourceSelected(preset.data()); m_block = false; } } void PresetHistoryDock::canvasResourceChanged(int key, const QVariant& /*v*/) { if (m_block) return; if (m_canvas && key == KisCanvasResourceProvider::CurrentPaintOpPreset) { KisPaintOpPresetSP preset = m_canvas->resourceManager()->resource(KisCanvasResourceProvider::CurrentPaintOpPreset).value(); if (preset) { for (int i = 0; i < m_presetHistory->count(); ++i) { if (preset->name() == m_presetHistory->item(i)->text()) { m_presetHistory->setCurrentRow(i); return; } } addPreset(preset); } } } void PresetHistoryDock::addPreset(KisPaintOpPresetSP preset) { if (preset) { QListWidgetItem *item = new QListWidgetItem(QPixmap::fromImage(preset->image()), preset->name()); QVariant v = QVariant::fromValue(preset); item->setData(Qt::UserRole, v); m_presetHistory->insertItem(0, item); m_presetHistory->setCurrentRow(0); if (m_presetHistory->count() > 10) { m_presetHistory->takeItem(10); } } } diff --git a/plugins/dockers/presethistory/presethistory_dock.h b/plugins/dockers/presethistory/presethistory_dock.h index b25e54d229..7af9674812 100644 --- a/plugins/dockers/presethistory/presethistory_dock.h +++ b/plugins/dockers/presethistory/presethistory_dock.h @@ -1,55 +1,56 @@ /* * Copyright (c) 2015 Boudewijn Rempt * * 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. + * the Free Software Foundation; 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 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 _PRESETHISTORY_DOCK_H_ #define _PRESETHISTORY_DOCK_H_ #include #include #include #include #include #include class QListWidget; class QListWidgetItem; class PresetHistoryDock : public QDockWidget, public KoCanvasObserverBase { Q_OBJECT public: PresetHistoryDock(); QString observerName() override { return "PresetHistoryDock"; } void setCanvas(KoCanvasBase *canvas) override; void unsetCanvas() override; public Q_SLOTS: void slotScrollerStateChanged(QScroller::State state){ KisKineticScroller::updateCursor(this, state); } private Q_SLOTS: void presetSelected(QListWidgetItem* item); void canvasResourceChanged(int key, const QVariant& v); private: void addPreset(KisPaintOpPresetSP preset); private: QPointer m_canvas; QListWidget *m_presetHistory; bool m_block; bool m_initialized; }; #endif diff --git a/plugins/dockers/smallcolorselector/kis_small_color_widget.cc b/plugins/dockers/smallcolorselector/kis_small_color_widget.cc index db47426e6d..db65f16ec6 100644 --- a/plugins/dockers/smallcolorselector/kis_small_color_widget.cc +++ b/plugins/dockers/smallcolorselector/kis_small_color_widget.cc @@ -1,516 +1,517 @@ /* * 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. + * the Free Software Foundation; 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 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_small_color_widget.h" #include #include "kis_slider_spin_box.h" #include #include "kis_signal_compressor.h" #include #include #include #include "kis_debug.h" #include "kis_assert.h" #include #include "KisGLImageF16.h" #include "KisGLImageWidget.h" #include "KisClickableGLImageWidget.h" #include "kis_display_color_converter.h" #include "kis_signal_auto_connection.h" #include "kis_signal_compressor_with_param.h" #include #include #include "kis_fixed_paint_device.h" #include struct KisSmallColorWidget::Private { qreal hue; // 0 ... 1.0 qreal value; // 0 ... 1.0 qreal saturation; // 0 ... 1.0 bool updateAllowed; KisClickableGLImageWidget *hueWidget; KisClickableGLImageWidget *valueWidget; KisSignalCompressor *repaintCompressor; KisSignalCompressor *resizeUpdateCompressor; KisSignalCompressor *valueSliderUpdateCompressor; KisSignalCompressor *colorChangedSignalCompressor; KisSignalCompressorWithParam *dynamicRangeCompressor; int huePreferredHeight = 32; KisSliderSpinBox *dynamicRange = 0; qreal currentRelativeDynamicRange = 1.0; KisDisplayColorConverter *displayColorConverter = KisDisplayColorConverter::dumbConverterInstance(); KisSignalAutoConnectionsStore colorConverterConnections; bool hasHDR = false; bool hasHardwareHDR = false; qreal effectiveRelativeDynamicRange() const { return hasHDR ? currentRelativeDynamicRange : 1.0; } const KoColorSpace *outputColorSpace() { return KoColorSpaceRegistry::instance()-> colorSpace(RGBAColorModelID.id(), Float32BitsColorDepthID.id(), displayColorConverter->openGLCanvasSurfaceProfile()); } const KoColorSpace *generationColorSpace() { const KoColorSpace *result = displayColorConverter->paintingColorSpace(); if (!result || result->colorModelId() != RGBAColorModelID) { result = outputColorSpace(); } else if (result->colorDepthId() != Float32BitsColorDepthID) { result = KoColorSpaceRegistry::instance()-> colorSpace(RGBAColorModelID.id(), Float32BitsColorDepthID.id(), result->profile()); } // PQ color space we deliniearize into linear one if (result->colorModelId() == RGBAColorModelID && result->profile()->uniqueId() == KoColorSpaceRegistry::instance()->p2020PQProfile()->uniqueId()) { result = KoColorSpaceRegistry::instance()-> colorSpace(RGBAColorModelID.id(), Float32BitsColorDepthID.id(), KoColorSpaceRegistry::instance()->p2020G10Profile()); } return result; } }; KisSmallColorWidget::KisSmallColorWidget(QWidget* parent) : QWidget(parent), d(new Private) { d->hue = 0.0; d->value = 0; d->saturation = 0; d->updateAllowed = true; d->repaintCompressor = new KisSignalCompressor(20, KisSignalCompressor::FIRST_ACTIVE, this); connect(d->repaintCompressor, SIGNAL(timeout()), SLOT(update())); d->resizeUpdateCompressor = new KisSignalCompressor(200, KisSignalCompressor::FIRST_ACTIVE, this); connect(d->resizeUpdateCompressor, SIGNAL(timeout()), SLOT(slotUpdatePalettes())); d->valueSliderUpdateCompressor = new KisSignalCompressor(100, KisSignalCompressor::FIRST_ACTIVE, this); connect(d->valueSliderUpdateCompressor, SIGNAL(timeout()), SLOT(updateSVPalette())); d->colorChangedSignalCompressor = new KisSignalCompressor(20, KisSignalCompressor::FIRST_ACTIVE, this); connect(d->colorChangedSignalCompressor, SIGNAL(timeout()), SLOT(slotTellColorChanged())); { using namespace std::placeholders; std::function callback( std::bind(&KisSmallColorWidget::updateDynamicRange, this, _1)); d->dynamicRangeCompressor = new KisSignalCompressorWithParam(50, callback); } const KisSurfaceColorSpace colorSpace = KisSurfaceColorSpace::DefaultColorSpace; d->hueWidget = new KisClickableGLImageWidget(colorSpace, this); d->hueWidget->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed); d->hueWidget->setHandlePaintingStrategy(new KisClickableGLImageWidget::VerticalLineHandleStrategy); connect(d->hueWidget, SIGNAL(selected(const QPointF&)), SLOT(slotHueSliderChanged(const QPointF&))); d->valueWidget = new KisClickableGLImageWidget(colorSpace, this); d->valueWidget->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Expanding); d->valueWidget->setHandlePaintingStrategy(new KisClickableGLImageWidget::CircularHandleStrategy); connect(d->valueWidget, SIGNAL(selected(const QPointF&)), SLOT(slotValueSliderChanged(const QPointF&))); d->hasHardwareHDR = KisOpenGLModeProber::instance()->useHDRMode(); if (d->hasHardwareHDR) { d->dynamicRange = new KisSliderSpinBox(this); d->dynamicRange->setRange(80, 10000); d->dynamicRange->setExponentRatio(3.0); d->dynamicRange->setSingleStep(1); d->dynamicRange->setPageStep(100); d->dynamicRange->setSuffix("cd/m²"); d->dynamicRange->setValue(80.0 * d->currentRelativeDynamicRange); connect(d->dynamicRange, SIGNAL(valueChanged(int)), SLOT(slotInitiateUpdateDynamicRange(int))); } QVBoxLayout *layout = new QVBoxLayout(this); layout->addWidget(d->hueWidget, 0); layout->addWidget(d->valueWidget, 1); if (d->dynamicRange) { layout->addSpacing(16); layout->addWidget(d->dynamicRange, 0); } setLayout(layout); slotUpdatePalettes(); } KisSmallColorWidget::~KisSmallColorWidget() { delete d; } void KisSmallColorWidget::setHue(qreal h) { h = qBound(0.0, h, 1.0); d->hue = h; d->colorChangedSignalCompressor->start(); d->valueSliderUpdateCompressor->start(); d->repaintCompressor->start(); } void KisSmallColorWidget::setHSV(qreal h, qreal s, qreal v, bool notifyChanged) { h = qBound(0.0, h, 1.0); s = qBound(0.0, s, 1.0); v = qBound(0.0, v, 1.0); bool newH = !qFuzzyCompare(d->hue, h); d->hue = h; d->value = v; d->saturation = s; // TODO: remove and make acyclic! if (notifyChanged) { d->colorChangedSignalCompressor->start(); } if(newH) { d->valueSliderUpdateCompressor->start(); } d->repaintCompressor->start(); } void KisSmallColorWidget::setColor(const KoColor &color) { if (!d->updateAllowed) return; KIS_SAFE_ASSERT_RECOVER(!d->dynamicRange || d->hasHDR == d->dynamicRange->isEnabled()) { slotDisplayConfigurationChanged(); } KIS_SAFE_ASSERT_RECOVER_RETURN(!d->hasHDR || d->hasHardwareHDR); const KoColorSpace *cs = d->generationColorSpace(); KIS_SAFE_ASSERT_RECOVER_RETURN(cs); KoColor newColor(color); newColor.convertTo(cs); QVector channels(4); cs->normalisedChannelsValue(newColor.data(), channels); float r, g, b; if (cs->colorDepthId() == Integer8BitsColorDepthID) { r = channels[2]; g = channels[1]; b = channels[0]; } else { r = channels[0]; g = channels[1]; b = channels[2]; } if (d->hasHDR) { qreal rangeCoeff = d->effectiveRelativeDynamicRange(); if (rangeCoeff < r || rangeCoeff < g || rangeCoeff < b) { rangeCoeff = std::max({r, g, b}) * 1.10f; const int newMaxLuminance = qRound(80.0 * rangeCoeff); updateDynamicRange(newMaxLuminance); d->dynamicRange->setValue(newMaxLuminance); } r /= rangeCoeff; g /= rangeCoeff; b /= rangeCoeff; } else { r = qBound(0.0f, r, 1.0f); g = qBound(0.0f, g, 1.0f); b = qBound(0.0f, b, 1.0f); } float denormHue, saturation, value; RGBToHSV(r, g, b, &denormHue, &saturation, &value); d->hueWidget->setNormalizedPos(QPointF(denormHue / 360.0, 0.0)); d->valueWidget->setNormalizedPos(QPointF(saturation, 1.0 - value)); setHSV(denormHue / 360.0, saturation, value, false); } void KisSmallColorWidget::slotUpdatePalettes() { updateHuePalette(); updateSVPalette(); } namespace { struct FillHPolicy { static inline void getRGB(qreal /*hue*/, float xPortionCoeff, float /*yPortionCoeff*/, int x, int /*y*/, float *r, float *g, float *b) { HSVToRGB(xPortionCoeff * x * 360.0f, 1.0, 1.0, r, g, b); } }; struct FillSVPolicy { static inline void getRGB(qreal hue, float xPortionCoeff, float yPortionCoeff, int x, int y, float *r, float *g, float *b) { HSVToRGB(hue * 360.0, xPortionCoeff * x, 1.0 - yPortionCoeff * y, r, g, b); } }; } template void KisSmallColorWidget::uploadPaletteData(KisGLImageWidget *widget, const QSize &size) { if (size.isEmpty()) return; KisGLImageF16 image(size); const float xPortionCoeff = 1.0 / image.width(); const float yPortionCoeff = 1.0 / image.height(); const float rangeCoeff = d->effectiveRelativeDynamicRange(); const KoColorSpace *generationColorSpace = d->generationColorSpace(); if (d->displayColorConverter->canSkipDisplayConversion(generationColorSpace)) { half *pixelPtr = image.data(); for (int y = 0; y < image.height(); y++) { for (int x = 0; x < image.width(); x++) { Imf::Rgba &pxl = reinterpret_cast(*pixelPtr); float r, g, b; FillPolicy::getRGB(d->hue, xPortionCoeff, yPortionCoeff, x, y, &r, &g, &b); pxl.r = r * rangeCoeff; pxl.g = g * rangeCoeff; pxl.b = b * rangeCoeff; pxl.a = 1.0; pixelPtr += 4; } } } else { KIS_SAFE_ASSERT_RECOVER_RETURN(d->displayColorConverter); KisFixedPaintDeviceSP device = new KisFixedPaintDevice(generationColorSpace); device->setRect(QRect(QPoint(), image.size())); device->reallocateBufferWithoutInitialization(); float *devicePtr = reinterpret_cast(device->data()); for (int y = 0; y < image.height(); y++) { for (int x = 0; x < image.width(); x++) { FillPolicy::getRGB(d->hue, xPortionCoeff, yPortionCoeff, x, y, devicePtr, devicePtr + 1, devicePtr + 2); devicePtr[0] *= rangeCoeff; devicePtr[1] *= rangeCoeff; devicePtr[2] *= rangeCoeff; devicePtr[3] = 1.0; devicePtr += 4; } } d->displayColorConverter->applyDisplayFilteringF32(device, Float32BitsColorDepthID); half *imagePtr = image.data(); devicePtr = reinterpret_cast(device->data()); for (int y = 0; y < image.height(); y++) { for (int x = 0; x < image.width(); x++) { imagePtr[0] = devicePtr[0]; imagePtr[1] = devicePtr[1]; imagePtr[2] = devicePtr[2]; imagePtr[3] = devicePtr[3]; devicePtr += 4; imagePtr += 4; } } } widget->loadImage(image); } void KisSmallColorWidget::updateHuePalette() { uploadPaletteData(d->hueWidget, QSize(d->hueWidget->width(), d->huePreferredHeight)); } void KisSmallColorWidget::updateSVPalette() { const int maxSize = 256; QSize newSize = d->valueWidget->size(); newSize.rwidth() = qMin(maxSize, newSize.width()); newSize.rheight() = qMin(maxSize, newSize.height()); uploadPaletteData(d->valueWidget, newSize); } void KisSmallColorWidget::slotHueSliderChanged(const QPointF &pos) { const qreal newHue = pos.x(); if (!qFuzzyCompare(newHue, d->hue)) { setHue(newHue); } } void KisSmallColorWidget::slotValueSliderChanged(const QPointF &pos) { const qreal newSaturation = pos.x(); const qreal newValue = 1.0 - pos.y(); if (!qFuzzyCompare(newSaturation, d->saturation) || !qFuzzyCompare(newValue, d->value)) { setHSV(d->hue, newSaturation, newValue); } } void KisSmallColorWidget::slotInitiateUpdateDynamicRange(int maxLuminance) { d->dynamicRangeCompressor->start(maxLuminance); } void KisSmallColorWidget::updateDynamicRange(int maxLuminance) { const qreal oldRange = d->currentRelativeDynamicRange; const qreal newRange = qreal(maxLuminance) / 80.0; if (qFuzzyCompare(oldRange, newRange)) return; float r, g, b; float denormHue = d->hue * 360.0; float saturation = d->saturation; float value = d->value; HSVToRGB(denormHue, saturation, value, &r, &g, &b); const qreal transformCoeff = oldRange / newRange; r = qBound(0.0, r * transformCoeff, 1.0); g = qBound(0.0, g * transformCoeff, 1.0); b = qBound(0.0, b * transformCoeff, 1.0); RGBToHSV(r, g, b, &denormHue, &saturation, &value); d->currentRelativeDynamicRange = newRange; slotUpdatePalettes(); setHSV(denormHue / 360.0, saturation, value, false); d->hueWidget->setNormalizedPos(QPointF(denormHue / 360.0, 0)); d->valueWidget->setNormalizedPos(QPointF(saturation, 1.0 - value)); } void KisSmallColorWidget::setDisplayColorConverter(KisDisplayColorConverter *converter) { d->colorConverterConnections.clear(); if (!converter) { converter = KisDisplayColorConverter::dumbConverterInstance(); } d->displayColorConverter = converter; if (d->displayColorConverter) { d->colorConverterConnections.addConnection( d->displayColorConverter, SIGNAL(displayConfigurationChanged()), this, SLOT(slotDisplayConfigurationChanged())); } slotDisplayConfigurationChanged(); } void KisSmallColorWidget::slotDisplayConfigurationChanged() { d->hasHDR = false; if (d->hasHardwareHDR) { const KoColorSpace *cs = d->displayColorConverter->paintingColorSpace(); d->hasHDR = cs->colorModelId() == RGBAColorModelID && (cs->colorDepthId() == Float16BitsColorDepthID || cs->colorDepthId() == Float32BitsColorDepthID || cs->colorDepthId() == Float64BitsColorDepthID || cs->profile()->uniqueId() == KoColorSpaceRegistry::instance()->p2020PQProfile()->uniqueId()); } if (d->dynamicRange) { d->dynamicRange->setEnabled(d->hasHDR); } d->hueWidget->setUseHandleOpacity(!d->hasHDR); d->valueWidget->setUseHandleOpacity(!d->hasHDR); slotUpdatePalettes(); // TODO: also set the currently selected color again } void KisSmallColorWidget::slotTellColorChanged() { d->updateAllowed = false; float r, g, b; HSVToRGB(d->hue * 360.0, d->saturation, d->value, &r, &g, &b); if (d->hasHDR) { const float rangeCoeff = d->effectiveRelativeDynamicRange(); r *= rangeCoeff; g *= rangeCoeff; b *= rangeCoeff; } const KoColorSpace *cs = d->generationColorSpace(); KIS_SAFE_ASSERT_RECOVER_RETURN(cs); QVector values(4); if (cs->colorDepthId() == Integer8BitsColorDepthID) { values[0] = b; values[1] = g; values[2] = r; values[3] = 1.0f; } else { values[0] = r; values[1] = g; values[2] = b; values[3] = 1.0f; } KoColor c(cs); cs->fromNormalisedChannelsValue(c.data(), values); emit colorChanged(c); d->updateAllowed = true; } void KisSmallColorWidget::resizeEvent(QResizeEvent * event) { QWidget::resizeEvent(event); update(); d->resizeUpdateCompressor->start(); } diff --git a/plugins/dockers/smallcolorselector/kis_small_color_widget.h b/plugins/dockers/smallcolorselector/kis_small_color_widget.h index e771d053af..40af9a5624 100644 --- a/plugins/dockers/smallcolorselector/kis_small_color_widget.h +++ b/plugins/dockers/smallcolorselector/kis_small_color_widget.h @@ -1,76 +1,77 @@ /* * 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. + * the Free Software Foundation; 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 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_SMALL_COLOR_WIDGET_H_ #define _KIS_SMALL_COLOR_WIDGET_H_ #include class KoColor; class KisDisplayColorConverter; class KisGLImageWidget; class KisSmallColorWidget : public QWidget { Q_OBJECT public: KisSmallColorWidget(QWidget* parent); ~KisSmallColorWidget() override; public: void resizeEvent(QResizeEvent * event) override; void setDisplayColorConverter(KisDisplayColorConverter *converter); public: public Q_SLOTS: void setHue(qreal h); void setHSV(qreal h, qreal s, qreal v, bool notifyChanged = true); void setColor(const KoColor &color); void slotUpdatePalettes(); void updateSVPalette(); Q_SIGNALS: void colorChanged(const KoColor&); void sigTellColorChangedInternal(); private Q_SLOTS: void slotHueSliderChanged(const QPointF &pos); void slotValueSliderChanged(const QPointF &pos); void slotInitiateUpdateDynamicRange(int maxLuminance); void slotDisplayConfigurationChanged(); void slotTellColorChanged(); private: void updateDynamicRange(int maxLuminance); private: void updateHuePalette(); template void uploadPaletteData(KisGLImageWidget *widget, const QSize &size); private: struct Private; Private* const d; }; #endif diff --git a/plugins/dockers/smallcolorselector/smallcolorselector.cc b/plugins/dockers/smallcolorselector/smallcolorselector.cc index b90d5ac00a..308bf0ad8b 100644 --- a/plugins/dockers/smallcolorselector/smallcolorselector.cc +++ b/plugins/dockers/smallcolorselector/smallcolorselector.cc @@ -1,68 +1,69 @@ /* * 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. + * the Free Software Foundation; 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 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 "smallcolorselector.h" #include #include #include #include "smallcolorselector_dock.h" K_PLUGIN_FACTORY_WITH_JSON(SmallColorSelectorPluginFactory, "krita_smallcolorselector.json", registerPlugin();) class SmallColorSelectorDockFactory : public KoDockFactoryBase { public: SmallColorSelectorDockFactory() { } QString id() const override { return QString("SmallColorSelector"); } virtual Qt::DockWidgetArea defaultDockWidgetArea() const { return Qt::RightDockWidgetArea; } QDockWidget* createDockWidget() override { SmallColorSelectorDock * dockWidget = new SmallColorSelectorDock(); dockWidget->setObjectName(id()); return dockWidget; } DockPosition defaultDockPosition() const override { return DockRight; } }; SmallColorSelectorPlugin::SmallColorSelectorPlugin(QObject *parent, const QVariantList &) : QObject(parent) { KoDockRegistry::instance()->add(new SmallColorSelectorDockFactory()); } SmallColorSelectorPlugin::~SmallColorSelectorPlugin() { } #include "smallcolorselector.moc" diff --git a/plugins/dockers/smallcolorselector/smallcolorselector.h b/plugins/dockers/smallcolorselector/smallcolorselector.h index 8c78bfb170..fb8752b776 100644 --- a/plugins/dockers/smallcolorselector/smallcolorselector.h +++ b/plugins/dockers/smallcolorselector/smallcolorselector.h @@ -1,36 +1,37 @@ /* * 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. + * the Free Software Foundation; 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 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 _SMALLCOLORSELECTOR_H_ #define _SMALLCOLORSELECTOR_H_ #include #include /** * Template of view plugin */ class SmallColorSelectorPlugin : public QObject { Q_OBJECT public: SmallColorSelectorPlugin(QObject *parent, const QVariantList &); ~SmallColorSelectorPlugin() override; }; #endif diff --git a/plugins/dockers/smallcolorselector/smallcolorselector_dock.cc b/plugins/dockers/smallcolorselector/smallcolorselector_dock.cc index 50fb2ca903..dc4279392c 100644 --- a/plugins/dockers/smallcolorselector/smallcolorselector_dock.cc +++ b/plugins/dockers/smallcolorselector/smallcolorselector_dock.cc @@ -1,84 +1,85 @@ /* * 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. + * the Free Software Foundation; 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 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 "smallcolorselector_dock.h" #include #include "kis_canvas2.h" #include "kis_small_color_widget.h" #include "kis_canvas_resource_provider.h" #include #include SmallColorSelectorDock::SmallColorSelectorDock() : QDockWidget() , m_canvas(0) { QWidget *page = new QWidget(this); QVBoxLayout *layout = new QVBoxLayout(page); m_smallColorWidget = new KisSmallColorWidget(this); layout->addWidget(m_smallColorWidget, 1); page->setLayout(layout); setWidget(page); m_smallColorWidget->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Expanding); connect(m_smallColorWidget, SIGNAL(colorChanged(KoColor)), this, SLOT(colorChangedProxy(KoColor))); connect(this, SIGNAL(dockLocationChanged(Qt::DockWidgetArea)), m_smallColorWidget, SLOT(update())); setWindowTitle(i18n("Small Color Selector")); } void SmallColorSelectorDock::setCanvas(KoCanvasBase * canvas) { setEnabled(canvas != 0); if (m_canvas) { m_canvas->disconnectCanvasObserver(this); m_smallColorWidget->setColor(KoColor(Qt::black, KoColorSpaceRegistry::instance()->rgb8())); m_smallColorWidget->setDisplayColorConverter(0); } m_canvas = canvas; if (m_canvas && m_canvas->resourceManager()) { connect(m_canvas->resourceManager(), SIGNAL(canvasResourceChanged(int,QVariant)), this, SLOT(canvasResourceChanged(int,QVariant))); KisCanvas2 *kisCanvas = dynamic_cast(canvas); m_smallColorWidget->setDisplayColorConverter(kisCanvas->displayColorConverter()); m_smallColorWidget->setColor(m_canvas->resourceManager()->foregroundColor()); } } void SmallColorSelectorDock::colorChangedProxy(const KoColor& c) { if (m_canvas) m_canvas->resourceManager()->setForegroundColor(c); } void SmallColorSelectorDock::canvasResourceChanged(int key, const QVariant& v) { if (key == KoCanvasResourceProvider::ForegroundColor) { m_smallColorWidget->setColor(v.value()); } } diff --git a/plugins/dockers/smallcolorselector/smallcolorselector_dock.h b/plugins/dockers/smallcolorselector/smallcolorselector_dock.h index c3c36a747d..b25b0601b2 100644 --- a/plugins/dockers/smallcolorselector/smallcolorselector_dock.h +++ b/plugins/dockers/smallcolorselector/smallcolorselector_dock.h @@ -1,48 +1,49 @@ /* * 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. + * the Free Software Foundation; 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 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 _SMALLCOLORSELECTOR_DOCK_H_ #define _SMALLCOLORSELECTOR_DOCK_H_ #include #include #include #include class KoColor; class KisSmallColorWidget; class SmallColorSelectorDock : public QDockWidget, public KoCanvasObserverBase { Q_OBJECT public: SmallColorSelectorDock(); QString observerName() override { return "SmallColorSelectorDock"; } /// reimplemented from KoCanvasObserverBase void setCanvas(KoCanvasBase *canvas) override; void unsetCanvas() override { m_canvas = 0; setEnabled(false); } public Q_SLOTS: void colorChangedProxy(const KoColor &); void canvasResourceChanged(int, const QVariant&); private: KisSmallColorWidget* m_smallColorWidget; QPointer m_canvas; }; #endif diff --git a/plugins/dockers/specificcolorselector/kis_specific_color_selector_widget.cc b/plugins/dockers/specificcolorselector/kis_specific_color_selector_widget.cc index 4aacf59369..94f5cab633 100644 --- a/plugins/dockers/specificcolorselector/kis_specific_color_selector_widget.cc +++ b/plugins/dockers/specificcolorselector/kis_specific_color_selector_widget.cc @@ -1,269 +1,270 @@ /* * Copyright (c) 2008 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 Lesser General Public License as published by - * the Free Software Foundation; version 2.1 of the License. + * the Free Software Foundation; 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 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_specific_color_selector_widget.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "ui_wdgSpecificColorSelectorWidget.h" KisSpecificColorSelectorWidget::KisSpecificColorSelectorWidget(QWidget* parent) : QWidget(parent) , m_colorSpace(0) , m_spacer(0) , m_updateCompressor(new KisSignalCompressor(10, KisSignalCompressor::POSTPONE, this)) , m_customColorSpaceSelected(false) , m_displayConverter(0) { m_ui = new Ui_wdgSpecificColorSelectorWidget(); m_ui->setupUi(this); m_updateAllowed = true; connect(m_updateCompressor, SIGNAL(timeout()), SLOT(updateTimeout())); m_colorspaceSelector = new KisColorSpaceSelector(this); connect(m_colorspaceSelector, SIGNAL(colorSpaceChanged(const KoColorSpace*)), this, SLOT(setCustomColorSpace(const KoColorSpace*))); m_ui->colorspacePopupButton->setPopupWidget(m_colorspaceSelector); connect(m_ui->chkUsePercentage, SIGNAL(toggled(bool)), this, SLOT(onChkUsePercentageChanged(bool))); KConfigGroup cfg = KSharedConfig::openConfig()->group(QString()); m_ui->chkUsePercentage->setChecked(cfg.readEntry("SpecificColorSelector/UsePercentage", false)); m_ui->chkUsePercentage->setIcon(KisIconUtils::loadIcon("ratio")); m_colorspaceSelector->showColorBrowserButton(false); m_spacer = new QSpacerItem(0, 0, QSizePolicy::Expanding, QSizePolicy::Expanding); m_ui->slidersLayout->addItem(m_spacer); } KisSpecificColorSelectorWidget::~KisSpecificColorSelectorWidget() { KConfigGroup cfg = KSharedConfig::openConfig()->group(QString()); cfg.writeEntry("SpecificColorSelector/UsePercentage", m_ui->chkUsePercentage->isChecked()); } bool KisSpecificColorSelectorWidget::customColorSpaceUsed() { return m_customColorSpaceSelected; } void KisSpecificColorSelectorWidget::resizeEvent(QResizeEvent *event) { QWidget::resizeEvent(event); if (m_colorSpace) { QString elidedColorspaceName = m_ui->colorspacePopupButton->fontMetrics().elidedText( m_colorSpace->name(), Qt::ElideRight, m_ui->colorspacePopupButton->width() ); m_ui->colorspacePopupButton->setText(elidedColorspaceName); } } void KisSpecificColorSelectorWidget::setDisplayConverter(KisDisplayColorConverter *displayConverter) { const bool needsForceUpdate = m_displayConverter != displayConverter; m_displayConverter = displayConverter; if (m_displayConverter) { m_converterConnection.clear(); m_converterConnection.addConnection(m_displayConverter, SIGNAL(displayConfigurationChanged()), this, SLOT(rereadCurrentColorSpace()), Qt::UniqueConnection); } rereadCurrentColorSpace(needsForceUpdate); } void KisSpecificColorSelectorWidget::rereadCurrentColorSpace(bool force) { if (m_displayConverter && !m_customColorSpaceSelected) { m_colorSpace = m_displayConverter->paintingColorSpace(); } setColorSpace(m_colorSpace, force); setColor(m_color); } void KisSpecificColorSelectorWidget::setColorSpace(const KoColorSpace* cs, bool force) { Q_ASSERT(cs); dbgPlugins << cs->id() << " " << cs->profile()->name(); if (*m_colorSpace == *cs && !force) { Q_FOREACH (KisColorInput* input, m_inputs) { input->update(); } return; } if (cs->colorDepthId() == Integer8BitsColorDepthID || cs->colorDepthId() == Integer16BitsColorDepthID) { m_ui->chkUsePercentage->setVisible(true); } else { m_ui->chkUsePercentage->setVisible(false); } m_colorSpace = KoColorSpaceRegistry::instance()->colorSpace(cs->colorModelId().id(), cs->colorDepthId().id(), cs->profile()); Q_ASSERT(m_colorSpace); Q_ASSERT(*m_colorSpace == *cs); QString elidedColorspaceName = m_ui->colorspacePopupButton->fontMetrics().elidedText( m_colorSpace->name(), Qt::ElideRight, m_ui->colorspacePopupButton->width() ); m_ui->colorspacePopupButton->setText(elidedColorspaceName); m_color = KoColor(m_color, m_colorSpace); Q_FOREACH (KisColorInput* input, m_inputs) { delete input; } m_inputs.clear(); m_ui->slidersLayout->removeItem(m_spacer); QList channels = KoChannelInfo::displayOrderSorted(m_colorSpace->channels()); KoColorDisplayRendererInterface *displayRenderer = m_displayConverter ? m_displayConverter->displayRendererInterface() : KisDisplayColorConverter::dumbConverterInstance()->displayRendererInterface(); Q_FOREACH (KoChannelInfo* channel, channels) { if (channel->channelType() == KoChannelInfo::COLOR) { KisColorInput* input = 0; switch (channel->channelValueType()) { case KoChannelInfo::UINT8: case KoChannelInfo::UINT16: case KoChannelInfo::UINT32: { input = new KisIntegerColorInput(this, channel, &m_color, displayRenderer, m_ui->chkUsePercentage->isChecked()); } break; case KoChannelInfo::FLOAT16: case KoChannelInfo::FLOAT32: { input = new KisFloatColorInput(this, channel, &m_color, displayRenderer); } break; default: Q_ASSERT(false); input = 0; } if (input) { connect(input, SIGNAL(updated()), this, SLOT(update())); connect(this, SIGNAL(updated()), input, SLOT(update())); m_inputs.append(input); m_ui->slidersLayout->addWidget(input); } } } QList labels; int labelWidth = 0; Q_FOREACH (KisColorInput* input, m_inputs) { Q_FOREACH (QLabel* label, input->findChildren()) { labels.append(label); labelWidth = qMax(labelWidth, label->sizeHint().width()); } } Q_FOREACH (QLabel *label, labels) { label->setMinimumWidth(labelWidth); } bool allChannels8Bit = true; Q_FOREACH (KoChannelInfo* channel, channels) { if (channel->channelType() == KoChannelInfo::COLOR && channel->channelValueType() != KoChannelInfo::UINT8) { allChannels8Bit = false; } } if (allChannels8Bit) { KisColorInput* input = new KisHexColorInput(this, &m_color, displayRenderer); m_inputs.append(input); m_ui->slidersLayout->addWidget(input); connect(input, SIGNAL(updated()), this, SLOT(update())); connect(this, SIGNAL(updated()), input, SLOT(update())); } m_ui->slidersLayout->addItem(m_spacer); m_colorspaceSelector->blockSignals(true); m_colorspaceSelector->setCurrentColorSpace(cs); m_colorspaceSelector->blockSignals(false); m_updateAllowed = false; emit(updated()); m_updateAllowed = true; } void KisSpecificColorSelectorWidget::update() { if (m_updateAllowed) { m_updateCompressor->start(); } } void KisSpecificColorSelectorWidget::setColor(const KoColor& c) { m_updateAllowed = false; m_color.fromKoColor(c); emit(updated()); m_updateAllowed = true; } void KisSpecificColorSelectorWidget::updateTimeout() { emit(colorChanged(m_color)); } void KisSpecificColorSelectorWidget::setCustomColorSpace(const KoColorSpace *colorSpace) { m_customColorSpaceSelected = true; setColorSpace(colorSpace); setColor(m_color); } void KisSpecificColorSelectorWidget::onChkUsePercentageChanged(bool isChecked) { for (auto input: m_inputs) { input->setPercentageWise(isChecked); } emit(updated()); } diff --git a/plugins/dockers/specificcolorselector/kis_specific_color_selector_widget.h b/plugins/dockers/specificcolorselector/kis_specific_color_selector_widget.h index 2b2b3c9340..272a3c54c1 100644 --- a/plugins/dockers/specificcolorselector/kis_specific_color_selector_widget.h +++ b/plugins/dockers/specificcolorselector/kis_specific_color_selector_widget.h @@ -1,80 +1,81 @@ /* * 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. + * the Free Software Foundation; 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 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_SPECIFIC_COLOR_SELECTOR_WIDGET_H_ #define _KIS_SPECIFIC_COLOR_SELECTOR_WIDGET_H_ #include #include #include "kis_signal_auto_connection.h" #include "ui_wdgSpecificColorSelectorWidget.h" class KoColorSpace; class QVBoxLayout; class KisColorInput; class KisColorSpaceSelector; class QCheckBox; class KisSignalCompressor; class QSpacerItem; class KisDisplayColorConverter; class KisPopupButton; class KisSpecificColorSelectorWidget : public QWidget { Q_OBJECT public: KisSpecificColorSelectorWidget(QWidget* parent); ~KisSpecificColorSelectorWidget() override; bool customColorSpaceUsed(); protected: void resizeEvent(QResizeEvent* event) override; public Q_SLOTS: void setDisplayConverter(KisDisplayColorConverter *colorConverter); void setColorSpace(const KoColorSpace *cs, bool force = false); void setColor(const KoColor&); private Q_SLOTS: void update(); void updateTimeout(); void setCustomColorSpace(const KoColorSpace *); void rereadCurrentColorSpace(bool force = false); void onChkUsePercentageChanged(bool); Q_SIGNALS: void colorChanged(const KoColor&); void updated(); private: QList m_inputs; const KoColorSpace* m_colorSpace; QSpacerItem *m_spacer; KoColor m_color; bool m_updateAllowed; KisSignalCompressor *m_updateCompressor; KisColorSpaceSelector *m_colorspaceSelector; bool m_customColorSpaceSelected; Ui_wdgSpecificColorSelectorWidget* m_ui; KisDisplayColorConverter *m_displayConverter; KisSignalAutoConnectionsStore m_converterConnection; }; #endif diff --git a/plugins/dockers/specificcolorselector/specificcolorselector.cc b/plugins/dockers/specificcolorselector/specificcolorselector.cc index 4a70c35028..2b163da342 100644 --- a/plugins/dockers/specificcolorselector/specificcolorselector.cc +++ b/plugins/dockers/specificcolorselector/specificcolorselector.cc @@ -1,81 +1,82 @@ /* * 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. + * the Free Software Foundation; 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 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 "specificcolorselector.h" #include #include #include #include #include #include #include #include "kis_config.h" #include "kis_cursor.h" #include "kis_global.h" #include "kis_types.h" #include "KisViewManager.h" #include "specificcolorselector_dock.h" K_PLUGIN_FACTORY_WITH_JSON(SpecificColorSelectorPluginFactory, "krita_specificcolorselector.json", registerPlugin();) class SpecificColorSelectorDockFactory : public KoDockFactoryBase { public: SpecificColorSelectorDockFactory() { } QString id() const override { return QString("SpecificColorSelector"); } virtual Qt::DockWidgetArea defaultDockWidgetArea() const { return Qt::RightDockWidgetArea; } QDockWidget* createDockWidget() override { SpecificColorSelectorDock * dockWidget = new SpecificColorSelectorDock(); dockWidget->setObjectName(id()); return dockWidget; } KoDockFactoryBase::DockPosition defaultDockPosition() const override { return DockMinimized; } }; SpecificColorSelectorPlugin::SpecificColorSelectorPlugin(QObject *parent, const QVariantList &) : QObject(parent) { dbgPlugins << "SpecificColorSelectorPlugin"; KoDockRegistry::instance()->add(new SpecificColorSelectorDockFactory()); } SpecificColorSelectorPlugin::~SpecificColorSelectorPlugin() { } #include "specificcolorselector.moc" diff --git a/plugins/dockers/specificcolorselector/specificcolorselector.h b/plugins/dockers/specificcolorselector/specificcolorselector.h index 52bec70c0b..42b3671483 100644 --- a/plugins/dockers/specificcolorselector/specificcolorselector.h +++ b/plugins/dockers/specificcolorselector/specificcolorselector.h @@ -1,36 +1,37 @@ /* * 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. + * the Free Software Foundation; 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 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 _SPECIFICCOLORSELECTOR_H_ #define _SPECIFICCOLORSELECTOR_H_ #include #include /** * Template of view plugin */ class SpecificColorSelectorPlugin : public QObject { Q_OBJECT public: SpecificColorSelectorPlugin(QObject *parent, const QVariantList &); ~SpecificColorSelectorPlugin() override; }; #endif diff --git a/plugins/dockers/specificcolorselector/specificcolorselector_dock.cc b/plugins/dockers/specificcolorselector/specificcolorselector_dock.cc index cc51c97ab8..04d9dd6939 100644 --- a/plugins/dockers/specificcolorselector/specificcolorselector_dock.cc +++ b/plugins/dockers/specificcolorselector/specificcolorselector_dock.cc @@ -1,74 +1,75 @@ /* * 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. + * the Free Software Foundation; 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 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 "specificcolorselector_dock.h" #include #include #include #include #include #include #include #include #include "kis_specific_color_selector_widget.h" SpecificColorSelectorDock::SpecificColorSelectorDock() : QDockWidget(i18n("Specific Color Selector")) , m_canvas(0) , m_view(0) , m_colorSelector(new KisSpecificColorSelectorWidget(this)) { setWidget(m_colorSelector); widget()->setContentsMargins(4,4,4,0); } void SpecificColorSelectorDock::setCanvas(KoCanvasBase * canvas) { setEnabled(canvas != 0); if (m_canvas) { m_canvas->disconnectCanvasObserver(this); } KisCanvas2* kisCanvas = dynamic_cast(canvas); m_canvas = kisCanvas; if (!kisCanvas) { return; } m_colorSelector->setDisplayConverter(kisCanvas->displayColorConverter()); } void SpecificColorSelectorDock::unsetCanvas() { setEnabled(false); m_canvas = 0; m_colorSelector->setDisplayConverter(0); } void SpecificColorSelectorDock::setViewManager(KisViewManager* kisview) { m_view = kisview; connect(m_view->canvasResourceProvider(), SIGNAL(sigFGColorChanged(KoColor)), m_colorSelector, SLOT(setColor(KoColor))); connect(m_colorSelector, SIGNAL(colorChanged(KoColor)), m_view->canvasResourceProvider(), SLOT(slotSetFGColor(KoColor))); } #include "moc_specificcolorselector_dock.cpp" diff --git a/plugins/dockers/specificcolorselector/specificcolorselector_dock.h b/plugins/dockers/specificcolorselector/specificcolorselector_dock.h index 619b3a3981..8ab881fe45 100644 --- a/plugins/dockers/specificcolorselector/specificcolorselector_dock.h +++ b/plugins/dockers/specificcolorselector/specificcolorselector_dock.h @@ -1,50 +1,51 @@ /* * 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. + * the Free Software Foundation; 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 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 _SPECIFICCOLORSELECTOR_DOCK_H_ #define _SPECIFICCOLORSELECTOR_DOCK_H_ #include #include #include #include #include class KisViewManager; class KisSpecificColorSelectorWidget; class SpecificColorSelectorDock : public QDockWidget, public KisMainwindowObserver { Q_OBJECT public: SpecificColorSelectorDock(); QString observerName() override { return "SpecificColorSelectorDock"; } /// reimplemented from KoCanvasObserverBase/KisMainwindowObserver void setCanvas(KoCanvasBase *canvas) override; void unsetCanvas() override; void setViewManager(KisViewManager* kisview) override; private: QPointer m_canvas; KisViewManager *m_view; KisSpecificColorSelectorWidget* m_colorSelector; }; #endif diff --git a/plugins/dockers/tasksetdocker/taskset_resource.cpp b/plugins/dockers/tasksetdocker/taskset_resource.cpp index f61a2835f3..ca6a81ede1 100644 --- a/plugins/dockers/tasksetdocker/taskset_resource.cpp +++ b/plugins/dockers/tasksetdocker/taskset_resource.cpp @@ -1,128 +1,129 @@ /* * Copyright (c) 2011 Sven Langkamp * * 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. + * the Free Software Foundation; 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 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 "taskset_resource.h" #include #include #include #include #include #include #define TASKSET_VERSION 1 TasksetResource::TasksetResource(const QString& f) : KoResource(f) { } TasksetResource::~TasksetResource() { } bool TasksetResource::save() { if (filename().isEmpty()) return false; QFile file(filename()); file.open(QIODevice::WriteOnly); bool res = saveToDevice(&file); file.close(); return res; } bool TasksetResource::load() { QString fn = filename(); if (fn.isEmpty()) return false; QFile file(fn); if (file.size() == 0) return false; if (!file.open(QIODevice::ReadOnly)) { warnKrita << "Can't open file " << filename(); return false; } bool res = loadFromDevice(&file); file.close(); return res; } bool TasksetResource::loadFromDevice(QIODevice *dev) { QDomDocument doc; if (!doc.setContent(dev)) { return false; } QDomElement element = doc.documentElement(); setName(element.attribute("name")); QDomNode node = element.firstChild(); while (!node.isNull()) { QDomElement child = node.toElement(); if (!child.isNull() && child.tagName() == "action") { m_actions.append(child.text()); } node = node.nextSibling(); } setValid(true); return true; } QString TasksetResource::defaultFileExtension() const { return QString(".kts"); } void TasksetResource::setActionList(const QStringList actions) { m_actions = actions; } QStringList TasksetResource::actionList() { return m_actions; } bool TasksetResource::saveToDevice(QIODevice *io) const { QDomDocument doc; QDomElement root = doc.createElement("Taskset"); root.setAttribute("name", name() ); root.setAttribute("version", TASKSET_VERSION); Q_FOREACH (const QString& action, m_actions) { QDomElement element = doc.createElement("action"); element.appendChild(doc.createTextNode(action)); root.appendChild(element); } doc.appendChild(root); QTextStream textStream(io); textStream.setCodec("UTF-8"); doc.save(textStream, 4); KoResource::saveToDevice(io); return true; } diff --git a/plugins/dockers/tasksetdocker/taskset_resource.h b/plugins/dockers/tasksetdocker/taskset_resource.h index 39ee14b2e4..5128ccb561 100644 --- a/plugins/dockers/tasksetdocker/taskset_resource.h +++ b/plugins/dockers/tasksetdocker/taskset_resource.h @@ -1,48 +1,49 @@ /* * Copyright (c) 2011 Sven Langkamp * * 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. + * the Free Software Foundation; 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 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 TASKSET_RESOURCE_H #define TASKSET_RESOURCE_H #include #include class TasksetResource : public KoResource { public: TasksetResource(const QString& filename); ~TasksetResource() override; bool load() override; bool loadFromDevice(QIODevice *dev) override; bool save() override; bool saveToDevice(QIODevice* dev) const override; QString defaultFileExtension() const override; void setActionList(const QStringList actions); QStringList actionList(); private: QStringList m_actions; }; #endif // TASKSET_RESOURCE_H diff --git a/plugins/dockers/tasksetdocker/tasksetdocker.cpp b/plugins/dockers/tasksetdocker/tasksetdocker.cpp index 667f8caf49..7d36f07813 100644 --- a/plugins/dockers/tasksetdocker/tasksetdocker.cpp +++ b/plugins/dockers/tasksetdocker/tasksetdocker.cpp @@ -1,77 +1,78 @@ /* * Copyright (c) 2011 Sven Langkamp * * 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. + * the Free Software Foundation; 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 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 "tasksetdocker.h" #include #include #include #include #include "tasksetdocker_dock.h" K_PLUGIN_FACTORY_WITH_JSON(TasksetDockerPluginFactory, "krita_tasksetdocker.json", registerPlugin();) class TasksetDockerDockFactory : public KoDockFactoryBase { public: TasksetDockerDockFactory() { } QString id() const override { return QString( "TasksetDocker" ); } virtual Qt::DockWidgetArea defaultDockWidgetArea() const { return Qt::RightDockWidgetArea; } QDockWidget* createDockWidget() override { TasksetDockerDock * dockWidget = new TasksetDockerDock(); dockWidget->setObjectName(id()); return dockWidget; } DockPosition defaultDockPosition() const override { return DockMinimized; } private: }; TasksetDockerPlugin::TasksetDockerPlugin(QObject *parent, const QVariantList &) : QObject(parent) { KoDockRegistry::instance()->add(new TasksetDockerDockFactory()); } TasksetDockerPlugin::~TasksetDockerPlugin() { } #include "tasksetdocker.moc" diff --git a/plugins/dockers/tasksetdocker/tasksetdocker.h b/plugins/dockers/tasksetdocker/tasksetdocker.h index fbacf0eec4..57dd4893fa 100644 --- a/plugins/dockers/tasksetdocker/tasksetdocker.h +++ b/plugins/dockers/tasksetdocker/tasksetdocker.h @@ -1,36 +1,37 @@ /* * Copyright (c) 2011 Sven Langkamp * * 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. + * the Free Software Foundation; 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 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 TASKSETDOCKER_H #define TASKSETDOCKER_H #include #include /** * Docker showing the channels of the current layer */ class TasksetDockerPlugin : public QObject { Q_OBJECT public: TasksetDockerPlugin(QObject *parent, const QVariantList &); ~TasksetDockerPlugin() override; }; #endif diff --git a/plugins/dockers/tasksetdocker/tasksetdocker_dock.cpp b/plugins/dockers/tasksetdocker/tasksetdocker_dock.cpp index 16f7c0b6b9..b78ff73ee5 100644 --- a/plugins/dockers/tasksetdocker/tasksetdocker_dock.cpp +++ b/plugins/dockers/tasksetdocker/tasksetdocker_dock.cpp @@ -1,241 +1,242 @@ /* * Copyright (c) 2011 Sven Langkamp * * 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. + * the Free Software Foundation; 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 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 "tasksetdocker_dock.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "tasksetmodel.h" class KisTasksetDelegate : public QStyledItemDelegate { public: KisTasksetDelegate(QObject * parent = 0) : QStyledItemDelegate(parent) {} ~KisTasksetDelegate() override {} /// reimplemented QSize sizeHint(const QStyleOptionViewItem & option, const QModelIndex & index) const override { return QSize(QStyledItemDelegate::sizeHint(option, index).width(), qMin(QStyledItemDelegate::sizeHint(option, index).width(), 25)); } }; class KisTasksetResourceDelegate : public QStyledItemDelegate { public: KisTasksetResourceDelegate(QObject * parent = 0) : QStyledItemDelegate(parent) {} ~KisTasksetResourceDelegate() override {} /// reimplemented void paint(QPainter *, const QStyleOptionViewItem &, const QModelIndex &) const override; }; void KisTasksetResourceDelegate::paint(QPainter * painter, const QStyleOptionViewItem & option, const QModelIndex & index) const { if (! index.isValid()) return; TasksetResource* taskset = static_cast(index.internalPointer()); if (option.state & QStyle::State_Selected) { painter->setPen(QPen(option.palette.highlight(), 2.0)); painter->fillRect(option.rect, option.palette.highlight()); painter->setBrush(option.palette.highlightedText()); } else { painter->setBrush(option.palette.text()); } painter->drawText(option.rect.x() + 5, option.rect.y() + painter->fontMetrics().ascent() + 5, taskset->name()); } TasksetDockerDock::TasksetDockerDock( ) : QDockWidget(i18n("Task Sets")), m_canvas(0), m_blocked(false) { QWidget* widget = new QWidget(this); setupUi(widget); m_model = new TasksetModel(this); tasksetView->setModel(m_model); tasksetView->setItemDelegate(new KisTasksetDelegate(this)); recordButton->setIcon(KisIconUtils::loadIcon("media-record")); recordButton->setCheckable(true); clearButton->setIcon(KisIconUtils::loadIcon("edit-delete")); saveButton->setIcon(KisIconUtils::loadIcon("document-save")); saveButton->setEnabled(false); chooserButton->setIcon(KisIconUtils::loadIcon("edit-copy")); m_rserver = new KoResourceServerSimpleConstruction("kis_taskset", "*.kts"); if (!QFileInfo(m_rserver->saveLocation()).exists()) { QDir().mkpath(m_rserver->saveLocation()); } QSharedPointer adapter (new KoResourceServerAdapter(m_rserver)); m_rserver->loadResources(KoResourceServerProvider::blacklistFileNames(m_rserver->fileNames(), m_rserver->blackListedFiles())); m_rserver->loadTags(); KoResourceItemChooser* itemChooser = new KoResourceItemChooser(adapter, this); itemChooser->setItemDelegate(new KisTasksetResourceDelegate(this)); itemChooser->setFixedSize(500, 250); itemChooser->setRowHeight(30); itemChooser->setColumnCount(1); itemChooser->showTaggingBar(true); chooserButton->setPopupWidget(itemChooser); connect(itemChooser, SIGNAL(resourceSelected(KoResource*)), this, SLOT(resourceSelected(KoResource*))); setWidget(widget); connect( tasksetView, SIGNAL(clicked(QModelIndex)), this, SLOT(activated(QModelIndex)) ); connect( recordButton, SIGNAL(toggled(bool)), this, SLOT(recordClicked())); connect( clearButton, SIGNAL(clicked(bool)), this, SLOT(clearClicked())); connect( saveButton, SIGNAL(clicked(bool)), this, SLOT(saveClicked())); } TasksetDockerDock::~TasksetDockerDock() { delete m_rserver; } void TasksetDockerDock::setCanvas(KoCanvasBase * canvas) { if (m_canvas && m_canvas->viewManager()) { m_canvas->viewManager()->actionCollection()->disconnect(this); Q_FOREACH (KXMLGUIClient* client, m_canvas->viewManager()->mainWindow()->childClients()) { client->actionCollection()->disconnect(this); } } m_canvas = dynamic_cast(canvas); } void TasksetDockerDock::unsetCanvas() { m_canvas = 0; m_model->clear(); } void TasksetDockerDock::actionTriggered(QAction* action) { if(action && !action->objectName().isEmpty() && !m_blocked && recordButton->isChecked()) { m_model->addAction(action); saveButton->setEnabled(true); } } void TasksetDockerDock::activated(const QModelIndex& index) { QAction* action = m_model->actionFromIndex(index); m_blocked = true; action->trigger(); m_blocked = false; } void TasksetDockerDock::recordClicked() { if(m_canvas) { KisViewManager* view = m_canvas->viewManager(); connect(view->actionCollection(), SIGNAL(actionTriggered(QAction*)), this, SLOT(actionTriggered(QAction*)), Qt::UniqueConnection); Q_FOREACH (KXMLGUIClient* client, view->mainWindow()->childClients()) { connect(client->actionCollection(), SIGNAL(actionTriggered(QAction*)), this, SLOT(actionTriggered(QAction*)), Qt::UniqueConnection); } } } void TasksetDockerDock::saveClicked() { bool ok; QString name = QInputDialog::getText(this, i18n("Taskset Name"), i18n("Name:"), QLineEdit::Normal, QString(), &ok); if (!ok) { return; } TasksetResource* taskset = new TasksetResource(QString()); QStringList actionNames; Q_FOREACH (QAction* action, m_model->actions()) { actionNames.append(action->objectName()); } taskset->setActionList(actionNames); taskset->setValid(true); QString saveLocation = m_rserver->saveLocation(); bool newName = false; if(name.isEmpty()) { newName = true; name = i18n("Taskset"); } QFileInfo fileInfo(saveLocation + name + taskset->defaultFileExtension()); int i = 1; while (fileInfo.exists()) { fileInfo.setFile(saveLocation + name + QString("%1").arg(i) + taskset->defaultFileExtension()); i++; } taskset->setFilename(fileInfo.filePath()); if(newName) { name = i18n("Taskset %1", i); } taskset->setName(name); m_rserver->addResource(taskset); } void TasksetDockerDock::clearClicked() { saveButton->setEnabled(false); m_model->clear(); } void TasksetDockerDock::resourceSelected(KoResource* resource) { if(!m_canvas) { return; } m_model->clear(); saveButton->setEnabled(true); Q_FOREACH (const QString& actionName, static_cast(resource)->actionList()) { QAction* action = m_canvas->viewManager()->actionCollection()->action(actionName); if(action) { m_model->addAction(action); } } } diff --git a/plugins/dockers/tasksetdocker/tasksetdocker_dock.h b/plugins/dockers/tasksetdocker/tasksetdocker_dock.h index 68efa9ccf3..6aecd2c25a 100644 --- a/plugins/dockers/tasksetdocker/tasksetdocker_dock.h +++ b/plugins/dockers/tasksetdocker/tasksetdocker_dock.h @@ -1,61 +1,62 @@ /* * Copyright (c) 2011 Sven Langkamp * * 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. + * the Free Software Foundation; 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 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 TASKSETDOCKER_DOCK_H #define TASKSETDOCKER_DOCK_H #include #include #include #include #include #include #include "taskset_resource.h" #include "ui_wdgtasksetdocker.h" class TasksetModel; class TasksetDockerDock : public QDockWidget, public KoCanvasObserverBase, public Ui_WdgTasksetDocker { Q_OBJECT public: TasksetDockerDock(); ~TasksetDockerDock() override; QString observerName() override { return "TasksetDockerDock"; } void setCanvas(KoCanvasBase *canvas) override; void unsetCanvas() override; private Q_SLOTS: void actionTriggered(QAction* action); void activated (const QModelIndex& index); void recordClicked(); void saveClicked(); void clearClicked(); void resourceSelected( KoResource * resource ); private: QPointer m_canvas; TasksetModel *m_model; bool m_blocked; KoResourceServer* m_rserver; }; #endif diff --git a/plugins/dockers/tasksetdocker/tasksetmodel.cpp b/plugins/dockers/tasksetdocker/tasksetmodel.cpp index 26661e1301..a95f09fff5 100644 --- a/plugins/dockers/tasksetdocker/tasksetmodel.cpp +++ b/plugins/dockers/tasksetdocker/tasksetmodel.cpp @@ -1,102 +1,103 @@ /* * Copyright (c) 2011 Sven Langkamp * * 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. + * the Free Software Foundation; 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 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 "tasksetmodel.h" #include #include #include TasksetModel::TasksetModel(QObject* parent): QAbstractTableModel(parent) { } TasksetModel::~TasksetModel() { } QVariant TasksetModel::data(const QModelIndex& index, int role) const { if (index.isValid()) { switch (role) { case Qt::DisplayRole: { return m_actions.at(index.row())->iconText(); } case Qt::DecorationRole: { const QIcon icon = m_actions.at(index.row())->icon(); if (icon.isNull()) { return KisIconUtils::loadIcon("tools-wizard"); } return icon; } } } return QVariant(); } QVariant TasksetModel::headerData(int /*section*/, Qt::Orientation /*orientation*/, int /*role*/) const { return i18n("Task"); } int TasksetModel::rowCount(const QModelIndex& /*parent*/) const { return m_actions.count(); } int TasksetModel::columnCount(const QModelIndex& /*parent*/) const { return 1; } Qt::ItemFlags TasksetModel::flags(const QModelIndex& /*index*/) const { Qt::ItemFlags flags = /*Qt::ItemIsSelectable |*/ Qt::ItemIsEnabled; return flags; } void TasksetModel::addAction(QAction* action) { m_actions.append(action); beginResetModel(); endResetModel(); } QVector< QAction* > TasksetModel::actions() { return m_actions; } QAction* TasksetModel::actionFromIndex(const QModelIndex& index) { if(index.isValid()) { return m_actions.at(index.row()); } return 0; } void TasksetModel::clear() { m_actions.clear(); beginResetModel(); endResetModel(); } diff --git a/plugins/dockers/tasksetdocker/tasksetmodel.h b/plugins/dockers/tasksetdocker/tasksetmodel.h index 524d75ad28..c8ac1c2af1 100644 --- a/plugins/dockers/tasksetdocker/tasksetmodel.h +++ b/plugins/dockers/tasksetdocker/tasksetmodel.h @@ -1,49 +1,50 @@ /* * Copyright (c) 2011 Sven Langkamp * * 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. + * the Free Software Foundation; 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 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 TASKSETMODEL_H #define TASKSETMODEL_H #include #include class QAction; class TasksetModel : public QAbstractTableModel { Q_OBJECT public: TasksetModel(QObject* parent = 0); ~TasksetModel() override; QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const override; QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const override; int rowCount(const QModelIndex& parent = QModelIndex()) const override; int columnCount(const QModelIndex& parent = QModelIndex()) const override; Qt::ItemFlags flags(const QModelIndex& index) const override; void addAction(QAction* action); QAction* actionFromIndex(const QModelIndex& index); QVector actions(); public Q_SLOTS: void clear(); private: QVector m_actions; }; #endif // TASKSETMODEL_H diff --git a/plugins/dockers/throttle/Throttle.h b/plugins/dockers/throttle/Throttle.h index 84e7a0a9b9..64af3f6b62 100644 --- a/plugins/dockers/throttle/Throttle.h +++ b/plugins/dockers/throttle/Throttle.h @@ -1,61 +1,62 @@ /* * Copyright (c) 2017 Boudewijn Rempt * * 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. + * the Free Software Foundation; 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 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 THROTTLE_H #define THROTTLE_H #include class KisCanvas2; class KisSignalCompressor; class ThreadManager : public QObject { Q_OBJECT Q_PROPERTY(int threadCount READ threadCount WRITE setThreadCount NOTIFY threadCountChanged) Q_PROPERTY(int maxThreadCount READ maxThreadCount) public: ThreadManager(QObject *parent = 0); ~ThreadManager() override; void setThreadCount(int threadCount); int threadCount() const; int maxThreadCount() const; private Q_SLOTS: void slotDoUpdateConfig(); Q_SIGNALS: void threadCountChanged(); private: int m_threadCount = 0; KisSignalCompressor *m_configUpdateCompressor; }; class Throttle : public QQuickWidget { Q_OBJECT public: Throttle(QWidget *parent); ~Throttle() override; private: ThreadManager *m_threadManager {0}; }; #endif diff --git a/plugins/dockers/throttle/ThrottlePlugin.h b/plugins/dockers/throttle/ThrottlePlugin.h index 3fb02c1868..2b3d0d16eb 100644 --- a/plugins/dockers/throttle/ThrottlePlugin.h +++ b/plugins/dockers/throttle/ThrottlePlugin.h @@ -1,49 +1,50 @@ /* * Copyright (c) 2017 Boudewijn Rempt * * 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. + * the Free Software Foundation; 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 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 THROTTLEPLUGIN_H #define THROTTLEPLUGIN_H #include #include #include #include #include class Throttle; class BasicDocker : public QDockWidget, public KoCanvasObserverBase { Q_OBJECT public: BasicDocker() : QDockWidget(i18n("CPU Throttle")) {} ~BasicDocker() override {} QString observerName() override { return "ThrottleDocker"; } void setCanvas(KoCanvasBase *) override {} void unsetCanvas() override {} }; class ThrottlePlugin : public QObject { Q_OBJECT public: ThrottlePlugin(QObject *parent, const QVariantList &); ~ThrottlePlugin() override; }; #endif diff --git a/plugins/dockers/touchdocker/TouchDockerDock.cpp b/plugins/dockers/touchdocker/TouchDockerDock.cpp index 281e087913..c81463d8a5 100644 --- a/plugins/dockers/touchdocker/TouchDockerDock.cpp +++ b/plugins/dockers/touchdocker/TouchDockerDock.cpp @@ -1,428 +1,429 @@ /* * Copyright (c) 2017 Boudewijn Rempt * * 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. + * the Free Software Foundation; 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 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 "TouchDockerDock.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 #include #include namespace { bool shouldSetAcceptTouchEvents() { // See https://bugreports.qt.io/browse/QTBUG-66718 static QVersionNumber qtVersion = QVersionNumber::fromString(qVersion()); static bool retval = qtVersion > QVersionNumber(5, 9, 3) && qtVersion.normalized() != QVersionNumber(5, 10); return retval; } } // namespace class TouchDockerDock::Private { public: Private() { } TouchDockerDock *q; bool allowClose {true}; KisSketchView *sketchView {0}; QString currentSketchPage; KoDialog *openDialog {0}; KoDialog *saveAsDialog {0}; QMap buttonMapping; bool shiftOn {false}; bool ctrlOn {false}; bool altOn {false}; }; TouchDockerDock::TouchDockerDock() : QDockWidget(i18n("Touch Docker")) , d(new Private()) { QStringList defaultMapping = QStringList() << "decrease_opacity" << "increase_opacity" << "make_brush_color_lighter" << "make_brush_color_darker" << "decrease_brush_size" << "increase_brush_size" << "previous_preset" << "clear"; QStringList mapping = KisConfig(true).readEntry("touchdockermapping", defaultMapping.join(',')).split(','); for (int i = 0; i < 8; ++i) { if (i < mapping.size()) { d->buttonMapping[QString("button%1").arg(i + 1)] = mapping[i]; } else if (i < defaultMapping.size()) { d->buttonMapping[QString("button%1").arg(i + 1)] = defaultMapping[i]; } } m_quickWidget = new QQuickWidget(this); if (shouldSetAcceptTouchEvents()) { m_quickWidget->setAttribute(Qt::WA_AcceptTouchEvents); } setWidget(m_quickWidget); setEnabled(true); m_quickWidget->engine()->rootContext()->setContextProperty("mainWindow", this); m_quickWidget->engine()->addImportPath(KoResourcePaths::getApplicationRoot() + "/lib/qml/"); m_quickWidget->engine()->addImportPath(KoResourcePaths::getApplicationRoot() + "/lib64/qml/"); m_quickWidget->engine()->addPluginPath(KoResourcePaths::getApplicationRoot() + "/lib/qml/"); m_quickWidget->engine()->addPluginPath(KoResourcePaths::getApplicationRoot() + "/lib64/qml/"); Settings *settings = new Settings(this); DocumentManager::instance()->setSettingsManager(settings); m_quickWidget->engine()->rootContext()->setContextProperty("Settings", settings); Theme *theme = Theme::load(KSharedConfig::openConfig()->group("General").readEntry("theme", "default"), m_quickWidget->engine()); if (theme) { settings->setTheme(theme); } m_quickWidget->setResizeMode(QQuickWidget::SizeRootObjectToView); m_quickWidget->setSource(QUrl("qrc:/touchstrip.qml")); } TouchDockerDock::~TouchDockerDock() { } bool TouchDockerDock::allowClose() const { return d->allowClose; } void TouchDockerDock::setAllowClose(bool allow) { d->allowClose = allow; } QString TouchDockerDock::currentSketchPage() const { return d->currentSketchPage; } void TouchDockerDock::setCurrentSketchPage(QString newPage) { d->currentSketchPage = newPage; emit currentSketchPageChanged(); } void TouchDockerDock::closeEvent(QCloseEvent* event) { if (!d->allowClose) { event->ignore(); emit closeRequested(); } else { event->accept(); } } void TouchDockerDock::slotButtonPressed(const QString &id) { if (id == "fileOpenButton") { showFileOpenDialog(); } else if (id == "fileSaveButton" && m_canvas && m_canvas->viewManager() && m_canvas->viewManager()->document()) { bool batchMode = m_canvas->viewManager()->document()->fileBatchMode(); m_canvas->viewManager()->document()->setFileBatchMode(true); m_canvas->viewManager()->document()->save(true, 0); m_canvas->viewManager()->document()->setFileBatchMode(batchMode); } else if (id == "fileSaveAsButton" && m_canvas && m_canvas->viewManager() && m_canvas->viewManager()->document()) { showFileSaveAsDialog(); } else { QAction *a = action(id); if (a) { if (a->isCheckable()) { a->toggle(); } else { a->trigger(); } } else if (id == "shift") { // set shift state for the next pointer event, somehow QKeyEvent event(d->shiftOn ? QEvent::KeyRelease : QEvent::KeyPress, 0, Qt::ShiftModifier); QApplication::sendEvent(KisPart::instance()->currentMainwindow(), &event); d->shiftOn = !d->shiftOn; } else if (id == "ctrl") { // set ctrl state for the next pointer event, somehow QKeyEvent event(d->ctrlOn ? QEvent::KeyRelease : QEvent::KeyPress, 0, Qt::ControlModifier); QApplication::sendEvent(KisPart::instance()->currentMainwindow(), &event); d->ctrlOn = !d->ctrlOn; } else if (id == "alt") { // set alt state for the next pointer event, somehow QKeyEvent event(d->altOn ? QEvent::KeyRelease : QEvent::KeyPress, 0, Qt::AltModifier); QApplication::sendEvent(KisPart::instance()->currentMainwindow(), &event); d->altOn = !d->altOn; } } } void TouchDockerDock::slotOpenImage(QString path) { if (d->openDialog) { d->openDialog->accept(); } KisPart::instance()->currentMainwindow()->openDocument(QUrl::fromLocalFile(path), KisMainWindow::None); } void TouchDockerDock::slotSaveAs(QString path, QString mime) { if (d->saveAsDialog) { d->saveAsDialog->accept(); } m_canvas->viewManager()->document()->saveAs(QUrl::fromLocalFile(path), mime.toLatin1(), true); m_canvas->viewManager()->document()->waitForSavingToComplete(); } void TouchDockerDock::hideFileOpenDialog() { if (d->openDialog) { d->openDialog->accept(); } } void TouchDockerDock::hideFileSaveAsDialog() { if (d->saveAsDialog) { d->saveAsDialog->accept(); } } QString TouchDockerDock::imageForButton(QString id) { if (d->buttonMapping.contains(id)) { id = d->buttonMapping[id]; } if (KisActionRegistry::instance()->hasAction(id)) { QString a = KisActionRegistry::instance()->getActionProperty(id, "icon"); if (!a.isEmpty()) { return "image://icon/" + a; } } return QString(); } QString TouchDockerDock::textForButton(QString id) { if (d->buttonMapping.contains(id)) { id = d->buttonMapping[id]; } if (KisActionRegistry::instance()->hasAction(id)) { QString a = KisActionRegistry::instance()->getActionProperty(id, "iconText"); if (a.isEmpty()) { a = KisActionRegistry::instance()->getActionProperty(id, "text"); } return a; } return id; } QAction *TouchDockerDock::action(QString id) const { if (m_canvas && m_canvas->viewManager()) { if (d->buttonMapping.contains(id)) { id = d->buttonMapping[id]; } return m_canvas->viewManager()->actionManager()->actionByName(id); } return 0; } void TouchDockerDock::showFileOpenDialog() { if (!d->openDialog) { d->openDialog = createDialog("qrc:/opendialog.qml"); } d->openDialog->exec(); } void TouchDockerDock::showFileSaveAsDialog() { if (!d->saveAsDialog) { d->saveAsDialog = createDialog("qrc:/saveasdialog.qml"); } d->saveAsDialog->exec(); } void TouchDockerDock::changeEvent(QEvent *event) { if (event->type() == QEvent::PaletteChange) { m_quickWidget->setSource(QUrl("qrc:/touchstrip.qml")); event->accept(); } else { event->ignore(); } } void TouchDockerDock::tabletEvent(QTabletEvent *event) { #ifdef Q_OS_WIN /** * On Windows (only in WinInk mode), unless we accept the tablet event, * OS will start windows gestures, like click+hold for right click. * It will block any mouse events generation. * * In our own (hacky) implementation, if we accept the event, we block * the gesture, but still generate a fake mouse event. */ event->accept(); #else QDockWidget::tabletEvent(event); #endif } KoDialog *TouchDockerDock::createDialog(const QString qml) { KoDialog *dlg = new KoDialog(this); dlg->setButtons(KoDialog::None); QQuickWidget *quickWidget = new QQuickWidget(this); if (shouldSetAcceptTouchEvents()) { quickWidget->setAttribute(Qt::WA_AcceptTouchEvents); } dlg->setMainWidget(quickWidget); setEnabled(true); quickWidget->engine()->rootContext()->setContextProperty("mainWindow", this); quickWidget->engine()->addImportPath(KoResourcePaths::getApplicationRoot() + "/lib/qml/"); quickWidget->engine()->addImportPath(KoResourcePaths::getApplicationRoot() + "/lib64/qml/"); quickWidget->engine()->addPluginPath(KoResourcePaths::getApplicationRoot() + "/lib/qml/"); quickWidget->engine()->addPluginPath(KoResourcePaths::getApplicationRoot() + "/lib64/qml/"); Settings *settings = new Settings(this); DocumentManager::instance()->setSettingsManager(settings); quickWidget->engine()->rootContext()->setContextProperty("Settings", settings); Theme *theme = Theme::load(KSharedConfig::openConfig()->group("General").readEntry("theme", "default"), quickWidget->engine()); settings->setTheme(theme); quickWidget->setSource(QUrl(qml)); quickWidget->setResizeMode(QQuickWidget::SizeRootObjectToView); dlg->setMinimumSize(1280, 768); return dlg; } QObject *TouchDockerDock::sketchKisView() const { return d->sketchView; } void TouchDockerDock::setSketchKisView(QObject* newView) { if (d->sketchView) { d->sketchView->disconnect(this); } if (d->sketchView != newView) { d->sketchView = qobject_cast(newView); emit sketchKisViewChanged(); } } void TouchDockerDock::setCanvas(KoCanvasBase *canvas) { setEnabled(true); if (m_canvas == canvas) { return; } if (m_canvas) { m_canvas->disconnectCanvasObserver(this); } if (!canvas) { m_canvas = 0; return; } m_canvas = dynamic_cast(canvas); } void TouchDockerDock::unsetCanvas() { setEnabled(true); m_canvas = 0; } diff --git a/plugins/dockers/touchdocker/TouchDockerDock.h b/plugins/dockers/touchdocker/TouchDockerDock.h index 478bc0c530..058b1d265b 100644 --- a/plugins/dockers/touchdocker/TouchDockerDock.h +++ b/plugins/dockers/touchdocker/TouchDockerDock.h @@ -1,93 +1,94 @@ /* * Copyright (c) 2017 Boudewijn Rempt * * 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. + * the Free Software Foundation; 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 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 TOUCHDOCKER_DOCK_H #define TOUCHDOCKER_DOCK_H #include #include #include #include #include class KoDialog; class QQuickWidget; class TouchDockerDock : public QDockWidget, public KoCanvasObserverBase { Q_OBJECT Q_PROPERTY(bool allowClose READ allowClose WRITE setAllowClose) Q_PROPERTY(QString currentSketchPage READ currentSketchPage WRITE setCurrentSketchPage NOTIFY currentSketchPageChanged) Q_PROPERTY(QObject* sketchKisView READ sketchKisView WRITE setSketchKisView NOTIFY sketchKisViewChanged) public: TouchDockerDock(); ~TouchDockerDock() override; QString observerName() override { return "TouchDockerDock"; } void setCanvas(KoCanvasBase *canvas) override; void unsetCanvas() override; bool allowClose() const; void setAllowClose(bool allow); QString currentSketchPage() const; void setCurrentSketchPage(QString newPage); QObject *sketchKisView() const; void setSketchKisView(QObject *newView); virtual void closeEvent(QCloseEvent *event); Q_SIGNALS: void closeRequested(); void currentSketchPageChanged(); void sketchKisViewChanged(); public Q_SLOTS: void slotButtonPressed(const QString &id); void slotOpenImage(QString path); void slotSaveAs(QString path, QString mime); void hideFileOpenDialog(); void hideFileSaveAsDialog(); QString imageForButton(QString id); QString textForButton(QString id); QAction *action(QString id) const; private: void showFileOpenDialog(); void showFileSaveAsDialog(); void changeEvent(QEvent* event) override; void tabletEvent(QTabletEvent *event) override; KoDialog *createDialog(const QString qml); QPointer m_canvas; QQuickWidget *m_quickWidget {0}; class Private; const QScopedPointer d; }; #endif diff --git a/plugins/dockers/touchdocker/TouchDockerPlugin.cpp b/plugins/dockers/touchdocker/TouchDockerPlugin.cpp index ef16fc8ee5..97bdf0200b 100644 --- a/plugins/dockers/touchdocker/TouchDockerPlugin.cpp +++ b/plugins/dockers/touchdocker/TouchDockerPlugin.cpp @@ -1,77 +1,78 @@ /* * Copyright (c) 2017 Boudewijn Rempt * * 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. + * the Free Software Foundation; 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 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 "TouchDockerPlugin.h" #include #include #include #include #include "kis_config.h" #include "kis_types.h" #include "KisViewManager.h" #include "TouchDockerDock.h" #include K_PLUGIN_FACTORY_WITH_JSON(TouchDockerPluginFactory, "krita_touchdocker.json", registerPlugin();) class TouchDockerDockFactory : public KoDockFactoryBase { public: TouchDockerDockFactory() { } QString id() const override { return QString( "TouchDocker" ); } virtual Qt::DockWidgetArea defaultDockWidgetArea() const { return Qt::RightDockWidgetArea; } QDockWidget* createDockWidget() override { TouchDockerDock * dockWidget = new TouchDockerDock(); dockWidget->setObjectName(id()); return dockWidget; } DockPosition defaultDockPosition() const override { return DockMinimized; } }; TouchDockerPlugin::TouchDockerPlugin(QObject *parent, const QVariantList &) : QObject(parent) { KoDockRegistry::instance()->add(new TouchDockerDockFactory()); } TouchDockerPlugin::~TouchDockerPlugin() { } #include "TouchDockerPlugin.moc" diff --git a/plugins/dockers/touchdocker/TouchDockerPlugin.h b/plugins/dockers/touchdocker/TouchDockerPlugin.h index fc120672dc..73c38764c7 100644 --- a/plugins/dockers/touchdocker/TouchDockerPlugin.h +++ b/plugins/dockers/touchdocker/TouchDockerPlugin.h @@ -1,32 +1,33 @@ /* * Copyright (c) 2017 Boudewijn Rempt * * 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. + * the Free Software Foundation; 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 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 TOUCHDOCKERPLUGIN_H #define TOUCHDOCKERPLUGIN_H #include #include class TouchDockerPlugin : public QObject { Q_OBJECT public: TouchDockerPlugin(QObject *parent, const QVariantList &); ~TouchDockerPlugin() override; }; #endif diff --git a/plugins/filters/dodgeburn/DodgeBurn.cpp b/plugins/filters/dodgeburn/DodgeBurn.cpp index 322f767ba4..f5526f255c 100644 --- a/plugins/filters/dodgeburn/DodgeBurn.cpp +++ b/plugins/filters/dodgeburn/DodgeBurn.cpp @@ -1,112 +1,113 @@ /* * Copyright (c) 2009 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. + * the Free Software Foundation; 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 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 "DodgeBurn.h" #include #include #include #include "ui_DodgeBurnConfigurationBaseWidget.h" KisFilterDodgeBurn::KisFilterDodgeBurn(const QString& id, const QString& prefix, const QString& name ) : KisColorTransformationFilter(KoID(id, name), FiltersCategoryAdjustId, name), m_prefix(prefix) { setColorSpaceIndependence(FULLY_INDEPENDENT); setSupportsPainting(true); } KisConfigWidget * KisFilterDodgeBurn::createConfigurationWidget(QWidget* parent, const KisPaintDeviceSP dev, bool) const { Q_UNUSED(dev); return new KisDodgeBurnConfigWidget(parent, id()); } KoColorTransformation* KisFilterDodgeBurn::createTransformation(const KoColorSpace* cs, const KisFilterConfigurationSP config) const { QHash params; QString suffix = "Midtones"; if (config) { params["exposure"] = config->getDouble("exposure", 0.5); int type = config->getInt("type", KisFilterDodgeBurn::MIDTONES); switch(type) { case KisFilterDodgeBurn::HIGHLIGHTS: suffix = "Highlights"; break; case KisFilterDodgeBurn::SHADOWS: suffix = "Shadows"; break; default: break; } } return cs->createColorTransformation(m_prefix + suffix, params); } KisDodgeBurnConfigWidget::KisDodgeBurnConfigWidget(QWidget * parent, const QString& id) : KisConfigWidget(parent), m_id(id) { m_page = new Ui_DodgeBurnConfigurationBaseWidget(); m_page->setupUi(this); connect(m_page->radioButtonHighlights, SIGNAL(toggled(bool)), SIGNAL(sigConfigurationItemChanged())); connect(m_page->radioButtonMidtones, SIGNAL(toggled(bool)), SIGNAL(sigConfigurationItemChanged())); connect(m_page->radioButtonShadows, SIGNAL(toggled(bool)), SIGNAL(sigConfigurationItemChanged())); connect(m_page->sliderExposure, SIGNAL(valueChanged(int)), SIGNAL(sigConfigurationItemChanged())); } KisDodgeBurnConfigWidget::~KisDodgeBurnConfigWidget() { delete m_page; } KisPropertiesConfigurationSP KisDodgeBurnConfigWidget::configuration() const { KisColorTransformationConfigurationSP c = new KisColorTransformationConfiguration(m_id, 0); int type = 0; if(m_page->radioButtonHighlights->isChecked()) { type = KisFilterDodgeBurn::HIGHLIGHTS; } else if(m_page->radioButtonShadows->isChecked()) { type = KisFilterDodgeBurn::SHADOWS; } else { type = KisFilterDodgeBurn::MIDTONES; } c->setProperty("type", type); c->setProperty("exposure", m_page->sliderExposure->value() / 100.0); return c; } void KisDodgeBurnConfigWidget::setConfiguration(const KisPropertiesConfigurationSP config) { int type = config->getInt("type", KisFilterDodgeBurn::MIDTONES); switch(type) { case KisFilterDodgeBurn::HIGHLIGHTS: m_page->radioButtonHighlights->setChecked(true); break; case KisFilterDodgeBurn::SHADOWS: m_page->radioButtonShadows->setChecked(true); break; default: case KisFilterDodgeBurn::MIDTONES: m_page->radioButtonMidtones->setChecked(true); break; } m_page->sliderExposure->setValue(config->getDouble("exposure", 0.5) * 100); } diff --git a/plugins/filters/dodgeburn/DodgeBurn.h b/plugins/filters/dodgeburn/DodgeBurn.h index 06dc1fa757..b7123ca13c 100644 --- a/plugins/filters/dodgeburn/DodgeBurn.h +++ b/plugins/filters/dodgeburn/DodgeBurn.h @@ -1,58 +1,59 @@ /* * Copyright (c) 2009 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. + * the Free Software Foundation; 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 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 DODGE_BURN_H #define DODGE_BURN_H #include "filter/kis_color_transformation_filter.h" #include "kis_config_widget.h" class KisFilterDodgeBurn : public KisColorTransformationFilter { public: enum Type { SHADOWS, MIDTONES, HIGHLIGHTS }; public: KisFilterDodgeBurn(const QString& id, const QString& prefix, const QString& name ); public: KoColorTransformation* createTransformation(const KoColorSpace* cs, const KisFilterConfigurationSP config) const override; KisConfigWidget * createConfigurationWidget(QWidget* parent, const KisPaintDeviceSP dev, bool useForMasks) const override; private: QString m_prefix; }; class Ui_DodgeBurnConfigurationBaseWidget; class KisDodgeBurnConfigWidget : public KisConfigWidget { public: KisDodgeBurnConfigWidget(QWidget * parent, const QString& id); ~KisDodgeBurnConfigWidget() override; KisPropertiesConfigurationSP configuration() const override; void setConfiguration(const KisPropertiesConfigurationSP config) override; QString m_id; Ui_DodgeBurnConfigurationBaseWidget * m_page; }; #endif diff --git a/plugins/filters/dodgeburn/DodgeBurnPlugin.cpp b/plugins/filters/dodgeburn/DodgeBurnPlugin.cpp index 4f1dc7d695..942ad93fbe 100644 --- a/plugins/filters/dodgeburn/DodgeBurnPlugin.cpp +++ b/plugins/filters/dodgeburn/DodgeBurnPlugin.cpp @@ -1,38 +1,39 @@ /* * Copyright (c) 2009 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. + * the Free Software Foundation; 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 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 "DodgeBurnPlugin.h" #include #include #include "DodgeBurn.h" K_PLUGIN_FACTORY_WITH_JSON(DodgeBurnPluginFactory, "kritadodgeburn.json", registerPlugin();) DodgeBurnPlugin::DodgeBurnPlugin(QObject *parent, const QVariantList &) { Q_UNUSED(parent); KisFilterRegistry::instance()->add(new KisFilterDodgeBurn("dodge", "Dodge", i18n("Dodge"))); KisFilterRegistry::instance()->add(new KisFilterDodgeBurn("burn", "Burn", i18n("Burn"))); } DodgeBurnPlugin::~DodgeBurnPlugin() { } #include "DodgeBurnPlugin.moc" diff --git a/plugins/filters/dodgeburn/DodgeBurnPlugin.h b/plugins/filters/dodgeburn/DodgeBurnPlugin.h index b039ae9de0..2379e37145 100644 --- a/plugins/filters/dodgeburn/DodgeBurnPlugin.h +++ b/plugins/filters/dodgeburn/DodgeBurnPlugin.h @@ -1,32 +1,33 @@ /* * Copyright (c) 2009 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. + * the Free Software Foundation; 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 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 _DODGE_BURN_PLUGIN_H_ #define _DODGE_BURN_PLUGIN_H_ #include #include class DodgeBurnPlugin : public QObject { Q_OBJECT public: DodgeBurnPlugin(QObject *parent, const QVariantList &); ~DodgeBurnPlugin() override; }; #endif diff --git a/plugins/impex/heightmap/kis_heightmap_export.cpp b/plugins/impex/heightmap/kis_heightmap_export.cpp index bf4554c9a8..cea427fac5 100644 --- a/plugins/impex/heightmap/kis_heightmap_export.cpp +++ b/plugins/impex/heightmap/kis_heightmap_export.cpp @@ -1,149 +1,150 @@ /* * Copyright (c) 2014 Boudewijn Rempt * Copyright (c) 2017 Victor Wåhlström * * 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. + * the Free Software Foundation; 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 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_heightmap_export.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "kis_wdg_options_heightmap.h" #include "kis_heightmap_utils.h" K_PLUGIN_FACTORY_WITH_JSON(KisHeightMapExportFactory, "krita_heightmap_export.json", registerPlugin();) template static void writeData(KisPaintDeviceSP pd, const QRect &bounds, QDataStream &out_stream) { KIS_ASSERT_RECOVER_RETURN(pd); KisSequentialConstIterator it(pd, bounds); while (it.nextPixel()) { out_stream << KoGrayTraits::gray(const_cast(it.rawDataConst())); } } KisHeightMapExport::KisHeightMapExport(QObject *parent, const QVariantList &) : KisImportExportFilter(parent) { } KisHeightMapExport::~KisHeightMapExport() { } KisPropertiesConfigurationSP KisHeightMapExport::defaultConfiguration(const QByteArray &from, const QByteArray &to) const { Q_UNUSED(from); Q_UNUSED(to); KisPropertiesConfigurationSP cfg = new KisPropertiesConfiguration(); cfg->setProperty("endianness", 0); return cfg; } KisConfigWidget *KisHeightMapExport::createConfigurationWidget(QWidget *parent, const QByteArray &from, const QByteArray &to) const { Q_UNUSED(from); Q_UNUSED(to); bool export_mode = true; KisWdgOptionsHeightmap* wdg = new KisWdgOptionsHeightmap(parent, export_mode); return wdg; } void KisHeightMapExport::initializeCapabilities() { if (mimeType() == "image/x-r8") { QList > supportedColorModels; supportedColorModels << QPair() << QPair(GrayAColorModelID, Integer8BitsColorDepthID); addSupportedColorModels(supportedColorModels, "R8 Heightmap"); } else if (mimeType() == "image/x-r16") { QList > supportedColorModels; supportedColorModels << QPair() << QPair(GrayAColorModelID, Integer16BitsColorDepthID); addSupportedColorModels(supportedColorModels, "R16 Heightmap"); } else if (mimeType() == "image/x-r32") { QList > supportedColorModels; supportedColorModels << QPair() << QPair(GrayAColorModelID, Float32BitsColorDepthID); addSupportedColorModels(supportedColorModels, "R32 Heightmap"); } } KisImportExportErrorCode KisHeightMapExport::convert(KisDocument *document, QIODevice *io, KisPropertiesConfigurationSP configuration) { KIS_ASSERT_RECOVER_RETURN_VALUE(mimeType() == "image/x-r16" || mimeType() == "image/x-r8" || mimeType() == "image/x-r32", ImportExportCodes::FileFormatIncorrect); KisImageSP image = document->savingImage(); QDataStream::ByteOrder bo = configuration->getInt("endianness", 1) == 0 ? QDataStream::BigEndian : QDataStream::LittleEndian; KisPaintDeviceSP pd = new KisPaintDevice(*image->projection()); QDataStream s(io); s.setByteOrder(bo); // needed for 32bit float data s.setFloatingPointPrecision(QDataStream::SinglePrecision); KoID target_co_model = GrayAColorModelID; KoID target_co_depth = KisHeightmapUtils::mimeTypeToKoID(mimeType()); KIS_ASSERT(!target_co_depth.id().isNull()); if (pd->colorSpace()->colorModelId() != target_co_model || pd->colorSpace()->colorDepthId() != target_co_depth) { pd = new KisPaintDevice(*pd.data()); pd->convertTo(KoColorSpaceRegistry::instance()->colorSpace(target_co_model.id(), target_co_depth.id())); } if (target_co_depth == Float32BitsColorDepthID) { writeData(pd, image->bounds(), s); } else if (target_co_depth == Integer16BitsColorDepthID) { writeData(pd, image->bounds(), s); } else if (target_co_depth == Integer8BitsColorDepthID) { writeData(pd, image->bounds(), s); } else { KIS_ASSERT_RECOVER_RETURN_VALUE(true, ImportExportCodes::InternalError); return ImportExportCodes::InternalError; } return ImportExportCodes::OK; } #include "kis_heightmap_export.moc" diff --git a/plugins/impex/heightmap/kis_heightmap_export.h b/plugins/impex/heightmap/kis_heightmap_export.h index cf966192c9..0ff29cb890 100644 --- a/plugins/impex/heightmap/kis_heightmap_export.h +++ b/plugins/impex/heightmap/kis_heightmap_export.h @@ -1,41 +1,42 @@ /* * Copyright (c) 2014 Boudewijn Rempt * Copyright (c) 2017 Victor Wåhlström * * 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. + * the Free Software Foundation; 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 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_HeightMap_EXPORT_H_ #define _KIS_HeightMap_EXPORT_H_ #include #include #include class KisHeightMapExport : public KisImportExportFilter { Q_OBJECT public: KisHeightMapExport(QObject *parent, const QVariantList &); ~KisHeightMapExport() override; KisPropertiesConfigurationSP defaultConfiguration(const QByteArray& from = "", const QByteArray& to = "") const override; KisConfigWidget *createConfigurationWidget(QWidget *parent, const QByteArray& from = "", const QByteArray& to = "") const override; void initializeCapabilities() override; KisImportExportErrorCode convert(KisDocument *document, QIODevice *io, KisPropertiesConfigurationSP configuration = 0) override; }; #endif diff --git a/plugins/impex/ora/kis_open_raster_load_context.cpp b/plugins/impex/ora/kis_open_raster_load_context.cpp index 7a073b3426..4b06ac9d48 100644 --- a/plugins/impex/ora/kis_open_raster_load_context.cpp +++ b/plugins/impex/ora/kis_open_raster_load_context.cpp @@ -1,62 +1,63 @@ /* * Copyright (c) 2007 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. + * the Free Software Foundation; 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 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_open_raster_load_context.h" #include #include #include #include #include #include "kis_png_converter.h" KisOpenRasterLoadContext::KisOpenRasterLoadContext(KoStore* _store) : m_store(_store) { } KisImageSP KisOpenRasterLoadContext::loadDeviceData(const QString & filename) { if (m_store->open(filename)) { KoStoreDevice io(m_store); if (!io.open(QIODevice::ReadOnly)) { dbgFile << "Could not open for reading:" << filename; return 0; } KisPNGConverter pngConv(0); pngConv.buildImage(&io); io.close(); m_store->close(); return pngConv.image(); } return 0; } QDomDocument KisOpenRasterLoadContext::loadStack() { m_store->open("stack.xml"); KoStoreDevice io(m_store); QDomDocument doc; doc.setContent(&io, false); io.close(); m_store->close(); return doc; } diff --git a/plugins/impex/ora/kis_open_raster_save_context.cpp b/plugins/impex/ora/kis_open_raster_save_context.cpp index 142a19607b..e9ff568a0d 100644 --- a/plugins/impex/ora/kis_open_raster_save_context.cpp +++ b/plugins/impex/ora/kis_open_raster_save_context.cpp @@ -1,60 +1,61 @@ /* * Copyright (c) 2007 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. + * the Free Software Foundation; 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 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_open_raster_save_context.h" #include #include #include #include #include #include #include #include #include #include "kis_png_converter.h" KisOpenRasterSaveContext::KisOpenRasterSaveContext(KoStore* store) : m_id(0) , m_store(store) { } QString KisOpenRasterSaveContext::saveDeviceData(KisPaintDeviceSP dev, KisMetaData::Store* metaData, const QRect &imageRect, const qreal xRes, const qreal yRes) { QString filename = QString("data/layer%1.png").arg(m_id++); if (KisPNGConverter::saveDeviceToStore(filename, imageRect, xRes, yRes, dev, m_store, metaData)) { return filename; } return ""; } void KisOpenRasterSaveContext::saveStack(const QDomDocument& doc) { if (m_store->open("stack.xml")) { KoStoreDevice io(m_store); io.write(doc.toByteArray()); io.close(); m_store->close(); } else { dbgFile << "Opening of the stack.xml file failed :"; } } diff --git a/plugins/impex/ora/ora_converter.cpp b/plugins/impex/ora/ora_converter.cpp index 1df32a0c15..49667f9058 100644 --- a/plugins/impex/ora/ora_converter.cpp +++ b/plugins/impex/ora/ora_converter.cpp @@ -1,117 +1,118 @@ /* * Copyright (c) 2007 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. + * the Free Software Foundation; 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 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 "ora_converter.h" #include #include #include #include #include #include #include #include #include #include #include #include "kis_png_converter.h" #include "kis_open_raster_load_context.h" #include "kis_open_raster_save_context.h" OraConverter::OraConverter(KisDocument *doc) : m_doc(doc) , m_stop(false) { } OraConverter::~OraConverter() { } KisImportExportErrorCode OraConverter::buildImage(QIODevice *io) { KoStore* store = KoStore::createStore(io, KoStore::Read, "image/openraster", KoStore::Zip); if (!store) { delete store; return ImportExportCodes::Failure; } KisOpenRasterLoadContext olc(store); KisOpenRasterStackLoadVisitor orslv(m_doc->createUndoStore(), &olc); orslv.loadImage(); m_image = orslv.image(); m_activeNodes = orslv.activeNodes(); delete store; return ImportExportCodes::OK; } KisImageSP OraConverter::image() { return m_image; } vKisNodeSP OraConverter::activeNodes() { return m_activeNodes; } KisImportExportErrorCode OraConverter::buildFile(QIODevice *io, KisImageSP image, vKisNodeSP activeNodes) { // Open file for writing KoStore* store = KoStore::createStore(io, KoStore::Write, "image/openraster", KoStore::Zip); if (!store) { delete store; return ImportExportCodes::Failure; } KisOpenRasterSaveContext osc(store); KisOpenRasterStackSaveVisitor orssv(&osc, activeNodes); image->rootLayer()->accept(orssv); if (store->open("Thumbnails/thumbnail.png")) { QSize previewSize = image->bounds().size(); previewSize.scale(QSize(256,256), Qt::KeepAspectRatio); QImage preview = image->convertToQImage(previewSize, 0); KoStoreDevice io(store); if (io.open(QIODevice::WriteOnly)) { preview.save(&io, "PNG"); } io.close(); store->close(); } KisPaintDeviceSP dev = image->projection(); KisPNGConverter::saveDeviceToStore("mergedimage.png", image->bounds(), image->xRes(), image->yRes(), dev, store); delete store; return ImportExportCodes::OK; } void OraConverter::cancel() { m_stop = true; } diff --git a/plugins/impex/ora/ora_converter.h b/plugins/impex/ora/ora_converter.h index 5e1c2f0c27..b215e786e0 100644 --- a/plugins/impex/ora/ora_converter.h +++ b/plugins/impex/ora/ora_converter.h @@ -1,53 +1,54 @@ /* * Copyright (c) 2007 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. + * the Free Software Foundation; 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 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 _ORA_CONVERTER_H_ #define _ORA_CONVERTER_H_ #include #include #include "kis_png_converter.h" #include "kis_types.h" class KisDocument; class OraConverter : public QObject { Q_OBJECT public: OraConverter(KisDocument *doc); ~OraConverter() override; public: KisImportExportErrorCode buildImage(QIODevice *io); KisImportExportErrorCode buildFile(QIODevice *io, KisImageSP image, vKisNodeSP activeNodes); /** * Retrieve the constructed image */ KisImageSP image(); vKisNodeSP activeNodes(); public Q_SLOTS: virtual void cancel(); private: KisImageSP m_image; KisDocument *m_doc; vKisNodeSP m_activeNodes; bool m_stop; }; #endif diff --git a/plugins/impex/ora/ora_export.cc b/plugins/impex/ora/ora_export.cc index e352f63005..8d2d28f714 100644 --- a/plugins/impex/ora/ora_export.cc +++ b/plugins/impex/ora/ora_export.cc @@ -1,117 +1,118 @@ /* * Copyright (c) 2007 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. + * the Free Software Foundation; 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 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 "ora_export.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "ora_converter.h" class KisExternalLayer; K_PLUGIN_FACTORY_WITH_JSON(ExportFactory, "krita_ora_export.json", registerPlugin();) OraExport::OraExport(QObject *parent, const QVariantList &) : KisImportExportFilter(parent) { } OraExport::~OraExport() { } bool hasShapeLayerChild(KisNodeSP node) { if (!node) return false; Q_FOREACH (KisNodeSP child, node->childNodes(QStringList(), KoProperties())) { if (child->inherits("KisShapeLayer") || child->inherits("KisGeneratorLayer") || child->inherits("KisCloneLayer")) { return true; } else { if (hasShapeLayerChild(child)) { return true; } } } return false; } KisImportExportErrorCode OraExport::convert(KisDocument *document, QIODevice *io, KisPropertiesConfigurationSP /*configuration*/) { KisImageSP image = document->savingImage(); Q_CHECK_PTR(image); OraConverter oraConverter(document); KisImportExportErrorCode res = oraConverter.buildFile(io, image, {document->preActivatedNode()}); return res; } void OraExport::initializeCapabilities() { addCapability(KisExportCheckRegistry::instance()->get("MultiLayerCheck")->create(KisExportCheckBase::SUPPORTED)); addCapability(KisExportCheckRegistry::instance()->get("NodeTypeCheck/KisGroupLayer")->create(KisExportCheckBase::SUPPORTED)); addCapability(KisExportCheckRegistry::instance()->get("NodeTypeCheck/KisAdjustmentLayer")->create(KisExportCheckBase::SUPPORTED)); addCapability(KisExportCheckRegistry::instance()->get("sRGBProfileCheck")->create(KisExportCheckBase::SUPPORTED)); addCapability(KisExportCheckRegistry::instance()->get("ColorModelHomogenousCheck")->create(KisExportCheckBase::SUPPORTED)); QList > supportedColorModels; supportedColorModels << QPair() << QPair(RGBAColorModelID, Integer8BitsColorDepthID) << QPair(RGBAColorModelID, Integer16BitsColorDepthID) << QPair(GrayAColorModelID, Integer8BitsColorDepthID) << QPair(GrayAColorModelID, Integer16BitsColorDepthID); addSupportedColorModels(supportedColorModels, "OpenRaster"); } QString OraExport::verify(const QString &fileName) const { QString error = KisImportExportFilter::verify(fileName); if (error.isEmpty()) { return KisImportExportFilter::verifyZiPBasedFiles(fileName, QStringList() << "mimetype" << "stack.xml" << "mergedimage.png"); } return error; } #include diff --git a/plugins/impex/ora/ora_export.h b/plugins/impex/ora/ora_export.h index a9e1a657d3..896d8fbf1a 100644 --- a/plugins/impex/ora/ora_export.h +++ b/plugins/impex/ora/ora_export.h @@ -1,37 +1,38 @@ /* * Copyright (c) 2007 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. + * the Free Software Foundation; 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 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 _ORA_EXPORT_H_ #define _ORA_EXPORT_H_ #include #include class OraExport : public KisImportExportFilter { Q_OBJECT public: OraExport(QObject *parent, const QVariantList &); ~OraExport() override; public: KisImportExportErrorCode convert(KisDocument *document, QIODevice *io, KisPropertiesConfigurationSP configuration = 0) override; void initializeCapabilities() override; QString verify(const QString &fileName) const override; }; #endif diff --git a/plugins/impex/ora/ora_import.cc b/plugins/impex/ora/ora_import.cc index 2d49dee39c..d558a1d3de 100644 --- a/plugins/impex/ora/ora_import.cc +++ b/plugins/impex/ora/ora_import.cc @@ -1,52 +1,53 @@ /* * Copyright (c) 2007 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. + * the Free Software Foundation; 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 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 "ora_import.h" #include #include #include #include #include "ora_converter.h" K_PLUGIN_FACTORY_WITH_JSON(ImportFactory, "krita_ora_import.json", registerPlugin();) OraImport::OraImport(QObject *parent, const QVariantList &) : KisImportExportFilter(parent) { } OraImport::~OraImport() { } KisImportExportErrorCode OraImport::convert(KisDocument *document, QIODevice *io, KisPropertiesConfigurationSP /*configuration*/) { OraConverter oraConverter(document); KisImportExportErrorCode result = oraConverter.buildImage(io); if (result.isOk()) { document->setCurrentImage(oraConverter.image()); if (oraConverter.activeNodes().size() > 0) { document->setPreActivatedNode(oraConverter.activeNodes()[0]); } } return result; } #include diff --git a/plugins/impex/ora/ora_import.h b/plugins/impex/ora/ora_import.h index 7e8b434752..56f26ab538 100644 --- a/plugins/impex/ora/ora_import.h +++ b/plugins/impex/ora/ora_import.h @@ -1,35 +1,36 @@ /* * Copyright (c) 2007 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. + * the Free Software Foundation; 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 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 ORA_IMPORT_H_ #define ORA_IMPORT_H_ #include #include class OraImport : public KisImportExportFilter { Q_OBJECT public: OraImport(QObject *parent, const QVariantList &); ~OraImport() override; public: KisImportExportErrorCode convert(KisDocument *document, QIODevice *io, KisPropertiesConfigurationSP configuration = 0) override; }; #endif diff --git a/plugins/impex/ppm/kis_ppm_export.cpp b/plugins/impex/ppm/kis_ppm_export.cpp index 9dcb24478a..e76bccd566 100644 --- a/plugins/impex/ppm/kis_ppm_export.cpp +++ b/plugins/impex/ppm/kis_ppm_export.cpp @@ -1,316 +1,317 @@ /* * Copyright (c) 2009 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. + * the Free Software Foundation; 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 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_ppm_export.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "kis_iterator_ng.h" #include K_PLUGIN_FACTORY_WITH_JSON(KisPPMExportFactory, "krita_ppm_export.json", registerPlugin();) KisPPMExport::KisPPMExport(QObject *parent, const QVariantList &) : KisImportExportFilter(parent) { } KisPPMExport::~KisPPMExport() { } class KisPPMFlow { public: KisPPMFlow() { } virtual ~KisPPMFlow() { } virtual void writeBool(quint8 v) = 0; virtual void writeBool(quint16 v) = 0; virtual void writeNumber(quint8 v) = 0; virtual void writeNumber(quint16 v) = 0; virtual void flush() = 0; private: }; class KisPPMAsciiFlow : public KisPPMFlow { public: KisPPMAsciiFlow(QIODevice* device) : m_device(device) { } ~KisPPMAsciiFlow() override { } void writeBool(quint8 v) override { if (v > 127) { m_device->write("1 "); } else { m_device->write("0 "); } } void writeBool(quint16 v) override { writeBool(quint8(v >> 8)); } void writeNumber(quint8 v) override { m_device->write(QByteArray::number(v)); m_device->write(" "); } void writeNumber(quint16 v) override { m_device->write(QByteArray::number(v)); m_device->write(" "); } void flush() override { } private: QIODevice* m_device; }; class KisPPMBinaryFlow : public KisPPMFlow { public: KisPPMBinaryFlow(QIODevice* device) : m_device(device), m_pos(0), m_current(0) { } ~KisPPMBinaryFlow() override { } void writeBool(quint8 v) override { m_current = m_current << 1; m_current |= (v > 127); ++m_pos; if (m_pos >= 8) { m_current = 0; m_pos = 0; flush(); } } void writeBool(quint16 v) override { writeBool(quint8(v >> 8)); } void writeNumber(quint8 v) override { m_device->write((char*)&v, 1); } void writeNumber(quint16 v) override { quint16 vo = qToBigEndian(v); m_device->write((char*)&vo, 2); } void flush() override { m_device->write((char*)&m_current, 1); } private: QIODevice* m_device; int m_pos; quint8 m_current; }; KisImportExportErrorCode KisPPMExport::convert(KisDocument *document, QIODevice *io, KisPropertiesConfigurationSP configuration) { bool rgb = (mimeType() == "image/x-portable-pixmap"); bool binary = (configuration->getInt("type") == 0); bool bitmap = (mimeType() == "image/x-portable-bitmap"); KisImageSP image = document->savingImage(); KisPaintDeviceSP pd = new KisPaintDevice(*image->projection()); // Test color space if (((rgb && (pd->colorSpace()->id() != "RGBA" && pd->colorSpace()->id() != "RGBA16")) || (!rgb && (pd->colorSpace()->id() != "GRAYA" && pd->colorSpace()->id() != "GRAYA16" && pd->colorSpace()->id() != "GRAYAU16")))) { if (rgb) { pd->convertTo(KoColorSpaceRegistry::instance()->rgb8(0), KoColorConversionTransformation::internalRenderingIntent(), KoColorConversionTransformation::internalConversionFlags()); } else { pd->convertTo(KoColorSpaceRegistry::instance()->colorSpace(GrayAColorModelID.id(), Integer8BitsColorDepthID.id(), 0), KoColorConversionTransformation::internalRenderingIntent(), KoColorConversionTransformation::internalConversionFlags()); } } bool is16bit = pd->colorSpace()->id() == "RGBA16" || pd->colorSpace()->id() == "GRAYAU16"; // Write the magic QString toWrite = ""; int written = 0; if (rgb) { if (binary) { toWrite = "P6"; } else { toWrite = "P3"; } } else if (bitmap) { if (binary) { toWrite = "P4"; } else { toWrite = "P1"; } } else { if (binary) { toWrite = "P5"; } else { toWrite = "P2"; } } written = io->write(toWrite.toUtf8()); if (written != toWrite.toUtf8().length()) { return ImportExportCodes::ErrorWhileWriting; } written = io->write("\n"); // Write the header QByteArray width = QByteArray::number(image->width()); QByteArray height = QByteArray::number(image->height()); written += io->write(width); written += io->write(" "); written += io->write(height); if (written != QString(" ").length() + QString("\n").length() + width.length() + height.length()) { return ImportExportCodes::ErrorWhileWriting; } if (!bitmap) { if (is16bit) { toWrite = " 65535\n"; } else { toWrite = " 255\n"; } } else { toWrite = "\n"; } written = io->write(toWrite.toUtf8()); if (written != toWrite.toUtf8().length()) { return ImportExportCodes::ErrorWhileWriting; } // Write the data KisPPMFlow* flow = 0; if (binary) flow = new KisPPMBinaryFlow(io); else flow = new KisPPMAsciiFlow(io); for (int y = 0; y < image->height(); ++y) { KisHLineIteratorSP it = pd->createHLineIteratorNG(0, y, image->width()); if (is16bit) { if (rgb) { do { flow->writeNumber(KoBgrU16Traits::red(it->rawData())); flow->writeNumber(KoBgrU16Traits::green(it->rawData())); flow->writeNumber(KoBgrU16Traits::blue(it->rawData())); } while (it->nextPixel()); } else if (bitmap) { do { flow->writeBool(*reinterpret_cast(it->rawData())); } while (it->nextPixel()); } else { do { flow->writeNumber(*reinterpret_cast(it->rawData())); } while (it->nextPixel()); } } else { if (rgb) { do { flow->writeNumber(KoBgrTraits::red(it->rawData())); flow->writeNumber(KoBgrTraits::green(it->rawData())); flow->writeNumber(KoBgrTraits::blue(it->rawData())); } while (it->nextPixel()); } else if (bitmap) { do { flow->writeBool(*reinterpret_cast(it->rawData())); } while (it->nextPixel()); } else { do { flow->writeNumber(*reinterpret_cast(it->rawData())); } while (it->nextPixel()); } } } if (bitmap) { flow->flush(); } delete flow; return ImportExportCodes::OK; } KisPropertiesConfigurationSP KisPPMExport::defaultConfiguration(const QByteArray &/*from*/, const QByteArray &/*to*/) const { KisPropertiesConfigurationSP cfg = new KisPropertiesConfiguration(); cfg->setProperty("type", 0); return cfg; } KisConfigWidget *KisPPMExport::createConfigurationWidget(QWidget *parent, const QByteArray &/*from*/, const QByteArray &/*to*/) const { return new KisWdgOptionsPPM(parent); } void KisWdgOptionsPPM::setConfiguration(const KisPropertiesConfigurationSP cfg) { cmbType->setCurrentIndex(cfg->getInt("type", 0)); } KisPropertiesConfigurationSP KisWdgOptionsPPM::configuration() const { KisPropertiesConfigurationSP cfg = new KisPropertiesConfiguration(); cfg->setProperty("type", cmbType->currentIndex()); return cfg; } void KisPPMExport::initializeCapabilities() { addCapability(KisExportCheckRegistry::instance()->get("ColorModelCheck/" + RGBAColorModelID.id() + "/" + Integer8BitsColorDepthID.id())->create(KisExportCheckBase::SUPPORTED)); addCapability(KisExportCheckRegistry::instance()->get("ColorModelCheck/" + RGBAColorModelID.id() + "/" + Integer16BitsColorDepthID.id())->create(KisExportCheckBase::SUPPORTED)); addCapability(KisExportCheckRegistry::instance()->get("ColorModelCheck/" + GrayAColorModelID.id() + "/" + Integer8BitsColorDepthID.id())->create(KisExportCheckBase::SUPPORTED)); addCapability(KisExportCheckRegistry::instance()->get("ColorModelCheck/" + GrayAColorModelID.id() + "/" + Integer16BitsColorDepthID.id())->create(KisExportCheckBase::SUPPORTED)); QList > supportedColorModels; supportedColorModels << QPair() << QPair(RGBAColorModelID, Integer8BitsColorDepthID) << QPair(RGBAColorModelID, Integer16BitsColorDepthID) << QPair(GrayAColorModelID, Integer8BitsColorDepthID) << QPair(GrayAColorModelID, Integer16BitsColorDepthID); addSupportedColorModels(supportedColorModels, "PPM"); } #include "kis_ppm_export.moc" diff --git a/plugins/impex/ppm/kis_ppm_export.h b/plugins/impex/ppm/kis_ppm_export.h index 53f15c5e70..070db83b7a 100644 --- a/plugins/impex/ppm/kis_ppm_export.h +++ b/plugins/impex/ppm/kis_ppm_export.h @@ -1,58 +1,59 @@ /* * Copyright (c) 2009 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. + * the Free Software Foundation; 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 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_PPM_EXPORT_H_ #define _KIS_PPM_EXPORT_H_ #include #include #include #include "ui_kis_wdg_options_ppm.h" class KisWdgOptionsPPM : public KisConfigWidget, public Ui::WdgOptionsPPM { Q_OBJECT public: KisWdgOptionsPPM(QWidget *parent) : KisConfigWidget(parent) { setupUi(this); } void setConfiguration(const KisPropertiesConfigurationSP cfg) override; KisPropertiesConfigurationSP configuration() const override; }; class KisPPMExport : public KisImportExportFilter { Q_OBJECT public: KisPPMExport(QObject *parent, const QVariantList &); ~KisPPMExport() override; public: KisImportExportErrorCode convert(KisDocument *document, QIODevice *io, KisPropertiesConfigurationSP configuration = 0) override; KisPropertiesConfigurationSP defaultConfiguration(const QByteArray& from = "", const QByteArray& to = "") const override; KisConfigWidget *createConfigurationWidget(QWidget *parent, const QByteArray& from = "", const QByteArray& to = "") const override; void initializeCapabilities() override; }; #endif diff --git a/plugins/impex/qml/qml_converter.cc b/plugins/impex/qml/qml_converter.cc index 4d98234f0a..48b9440982 100644 --- a/plugins/impex/qml/qml_converter.cc +++ b/plugins/impex/qml/qml_converter.cc @@ -1,96 +1,97 @@ /* * Copyright (c) 2013 Sven Langkamp * * 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. + * the Free Software Foundation; 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 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 "qml_converter.h" #include #include #include #include #define SPACE " " QMLConverter::QMLConverter() { } QMLConverter::~QMLConverter() { } KisImportExportErrorCode QMLConverter::buildFile(const QString &filename, const QString &realFilename, QIODevice *io, KisImageSP image) { QTextStream out(io); out.setCodec("UTF-8"); out << "import QtQuick 1.1" << "\n\n"; out << "Rectangle {\n"; writeInt(out, 1, "width", image->width()); writeInt(out, 1, "height", image->height()); out << "\n"; QFileInfo info(filename); QFileInfo infoRealFile(realFilename); KisNodeSP node = image->rootLayer()->firstChild(); QString imageDir = infoRealFile.baseName() + "_images"; QString imagePath = infoRealFile.absolutePath() + '/' + imageDir; if (node) { QDir dir; bool success = dir.mkpath(imagePath); if (!success) { return ImportExportCodes::CannotCreateFile; } } dbgFile << "Saving images to " << imagePath; while(node) { KisPaintDeviceSP projection = node->projection(); QRect rect = projection->exactBounds(); QImage qmlImage = projection->convertToQImage(0, rect.x(), rect.y(), rect.width(), rect.height()); QString name = node->name().replace(' ', '_').toLower(); QString fileName = name + ".png"; qmlImage.save(imagePath +'/'+ fileName); out << SPACE << "Image {\n"; writeString(out, 2, "id", name); writeInt(out, 2, "x", rect.x()); writeInt(out, 2, "y", rect.y()); writeInt(out, 2, "width", rect.width()); writeInt(out, 2, "height", rect.height()); writeString(out, 2, "source", "\"" + imageDir + '/' + fileName + "\"" ); writeString(out, 2, "opacity", QString().setNum(node->opacity()/255.0)); out << SPACE << "}\n"; node = node->nextSibling(); } out << "}\n"; return ImportExportCodes::OK; } void QMLConverter::writeString(QTextStream& out, int spacing, const QString& setting, const QString& value) { for (int space = 0; space < spacing; space++) { out << SPACE; } out << setting << ": " << value << "\n"; } void QMLConverter::writeInt(QTextStream& out, int spacing, const QString& setting, int value) { writeString(out, spacing, setting, QString::number(value)); } diff --git a/plugins/impex/qml/qml_converter.h b/plugins/impex/qml/qml_converter.h index ab03696947..f0b1ccb122 100644 --- a/plugins/impex/qml/qml_converter.h +++ b/plugins/impex/qml/qml_converter.h @@ -1,44 +1,45 @@ /* * Copyright (c) 2013 Sven Langkamp * * 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. + * the Free Software Foundation; 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 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 _QML_CONVERTER_H_ #define _QML_CONVERTER_H_ #include #include #include #include "kis_types.h" #include class QMLConverter : public QObject { Q_OBJECT public: QMLConverter(); ~QMLConverter() override; public: KisImportExportErrorCode buildFile(const QString &filename, const QString &realFilename, QIODevice *io, KisImageSP image); private: void writeString(QTextStream& out, int spacing, const QString& setting, const QString& value); void writeInt(QTextStream& out, int spacing, const QString& setting, int value); }; #endif diff --git a/plugins/impex/qml/qml_export.cc b/plugins/impex/qml/qml_export.cc index 8de5713de9..732b277aa7 100644 --- a/plugins/impex/qml/qml_export.cc +++ b/plugins/impex/qml/qml_export.cc @@ -1,67 +1,68 @@ /* * Copyright (c) 2013 Sven Langkamp * * 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. + * the Free Software Foundation; 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 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 "qml_export.h" #include #include #include #include #include #include #include #include #include "qml_converter.h" #include K_PLUGIN_FACTORY_WITH_JSON(ExportFactory, "krita_qml_export.json", registerPlugin();) QMLExport::QMLExport(QObject *parent, const QVariantList &) : KisImportExportFilter(parent) { } QMLExport::~QMLExport() { } KisImportExportErrorCode QMLExport::convert(KisDocument *document, QIODevice *io, KisPropertiesConfigurationSP /*configuration*/) { KisImageSP image = document->savingImage(); Q_CHECK_PTR(image); QMLConverter converter; return converter.buildFile(filename(), realFilename(), io, image); } void QMLExport::initializeCapabilities() { addCapability(KisExportCheckRegistry::instance()->get("MultiLayerCheck")->create(KisExportCheckBase::SUPPORTED)); QList > supportedColorModels; supportedColorModels << QPair() << QPair(RGBAColorModelID, Integer8BitsColorDepthID) << QPair(GrayAColorModelID, Integer8BitsColorDepthID); addSupportedColorModels(supportedColorModels, "QML"); } #include diff --git a/plugins/impex/qml/qml_export.h b/plugins/impex/qml/qml_export.h index 7ca4de2a36..e951a92843 100644 --- a/plugins/impex/qml/qml_export.h +++ b/plugins/impex/qml/qml_export.h @@ -1,36 +1,37 @@ /* * Copyright (c) 2013 Sven Langkamp * * 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. + * the Free Software Foundation; 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 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 _QML_EXPORT_H_ #define _QML_EXPORT_H_ #include #include class QMLExport : public KisImportExportFilter { Q_OBJECT public: QMLExport(QObject *parent, const QVariantList &); ~QMLExport() override; public: KisImportExportErrorCode convert(KisDocument *document, QIODevice *io, KisPropertiesConfigurationSP configuration = 0) override; void initializeCapabilities() override; }; #endif diff --git a/plugins/paintops/libpaintop/kis_color_source.cpp b/plugins/paintops/libpaintop/kis_color_source.cpp index ae2bca7f10..5b7ea8ede6 100644 --- a/plugins/paintops/libpaintop/kis_color_source.cpp +++ b/plugins/paintops/libpaintop/kis_color_source.cpp @@ -1,296 +1,297 @@ /* * Copyright (c) 2006-2007, 2009 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. + * the Free Software Foundation; 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 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_source.h" #include #include #include #include #include #include #include #include "kis_iterator_ng.h" #include "kis_selection.h" #include #include #include KisColorSource::~KisColorSource() { } const KoColor black; const KoColor& KisColorSource::uniformColor() const { qFatal("Not an uniform color."); return black; } KisUniformColorSource::KisUniformColorSource() { } KisUniformColorSource::~KisUniformColorSource() { } void KisUniformColorSource::rotate(double) {} void KisUniformColorSource::resize(double , double) { // Do nothing as plain color does not have size } void KisUniformColorSource::colorize(KisPaintDeviceSP dev, const QRect& size, const QPoint&) const { Q_UNUSED(size); KoColor c(dev->colorSpace()); c.fromKoColor(m_color); dev->dataManager()->setDefaultPixel(c.data()); dev->clear(); } const KoColor& KisUniformColorSource::uniformColor() const { return m_color; } void KisUniformColorSource::applyColorTransformation(const KoColorTransformation* transfo) { transfo->transform(m_color.data(), m_color.data(), 1); } const KoColorSpace* KisUniformColorSource::colorSpace() const { return m_color.colorSpace(); } bool KisUniformColorSource::isUniformColor() const { return true; } //-------------------------------------------------// //---------------- KisPlainColorSource ---------------// //-------------------------------------------------// KisPlainColorSource::KisPlainColorSource(const KoColor& backGroundColor, const KoColor& foreGroundColor) : m_backGroundColor(backGroundColor) , m_cachedBackGroundColor(backGroundColor) , m_foreGroundColor(foreGroundColor) { } KisPlainColorSource::~KisPlainColorSource() { } void KisPlainColorSource::selectColor(double mix, const KisPaintInformation &pi) { Q_UNUSED(pi); if (m_color.colorSpace() != m_foreGroundColor.colorSpace()) { m_color = KoColor(m_foreGroundColor.colorSpace()); m_cachedBackGroundColor = KoColor(m_foreGroundColor.colorSpace()); m_cachedBackGroundColor.fromKoColor(m_backGroundColor); } const quint8 *colors[2]; colors[0] = m_cachedBackGroundColor.data(); colors[1] = m_foreGroundColor.data(); // equally distribute mix factor over [0..255] // mix * 256 ensures that, with exception of mix==1.0, which gets special handling const int weight = (mix == 1.0) ? 255 : (int)(mix * 256); const qint16 weights[2] = { (qint16)(255 - weight), (qint16)weight }; m_color.colorSpace()->mixColorsOp()->mixColors(colors, weights, 2, m_color.data()); } //-------------------------------------------------// //--------------- KisGradientColorSource -------------// //-------------------------------------------------// KisGradientColorSource::KisGradientColorSource(const KoAbstractGradient* gradient, const KoColorSpace* workingCS) : m_gradient(gradient) { m_color = KoColor(workingCS); Q_ASSERT(gradient); } KisGradientColorSource::~KisGradientColorSource() { } void KisGradientColorSource::selectColor(double mix, const KisPaintInformation &pi) { Q_UNUSED(pi); if (m_gradient) { m_gradient->colorAt(m_color, mix); } } //-------------------------------------------------// //--------------- KisGradientColorSource -------------// //-------------------------------------------------// KisUniformRandomColorSource::KisUniformRandomColorSource() { } KisUniformRandomColorSource::~KisUniformRandomColorSource() { } void KisUniformRandomColorSource::selectColor(double mix, const KisPaintInformation &pi) { Q_UNUSED(pi); Q_UNUSED(mix); KisRandomSourceSP source = pi.randomSource(); m_color.fromQColor(QColor((int)source->generate(0, 255), (int)source->generate(0, 255), (int)source->generate(0, 255))); } //------------------------------------------------------// //--------------- KisTotalRandomColorSource ---------------// //------------------------------------------------------// KisTotalRandomColorSource::KisTotalRandomColorSource() : m_colorSpace(KoColorSpaceRegistry::instance()->rgb8()) { } KisTotalRandomColorSource::~KisTotalRandomColorSource() { } void KisTotalRandomColorSource::selectColor(double mix, const KisPaintInformation &pi) { Q_UNUSED(mix); Q_UNUSED(pi); } void KisTotalRandomColorSource::applyColorTransformation(const KoColorTransformation*) {} const KoColorSpace* KisTotalRandomColorSource::colorSpace() const { return m_colorSpace; } void KisTotalRandomColorSource::colorize(KisPaintDeviceSP dev, const QRect& rect, const QPoint&) const { KoColor kc(dev->colorSpace()); QColor qc; std::random_device rand_dev; std::default_random_engine rand_engine{rand_dev()}; std::uniform_int_distribution<> rand_distr(0, 255); int pixelSize = dev->colorSpace()->pixelSize(); KisHLineIteratorSP it = dev->createHLineIteratorNG(rect.x(), rect.y(), rect.width()); for (int y = 0; y < rect.height(); y++) { do { qc.setRgb(rand_distr(rand_engine), rand_distr(rand_engine), rand_distr(rand_engine)); kc.fromQColor(qc); memcpy(it->rawData(), kc.data(), pixelSize); } while (it->nextPixel()); it->nextRow(); } } bool KisTotalRandomColorSource::isUniformColor() const { return false; } void KisTotalRandomColorSource::rotate(double) {} void KisTotalRandomColorSource::resize(double , double) {} KoPatternColorSource::KoPatternColorSource(KisPaintDeviceSP _pattern, int _width, int _height, bool _locked) : m_device(_pattern) , m_bounds(QRect(0, 0, _width, _height)) , m_locked(_locked) { } KoPatternColorSource::~KoPatternColorSource() { } void KoPatternColorSource::selectColor(double mix, const KisPaintInformation &pi) { Q_UNUSED(mix); Q_UNUSED(pi); } void KoPatternColorSource::applyColorTransformation(const KoColorTransformation* transfo) { Q_UNUSED(transfo); } const KoColorSpace* KoPatternColorSource::colorSpace() const { return m_device->colorSpace(); } void KoPatternColorSource::colorize(KisPaintDeviceSP device, const QRect& rect, const QPoint& offset) const { KisFillPainter painter(device); if (m_locked) { painter.fillRect(rect.x(), rect.y(), rect.width(), rect.height(), m_device, m_bounds); } else { int x = offset.x() % m_bounds.width(); int y = offset.y() % m_bounds.height(); // Change the position, because the pattern is always applied starting // from (0,0) in the paint device reference device->setX(x); device->setY(y); painter.fillRect(rect.x() + x, rect.y() + y, rect.width(), rect.height(), m_device, m_bounds); device->setX(0); device->setY(0); } } void KoPatternColorSource::rotate(double r) { Q_UNUSED(r); } void KoPatternColorSource::resize(double xs, double ys) { Q_UNUSED(xs); Q_UNUSED(ys); } bool KoPatternColorSource::isUniformColor() const { return false; } diff --git a/plugins/paintops/libpaintop/kis_color_source.h b/plugins/paintops/libpaintop/kis_color_source.h index 2801522860..ece32ca36e 100644 --- a/plugins/paintops/libpaintop/kis_color_source.h +++ b/plugins/paintops/libpaintop/kis_color_source.h @@ -1,152 +1,153 @@ /* * Copyright (c) 2006-2007, 2009 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. + * the Free Software Foundation; 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 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_DYNAMIC_COLORING_H_ #define _KIS_DYNAMIC_COLORING_H_ #include "kis_paintop_option.h" #include #include #include #include class KoAbstractGradient; class KoColorTransformation; class KisPaintInformation; /** * A color source allow to abstract how a brush is colorized, * and to apply transformation. * * The first function to call is @ref selectColor , then any of the transformation. */ class PAINTOP_EXPORT KisColorSource { public: virtual ~KisColorSource(); public: /** * This is function is called to initialize the color that will be used for the dab. * @param mix is a parameter between 0.0 and 1.0 * @param pi paint information */ virtual void selectColor(double mix, const KisPaintInformation &pi) = 0; /** * Apply a color transformation on the selected color */ virtual void applyColorTransformation(const KoColorTransformation* transfo) = 0; virtual const KoColorSpace* colorSpace() const = 0; /** * Apply the color on a paint device */ virtual void colorize(KisPaintDeviceSP, const QRect& rect, const QPoint& _offset) const = 0; /** * @return true if the color is an uniform color */ virtual bool isUniformColor() const = 0; /** * @return the color if the color is uniformed */ virtual const KoColor& uniformColor() const; }; class PAINTOP_EXPORT KisUniformColorSource : public KisColorSource { public: KisUniformColorSource(); ~KisUniformColorSource() override; virtual void rotate(double); virtual void resize(double , double); void applyColorTransformation(const KoColorTransformation* transfo) override; const KoColorSpace* colorSpace() const override; void colorize(KisPaintDeviceSP, const QRect& rect, const QPoint& offset) const override; bool isUniformColor() const override; const KoColor& uniformColor() const override; protected: KoColor m_color; }; class PAINTOP_EXPORT KisPlainColorSource : public KisUniformColorSource { public: KisPlainColorSource(const KoColor& backGroundColor, const KoColor& foreGroundColor); ~KisPlainColorSource() override; void selectColor(double mix, const KisPaintInformation &pi) override; private: KoColor m_backGroundColor; KoColor m_cachedBackGroundColor; KoColor m_foreGroundColor; }; class PAINTOP_EXPORT KisGradientColorSource : public KisUniformColorSource { public: KisGradientColorSource(const KoAbstractGradient* gradient, const KoColorSpace* workingCS); ~KisGradientColorSource() override; void selectColor(double mix, const KisPaintInformation &pi) override; private: const KoAbstractGradient* m_gradient; }; class PAINTOP_EXPORT KisUniformRandomColorSource : public KisUniformColorSource { public: KisUniformRandomColorSource(); ~KisUniformRandomColorSource() override; void selectColor(double mix, const KisPaintInformation &pi) override; }; class PAINTOP_EXPORT KisTotalRandomColorSource : public KisColorSource { public: KisTotalRandomColorSource(); ~KisTotalRandomColorSource() override; public: void selectColor(double mix, const KisPaintInformation &pi) override; void applyColorTransformation(const KoColorTransformation* transfo) override; const KoColorSpace* colorSpace() const override; void colorize(KisPaintDeviceSP, const QRect& rect, const QPoint& offset) const override; virtual void rotate(double r); virtual void resize(double xs, double ys); bool isUniformColor() const override; private: const KoColorSpace* m_colorSpace; }; class PAINTOP_EXPORT KoPatternColorSource : public KisColorSource { public: KoPatternColorSource(KisPaintDeviceSP _pattern, int _width, int _height, bool _locked); ~KoPatternColorSource() override; public: void selectColor(double mix, const KisPaintInformation &pi) override; void applyColorTransformation(const KoColorTransformation* transfo) override; const KoColorSpace* colorSpace() const override; void colorize(KisPaintDeviceSP, const QRect& rect, const QPoint& _offset) const override; virtual void rotate(double r); virtual void resize(double xs, double ys); bool isUniformColor() const override; private: const KisPaintDeviceSP m_device; QRect m_bounds; bool m_locked; }; #endif diff --git a/plugins/paintops/libpaintop/kis_curve_label.h b/plugins/paintops/libpaintop/kis_curve_label.h index 97168acbb8..be52b620fe 100644 --- a/plugins/paintops/libpaintop/kis_curve_label.h +++ b/plugins/paintops/libpaintop/kis_curve_label.h @@ -1,44 +1,45 @@ /* * Copyright (c) 2010 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. + * the Free Software Foundation; 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 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_CURVE_LABEL_H_ #define _KIS_CURVE_LABEL_H_ #include class QString; class QImage; struct PAINTOP_EXPORT KisCurveLabel { public: KisCurveLabel(); KisCurveLabel(const QString&); KisCurveLabel(const QImage&); KisCurveLabel(const KisCurveLabel&); KisCurveLabel& operator=(const KisCurveLabel&); ~KisCurveLabel(); QString name() const; QImage icon() const; private: struct Private; Private* const d; }; #endif diff --git a/plugins/paintops/libpaintop/kis_dynamic_sensor.cc b/plugins/paintops/libpaintop/kis_dynamic_sensor.cc index 8f31aa9a1a..0c56495f77 100644 --- a/plugins/paintops/libpaintop/kis_dynamic_sensor.cc +++ b/plugins/paintops/libpaintop/kis_dynamic_sensor.cc @@ -1,575 +1,576 @@ /* * Copyright (c) 2007 Cyrille Berger * Copyright (c) 2011 Lukáš Tvrdý * * 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. + * the Free Software Foundation; 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 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_dynamic_sensor.h" #include #include "kis_algebra_2d.h" #include "sensors/kis_dynamic_sensors.h" #include "sensors/kis_dynamic_sensor_distance.h" #include "sensors/kis_dynamic_sensor_drawing_angle.h" #include "sensors/kis_dynamic_sensor_time.h" #include "sensors/kis_dynamic_sensor_fade.h" #include "sensors/kis_dynamic_sensor_fuzzy.h" KisDynamicSensor::KisDynamicSensor(DynamicSensorType type) : m_length(-1) , m_type(type) , m_customCurve(false) , m_active(false) { } KisDynamicSensor::~KisDynamicSensor() { } QWidget* KisDynamicSensor::createConfigurationWidget(QWidget* parent, QWidget*) { Q_UNUSED(parent); return 0; } void KisDynamicSensor::reset() { } KisDynamicSensorSP KisDynamicSensor::id2Sensor(const KoID& id, const QString &parentOptionName) { if (id.id() == PressureId.id()) { return new KisDynamicSensorPressure(); } else if (id.id() == PressureInId.id()) { return new KisDynamicSensorPressureIn(); } else if (id.id() == XTiltId.id()) { return new KisDynamicSensorXTilt(); } else if (id.id() == YTiltId.id()) { return new KisDynamicSensorYTilt(); } else if (id.id() == TiltDirectionId.id()) { return new KisDynamicSensorTiltDirection(); } else if (id.id() == TiltElevationId.id()) { return new KisDynamicSensorTiltElevation(); } else if (id.id() == SpeedId.id()) { return new KisDynamicSensorSpeed(); } else if (id.id() == DrawingAngleId.id()) { return new KisDynamicSensorDrawingAngle(); } else if (id.id() == RotationId.id()) { return new KisDynamicSensorRotation(); } else if (id.id() == DistanceId.id()) { return new KisDynamicSensorDistance(); } else if (id.id() == TimeId.id()) { return new KisDynamicSensorTime(); } else if (id.id() == FuzzyPerDabId.id()) { return new KisDynamicSensorFuzzy(false, parentOptionName); } else if (id.id() == FuzzyPerStrokeId.id()) { return new KisDynamicSensorFuzzy(true, parentOptionName); } else if (id.id() == FadeId.id()) { return new KisDynamicSensorFade(); } else if (id.id() == PerspectiveId.id()) { return new KisDynamicSensorPerspective(); } else if (id.id() == TangentialPressureId.id()) { return new KisDynamicSensorTangentialPressure(); } dbgPlugins << "Unknown transform parameter :" << id.id(); return 0; } DynamicSensorType KisDynamicSensor::id2Type(const KoID &id) { if (id.id() == PressureId.id()) { return PRESSURE; } else if (id.id() == PressureInId.id()) { return PRESSURE_IN; } else if (id.id() == XTiltId.id()) { return XTILT; } else if (id.id() == YTiltId.id()) { return YTILT; } else if (id.id() == TiltDirectionId.id()) { return TILT_DIRECTION; } else if (id.id() == TiltElevationId.id()) { return TILT_ELEVATATION; } else if (id.id() == SpeedId.id()) { return SPEED; } else if (id.id() == DrawingAngleId.id()) { return ANGLE; } else if (id.id() == RotationId.id()) { return ROTATION; } else if (id.id() == DistanceId.id()) { return DISTANCE; } else if (id.id() == TimeId.id()) { return TIME; } else if (id.id() == FuzzyPerDabId.id()) { return FUZZY_PER_DAB; } else if (id.id() == FuzzyPerStrokeId.id()) { return FUZZY_PER_STROKE; } else if (id.id() == FadeId.id()) { return FADE; } else if (id.id() == PerspectiveId.id()) { return PERSPECTIVE; } else if (id.id() == TangentialPressureId.id()) { return TANGENTIAL_PRESSURE; } return UNKNOWN; } KisDynamicSensorSP KisDynamicSensor::type2Sensor(DynamicSensorType sensorType, const QString &parentOptionName) { switch (sensorType) { case FUZZY_PER_DAB: return new KisDynamicSensorFuzzy(false, parentOptionName); case FUZZY_PER_STROKE: return new KisDynamicSensorFuzzy(true, parentOptionName); case SPEED: return new KisDynamicSensorSpeed(); case FADE: return new KisDynamicSensorFade(); case DISTANCE: return new KisDynamicSensorDistance(); case TIME: return new KisDynamicSensorTime(); case ANGLE: return new KisDynamicSensorDrawingAngle(); case ROTATION: return new KisDynamicSensorRotation(); case PRESSURE: return new KisDynamicSensorPressure(); case XTILT: return new KisDynamicSensorXTilt(); case YTILT: return new KisDynamicSensorYTilt(); case TILT_DIRECTION: return new KisDynamicSensorTiltDirection(); case TILT_ELEVATATION: return new KisDynamicSensorTiltElevation(); case PERSPECTIVE: return new KisDynamicSensorPerspective(); case TANGENTIAL_PRESSURE: return new KisDynamicSensorTangentialPressure(); case PRESSURE_IN: return new KisDynamicSensorPressureIn(); default: return 0; } } QString KisDynamicSensor::minimumLabel(DynamicSensorType sensorType) { switch (sensorType) { case FUZZY_PER_DAB: case FUZZY_PER_STROKE: return QString(); case FADE: return i18n("0"); case DISTANCE: return i18n("0 px"); case TIME: return i18n("0 s"); case ANGLE: return i18n("0°"); case SPEED: return i18n("Slow"); case ROTATION: return i18n("0°"); case PRESSURE: return i18n("Low"); case XTILT: return i18n("-30°"); case YTILT: return i18n("-30°"); case TILT_DIRECTION: return i18n("0°"); case TILT_ELEVATATION: return i18n("90°"); case PERSPECTIVE: return i18n("Far"); case TANGENTIAL_PRESSURE: case PRESSURE_IN: return i18n("Low"); default: return i18n("0.0"); } } QString KisDynamicSensor::maximumLabel(DynamicSensorType sensorType, int max) { switch (sensorType) { case FUZZY_PER_DAB: case FUZZY_PER_STROKE: return QString(); case FADE: if (max < 0) return i18n("1000"); else return i18n("%1", max); case DISTANCE: if (max < 0) return i18n("30 px"); else return i18n("%1 px", max); case TIME: if (max < 0) return i18n("3 s"); else return i18n("%1 s", max / 1000); case ANGLE: return i18n("360°"); case SPEED: return i18n("Fast"); case ROTATION: return i18n("360°"); case PRESSURE: return i18n("High"); case XTILT: return i18n("30°"); case YTILT: return i18n("30°"); case TILT_DIRECTION: return i18n("360°"); case TILT_ELEVATATION: return i18n("0°"); case PERSPECTIVE: return i18n("Near"); case TANGENTIAL_PRESSURE: case PRESSURE_IN: return i18n("High"); default: return i18n("1.0"); }; } int KisDynamicSensor::minimumValue(DynamicSensorType sensorType) { switch (sensorType) { case FUZZY_PER_DAB: case FUZZY_PER_STROKE: case FADE: case DISTANCE: case TIME: case ANGLE: case SPEED: case ROTATION: case PRESSURE: case TILT_DIRECTION: case PERSPECTIVE: case PRESSURE_IN: return 0; case XTILT: case YTILT: return -30; case TILT_ELEVATATION: return 90; case TANGENTIAL_PRESSURE: default: return 0; } } int KisDynamicSensor::maximumValue(DynamicSensorType sensorType, int max) { switch (sensorType) { case FUZZY_PER_DAB: case FUZZY_PER_STROKE: case SPEED: case PERSPECTIVE: case TANGENTIAL_PRESSURE: case PRESSURE_IN: case PRESSURE: return 100; case FADE: if (max < 0) { return 1000; } else { return max; } case DISTANCE: if (max < 0) { return 30; } else { return max; } case TIME: if (max < 0) { return 3000; } else { return max; } case ANGLE: case ROTATION: case TILT_DIRECTION: return 360; case XTILT: case YTILT: return 30; case TILT_ELEVATATION: return 0; default: return 100; }; } QString KisDynamicSensor::valueSuffix(DynamicSensorType sensorType) { switch (sensorType) { case FUZZY_PER_DAB: case FUZZY_PER_STROKE: case SPEED: case PRESSURE: case PERSPECTIVE: case TANGENTIAL_PRESSURE: case PRESSURE_IN: return i18n("%"); case FADE: return QString(); case DISTANCE: return i18n(" px"); case TIME: return i18n(" ms"); case ANGLE: case ROTATION: case XTILT: case YTILT: case TILT_DIRECTION: case TILT_ELEVATATION: return i18n("°"); default: return i18n("%"); }; } KisDynamicSensorSP KisDynamicSensor::createFromXML(const QString& s, const QString &parentOptionName) { QDomDocument doc; doc.setContent(s); QDomElement e = doc.documentElement(); return createFromXML(e, parentOptionName); } KisDynamicSensorSP KisDynamicSensor::createFromXML(const QDomElement& e, const QString &parentOptionName) { QString id = e.attribute("id", ""); KisDynamicSensorSP sensor = id2Sensor(id, parentOptionName); if (sensor) { sensor->fromXML(e); } return sensor; } QList KisDynamicSensor::sensorsIds() { QList ids; ids << PressureId << PressureInId << XTiltId << YTiltId << TiltDirectionId << TiltElevationId << SpeedId << DrawingAngleId << RotationId << DistanceId << TimeId << FuzzyPerDabId << FuzzyPerStrokeId << FadeId << PerspectiveId << TangentialPressureId; return ids; } QList KisDynamicSensor::sensorsTypes() { QList sensorTypes; sensorTypes << PRESSURE << PRESSURE_IN << XTILT << YTILT << TILT_DIRECTION << TILT_ELEVATATION << SPEED << ANGLE << ROTATION << DISTANCE << TIME << FUZZY_PER_DAB << FUZZY_PER_STROKE << FADE << PERSPECTIVE << TANGENTIAL_PRESSURE; return sensorTypes; } QString KisDynamicSensor::id(DynamicSensorType sensorType) { switch (sensorType) { case FUZZY_PER_DAB: return "fuzzy"; case FUZZY_PER_STROKE: return "fuzzystroke"; case FADE: return "fade"; case DISTANCE: return "distance"; case TIME: return "time"; case ANGLE: return "drawingangle"; case SPEED: return "speed"; case ROTATION: return "rotation"; case PRESSURE: return "pressure"; case XTILT: return "xtilt"; case YTILT: return "ytilt"; case TILT_DIRECTION: return "ascension"; case TILT_ELEVATATION: return "declination"; case PERSPECTIVE: return "perspective"; case TANGENTIAL_PRESSURE: return "tangentialpressure"; case PRESSURE_IN: return "pressurein"; case SENSORS_LIST: return "sensorslist"; default: return QString(); }; } void KisDynamicSensor::toXML(QDomDocument& doc, QDomElement& elt) const { elt.setAttribute("id", id(sensorType())); if (m_customCurve) { QDomElement curve_elt = doc.createElement("curve"); QDomText text = doc.createTextNode(m_curve.toString()); curve_elt.appendChild(text); elt.appendChild(curve_elt); } } void KisDynamicSensor::fromXML(const QDomElement& e) { Q_ASSERT(e.attribute("id", "") == id(sensorType())); m_customCurve = false; QDomElement curve_elt = e.firstChildElement("curve"); if (!curve_elt.isNull()) { m_customCurve = true; m_curve.fromString(curve_elt.text()); } } qreal KisDynamicSensor::parameter(const KisPaintInformation& info) { const qreal val = value(info); if (m_customCurve) { qreal scaledVal = isAdditive() ? additiveToScaling(val) : val; const QVector transfer = m_curve.floatTransfer(256); scaledVal = KisCubicCurve::interpolateLinear(scaledVal, transfer); return isAdditive() ? scalingToAdditive(scaledVal) : scaledVal; } else { return val; } } void KisDynamicSensor::setCurve(const KisCubicCurve& curve) { m_customCurve = true; m_curve = curve; } const KisCubicCurve& KisDynamicSensor::curve() const { return m_curve; } void KisDynamicSensor::removeCurve() { m_customCurve = false; } bool KisDynamicSensor::hasCustomCurve() const { return m_customCurve; } bool KisDynamicSensor::dependsOnCanvasRotation() const { return true; } bool KisDynamicSensor::isAdditive() const { return false; } bool KisDynamicSensor::isAbsoluteRotation() const { return false; } void KisDynamicSensor::setActive(bool active) { m_active = active; } bool KisDynamicSensor::isActive() const { return m_active; } diff --git a/plugins/paintops/libpaintop/kis_dynamic_sensor.h b/plugins/paintops/libpaintop/kis_dynamic_sensor.h index a4b843c36f..b349822eda 100644 --- a/plugins/paintops/libpaintop/kis_dynamic_sensor.h +++ b/plugins/paintops/libpaintop/kis_dynamic_sensor.h @@ -1,221 +1,222 @@ /* * Copyright (c) 2006 Cyrille Berger * Copyright (c) 2011 Lukáš Tvrdý * * 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. + * the Free Software Foundation; 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 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_DYNAMIC_SENSOR_H_ #define _KIS_DYNAMIC_SENSOR_H_ #include #include #include #include #include "kis_serializable_configuration.h" #include "kis_curve_label.h" #include #include #include class QWidget; class KisPaintInformation; const KoID FuzzyPerDabId("fuzzy", ki18n("Fuzzy Dab")); ///< generate a random number const KoID FuzzyPerStrokeId("fuzzystroke", ki18n("Fuzzy Stroke")); ///< generate a random number const KoID SpeedId("speed", ki18n("Speed")); ///< generate a number depending on the speed of the cursor const KoID FadeId("fade", ki18n("Fade")); ///< generate a number that increase every time you call it (e.g. per dab) const KoID DistanceId("distance", ki18n("Distance")); ///< generate a number that increase with distance const KoID TimeId("time", ki18n("Time")); ///< generate a number that increase with time const KoID DrawingAngleId("drawingangle", ki18n("Drawing angle")); ///< number depending on the angle const KoID RotationId("rotation", ki18n("Rotation")); ///< rotation coming from the device const KoID PressureId("pressure", ki18n("Pressure")); ///< number depending on the pressure const KoID PressureInId("pressurein", ki18n("PressureIn")); ///< number depending on the pressure const KoID XTiltId("xtilt", ki18n("X-Tilt")); ///< number depending on X-tilt const KoID YTiltId("ytilt", ki18n("Y-Tilt")); ///< number depending on Y-tilt /** * "TiltDirection" and "TiltElevation" parameters are written to * preset files as "ascension" and "declination" to keep backward * compatibility with older presets from the days when they were called * differently. */ const KoID TiltDirectionId("ascension", ki18n("Tilt direction")); /// < number depending on the X and Y tilt, tilt direction is 0 when stylus nib points to you and changes clockwise from -180 to +180. const KoID TiltElevationId("declination", ki18n("Tilt elevation")); /// < tilt elevation is 90 when stylus is perpendicular to tablet and 0 when it's parallel to tablet const KoID PerspectiveId("perspective", ki18n("Perspective")); ///< number depending on the distance on the perspective grid const KoID TangentialPressureId("tangentialpressure", ki18n("Tangential pressure")); ///< the wheel on an airbrush device const KoID SensorsListId("sensorslist", "SHOULD NOT APPEAR IN THE UI !"); ///< this a non user-visible sensor that can store a list of other sensors, and multiply their output class KisDynamicSensor; typedef KisSharedPtr KisDynamicSensorSP; enum DynamicSensorType { FUZZY_PER_DAB, FUZZY_PER_STROKE, SPEED, FADE, DISTANCE, TIME, ANGLE, ROTATION, PRESSURE, XTILT, YTILT, TILT_DIRECTION, TILT_ELEVATATION, PERSPECTIVE, TANGENTIAL_PRESSURE, SENSORS_LIST, PRESSURE_IN, UNKNOWN = 255 }; /** * Sensors are used to extract from KisPaintInformation a single * double value which can be used to control the parameters of * a brush. */ class PAINTOP_EXPORT KisDynamicSensor : public KisSerializableConfiguration { public: enum ParameterSign { NegativeParameter = -1, UnSignedParameter = 0, PositiveParameter = 1 }; protected: KisDynamicSensor(DynamicSensorType type); public: ~KisDynamicSensor() override; /** * @return the value of this sensor for the given KisPaintInformation */ qreal parameter(const KisPaintInformation& info); /** * This function is call before beginning a stroke to reset the sensor. * Default implementation does nothing. */ virtual void reset(); /** * @param parent the parent QWidget * @param selector is a \ref QWidget that contains a signal called "parametersChanged()" */ virtual QWidget* createConfigurationWidget(QWidget* parent, QWidget* selector); /** * Creates a sensor from its identifier. */ static KisDynamicSensorSP id2Sensor(const KoID& id, const QString &parentOptionName); static KisDynamicSensorSP id2Sensor(const QString& s, const QString &parentOptionName) { return id2Sensor(KoID(s), parentOptionName); } static DynamicSensorType id2Type(const KoID& id); static DynamicSensorType id2Type(const QString& s) { return id2Type(KoID(s)); } /** * type2Sensor creates a new sensor for the give type */ static KisDynamicSensorSP type2Sensor(DynamicSensorType sensorType, const QString &parentOptionName); static QString minimumLabel(DynamicSensorType sensorType); static QString maximumLabel(DynamicSensorType sensorType, int max = -1); static int minimumValue(DynamicSensorType sensorType); static int maximumValue(DynamicSensorType sensorType, int max = -1); static QString valueSuffix(DynamicSensorType sensorType); static KisDynamicSensorSP createFromXML(const QString&, const QString &parentOptionName); static KisDynamicSensorSP createFromXML(const QDomElement&, const QString &parentOptionName); /** * @return the list of sensors */ static QList sensorsIds(); static QList sensorsTypes(); /** * @return the identifier of this sensor */ static QString id(DynamicSensorType sensorType); using KisSerializableConfiguration::fromXML; using KisSerializableConfiguration::toXML; void toXML(QDomDocument&, QDomElement&) const override; void fromXML(const QDomElement&) override; void setCurve(const KisCubicCurve& curve); const KisCubicCurve& curve() const; void removeCurve(); bool hasCustomCurve() const; void setActive(bool active); bool isActive() const; virtual bool dependsOnCanvasRotation() const; virtual bool isAdditive() const; virtual bool isAbsoluteRotation() const; inline DynamicSensorType sensorType() const { return m_type; } /** * @return the currently set length or -1 if not relevant */ int length() { return m_length; } public: static inline qreal scalingToAdditive(qreal x) { return -1.0 + 2.0 * x; } static inline qreal additiveToScaling(qreal x) { return 0.5 * (1.0 + x); } protected: virtual qreal value(const KisPaintInformation& info) = 0; int m_length; private: Q_DISABLE_COPY(KisDynamicSensor) DynamicSensorType m_type; bool m_customCurve; KisCubicCurve m_curve; bool m_active; }; #endif diff --git a/plugins/paintops/libpaintop/kis_dynamic_sensors.h b/plugins/paintops/libpaintop/kis_dynamic_sensors.h index 34dc12a7f0..2bd15cc820 100644 --- a/plugins/paintops/libpaintop/kis_dynamic_sensors.h +++ b/plugins/paintops/libpaintop/kis_dynamic_sensors.h @@ -1,140 +1,141 @@ /* * Copyright (c) 2006-2007,2010 Cyrille Berger * Copyright (c) 2011 Lukáš Tvrdý * * 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. + * the Free Software Foundation; 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 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_DYNAMIC_SENSORS_H_ #define _KIS_DYNAMIC_SENSORS_H_ #include "../kis_dynamic_sensor.h" #include "kis_paint_information.h" class KisDynamicSensorSpeed : public KisDynamicSensor { public: KisDynamicSensorSpeed(); virtual ~KisDynamicSensorSpeed() { } virtual qreal value(const KisPaintInformation& info); void reset() { m_speed = -1.0; } private: double m_speed; }; class KisDynamicSensorRotation : public KisDynamicSensor { public: KisDynamicSensorRotation(); virtual ~KisDynamicSensorRotation() { } virtual qreal value(const KisPaintInformation& info) { return info.rotation() / 360.0; } }; class KisDynamicSensorPressure : public KisDynamicSensor { public: KisDynamicSensorPressure(); virtual ~KisDynamicSensorPressure() { } virtual qreal value(const KisPaintInformation& info) { return info.pressure(); } }; class KisDynamicSensorPressureIn : public KisDynamicSensor { public: KisDynamicSensorPressureIn(); virtual ~KisDynamicSensorPressureIn() { } virtual qreal value(const KisPaintInformation& info) { if(!info.isHoveringMode()) { if(info.pressure() > lastPressure) { lastPressure = info.pressure(); } return lastPressure; } lastPressure = 0.0; return 0.0; } private: qreal lastPressure; }; class KisDynamicSensorXTilt : public KisDynamicSensor { public: KisDynamicSensorXTilt(); virtual ~KisDynamicSensorXTilt() { } virtual qreal value(const KisPaintInformation& info) { return 1.0 - fabs(info.xTilt()) / 60.0; } }; class KisDynamicSensorYTilt : public KisDynamicSensor { public: KisDynamicSensorYTilt(); virtual ~KisDynamicSensorYTilt() { } virtual qreal value(const KisPaintInformation& info) { return 1.0 - fabs(info.yTilt()) / 60.0; } }; class KisDynamicSensorTiltDirection : public KisDynamicSensor { public: KisDynamicSensorTiltDirection(); virtual ~KisDynamicSensorTiltDirection() {} virtual qreal value(const KisPaintInformation& info) { return KisPaintInformation::tiltDirection(info, true); } }; class KisDynamicSensorTiltElevation : public KisDynamicSensor { public: KisDynamicSensorTiltElevation(); virtual ~KisDynamicSensorTiltElevation() {} virtual qreal value(const KisPaintInformation& info) { return KisPaintInformation::tiltElevation(info, 60.0, 60.0, true); } }; class KisDynamicSensorPerspective : public KisDynamicSensor { public: KisDynamicSensorPerspective(); virtual ~KisDynamicSensorPerspective() { } virtual qreal value(const KisPaintInformation& info) { return info.perspective(); } }; class KisDynamicSensorTangentialPressure : public KisDynamicSensor { public: KisDynamicSensorTangentialPressure(); virtual ~KisDynamicSensorTangentialPressure() { } virtual qreal value(const KisPaintInformation& info) { return info.tangentialPressure(); } }; #endif diff --git a/plugins/paintops/libpaintop/sensors/kis_dynamic_sensor_distance.cc b/plugins/paintops/libpaintop/sensors/kis_dynamic_sensor_distance.cc index 02347e68dc..25af0e2aa0 100644 --- a/plugins/paintops/libpaintop/sensors/kis_dynamic_sensor_distance.cc +++ b/plugins/paintops/libpaintop/sensors/kis_dynamic_sensor_distance.cc @@ -1,84 +1,85 @@ /* * Copyright (c) 2007 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. + * the Free Software Foundation; 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 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_dynamic_sensor_distance.h" #include #include #include "ui_SensorDistanceConfiguration.h" #include KisDynamicSensorDistance::KisDynamicSensorDistance() : KisDynamicSensor(DISTANCE) , m_periodic(true) { setLength(30); } qreal KisDynamicSensorDistance::value(const KisPaintInformation& pi) { if (pi.isHoveringMode()) return 1.0; const qreal distance = m_periodic ? fmod(pi.totalStrokeLength(), m_length) : qMin(pi.totalStrokeLength(), (qreal)m_length); return distance / m_length; } void KisDynamicSensorDistance::setPeriodic(bool periodic) { m_periodic = periodic; } void KisDynamicSensorDistance::setLength(int length) { m_length = length; } QWidget* KisDynamicSensorDistance::createConfigurationWidget(QWidget* parent, QWidget* ss) { QWidget* wdg = new QWidget(parent); Ui_SensorDistanceConfiguration stc; stc.setupUi(wdg); stc.checkBoxRepeat->setChecked(m_periodic); connect(stc.checkBoxRepeat, SIGNAL(toggled(bool)), SLOT(setPeriodic(bool))); connect(stc.checkBoxRepeat, SIGNAL(toggled(bool)), ss, SIGNAL(parametersChanged())); stc.spinBoxLength->setValue(m_length); connect(stc.spinBoxLength, SIGNAL(valueChanged(int)), SLOT(setLength(int))); connect(stc.spinBoxLength, SIGNAL(valueChanged(int)), ss, SIGNAL(parametersChanged())); return wdg; } void KisDynamicSensorDistance::toXML(QDomDocument& doc, QDomElement& e) const { KisDynamicSensor::toXML(doc, e); e.setAttribute("periodic", m_periodic); e.setAttribute("length", m_length); } void KisDynamicSensorDistance::fromXML(const QDomElement& e) { KisDynamicSensor::fromXML(e); m_periodic = e.attribute("periodic", "0").toInt(); m_length = e.attribute("length", "30").toInt(); } diff --git a/plugins/paintops/libpaintop/sensors/kis_dynamic_sensor_distance.h b/plugins/paintops/libpaintop/sensors/kis_dynamic_sensor_distance.h index 7cc1b7093a..b63c0c9f9a 100644 --- a/plugins/paintops/libpaintop/sensors/kis_dynamic_sensor_distance.h +++ b/plugins/paintops/libpaintop/sensors/kis_dynamic_sensor_distance.h @@ -1,45 +1,46 @@ /* * Copyright (c) 2006 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. + * the Free Software Foundation; 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 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_DYNAMIC_SENSOR_DISTANCE_H_ #define _KIS_DYNAMIC_SENSOR_DISTANCE_H_ #include "kis_dynamic_sensor.h" // class KisDynamicSensorDistance : public QObject, public KisDynamicSensor { Q_OBJECT public: using KisSerializableConfiguration::fromXML; using KisSerializableConfiguration::toXML; KisDynamicSensorDistance(); ~KisDynamicSensorDistance() override { } qreal value(const KisPaintInformation&) override; QWidget* createConfigurationWidget(QWidget* parent, QWidget*) override; public Q_SLOTS: virtual void setPeriodic(bool periodic); virtual void setLength(int length); void toXML(QDomDocument&, QDomElement&) const override; void fromXML(const QDomElement&) override; private: bool m_periodic; }; #endif diff --git a/plugins/paintops/libpaintop/sensors/kis_dynamic_sensor_fade.cpp b/plugins/paintops/libpaintop/sensors/kis_dynamic_sensor_fade.cpp index 8eeff9ae21..b3eb6f119b 100644 --- a/plugins/paintops/libpaintop/sensors/kis_dynamic_sensor_fade.cpp +++ b/plugins/paintops/libpaintop/sensors/kis_dynamic_sensor_fade.cpp @@ -1,89 +1,90 @@ /* * Copyright (c) 2010 Lukáš Tvrdý * * 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. + * the Free Software Foundation; 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 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_dynamic_sensor_fade.h" #include #include #include "ui_SensorFadeConfiguration.h" #include static const int DEFAULT_LENGTH = 1000; KisDynamicSensorFade::KisDynamicSensorFade() : KisDynamicSensor(FADE) , m_periodic(false) { setLength(DEFAULT_LENGTH); } qreal KisDynamicSensorFade::value(const KisPaintInformation& pi) { if (pi.isHoveringMode()) return 1.0; const int currentValue = m_periodic ? pi.currentDabSeqNo() % m_length : qMin(pi.currentDabSeqNo(), m_length); return qreal(currentValue) / m_length; } void KisDynamicSensorFade::setPeriodic(bool periodic) { m_periodic = periodic; } void KisDynamicSensorFade::setLength(int length) { m_length = length; } QWidget* KisDynamicSensorFade::createConfigurationWidget(QWidget* parent, QWidget* ss) { QWidget* wdg = new QWidget(parent); Ui_SensorFadeConfiguration stc; stc.setupUi(wdg); stc.checkBoxRepeat->setChecked(m_periodic); stc.spinBoxLength->setSuffix(i18n(" px")); stc.spinBoxLength->setExponentRatio(3.0); connect(stc.checkBoxRepeat, SIGNAL(toggled(bool)), SLOT(setPeriodic(bool))); connect(stc.checkBoxRepeat, SIGNAL(toggled(bool)), ss, SIGNAL(parametersChanged())); stc.spinBoxLength->setValue(m_length); connect(stc.spinBoxLength, SIGNAL(valueChanged(int)), SLOT(setLength(int))); connect(stc.spinBoxLength, SIGNAL(valueChanged(int)), ss, SIGNAL(parametersChanged())); return wdg; } void KisDynamicSensorFade::toXML(QDomDocument& doc, QDomElement& e) const { KisDynamicSensor::toXML(doc, e); e.setAttribute("periodic", m_periodic); e.setAttribute("length", m_length); } void KisDynamicSensorFade::fromXML(const QDomElement& e) { KisDynamicSensor::fromXML(e); m_periodic = e.attribute("periodic", "0").toInt(); m_length = e.attribute("length", QString::number(DEFAULT_LENGTH)).toInt(); } diff --git a/plugins/paintops/libpaintop/sensors/kis_dynamic_sensor_fade.h b/plugins/paintops/libpaintop/sensors/kis_dynamic_sensor_fade.h index 4384b93d89..3c5d5af6e2 100644 --- a/plugins/paintops/libpaintop/sensors/kis_dynamic_sensor_fade.h +++ b/plugins/paintops/libpaintop/sensors/kis_dynamic_sensor_fade.h @@ -1,46 +1,47 @@ /* * Copyright (c) 2010 Lukáš Tvrdý * * 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. + * the Free Software Foundation; 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 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_DYNAMIC_SENSOR_FADE_H_ #define _KIS_DYNAMIC_SENSOR_FADE_H_ #include "kis_dynamic_sensor.h" class KisDynamicSensorFade : public QObject, public KisDynamicSensor { Q_OBJECT public: using KisSerializableConfiguration::fromXML; using KisSerializableConfiguration::toXML; KisDynamicSensorFade(); ~KisDynamicSensorFade() override { } qreal value(const KisPaintInformation&) override; QWidget* createConfigurationWidget(QWidget* parent, QWidget*) override; public Q_SLOTS: virtual void setPeriodic(bool periodic); virtual void setLength(int length); void toXML(QDomDocument&, QDomElement&) const override; void fromXML(const QDomElement&) override; private: bool m_periodic; }; #endif diff --git a/plugins/paintops/libpaintop/sensors/kis_dynamic_sensor_time.cc b/plugins/paintops/libpaintop/sensors/kis_dynamic_sensor_time.cc index 9c9a4d9fad..ec1385b7da 100644 --- a/plugins/paintops/libpaintop/sensors/kis_dynamic_sensor_time.cc +++ b/plugins/paintops/libpaintop/sensors/kis_dynamic_sensor_time.cc @@ -1,94 +1,95 @@ /* * Copyright (c) 2007,2010 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. + * the Free Software Foundation; 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 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_dynamic_sensor_time.h" #include #include #include "ui_SensorTimeConfiguration.h" #include KisDynamicSensorTime::KisDynamicSensorTime() : KisDynamicSensor(TIME) , m_periodic(true) { setLength(3); } qreal KisDynamicSensorTime::value(const KisPaintInformation& pi) { if (pi.isHoveringMode()) return 1.0; const qreal currentTime = m_periodic ? std::fmod(pi.currentTime(), m_length) : qMin(pi.currentTime(), qreal(m_length)); return currentTime / qreal(m_length); } void KisDynamicSensorTime::reset() { } void KisDynamicSensorTime::setPeriodic(bool periodic) { m_periodic = periodic; } void KisDynamicSensorTime::setLength(qreal length) { m_length = (int)(length * 1000); // convert to milliseconds } QWidget* KisDynamicSensorTime::createConfigurationWidget(QWidget* parent, QWidget* ss) { QWidget* wdg = new QWidget(parent); Ui_SensorTimeConfiguration stc; stc.setupUi(wdg); stc.checkBoxRepeat->setChecked(m_periodic); connect(stc.checkBoxRepeat, SIGNAL(toggled(bool)), SLOT(setPeriodic(bool))); connect(stc.checkBoxRepeat, SIGNAL(toggled(bool)), ss, SIGNAL(parametersChanged())); stc.spinBoxDuration->setRange(0.02, 10.0, 2); stc.spinBoxDuration->setSuffix(i18n(" s")); stc.spinBoxDuration->setValue(m_length / 1000); connect(stc.spinBoxDuration, SIGNAL(valueChanged(qreal)), SLOT(setLength(qreal))); connect(stc.spinBoxDuration, SIGNAL(valueChanged(qreal)), ss, SIGNAL(parametersChanged())); return wdg; } void KisDynamicSensorTime::toXML(QDomDocument& doc, QDomElement& e) const { KisDynamicSensor::toXML(doc, e); e.setAttribute("periodic", m_periodic); e.setAttribute("duration", m_length); } void KisDynamicSensorTime::fromXML(const QDomElement& e) { KisDynamicSensor::fromXML(e); m_periodic = e.attribute("periodic", "0").toInt(); m_length = e.attribute("duration", "30").toInt(); } diff --git a/plugins/paintops/libpaintop/sensors/kis_dynamic_sensor_time.h b/plugins/paintops/libpaintop/sensors/kis_dynamic_sensor_time.h index 82e458cdc0..5a982dc532 100644 --- a/plugins/paintops/libpaintop/sensors/kis_dynamic_sensor_time.h +++ b/plugins/paintops/libpaintop/sensors/kis_dynamic_sensor_time.h @@ -1,47 +1,48 @@ /* * Copyright (c) 2006 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. + * the Free Software Foundation; 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 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_DYNAMIC_SENSOR_TIME_H_ #define _KIS_DYNAMIC_SENSOR_TIME_H_ #include "kis_dynamic_sensor.h" // class KisDynamicSensorTime : public QObject, public KisDynamicSensor { Q_OBJECT public: using KisSerializableConfiguration::fromXML; using KisSerializableConfiguration::toXML; KisDynamicSensorTime(); ~KisDynamicSensorTime() override { } qreal value(const KisPaintInformation&) override; void reset() override; QWidget* createConfigurationWidget(QWidget* parent, QWidget*) override; public Q_SLOTS: virtual void setPeriodic(bool periodic); virtual void setLength(qreal length); void toXML(QDomDocument&, QDomElement&) const override; void fromXML(const QDomElement&) override; private: bool m_periodic; }; #endif diff --git a/plugins/paintops/libpaintop/sensors/kis_dynamic_sensors.cc b/plugins/paintops/libpaintop/sensors/kis_dynamic_sensors.cc index f29e6c09b4..c871947bc4 100644 --- a/plugins/paintops/libpaintop/sensors/kis_dynamic_sensors.cc +++ b/plugins/paintops/libpaintop/sensors/kis_dynamic_sensors.cc @@ -1,96 +1,97 @@ /* * Copyright (c) 2007,2010 Cyrille Berger * Copyright (c) 2011 Lukáš Tvrdý * * 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. + * the Free Software Foundation; 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 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_dynamic_sensors.h" KisDynamicSensorSpeed::KisDynamicSensorSpeed() : KisDynamicSensor(SPEED) { } qreal KisDynamicSensorSpeed::value(const KisPaintInformation& info) { /** * The value of maximum speed was measured empirically. This is * the speed that is quite easy to get with an A6 tablet and quite * a big image. If you need smaller speeds, just change the curve. */ const qreal maxSpeed = 30.0; // px / ms const qreal blendExponent = 0.05; qreal currentSpeed = info.drawingSpeed() / maxSpeed; if (m_speed >= 0.0) { m_speed = qMin(1.0, (m_speed * (1 - blendExponent) + currentSpeed * blendExponent)); } else { m_speed = currentSpeed; } return m_speed; } KisDynamicSensorRotation::KisDynamicSensorRotation() : KisDynamicSensor(ROTATION) { } KisDynamicSensorPressure::KisDynamicSensorPressure() : KisDynamicSensor(PRESSURE) { } KisDynamicSensorPressureIn::KisDynamicSensorPressureIn() : KisDynamicSensor(PRESSURE_IN) , lastPressure(0.0) { } KisDynamicSensorXTilt::KisDynamicSensorXTilt() : KisDynamicSensor(XTILT) { } KisDynamicSensorYTilt::KisDynamicSensorYTilt() : KisDynamicSensor(YTILT) { } KisDynamicSensorTiltDirection::KisDynamicSensorTiltDirection() : KisDynamicSensor(TILT_DIRECTION) { } KisDynamicSensorTiltElevation::KisDynamicSensorTiltElevation() : KisDynamicSensor(TILT_ELEVATATION) { } KisDynamicSensorPerspective::KisDynamicSensorPerspective() : KisDynamicSensor(PERSPECTIVE) { } KisDynamicSensorTangentialPressure::KisDynamicSensorTangentialPressure() : KisDynamicSensor(TANGENTIAL_PRESSURE) { } diff --git a/plugins/paintops/libpaintop/sensors/kis_dynamic_sensors.h b/plugins/paintops/libpaintop/sensors/kis_dynamic_sensors.h index 1d21d68fb0..e2c05c7e94 100644 --- a/plugins/paintops/libpaintop/sensors/kis_dynamic_sensors.h +++ b/plugins/paintops/libpaintop/sensors/kis_dynamic_sensors.h @@ -1,140 +1,141 @@ /* * Copyright (c) 2006-2007,2010 Cyrille Berger * Copyright (c) 2011 Lukáš Tvrdý * * 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. + * the Free Software Foundation; 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 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_DYNAMIC_SENSORS_H_ #define _KIS_DYNAMIC_SENSORS_H_ #include "../kis_dynamic_sensor.h" #include class KisDynamicSensorSpeed : public KisDynamicSensor { public: KisDynamicSensorSpeed(); ~KisDynamicSensorSpeed() override { } qreal value(const KisPaintInformation& info) override; void reset() override { m_speed = -1.0; } private: double m_speed; }; class KisDynamicSensorRotation : public KisDynamicSensor { public: KisDynamicSensorRotation(); ~KisDynamicSensorRotation() override { } qreal value(const KisPaintInformation& info) override { return info.rotation() / 360.0; } }; class KisDynamicSensorPressure : public KisDynamicSensor { public: KisDynamicSensorPressure(); ~KisDynamicSensorPressure() override { } qreal value(const KisPaintInformation& info) override { return info.pressure(); } }; class KisDynamicSensorPressureIn : public KisDynamicSensor { public: KisDynamicSensorPressureIn(); ~KisDynamicSensorPressureIn() override { } qreal value(const KisPaintInformation& info) override { if(!info.isHoveringMode()) { if(info.pressure() > lastPressure) { lastPressure = info.pressure(); } return lastPressure; } lastPressure = 0.0; return 0.0; } private: qreal lastPressure; }; class KisDynamicSensorXTilt : public KisDynamicSensor { public: KisDynamicSensorXTilt(); ~KisDynamicSensorXTilt() override { } qreal value(const KisPaintInformation& info) override { return 1.0 - fabs(info.xTilt()) / 60.0; } }; class KisDynamicSensorYTilt : public KisDynamicSensor { public: KisDynamicSensorYTilt(); ~KisDynamicSensorYTilt() override { } qreal value(const KisPaintInformation& info) override { return 1.0 - fabs(info.yTilt()) / 60.0; } }; class KisDynamicSensorTiltDirection : public KisDynamicSensor { public: KisDynamicSensorTiltDirection(); ~KisDynamicSensorTiltDirection() override {} qreal value(const KisPaintInformation& info) override { return KisPaintInformation::tiltDirection(info, true); } }; class KisDynamicSensorTiltElevation : public KisDynamicSensor { public: KisDynamicSensorTiltElevation(); ~KisDynamicSensorTiltElevation() override {} qreal value(const KisPaintInformation& info) override { return KisPaintInformation::tiltElevation(info, 60.0, 60.0, true); } }; class KisDynamicSensorPerspective : public KisDynamicSensor { public: KisDynamicSensorPerspective(); ~KisDynamicSensorPerspective() override { } qreal value(const KisPaintInformation& info) override { return info.perspective(); } }; class KisDynamicSensorTangentialPressure : public KisDynamicSensor { public: KisDynamicSensorTangentialPressure(); ~KisDynamicSensorTangentialPressure() override { } qreal value(const KisPaintInformation& info) override { return info.tangentialPressure(); } }; #endif diff --git a/plugins/tools/defaulttool/referenceimagestool/ToolReferenceImages.cpp b/plugins/tools/defaulttool/referenceimagestool/ToolReferenceImages.cpp index 80b7d34ef1..54f9dbbaa7 100644 --- a/plugins/tools/defaulttool/referenceimagestool/ToolReferenceImages.cpp +++ b/plugins/tools/defaulttool/referenceimagestool/ToolReferenceImages.cpp @@ -1,304 +1,305 @@ /* * Copyright (c) 2017 Boudewijn Rempt * * 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. + * the Free Software Foundation; 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 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 "ToolReferenceImages.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "ToolReferenceImagesWidget.h" #include "KisReferenceImageCollection.h" ToolReferenceImages::ToolReferenceImages(KoCanvasBase * canvas) : DefaultTool(canvas, false) { setObjectName("ToolReferenceImages"); } ToolReferenceImages::~ToolReferenceImages() { } void ToolReferenceImages::activate(ToolActivation toolActivation, const QSet &shapes) { DefaultTool::activate(toolActivation, shapes); auto kisCanvas = dynamic_cast(canvas()); connect(kisCanvas->image(), SIGNAL(sigNodeAddedAsync(KisNodeSP)), this, SLOT(slotNodeAdded(KisNodeSP))); connect(kisCanvas->imageView()->document(), &KisDocument::sigReferenceImagesLayerChanged, this, &ToolReferenceImages::slotNodeAdded); auto referenceImageLayer = document()->referenceImagesLayer(); if (referenceImageLayer) { setReferenceImageLayer(referenceImageLayer); } } void ToolReferenceImages::deactivate() { DefaultTool::deactivate(); } void ToolReferenceImages::slotNodeAdded(KisNodeSP node) { auto *referenceImagesLayer = dynamic_cast(node.data()); if (referenceImagesLayer) { setReferenceImageLayer(referenceImagesLayer); } } void ToolReferenceImages::setReferenceImageLayer(KisSharedPtr layer) { m_layer = layer; connect(layer.data(), SIGNAL(selectionChanged()), this, SLOT(slotSelectionChanged())); } void ToolReferenceImages::addReferenceImage() { auto kisCanvas = dynamic_cast(canvas()); KIS_ASSERT_RECOVER_RETURN(kisCanvas) KoFileDialog dialog(kisCanvas->viewManager()->mainWindow(), KoFileDialog::OpenFile, "OpenReferenceImage"); dialog.setCaption(i18n("Select a Reference Image")); QStringList locations = QStandardPaths::standardLocations(QStandardPaths::PicturesLocation); if (!locations.isEmpty()) { dialog.setDefaultDir(locations.first()); } QString filename = dialog.filename(); if (filename.isEmpty()) return; if (!QFileInfo(filename).exists()) return; auto *reference = KisReferenceImage::fromFile(filename, *kisCanvas->coordinatesConverter(), canvas()->canvasWidget()); if (reference) { KisDocument *doc = document(); doc->addCommand(KisReferenceImagesLayer::addReferenceImages(doc, {reference})); } } void ToolReferenceImages::pasteReferenceImage() { KisCanvas2* kisCanvas = dynamic_cast(canvas()); KIS_ASSERT_RECOVER_RETURN(kisCanvas) KisReferenceImage* reference = KisReferenceImage::fromClipboard(*kisCanvas->coordinatesConverter()); if(reference) { KisDocument *doc = document(); doc->addCommand(KisReferenceImagesLayer::addReferenceImages(doc, {reference})); } } void ToolReferenceImages::removeAllReferenceImages() { auto layer = m_layer.toStrongRef(); if (!layer) return; canvas()->addCommand(layer->removeReferenceImages(document(), layer->shapes())); } void ToolReferenceImages::loadReferenceImages() { auto kisCanvas = dynamic_cast(canvas()); KIS_ASSERT_RECOVER_RETURN(kisCanvas) KoFileDialog dialog(kisCanvas->viewManager()->mainWindow(), KoFileDialog::OpenFile, "OpenReferenceImageCollection"); dialog.setMimeTypeFilters(QStringList() << "application/x-krita-reference-images"); dialog.setCaption(i18n("Load Reference Images")); QStringList locations = QStandardPaths::standardLocations(QStandardPaths::PicturesLocation); if (!locations.isEmpty()) { dialog.setDefaultDir(locations.first()); } QString filename = dialog.filename(); if (filename.isEmpty()) return; if (!QFileInfo(filename).exists()) return; QFile file(filename); if (!file.open(QIODevice::ReadOnly)) { QMessageBox::critical(nullptr, i18nc("@title:window", "Krita"), i18n("Could not open '%1'.", filename)); return; } KisReferenceImageCollection collection; if (collection.load(&file)) { QList shapes; Q_FOREACH(auto *reference, collection.referenceImages()) { shapes.append(reference); } KisDocument *doc = document(); doc->addCommand(KisReferenceImagesLayer::addReferenceImages(doc, shapes)); } else { QMessageBox::critical(nullptr, i18nc("@title:window", "Krita"), i18n("Could not load reference images from '%1'.", filename)); } file.close(); } void ToolReferenceImages::saveReferenceImages() { auto layer = m_layer.toStrongRef(); if (!layer || layer->shapeCount() == 0) return; auto kisCanvas = dynamic_cast(canvas()); KIS_ASSERT_RECOVER_RETURN(kisCanvas) KoFileDialog dialog(kisCanvas->viewManager()->mainWindow(), KoFileDialog::SaveFile, "SaveReferenceImageCollection"); dialog.setMimeTypeFilters(QStringList() << "application/x-krita-reference-images"); dialog.setCaption(i18n("Save Reference Images")); QStringList locations = QStandardPaths::standardLocations(QStandardPaths::PicturesLocation); if (!locations.isEmpty()) { dialog.setDefaultDir(locations.first()); } QString filename = dialog.filename(); if (filename.isEmpty()) return; QFile file(filename); if (!file.open(QIODevice::WriteOnly)) { QMessageBox::critical(nullptr, i18nc("@title:window", "Krita"), i18n("Could not open '%1' for saving.", filename)); return; } KisReferenceImageCollection collection(layer->referenceImages()); bool ok = collection.save(&file); file.close(); if (!ok) { QMessageBox::critical(nullptr, i18nc("@title:window", "Krita"), i18n("Failed to save reference images.")); } } void ToolReferenceImages::slotSelectionChanged() { auto layer = m_layer.toStrongRef(); if (!layer) return; m_optionsWidget->selectionChanged(layer->shapeManager()->selection()); updateActions(); } QList> ToolReferenceImages::createOptionWidgets() { // Instead of inheriting DefaultTool's multi-tab implementation, inherit straight from KoToolBase return KoToolBase::createOptionWidgets(); } QWidget *ToolReferenceImages::createOptionWidget() { if (!m_optionsWidget) { m_optionsWidget = new ToolReferenceImagesWidget(this); // See https://bugs.kde.org/show_bug.cgi?id=316896 QWidget *specialSpacer = new QWidget(m_optionsWidget); specialSpacer->setObjectName("SpecialSpacer"); specialSpacer->setFixedSize(0, 0); m_optionsWidget->layout()->addWidget(specialSpacer); } return m_optionsWidget; } bool ToolReferenceImages::isValidForCurrentLayer() const { return true; } KoShapeManager *ToolReferenceImages::shapeManager() const { auto layer = m_layer.toStrongRef(); return layer ? layer->shapeManager() : nullptr; } KoSelection *ToolReferenceImages::koSelection() const { auto manager = shapeManager(); return manager ? manager->selection() : nullptr; } void ToolReferenceImages::updateDistinctiveActions(const QList &) { action("object_group")->setEnabled(false); action("object_unite")->setEnabled(false); action("object_intersect")->setEnabled(false); action("object_subtract")->setEnabled(false); action("object_split")->setEnabled(false); action("object_ungroup")->setEnabled(false); } void ToolReferenceImages::deleteSelection() { auto layer = m_layer.toStrongRef(); if (!layer) return; QList shapes = koSelection()->selectedShapes(); if (!shapes.empty()) { canvas()->addCommand(layer->removeReferenceImages(document(), shapes)); } } KisDocument *ToolReferenceImages::document() const { auto kisCanvas = dynamic_cast(canvas()); return kisCanvas->imageView()->document(); } QList ToolReferenceImagesFactory::createActionsImpl() { KisActionRegistry *actionRegistry = KisActionRegistry::instance(); QList actions = DefaultToolFactory::createActionsImpl(); actions << actionRegistry->makeQAction("object_order_front"); actions << actionRegistry->makeQAction("object_order_raise"); actions << actionRegistry->makeQAction("object_order_lower"); actions << actionRegistry->makeQAction("object_order_back"); actions << actionRegistry->makeQAction("object_group"); actions << actionRegistry->makeQAction("object_ungroup"); actions << actionRegistry->makeQAction("object_transform_rotate_90_cw"); actions << actionRegistry->makeQAction("object_transform_rotate_90_ccw"); actions << actionRegistry->makeQAction("object_transform_rotate_180"); actions << actionRegistry->makeQAction("object_transform_mirror_horizontally"); actions << actionRegistry->makeQAction("object_transform_mirror_vertically"); actions << actionRegistry->makeQAction("object_transform_reset"); actions << actionRegistry->makeQAction("object_unite"); actions << actionRegistry->makeQAction("object_intersect"); actions << actionRegistry->makeQAction("object_subtract"); actions << actionRegistry->makeQAction("object_split"); return actions; } diff --git a/plugins/tools/defaulttool/referenceimagestool/ToolReferenceImages.h b/plugins/tools/defaulttool/referenceimagestool/ToolReferenceImages.h index 02d4a3c327..9a430a6c56 100644 --- a/plugins/tools/defaulttool/referenceimagestool/ToolReferenceImages.h +++ b/plugins/tools/defaulttool/referenceimagestool/ToolReferenceImages.h @@ -1,111 +1,112 @@ /* * Copyright (c) 2017 Boudewijn Rempt * * 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. + * the Free Software Foundation; 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 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 TOOL_REFERENCE_IMAGES_H #define TOOL_REFERENCE_IMAGES_H #include #include #include #include #include "kis_painting_assistant.h" #include #include #include #include class ToolReferenceImagesWidget; class KisReferenceImagesLayer; class ToolReferenceImages : public DefaultTool { Q_OBJECT public: ToolReferenceImages(KoCanvasBase * canvas); ~ToolReferenceImages() override; virtual quint32 priority() { return 3; } void mouseDoubleClickEvent(KoPointerEvent */*event*/) override {} void deleteSelection() override; protected: QList> createOptionWidgets() override; QWidget *createOptionWidget() override; bool isValidForCurrentLayer() const override; KoShapeManager *shapeManager() const override; KoSelection *koSelection() const override; void updateDistinctiveActions(const QList &editableShapes) override; public Q_SLOTS: void activate(ToolActivation toolActivation, const QSet &shapes) override; void deactivate() override; void addReferenceImage(); void pasteReferenceImage(); void removeAllReferenceImages(); void saveReferenceImages(); void loadReferenceImages(); void slotNodeAdded(KisNodeSP node); void slotSelectionChanged(); private: friend class ToolReferenceImagesWidget; ToolReferenceImagesWidget *m_optionsWidget = nullptr; KisWeakSharedPtr m_layer; KisDocument *document() const; void setReferenceImageLayer(KisSharedPtr layer); }; class ToolReferenceImagesFactory : public DefaultToolFactory { public: ToolReferenceImagesFactory() : DefaultToolFactory("ToolReferenceImages") { setToolTip(i18n("Reference Images Tool")); setSection(TOOL_TYPE_VIEW); setIconName(koIconNameCStr("krita_tool_reference_images")); setPriority(2); setActivationShapeId(KRITA_TOOL_ACTIVATION_ID); }; ~ToolReferenceImagesFactory() override {} KoToolBase * createTool(KoCanvasBase * canvas) override { return new ToolReferenceImages(canvas); } QList createActionsImpl() override; }; #endif