diff --git a/libs/libkis/Action.cpp b/libs/libkis/Action.cpp index 1aa8bfd2eb..76793e496a 100644 --- a/libs/libkis/Action.cpp +++ b/libs/libkis/Action.cpp @@ -1,136 +1,148 @@ /* * Copyright (c) 2016 Boudewijn Rempt * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU 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 "Action.h" struct Action::Private { Private() {} QAction *action {0}; }; Action::Action(QObject *parent) : QObject(parent) , d(new Private) { d->action = new KisAction(this); d->action->setProperty("menu", "tools/scripts"); connect(d->action, SIGNAL(triggered(bool)), SIGNAL(triggered(bool))); } Action::Action(const QString &name, QAction *action, QObject *parent) : QObject(parent) , d(new Private) { d->action = action; d->action->setObjectName(name); d->action->setProperty("menu", "tools/scripts"); connect(d->action, SIGNAL(triggered(bool)), SIGNAL(triggered(bool))); } Action::~Action() { delete d; } +QString Action::text() const +{ + if (!d->action) return ""; + return d->action->text(); +} + +void Action::settext(QString text) +{ + if (!d->action) return; + d->action->setText(text); +} + QString Action::name() const { if (!d->action) return ""; return d->action->objectName(); } void Action::setName(QString name) { if (!d->action) return; d->action->setObjectName(name); } bool Action::isCheckable() const { if (!d->action) return false; return d->action->isCheckable(); } void Action::setCheckable(bool value) { if (!d->action) return; d->action->setCheckable(value); } bool Action::isChecked() const { if (!d->action) return false; return d->action->isChecked(); } void Action::setChecked(bool value) { if (!d->action) return; d->action->setChecked(value); } QString Action::shortcut() const { if (!d->action) return QString(); return d->action->shortcut().toString(); } void Action::setShortcut(QString value) { if (!d->action) return; d->action->setShortcut(QKeySequence::fromString(value)); } bool Action::isVisible() const { if (!d->action) return false; return d->action->property("menu").toString() == "tools/scripts"; } void Action::setVisible(bool value) { if (!d->action) return; if (value) { d->action->setProperty("menu", "tools/scripts"); } else { d->action->setProperty("menu", ""); } } bool Action::isEnabled() const { if (!d->action) return false; return d->action->isEnabled(); } void Action::setEnabled(bool value) { if (!d->action) return; d->action->setEnabled(value); } void Action::setToolTip(QString tooltip) { if (!d->action) return; d->action->setToolTip(tooltip); } void Action::trigger() { d->action->trigger(); } diff --git a/libs/libkis/Action.h b/libs/libkis/Action.h index 9cd17f2d75..1b6c0a1d09 100644 --- a/libs/libkis/Action.h +++ b/libs/libkis/Action.h @@ -1,77 +1,145 @@ /* * Copyright (c) 2016 Boudewijn Rempt * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU 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 LIBKIS_ACTION_H #define LIBKIS_ACTION_H #include #include "kritalibkis_export.h" #include "libkis.h" /** * Action encapsulates a KisAction. By default, actions are put in the Tools/Scripts menu. */ class KRITALIBKIS_EXPORT Action : public QObject { Q_OBJECT public: + /** + * @brief Action Create a new action object + * @param parent the parent if it's in a QObject hierarchy + */ explicit Action(QObject *parent = 0); + + /** + * @brief Action Create a new action object + * @param name the name of the action + * @param action the QAction it wraps + * @param parent the parent if it's in a QObject hierarchy + */ Action(const QString &name, QAction *action, QObject *parent = 0); virtual ~Action(); public Q_SLOTS: + /** + * @return the user-visible text of the action. + */ + QString text() const; + + /** + * set the user-visible text of the action to @param text. + */ + void settext(QString text); + + /** + * @return the internal name of the action. + */ QString name() const; + + /** + * set the name of the action to @param name. This is not the user-visible name, but the internal one + */ void setName(QString name); + /** + * @return true if the action is checkable, false if it isn't* + */ bool isCheckable() const; + + /** + * Set the action action checkable if @param value is true, unchecked if it's false + */ void setCheckable(bool value); + /** + * @return true if the action is checked, false if it isn't + */ bool isChecked() const; + + /** + * Set the action checked if @param value is true, unchecked if it's false + */ void setChecked(bool value); + /** + * Return the action's shortcut as a string + */ QString shortcut() const; + + /** + * set the action's shortcut to the given string. + * @code + * action.setShortcut("CTRL+SHIFT+S") + * @endcode + */ void setShortcut(QString value); bool isVisible() const; /** * @brief setVisible determines whether the action will be visible in the scripting menu. * @param value true if the action is to be shown in the menu, false otherwise */ void setVisible(bool value); + /** + * @return true if the action is enabled, false if not + */ bool isEnabled() const; + + /** + * Set the action enabled or disabled according to @param value + */ void setEnabled(bool value); + /** + * Set the tooltip to the given @param tooltip + */ void setToolTip(QString tooltip); + /** + * Trigger this action + */ void trigger(); Q_SIGNALS: + /** + * Emitted whenever the action is triggered. + */ void triggered(bool); private: struct Private; Private *const d; }; #endif // LIBKIS_ACTION_H diff --git a/libs/libkis/Canvas.cpp b/libs/libkis/Canvas.cpp index e2b27aa309..c378bf89e2 100644 --- a/libs/libkis/Canvas.cpp +++ b/libs/libkis/Canvas.cpp @@ -1,124 +1,124 @@ /* * Copyright (c) 2016 Boudewijn Rempt * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU 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 "Canvas.h" #include #include #include #include #include #include #include #include struct Canvas::Private { Private() {} KisCanvas2 *canvas; }; Canvas::Canvas(KoCanvasBase *canvas, QObject *parent) : QObject(parent) , d(new Private) { d->canvas = static_cast(canvas); } Canvas::~Canvas() { delete d; } qreal Canvas::zoomLevel() const { - if (!d->canvas) return 100; + if (!d->canvas) return 1.0; return d->canvas->imageView()->zoomManager()->zoom(); } void Canvas::setZoomLevel(qreal value) { if (!d->canvas) return; d->canvas->imageView()->zoomController()->setZoom(KoZoomMode::ZOOM_CONSTANT, value); } void Canvas::resetZoom() { if (!d->canvas) return; d->canvas->imageView()->zoomManager()->zoomTo100(); } void Canvas::resetRotation() { if (!d->canvas) return; d->canvas->imageView()->canvasController()->resetCanvasRotation(); } qreal Canvas::rotation() const { if (!d->canvas) return 0; return d->canvas->imageView()->canvasController()->rotation(); } void Canvas::setRotation(qreal angle) { if (!d->canvas) return; d->canvas->imageView()->canvasController()->rotateCanvas(angle); } bool Canvas::mirror() const { if (!d->canvas) return false; return d->canvas->imageView()->canvasIsMirrored(); } void Canvas::setMirror(bool value) { if (!d->canvas) return; d->canvas->imageView()->canvasController()->mirrorCanvas(value); } View *Canvas::view() const { if (!d->canvas) return 0; View *view = new View(d->canvas->imageView()); return view; } bool Canvas::wrapAroundMode() const { if (!d->canvas) return false; return d->canvas->imageView()->canvasController()->levelOfDetailMode(); } void Canvas::setWrapAroundMode(bool enable) { if (!d->canvas) return; d->canvas->imageView()->canvasController()->slotToggleWrapAroundMode(enable); } bool Canvas::levelOfDetailMode() const { if (!d->canvas) return false; return d->canvas->imageView()->canvasController()->levelOfDetailMode(); } void Canvas::setLevelOfDetailMode(bool enable) { if (!d->canvas) return; return d->canvas->imageView()->canvasController()->slotToggleLevelOfDetailMode(enable); } diff --git a/libs/libkis/Canvas.h b/libs/libkis/Canvas.h index 1e510b5918..1bbff3040f 100644 --- a/libs/libkis/Canvas.h +++ b/libs/libkis/Canvas.h @@ -1,67 +1,116 @@ /* * Copyright (c) 2016 Boudewijn Rempt * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU 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 LIBKIS_CANVAS_H #define LIBKIS_CANVAS_H #include #include "kritalibkis_export.h" #include "libkis.h" class KoCanvasBase; /** - * Canvas + * Canvas wraps the canvas inside a view on an image/document. + * It is responsible for the view parameters of the document: + * zoom, rotation, mirror, wraparound and instant preview. */ class KRITALIBKIS_EXPORT Canvas : public QObject { Q_OBJECT - Q_DISABLE_COPY(Canvas) public: explicit Canvas(KoCanvasBase *canvas, QObject *parent = 0); virtual ~Canvas(); public Q_SLOTS: + /** + * @return the current zoomlevel. 1.0 is 100%. + */ qreal zoomLevel() const; + + /** + * @brief setZoomLevel set the zoomlevel to the given @param value. 1.0 is 100%. + */ void setZoomLevel(qreal value); + + /** + * @brief resetZoom set the zoomlevel to 100% + */ void resetZoom(); - void resetRotation(); + /** + * @return the rotation of the canvas in degrees. + */ qreal rotation() const; + + /** + * @brief setRotation set the rotation of the canvas to the given @param angle in degrees. + */ void setRotation(qreal angle); + /** + * @brief resetRotation reset the canvas rotation. + */ + void resetRotation(); + + /** + * @return return true if the canvas is mirrored, false otherwise. + */ bool mirror() const; + + /** + * @brief setMirror turn the canvas mirroring on or off depending on @param value + */ void setMirror(bool value); + /** + * @return true if the canvas is in wraparound mode, false if not. Only when OpenGL is enabled, + * is wraparound mode available. + */ bool wrapAroundMode() const; + + /** + * @brief setWrapAroundMode set wraparound mode to @param enable + */ void setWrapAroundMode(bool enable); + /** + * @return true if the canvas is in Instant Preview mode, false if not. Only when OpenGL is enabled, + * is Instant Preview mode available. + */ bool levelOfDetailMode() const; + + /** + * @brief setLevelOfDetailMode sets Instant Preview to @param enable + */ void setLevelOfDetailMode(bool enable); + /** + * @return the view that holds this canvas + */ View *view() const; private: struct Private; Private *const d; }; #endif // LIBKIS_CANVAS_H diff --git a/libs/libkis/DockWidget.cpp b/libs/libkis/DockWidget.cpp index 0041f0e7c4..f7cc48d949 100644 --- a/libs/libkis/DockWidget.cpp +++ b/libs/libkis/DockWidget.cpp @@ -1,58 +1,58 @@ /* * Copyright (c) 2016 Boudewijn Rempt * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU 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 "DockWidget.h" #include #include #include "Canvas.h" struct DockWidget::Private { Private() {} Canvas *canvas {0}; }; DockWidget::DockWidget() : QDockWidget() , d(new Private) { } DockWidget::~DockWidget() { delete d; } Canvas* DockWidget::canvas() const { - return 0; + return d->canvas; } void DockWidget::setCanvas(KoCanvasBase* canvas) { delete d->canvas; d->canvas = new Canvas(canvas); canvasChanged(d->canvas); } void DockWidget::unsetCanvas() { delete d->canvas; d->canvas = 0; } diff --git a/libs/libkis/DockWidget.h b/libs/libkis/DockWidget.h index 61f775dac2..e038268151 100644 --- a/libs/libkis/DockWidget.h +++ b/libs/libkis/DockWidget.h @@ -1,58 +1,87 @@ /* * Copyright (c) 2016 Boudewijn Rempt * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU 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 LIBKIS_DOCKWIDGET_H #define LIBKIS_DOCKWIDGET_H #include #include "kritalibkis_export.h" #include "libkis.h" #include class KoCanvasBase; /** - * DockWidget + * DockWidget is the base class for custom Dockers. Dockers are created by a + * factory class which needs to be registered by calling Application.addDockWidgetFactory: + * + * @code + * class HelloDocker(DockWidget): + * def __init__(self): + * super().__init__() + * label = QLabel("Hello", self) + * self.setWidget(label) + * self.label = label + * + * def canvasChanged(self, canvas): + * self.label.setText("Hellodocker: canvas changed"); + * + * Application.addDockWidgetFactory(DockWidgetFactory("hello", DockWidgetFactoryBase.DockRight, HelloDocker)) + * + * @endcode + * + * One docker per window will be created, not one docker per canvas or view. When the user + * switches between views/canvases, canvasChanged will be called. You can override that + * method to reset your docker's internal state, if necessary. */ class KRITALIBKIS_EXPORT DockWidget : public QDockWidget, public KoCanvasObserverBase { Q_OBJECT Q_DISABLE_COPY(DockWidget) public: explicit DockWidget(); virtual ~DockWidget(); protected Q_SLOTS: // Krita API virtual void setCanvas(KoCanvasBase* canvas); virtual void unsetCanvas(); protected Q_SLOTS: // PyKrita API + /** + * @@return the canvas object that this docker is currently associated with + */ Canvas* canvas() const; + + /** + * @brief canvasChanged is called whenever the current canvas is changed + * in the mainwindow this dockwidget instance is shown in. + * @param canvas The new canvas. + */ virtual void canvasChanged(Canvas *canvas) = 0; private: struct Private; Private *const d; }; #endif // LIBKIS_DOCKWIDGET_H diff --git a/libs/libkis/DockWidgetFactoryBase.h b/libs/libkis/DockWidgetFactoryBase.h index d06f384451..0eb2920933 100644 --- a/libs/libkis/DockWidgetFactoryBase.h +++ b/libs/libkis/DockWidgetFactoryBase.h @@ -1,42 +1,63 @@ /* * Copyright (c) 2015 Cyrille Berger * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU 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 LIBKIS_DOCKWIDGETFACTORY_H #define LIBKIS_DOCKWIDGETFACTORY_H #include #include #include "kritalibkis_export.h" +/** + * @brief The DockWidgetFactoryBase class is the base class for plugins that want + * to add a dock widget to every window. You do not need to implement this class + * yourself, but create a DockWidget implementation and then add the DockWidgetFactory + * to the Krita instance like this: + * + * @code + * class HelloDocker(DockWidget): + * def __init__(self): + * super().__init__() + * label = QLabel("Hello", self) + * self.setWidget(label) + * self.label = label + * + * def canvasChanged(self, canvas): + * self.label.setText("Hellodocker: canvas changed"); + * + * Application.addDockWidgetFactory(DockWidgetFactory("hello", DockWidgetFactoryBase.DockRight, HelloDocker)) + * + * @endcode + */ class KRITALIBKIS_EXPORT DockWidgetFactoryBase : public KoDockFactoryBase { public: DockWidgetFactoryBase(const QString& _id, DockPosition _dockPosition, bool _isCollapsable = true, bool _defaultCollapsed = false); virtual ~DockWidgetFactoryBase(); virtual QString id() const; virtual DockPosition defaultDockPosition() const; virtual bool isCollapsable() const; virtual bool defaultCollapsed() const; private: QString m_id; DockPosition m_dockPosition; bool m_isCollapsable, m_defaultCollapsed; }; #endif diff --git a/libs/libkis/Document.h b/libs/libkis/Document.h index ba703a5d74..96e31d126d 100644 --- a/libs/libkis/Document.h +++ b/libs/libkis/Document.h @@ -1,319 +1,437 @@ /* * Copyright (c) 2016 Boudewijn Rempt * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU 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 LIBKIS_DOCUMENT_H #define LIBKIS_DOCUMENT_H #include #include "kritalibkis_export.h" #include "libkis.h" class KisDocument; /** * The Document class encapsulates a Krita Document/Image. A Krita document is an Image with - * a filename. + * a filename. Libkis does not differentiate between a document and an image, like Krita does + * internally. */ class KRITALIBKIS_EXPORT Document : public QObject { Q_OBJECT Q_DISABLE_COPY(Document) public: explicit Document(KisDocument *document, QObject *parent = 0); virtual ~Document(); public Q_SLOTS: + /** + * Batchmode means that no actions on the document should show dialogs or popups. + * @return true if the document is in batchmode. + */ bool batchmode() const; + + /** + * Set batchmode to @param value. If batchmode is true, then there should be no popups + * or dialogs shown to the user. + */ void setBatchmode(bool value); /** * @brief activeNode retrieve the node that is currently active in the currently active window * @return the active node. If there is no active window, the first child node is returned. */ Node* activeNode() const; /** * @brief setActiveNode make the given node active in the currently active view and window * @param value the node to make active. */ void setActiveNode(Node* value); /** * @brief toplevelNodels return a list with all top level nodes in the image graph */ QList toplevelNodes() const; /** * @brief nodeByName searches the node tree for a node with the given name and returns it * @param name the name of the node * @return the first node with the given name or 0 if no node is found */ Node *nodeByName(const QString &name) const; /** * colorDepth A string describing the color depth of the image: *
    *
  • U8: unsigned 8 bits integer, the most common type
  • *
  • U16: unsigned 16 bits integer
  • *
  • F16: half, 16 bits floating point. Only available if Krita was built with OpenEXR
  • *
  • F32: 32 bits floating point
  • *
* @return the color depth. */ QString colorDepth() const; /** * @brief colorModel retrieve the current color model of this document: *
    *
  • A: Alpha mask
  • *
  • RGBA: RGB with alpha channel (The actual order of channels is most often BGR!)
  • *
  • XYZA: XYZ with alpha channel
  • *
  • LABA: LAB with alpha channel
  • *
  • CMYKA: CMYK with alpha channel
  • *
  • GRAYA: Gray with alpha channel
  • *
  • YCbCrA: YCbCr with alpha channel
  • *
* @return the internal color model string. */ QString colorModel() const; /** * @return the name of the current color profile */ QString colorProfile() const; /** * @brief setColorProfile set the color profile of the image to the given profile. The profile has to * be registered with krita and be compatible with the current color model and depth; the image data * is not converted. * @param colorProfile * @return false if the colorProfile name does not correspond to to a registered profile or if assigning * the profile failed. */ bool setColorProfile(const QString &colorProfile); /** * @brief setColorSpace convert the nodes and the image to the given colorspace. The conversion is * done with Perceptual as intent, High Quality and No LCMS Optimizations as flags and no blackpoint * compensation. * * @param colorModel A string describing the color model of the image: *
    *
  • A: Alpha mask
  • *
  • RGBA: RGB with alpha channel (The actual order of channels is most often BGR!)
  • *
  • XYZA: XYZ with alpha channel
  • *
  • LABA: LAB with alpha channel
  • *
  • CMYKA: CMYK with alpha channel
  • *
  • GRAYA: Gray with alpha channel
  • *
  • YCbCrA: YCbCr with alpha channel
  • *
* @param colorDepth A string describing the color depth of the image: *
    *
  • U8: unsigned 8 bits integer, the most common type
  • *
  • U16: unsigned 16 bits integer
  • *
  • F16: half, 16 bits floating point. Only available if Krita was built with OpenEXR
  • *
  • F32: 32 bits floating point
  • *
* @param colorProfile a valid color profile for this color model and color depth combination. * @return false the combination of these arguments does not correspond to a colorspace. */ bool setColorSpace(const QString &colorModel, const QString &colorDepth, const QString &colorProfile); /** * @brief documentInfo creates and XML document representing document and author information. - * @return a string containing a valid XML document + * @return a string containing a valid XML document with the right information about the document + * and author. The DTD can be found here: + * + * https://phabricator.kde.org/source/krita/browse/master/krita/dtd/ + * + * @code + * + * + * + * + * My Document + * + * + * + * + * Unknown + * 1 + * 35 + * 2017-02-27T20:15:09 + * 2017-02-27T20:14:33 + * + * + * + * Boudewijn Rempt + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * @endcode + * */ QString documentInfo() const; + + /** + * @brief setDocumentInfo set the Document information to the information contained in document + * @param document A string containing a valid XML document that conforms to the document-info DTD + * that can be found here: + * + * https://phabricator.kde.org/source/krita/browse/master/krita/dtd/ + */ void setDocumentInfo(const QString &document); + /** + * @return the full path to the document, if it has been set. + */ QString fileName() const; + + /** + * @brief setFileName set the full path of the document to @param value + */ void setFileName(QString value); + /** + * @return the height of the image in pixels + */ int height() const; + + /** + * @brief setHeight resize the document to @param value height. This is a canvas resize, not a scale. + */ void setHeight(int value); + /** + * @return the name of the document. This is the title field in the @see documentInfo + */ QString name() const; + + /** + * @brief setName sets the name of the document to @param value. This is the title field in the @see documentInfo + */ void setName(QString value); /** * @return the resolution in pixels per inch */ int resolution() const; /** * @brief setResolution set the resolution of the image; this does not scale the image * @param value the resolution in pixels per inch */ void setResolution(int value); /** * @brief rootNode the root node is the invisible group layer that contains the entire node * hierarchy. * @return the root of the image */ Node* rootNode() const; /** * @brief selection Create a Selection object around the global selection, if there is one. * @return the global selection or None if there is no global selection. */ Selection* selection() const; /** * @brief setSelection set or replace the global selection * @param value a valid selection object. */ void setSelection(Selection* value); + /** + * @return the width of the image in pixels. + */ int width() const; + + /** + * @brief setWidth resize the document to @param value width. This is a canvas resize, not a scale. + */ void setWidth(int value); /** * @return xRes the horizontal resolution of the image in pixels per pt (there are 72 pts to an inch) */ double xRes() const; + + /** + * @brief setXRes set the horizontal resolution of the image to xRes in pixels per pt. (there are 72 pts to an inch) + */ void setXRes(double xRes) const; /** * @return yRes the vertical resolution of the image in pixels per pt (there are 72 pts to an inch) */ double yRes() const; + + /** + * @brief setYRes set the vertical resolution of the image to yRes in pixels per pt. (there are 72 pts to an inch) + */ void setyRes(double yRes) const; /** * @brief pixelData reads the given rectangle from the image projection and returns it as a byte * array. The pixel data starts top-left, and is ordered row-first. * * The byte array can be interpreted as follows: 8 bits images have one byte per channel, * and as many bytes as there are channels. 16 bits integer images have two bytes per channel, * representing an unsigned short. 16 bits float images have two bytes per channel, representing * a half, or 16 bits float. 32 bits float images have four bytes per channel, representing a * float. * * You can read outside the image boundaries; those pixels will be transparent black. * * The order of channels is: * *
    *
  • Integer RGBA: Blue, Green, Red, Alpha *
  • Float RGBA: Red, Green, Blue, Alpha *
  • LabA: L, a, b, Alpha *
  • CMYKA: Cyan, Magenta, Yellow, Key, Alpha *
  • XYZA: X, Y, Z, A *
  • YCbCrA: Y, Cb, Cr, Alpha *
* * The byte array is a copy of the original image data. In Python, you can use bytes, bytearray * and the struct module to interpret the data and construct, for instance, a Pillow Image object. * * @param x x position from where to start reading * @param y y position from where to start reading * @param w row length to read * @param h number of rows to read * @return a QByteArray with the pixel data. The byte array may be empty. */ QByteArray pixelData(int x, int y, int w, int h) const; /** * @brief close Close the document: remove it from Krita's internal list of documents and * close all views. If the document is modified, you should save it first. There will be * no prompt for saving. * @return true if the document is closed. */ bool close(); + /** + * @brief crop the image to rectangle described by @param x, @param y, + * @param w and @param h + */ void crop(int x, int y, int w, int h); + /** + * @brief exportImage export the image, without changing its URL to the given path. + * @param filename the full path to which the image is to be saved + * @param exportConfiguration a configuration object appropriate to the file format + * @return true if the export succeeded, false if it failed. + */ bool exportImage(const QString &filename, const InfoObject &exportConfiguration); + /** + * @brief flatten all layers in the image + */ void flatten(); + /** + * @brief resizeImage resize the image to the given width and height. + * @param w the new width + * @param h the new height + */ void resizeImage(int w, int h); + /** + * @brief save the image to its currently set path. The modified flag of the + * document will be reset + * @return true if saving succeeded, false otherwise. + */ bool save(); + /** + * @brief saveAs save the document under the @param filename. The document's + * filename will be reset to @param filename. + * @param filename the new filename (full path) for the document + * @return true if saving succeeded, false otherwise. + */ bool saveAs(const QString &filename); /** * @brief createNode create a new node of the given type. The node is not added * to the node hierarchy; you need to do that by finding the right parent node, * getting its list of child nodes and adding the node in the right place, then * calling Node::SetChildNodes * * @param name The name of the node * * @param nodeType The type of the node. Valid types are: *
    *
  • paintlayer *
  • grouplayer *
  • filelayer *
  • filterlayer *
  • filllayer *
  • clonelayer *
  • vectorlayer *
  • transparencymask *
  • filtermask *
  • transformmask *
  • selectionmask *
* * When relevant, the new Node will have the colorspace of the image by default; * that can be changed with Node::setColorSpace. * * The settings and selections for relevant layer and mask types can also be set * after the Node has been created. * * @return the new Node. */ Node* createNode(const QString &name, const QString &nodeType); /** * @brief projection creates a QImage from the rendered image or * a cutout rectangle. */ QImage projection(int x = 0, int y = 0, int w = 0, int h = 0) const; /** * @brief thumbnail create a thumbnail of the given dimensions. * * If the requested size is too big a null QImage is created. * * @return a QImage representing the layer contents. */ QImage thumbnail(int w, int h) const; -Q_SIGNALS: - - void nodeCreated(Node *node); - private: friend class Krita; friend class Window; QPointer document() const; private: struct Private; Private *const d; }; #endif // LIBKIS_DOCUMENT_H diff --git a/libs/libkis/InfoObject.cpp b/libs/libkis/InfoObject.cpp index a761d74c07..c1ad4a773e 100644 --- a/libs/libkis/InfoObject.cpp +++ b/libs/libkis/InfoObject.cpp @@ -1,77 +1,78 @@ /* * Copyright (c) 2016 Boudewijn Rempt * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU 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 "InfoObject.h" #include struct InfoObject::Private { Private() {} KisPropertiesConfigurationSP properties; }; InfoObject::InfoObject(KisPropertiesConfigurationSP configuration) : QObject(0) , d(new Private) { d->properties = configuration; } InfoObject::InfoObject(QObject *parent) : QObject(parent) , d(new Private) { + d->properties = new KisPropertiesConfiguration(); } InfoObject::~InfoObject() { delete d; } QMap InfoObject::properties() const { return d->properties->getProperties(); } void InfoObject::setproperties(QMap proprertyMap) { Q_FOREACH(const QString & key, proprertyMap.keys()) { d->properties->setProperty(key, proprertyMap[key]); } } void InfoObject::setProperty(const QString &key, QVariant value) { d->properties->setProperty(key, value); } QVariant InfoObject::property(const QString &key) { QVariant v; if (d->properties->hasProperty(key)) { d->properties->getProperty(key, v); } return v; } KisPropertiesConfigurationSP InfoObject::configuration() const { return d->properties; } diff --git a/libs/libkis/InfoObject.h b/libs/libkis/InfoObject.h index 05ccfa4175..a6e3c4d26a 100644 --- a/libs/libkis/InfoObject.h +++ b/libs/libkis/InfoObject.h @@ -1,68 +1,84 @@ /* * Copyright (c) 2016 Boudewijn Rempt * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU 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 LIBKIS_INFOOBJECT_H #define LIBKIS_INFOOBJECT_H #include #include #include "kritalibkis_export.h" #include "libkis.h" /** - * InfoObject + * InfoObject wrap a properties map. These maps can be used to set the + * configuration for filters. */ class KRITALIBKIS_EXPORT InfoObject : public QObject { Q_OBJECT Q_DISABLE_COPY(InfoObject) Q_PROPERTY(QMap properties READ properties WRITE setproperties) public: InfoObject(KisPropertiesConfigurationSP configuration); + + /** + * Create a new, empty InfoObject. + */ explicit InfoObject(QObject *parent = 0); virtual ~InfoObject(); + /** + * Return all properties this InfoObject manages. + */ QMap properties() const; - void setproperties(QMap proprertyMap); + /** + * Add all properties in the @param propertyMap to this InfoObject + */ + void setproperties(QMap proprertyMap); public Q_SLOTS: - + /** + * set the property identified by @key to @value + */ void setProperty(const QString &key, QVariant value); - QVariant property(const QString &key); + /** + * return the value for the property identified by key, or None if there is no suck key. + */ + QVariant property(const QString &key); private: friend class Filter; friend class Document; /** * @brief configuration gives access to the internal configuration object. Must * be used used internally in libkis * @return the internal configuration object. */ KisPropertiesConfigurationSP configuration() const; struct Private; Private *d; }; #endif // LIBKIS_INFOOBJECT_H diff --git a/libs/libkis/Krita.cpp b/libs/libkis/Krita.cpp index b59eb8f6ed..0275aeb97e 100644 --- a/libs/libkis/Krita.cpp +++ b/libs/libkis/Krita.cpp @@ -1,377 +1,377 @@ /* * Copyright (c) 2016 Boudewijn Rempt * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU 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 "Krita.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 "View.h" #include "Document.h" #include "Window.h" #include "Extension.h" #include "DockWidgetFactoryBase.h" #include "Filter.h" #include "InfoObject.h" #include "Resource.h" Krita* Krita::s_instance = 0; struct Krita::Private { Private() {} - QList viewExtensions; + QList extensions; bool batchMode {false}; Notifier *notifier{new Notifier()}; }; Krita::Krita(QObject *parent) : QObject(parent) , d(new Private) { qRegisterMetaType(); } Krita::~Krita() { - qDeleteAll(d->viewExtensions); + qDeleteAll(d->extensions); delete d->notifier; delete d; } QList Krita::actions() const { QList actionList; KisMainWindow *mainWindow = KisPart::instance()->currentMainwindow(); if (!mainWindow) { return actionList; } KActionCollection *actionCollection = mainWindow->actionCollection(); Q_FOREACH(QAction *action, actionCollection->actions()) { actionList << new Action(action->objectName(), action); } return actionList; } Action *Krita::action(const QString &name) const { KisMainWindow *mainWindow = KisPart::instance()->currentMainwindow(); if (!mainWindow) { return 0; } KActionCollection *actionCollection = mainWindow->actionCollection(); QAction *action = actionCollection->action(name); if (action) { return new Action(name, action); } return 0; } Document* Krita::activeDocument() const { KisMainWindow *mainWindow = KisPart::instance()->currentMainwindow(); if (!mainWindow) { return 0; } KisView *view = mainWindow->activeView(); if (!view) { return 0; } KisDocument *document = view->document(); return new Document(document); } void Krita::setActiveDocument(Document* value) { Q_FOREACH(KisView *view, KisPart::instance()->views()) { if (view->document() == value->document().data()) { view->activateWindow(); break; } } } bool Krita::batchmode() const { return d->batchMode; } void Krita::setBatchmode(bool value) { d->batchMode = value; } QList Krita::documents() const { QList ret; foreach(QPointer doc, KisPart::instance()->documents()) { ret << new Document(doc); } return ret; } QStringList Krita::filters() const { QStringList ls = KisFilterRegistry::instance()->keys(); qSort(ls); return ls; } Filter *Krita::filter(const QString &name) const { if (!filters().contains(name)) return 0; Filter *filter = new Filter(); filter->setName(name); KisFilterSP f = KisFilterRegistry::instance()->value(name); KisFilterConfigurationSP fc = f->defaultConfiguration(); InfoObject *info = new InfoObject(fc); filter->setConfiguration(info); return filter; } QStringList Krita::profiles(const QString &colorModel, const QString &colorDepth) const { QSet profileNames; QString id = KoColorSpaceRegistry::instance()->colorSpaceId(colorModel, colorDepth); QList profiles = KoColorSpaceRegistry::instance()->profilesFor(id); Q_FOREACH(const KoColorProfile *profile, profiles) { profileNames << profile->name(); } return profileNames.toList(); } bool Krita::addProfile(const QString &profilePath) { KoColorSpaceEngine *iccEngine = KoColorSpaceEngineRegistry::instance()->get("icc"); return iccEngine->addProfile(profilePath); } Notifier* Krita::notifier() const { return d->notifier; } QString Krita::version() const { return KritaVersionWrapper::versionString(true); } QList Krita::views() const { QList ret; foreach(QPointer view, KisPart::instance()->views()) { ret << new View(view); } return ret; } Window *Krita::activeWindow() const { KisMainWindow *mainWindow = KisPart::instance()->currentMainwindow(); if (!mainWindow) { return 0; } return new Window(mainWindow); } QList Krita::windows() const { QList ret; foreach(QPointer mainWin, KisPart::instance()->mainWindows()) { ret << new Window(mainWin); } return ret; } QMap Krita::resources(const QString &type) const { QMap resources = QMap (); if (type == "pattern") { KoResourceServer* server = KoResourceServerProvider::instance()->patternServer(); Q_FOREACH (KoResource *res, server->resources()) { resources[res->name()] = new Resource(res); } } else if (type == "gradient") { KoResourceServer* server = KoResourceServerProvider::instance()->gradientServer(); Q_FOREACH (KoResource *res, server->resources()) { resources[res->name()] = new Resource(res); } } else if (type == "brush") { KisBrushResourceServer* server = KisBrushServer::instance()->brushServer(); Q_FOREACH (KisBrushSP res, server->resources()) { resources[res->name()] = new Resource(res.data()); } } else if (type == "preset") { KisPaintOpPresetResourceServer* server = KisResourceServerProvider::instance()->paintOpPresetServer(); Q_FOREACH (KisPaintOpPresetSP res, server->resources()) { resources[res->name()] = new Resource(res.data()); } } else if (type == "palette") { KoResourceServer* server = KoResourceServerProvider::instance()->paletteServer(); Q_FOREACH (KoResource *res, server->resources()) { resources[res->name()] = new Resource(res); } } else if (type == "workspace") { KoResourceServer< KisWorkspaceResource >* server = KisResourceServerProvider::instance()->workspaceServer(); Q_FOREACH (KoResource *res, server->resources()) { resources[res->name()] = new Resource(res); } } return resources; } Document* Krita::createDocument(int width, int height, const QString &name, const QString &colorModel, const QString &colorDepth, const QString &profile) { KisDocument *document = KisPart::instance()->createDocument(); KisPart::instance()->addDocument(document); const KoColorSpace *cs = KoColorSpaceRegistry::instance()->colorSpace(colorModel, colorDepth, profile); Q_ASSERT(cs); QColor qc(Qt::white); qc.setAlpha(0); KoColor bgColor(qc, cs); if (!document->newImage(name, width, height, cs, bgColor, true, 1, "", 100.0)) { qDebug() << "Could not create a new image"; return 0; } Q_ASSERT(document->image()); qDebug() << document->image()->objectName(); return new Document(document); } Document* Krita::openDocument(const QString &filename) { KisDocument *document = KisPart::instance()->createDocument(); KisPart::instance()->addDocument(document); document->openUrl(QUrl::fromLocalFile(filename), KisDocument::OPEN_URL_FLAG_DO_NOT_ADD_TO_RECENT_FILES); return new Document(document); } Window* Krita::openWindow() { KisMainWindow *mw = KisPart::instance()->createMainWindow(); return new Window(mw); } Action *Krita::createAction(const QString &text) { KisAction *action = new KisAction(text, this); KisPart::instance()->addScriptAction(action); return new Action(action->objectName(), action); } -void Krita::addExtension(Extension* viewExtension) +void Krita::addExtension(Extension* extension) { - d->viewExtensions.append(viewExtension); + d->extensions.append(extension); } -QList< Extension* > Krita::viewExtensions() +QList< Extension* > Krita::extensions() { - return d->viewExtensions; + return d->extensions; } void Krita::writeSetting(const QString &group, const QString &name, const QString &value) { KConfigGroup grp = KSharedConfig::openConfig()->group(group); grp.writeEntry(name, value); } QString Krita::readSetting(const QString &group, const QString &name, const QString &defaultValue) { KConfigGroup grp = KSharedConfig::openConfig()->group(group); return grp.readEntry(name, defaultValue); } void Krita::addDockWidgetFactory(DockWidgetFactoryBase* factory) { KoDockRegistry::instance()->add(factory); } Krita* Krita::instance() { if (!s_instance) { s_instance = new Krita; } return s_instance; } /** * Scripter.fromVariant(variant) * variant is a QVariant * returns instance of QObject-subclass * * This is a helper method for PyQt because PyQt cannot cast a variant to a QObject or QWidget */ QObject *Krita::fromVariant(const QVariant& v) { if (v.canConvert< QWidget* >()) { QObject* obj = qvariant_cast< QWidget* >(v); return obj; } else if (v.canConvert< QObject* >()) { QObject* obj = qvariant_cast< QObject* >(v); return obj; } else return 0; } diff --git a/libs/libkis/Krita.h b/libs/libkis/Krita.h index c253121679..42c65d7730 100644 --- a/libs/libkis/Krita.h +++ b/libs/libkis/Krita.h @@ -1,288 +1,293 @@ /* * Copyright (c) 2016 Boudewijn Rempt * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU 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 LIBKIS_KRITA_H #define LIBKIS_KRITA_H #include #include "kritalibkis_export.h" #include "libkis.h" #include "Extension.h" #include "Document.h" #include "Window.h" #include "View.h" #include "Action.h" #include "Notifier.h" class QAction; /** * Krita is a singleton class that offers the root access to the Krita object hierarchy. * * The Krita.instance() is aliased as two builtins: Scripter and Application. */ class KRITALIBKIS_EXPORT Krita : public QObject { Q_OBJECT public: explicit Krita(QObject *parent = 0); virtual ~Krita(); public Q_SLOTS: /** * @return the currently active document, if there is one. */ Document* activeDocument() const; /** * @brief setActiveDocument activates the first view that shows the given document * @param value the document we want to activate */ void setActiveDocument(Document* value); /** * @brief batchmode determines whether the script is run in batch mode. If batchmode * is true, scripts should now show messageboxes or dialog boxes. * * Note that this separate from Document.setBatchmode(), which determines whether * export/save option dialogs are shown. * * @return true if the script is run in batchmode */ bool batchmode() const; /** * @brief setBatchmode sets the the batchmode to @param value; if true, scripts should * not show dialogs or messageboxes. */ void setBatchmode(bool value); /** * @return return a list of all actions for the currently active mainWindow. */ QList actions() const; + + /** + * @return the action that has been registered under the given name, or 0 if no such action exists. + */ Action *action(const QString &name) const; /** * @return a list of all open Documents */ QList documents() const; /** * @brief Filters are identified by an internal name. This function returns a list * of all existing registered filters. * @return a list of all registered filters */ QStringList filters() const; /** * @brief filter construct a Filter object with a default configuration. * @param name the name of the filter. Use Krita.instance().filters() to get * a list of all possible filters. * @return the filter or None if there is no such filter. */ Filter *filter(const QString &name) const; /** * @brief profiles creates a list with the names of all color profiles compatible * with the given color model and color depth. * @param colorModel A string describing the color model of the image: *
    *
  • A: Alpha mask
  • *
  • RGBA: RGB with alpha channel (The actual order of channels is most often BGR!)
  • *
  • XYZA: XYZ with alpha channel
  • *
  • LABA: LAB with alpha channel
  • *
  • CMYKA: CMYK with alpha channel
  • *
  • GRAYA: Gray with alpha channel
  • *
  • YCbCrA: YCbCr with alpha channel
  • *
* @param colorDepth A string describing the color depth of the image: *
    *
  • U8: unsigned 8 bits integer, the most common type
  • *
  • U16: unsigned 16 bits integer
  • *
  • F16: half, 16 bits floating point. Only available if Krita was built with OpenEXR
  • *
  • F32: 32 bits floating point
  • *
* @return a list with valid names */ QStringList profiles(const QString &colorModel, const QString &colorDepth) const; /** * @brief addProfile load the given profile into the profile registry. * @param profilePath the path to the profile. * @return true if adding the profile succeeded. */ bool addProfile(const QString &profilePath); /** * @brief notifier the Notifier singleton emits signals when documents are opened and * closed, the configuration changes, views are opened and closed or windows are opened. * @return the notifier object */ Notifier* notifier() const; /** * @brief version Determine the version of Krita * * Usage: print(Application.version ()) * * @return the version string including git sha1 if Krita was built from git */ QString version() const; /** * @return a list of all views. A Document can be shown in more than one view. */ QList views() const; /** * @return the currently active window or None if there is no window */ Window *activeWindow() const; /** * @return a list of all windows */ QList windows() const; /** * @brief resources returns a list of Resource objects of the given type * @param type Valid types are: * *
    *
  • pattern
  • *
  • gradient
  • *
  • brush
  • *
  • preset
  • *
  • palette
  • *
  • workspace
  • - *
  • :
  • *
- */ QMap resources(const QString &type) const; /** * @brief createDocument creates a new document and image and registers the document with the Krita application. * * The document will have one transparent layer. * * @param width the width in pixels * @param height the height in pixels * @param name the name of the image (not the filename of the document) * @param colorModel A string describing the color model of the image: *
    *
  • A: Alpha mask
  • *
  • RGBA: RGB with alpha channel (The actual order of channels is most often BGR!)
  • *
  • XYZA: XYZ with alpha channel
  • *
  • LABA: LAB with alpha channel
  • *
  • CMYKA: CMYK with alpha channel
  • *
  • GRAYA: Gray with alpha channel
  • *
  • YCbCrA: YCbCr with alpha channel
  • *
* @param colorDepth A string describing the color depth of the image: *
    *
  • U8: unsigned 8 bits integer, the most common type
  • *
  • U16: unsigned 16 bits integer
  • *
  • F16: half, 16 bits floating point. Only available if Krita was built with OpenEXR
  • *
  • F32: 32 bits floating point
  • *
* @param profile The name of an icc profile that is known to Krita. If an empty string is passed, the default is * taken. * @return the created document. */ Document *createDocument(int width, int height, const QString &name, const QString &colorModel, const QString &colorDepth, const QString &profile); /** * @brief openDocument creates a new Document, registers it with the Krita application and loads the given file. * @param filename the file to open in the document * @return the document */ Document *openDocument(const QString &filename); /** * @brief openWindow create a new main window. The window is not shown by default. */ Window *openWindow(); /** * @brief createAction creates an action with the given text and passes it to Krita. Every newly created * mainwindow will create an instance of this action. * @param text the user-visible text * @return the Action you can connect a slot to. */ Action *createAction(const QString &text); /** - * @brief addExtension add the given plugin to Krita. For every window, a new instance of this - * extension will be made. - * @param viewExtension + * @brief addExtension add the given plugin to Krita. There will be a single instance of each Extension in the Krita process. + * @param extension the extension to add. + */ + void addExtension(Extension* extension); + + /** + * return a list with all registered extension objects. */ - void addExtension(Extension* viewExtension); - QList viewExtensions(); + QList extensions(); /** * @brief addDockWidgetFactory Add the given docker factory to the application. For scripts * loaded on startup, this means that every window will have one of the dockers created by the * factory. * @param factory The factory object. */ void addDockWidgetFactory(DockWidgetFactoryBase* factory ); /** * @brief writeSetting write the given setting under the given name to the kritarc file in * the given settings group. * @param group The group the setting belongs to. If empty, then the setting is written in the * general section * @param name The name of the setting * @param value The value of the setting. Script settings are always written as strings. */ void writeSetting(const QString &group, const QString &name, const QString &value); /** * @brief readSetting read the given setting value from the kritarc file. * @param group The group the setting is part of. If empty, then the setting is read from * the general group. * @param name The name of the setting * @param defaultValue The default value of the setting * @return a string representing the setting. */ QString readSetting(const QString &group, const QString &name, const QString &defaultValue); /** * @brief instance retrieve the singleton instance of the Application object. */ static Krita* instance(); - /// For mikro.py + // Internal only: for use with mikro.py static QObject *fromVariant(const QVariant& v); private: struct Private; Private *const d; static Krita* s_instance; }; Q_DECLARE_METATYPE(Notifier*); #endif // LIBKIS_KRITA_H diff --git a/libs/libkis/Node.cpp b/libs/libkis/Node.cpp index 5d47c2c7c0..daab6d060f 100644 --- a/libs/libkis/Node.cpp +++ b/libs/libkis/Node.cpp @@ -1,493 +1,495 @@ /* * Copyright (c) 2016 Boudewijn Rempt * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU 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 #include #include "Krita.h" #include "Node.h" #include "Channel.h" #include "Filter.h" #include "Selection.h" struct Node::Private { Private() {} KisImageSP image; KisNodeSP node; }; Node::Node(KisImageSP image, KisNodeSP node, QObject *parent) : QObject(parent) , d(new Private) { d->image = image; d->node = node; } Node::~Node() { delete d; } bool Node::alphaLocked() const { if (!d->node) return false; KisPaintLayerSP paintLayer = qobject_cast(d->node.data()); if (paintLayer) { return paintLayer->alphaLocked(); } return false; } void Node::setAlphaLocked(bool value) { if (!d->node) return; KisPaintLayerSP paintLayer = qobject_cast(d->node.data()); if (paintLayer) { paintLayer->setAlphaLocked(value); } } QString Node::blendingMode() const { if (!d->node) return QString(); return d->node->compositeOpId(); } void Node::setBlendingMode(QString value) { if (!d->node) return; d->node->setCompositeOpId(value); } QList Node::channels() const { QList channels; if (!d->node) return channels; if (!d->node->inherits("KisLayer")) return channels; Q_FOREACH(KoChannelInfo *info, d->node->colorSpace()->channels()) { Channel *channel = new Channel(d->node, info); channels << channel; } return channels; } QList Node::childNodes() const { QList nodes; if (d->node) { int childCount = d->node->childCount(); for (int i = 0; i < childCount; ++i) { nodes << new Node(d->image, d->node->at(i)); } } return nodes; } bool Node::addChildNode(Node *child, Node *above) { if (!d->node) return false; return d->image->addNode(child->node(), d->node, above->node()); } bool Node::removeChildNode(Node *child) { if (!d->node) return false; return d->image->removeNode(child->node()); } void Node::setChildNodes(QList nodes) { if (!d->node) return; KisNodeSP node = d->node->firstChild(); while (node) { d->image->removeNode(node); node = node->nextSibling(); } Q_FOREACH(Node *node, nodes) { d->image->addNode(node->node(), d->node); } } int Node::colorLabel() const { if (!d->node) return 0; return d->node->colorLabelIndex(); } void Node::setColorLabel(int index) { if (!d->node) return; d->node->setColorLabelIndex(index); } QString Node::colorDepth() const { if (!d->node) return ""; return d->node->colorSpace()->colorDepthId().id(); } QString Node::colorModel() const { if (!d->node) return ""; return d->node->colorSpace()->colorModelId().id(); } QString Node::colorProfile() const { if (!d->node) return ""; return d->node->colorSpace()->profile()->name(); } bool Node::setColorProfile(const QString &colorProfile) { if (!d->node) return false; if (!d->node->inherits("KisLayer")) return false; KisLayer *layer = qobject_cast(d->node.data()); const KoColorProfile *profile = KoColorSpaceRegistry::instance()->profileByName(colorProfile); const KoColorSpace *srcCS = layer->colorSpace(); const KoColorSpace *dstCs = KoColorSpaceRegistry::instance()->colorSpace(srcCS->colorModelId().id(), srcCS->colorDepthId().id(), profile); KisChangeProfileVisitor v(srcCS, dstCs); return layer->accept(v); } bool Node::setColorSpace(const QString &colorModel, const QString &colorDepth, const QString &colorProfile) { if (!d->node) return false; if (!d->node->inherits("KisLayer")) return false; KisLayer *layer = qobject_cast(d->node.data()); const KoColorProfile *profile = KoColorSpaceRegistry::instance()->profileByName(colorProfile); const KoColorSpace *srcCS = layer->colorSpace(); const KoColorSpace *dstCs = KoColorSpaceRegistry::instance()->colorSpace(colorModel, colorDepth, profile); KisColorSpaceConvertVisitor v(d->image, srcCS, dstCs, KoColorConversionTransformation::internalRenderingIntent(), KoColorConversionTransformation::internalConversionFlags()); return layer->accept(v); } bool Node::animated() const { if (!d->node) return false; return d->node->isAnimated(); } void Node::enableAnimation() const { if (!d->node) return; d->node->enableAnimation(); } bool Node::collapsed() const { if (!d->node) return false; return d->node->collapsed(); } void Node::setCollapsed(bool collapsed) { if (!d->node) return; d->node->setCollapsed(collapsed); } bool Node::inheritAlpha() const { if (!d->node) return false; if (!d->node->inherits("KisLayer")) return false; return qobject_cast(d->node)->alphaChannelDisabled(); } void Node::setInheritAlpha(bool value) { if (!d->node) return; if (!d->node->inherits("KisLayer")) return; const_cast(qobject_cast(d->node))->disableAlphaChannel(value); } bool Node::locked() const { if (!d->node) return false; return d->node->userLocked() || d->node->systemLocked(); } void Node::setLocked(bool value) { if (!d->node) return; d->node->setUserLocked(value); } QString Node::name() const { if (!d->node) return QString(); return d->node->name(); } void Node::setName(QString name) { if (!d->node) return; d->node->setName(name); } int Node::opacity() const { if (!d->node) return 0; return d->node->opacity(); } void Node::setOpacity(int value) { if (!d->node) return; + if (value < 0) value = 0; + if (value > 255) value = 255; d->node->setOpacity(value); } Node* Node::parentNode() const { if (!d->node) return 0; return new Node(d->image, d->node->parent()); } QString Node::type() const { if (!d->node) return QString(); return QString(); if (qobject_cast(d->node)) { return "paintlayer"; } else if (qobject_cast(d->node)) { return "grouplayer"; } if (qobject_cast(d->node)) { return "filelayer"; } if (qobject_cast(d->node)) { return "filterlayer"; } if (qobject_cast(d->node)) { return "filllayer"; } if (qobject_cast(d->node)) { return "clonelayer"; } if (qobject_cast(d->node)) { return "shapelayer"; } if (qobject_cast(d->node)) { return "transparencymask"; } if (qobject_cast(d->node)) { return "filtermask"; } if (qobject_cast(d->node)) { return "transformmask"; } if (qobject_cast(d->node)) { return "selectionmask"; } if (qobject_cast(d->node)) { return "colorizemask"; } } bool Node::visible() const { if (!d->node) return false; return d->node->visible();; } void Node::setVisible(bool visible) { if (!d->node) return; d->node->setVisible(visible); } QByteArray Node::pixelData(int x, int y, int w, int h) const { QByteArray ba; if (!d->node) return ba; KisPaintDeviceSP dev = d->node->paintDevice(); if (!dev) return ba; quint8 *data = new quint8[w * h * dev->pixelSize()]; dev->readBytes(data, x, y, w, h); ba = QByteArray((const char*)data, (int)(w * h * dev->pixelSize())); delete[] data; return ba; } QByteArray Node::projectionPixelData(int x, int y, int w, int h) const { QByteArray ba; if (!d->node) return ba; KisPaintDeviceSP dev = d->node->projection(); quint8 *data = new quint8[w * h * dev->pixelSize()]; dev->readBytes(data, x, y, w, h); ba = QByteArray((const char*)data, (int)(w * h * dev->pixelSize())); delete[] data; return ba; } void Node::setPixelData(QByteArray value, int x, int y, int w, int h) { if (!d->node) return; KisPaintDeviceSP dev = d->node->paintDevice(); if (!dev) return; dev->writeBytes((const quint8*)value.constData(), x, y, w, h); } QRect Node::bounds() const { if (!d->node) return QRect(); return d->node->exactBounds(); } void Node::move(int x, int y) { if (!d->node) return; d->node->setX(x); d->node->setY(y); } QPoint Node::position() const { if (!d->node) return QPoint(); return QPoint(d->node->x(), d->node->y()); } bool Node::remove() { if (!d->node) return false; if (!d->node->parent()) return false; return d->image->removeNode(d->node); } Node* Node::duplicate() { if (!d->node) return 0; return new Node(d->image, d->node->clone()); } bool Node::save(const QString &filename, double xRes, double yRes) { if (!d->node) return false; if (filename.isEmpty()) return false; KisPaintDeviceSP projection = d->node->projection(); QRect bounds = d->node->exactBounds(); QString mimefilter = KisMimeDatabase::mimeTypeForFile(filename);; QScopedPointer doc(KisPart::instance()->createDocument()); KisImageSP dst = new KisImage(doc->createUndoStore(), bounds.width(), bounds.height(), projection->compositionSourceColorSpace(), d->node->name()); dst->setResolution(xRes, yRes); doc->setFileBatchMode(Krita::instance()->batchmode()); doc->setCurrentImage(dst); KisPaintLayer* paintLayer = new KisPaintLayer(dst, "paint device", d->node->opacity()); paintLayer->paintDevice()->makeCloneFrom(projection, bounds); dst->addNode(paintLayer, dst->rootLayer(), KisLayerSP(0)); dst->initialRefreshGraph(); doc->setOutputMimeType(mimefilter.toLatin1()); bool r = doc->exportDocument(QUrl::fromLocalFile(filename)); if (!r) { qWarning() << doc->errorMessage(); } return r; } Node *Node::mergeDown() { if (!d->node) return 0; if (!qobject_cast(d->node.data())) return 0; if (!d->node->prevSibling()) return 0; KisLayerSP layer = qobject_cast(d->node->prevSibling().data()); if (!layer) return 0; d->image->mergeDown(qobject_cast(d->node.data()), KisMetaData::MergeStrategyRegistry::instance()->get("Drop")); return new Node(d->image, layer); } QImage Node::thumbnail(int w, int h) { if (!d->node) return QImage(); return d->node->createThumbnail(w, h); } KisPaintDeviceSP Node::paintDevice() const { return d->node->paintDevice(); } KisImageSP Node::image() const { return d->image; } KisNodeSP Node::node() const { return d->node; } diff --git a/libs/libkis/Node.h b/libs/libkis/Node.h index ded89183b0..580e56113b 100644 --- a/libs/libkis/Node.h +++ b/libs/libkis/Node.h @@ -1,429 +1,469 @@ /* * Copyright (c) 2016 Boudewijn Rempt * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU 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 LIBKIS_NODE_H #define LIBKIS_NODE_H #include #include #include "kritalibkis_export.h" #include "libkis.h" /** * Node represents a layer or mask in a Krita image's Node hierarchy. Group layers can contain * other layers and masks; layers can contain masks. * */ class KRITALIBKIS_EXPORT Node : public QObject { Q_OBJECT Q_DISABLE_COPY(Node) public: explicit Node(KisImageSP image, KisNodeSP node, QObject *parent = 0); virtual ~Node(); public Q_SLOTS: /** * @brief alphaLocked checks whether the node is a paint layer and returns whether it is alpha locked * @return whether the paint layer is alpha locked, or false if the node is not a paint layer */ bool alphaLocked() const; /** * @brief setAlphaLocked set the layer to value if the the node is paint layer. */ void setAlphaLocked(bool value); /** * @return the blending mode of the layer. The values of the blending modes are defined in @see KoCompositeOpRegistry.h */ QString blendingMode() const; /** * @brief setBlendingMode set the blending mode of the node to the given value * @param value one of the string values from @see KoCompositeOpRegistry.h */ void setBlendingMode(QString value); /** * @brief channels creates a list of Channel objects that can be used individually to * show or hide certain channels, and to retrieve the contents of each channel in a * node separately. * * Only layers have channels, masks do not, and calling channels on a Node that is a mask * will return an empty list. * * @return the list of channels ordered in by position of the channels in pixel position */ QList channels() const; /** * Return a list of child nodes of the current node. The nodes are ordered from the bottommost up. * The function is not recursive. */ QList childNodes() const; /** * @brief addChildNode adds the given node in the list of children. * @param child the node to be added * @param above the node above which this node will be placed * @return false if adding the node failed */ bool addChildNode(Node *child, Node *above); /** * @brief removeChildNode removes the given node from the list of children. * @param child the node to be removed */ bool removeChildNode(Node *child); /** * @brief setChildNodes this replaces the existing set of child nodes with the new set. * @param nodes The list of nodes that will become children, bottom-up -- the first node, * is the bottom-most node in the stack. */ void setChildNodes(QList nodes); /** * colorDepth A string describing the color depth of the image: *
    *
  • U8: unsigned 8 bits integer, the most common type
  • *
  • U16: unsigned 16 bits integer
  • *
  • F16: half, 16 bits floating point. Only available if Krita was built with OpenEXR
  • *
  • F32: 32 bits floating point
  • *
* @return the color depth. */ QString colorDepth() const; /** * @brief colorModel retrieve the current color model of this document: *
    *
  • A: Alpha mask
  • *
  • RGBA: RGB with alpha channel (The actual order of channels is most often BGR!)
  • *
  • XYZA: XYZ with alpha channel
  • *
  • LABA: LAB with alpha channel
  • *
  • CMYKA: CMYK with alpha channel
  • *
  • GRAYA: Gray with alpha channel
  • *
  • YCbCrA: YCbCr with alpha channel
  • *
* @return the internal color model string. */ QString colorModel() const; /** * @return the name of the current color profile */ QString colorProfile() const; /** * @brief setColorProfile set the color profile of the image to the given profile. The profile has to * be registered with krita and be compatible with the current color model and depth; the image data * is not converted. * @param colorProfile * @return if assigining the colorprofiel worked */ bool setColorProfile(const QString &colorProfile); /** * @brief setColorSpace convert the node to the given colorspace * @param colorModel A string describing the color model of the node: *
    *
  • A: Alpha mask
  • *
  • RGBA: RGB with alpha channel (The actual order of channels is most often BGR!)
  • *
  • XYZA: XYZ with alpha channel
  • *
  • LABA: LAB with alpha channel
  • *
  • CMYKA: CMYK with alpha channel
  • *
  • GRAYA: Gray with alpha channel
  • *
  • YCbCrA: YCbCr with alpha channel
  • *
* @param colorDepth A string describing the color depth of the image: *
    *
  • U8: unsigned 8 bits integer, the most common type
  • *
  • U16: unsigned 16 bits integer
  • *
  • F16: half, 16 bits floating point. Only available if Krita was built with OpenEXR
  • *
  • F32: 32 bits floating point
  • *
* @param colorProfile a valid color profile for this color model and color depth combinatiojn. */ bool setColorSpace(const QString &colorModel, const QString &colorDepth, const QString &colorProfile); /** * @brief Krita layers can be animated, i.e., have frames. * @return return true if the layer has frames. Currently, the scripting framework * does not give access to the animation features. */ bool animated() const; /** * @brief enableAnimation make the current layer animated, so it can have frames. */ void enableAnimation() const; /** * Sets the state of the node to the value of @param collapsed */ void setCollapsed(bool collapsed); /** * returns the collapsed state of this node */ bool collapsed() const; /** * Sets a color label index associated to the layer. The actual * color of the label and the number of available colors is * defined by Krita GUI configuration. */ int colorLabel() const; /** * @brief setColorLabel sets a color label index associated to the layer. The actual * color of the label and the number of available colors is * defined by Krita GUI configuration. * @param index an integer corresponding to the set of available color labels. */ void setColorLabel(int index); + /** + * @brief inheritAlpha checks whether this node has the inherits alpha flag set + * @return true if the Inherit Alpha is set + */ bool inheritAlpha() const; + + /** + * set the Inherit Alpha flag to the given value + */ void setInheritAlpha(bool value); + /** + * @brief locked checkes whether the Node is locked. A locked node cannot be changed. + * @return true if the Node is locked, false if it hasn't been locked. + */ bool locked() const; + + /** + * set the Locked flag to the give value + */ void setLocked(bool value); + /** + * @return the user-visible name of this node. + */ QString name() const; + + /** + * rename the Node to the given name + */ void setName(QString name); + /** + * return the opacity of the Node. The opacity is a value between 0 and 255. + */ int opacity() const; + + /** + * set the opacity of the Node to the given value. The opacity is a value between 0 and 255. + */ void setOpacity(int value); + /** + * return the Node that is the parent of the current Node, or 0 if this is the root Node. + */ Node* parentNode() const; /** * @brief type Krita has several types of nodes, split in layers and masks. Group * layers can contain other layers, any layer can contain masks. * * @return The type of the node. Valid types are: *
    *
  • paintlayer *
  • grouplayer *
  • filelayer *
  • filterlayer *
  • filllayer *
  • clonelayer *
  • vectorlayer *
  • transparencymask *
  • filtermask *
  • transformmask *
  • selectionmask *
  • colorizemask *
* * If the Node object isn't wrapping a valid Krita layer or mask object, and * empty string is returned. */ QString type() const; + /** + * Check whether the current Node is visible in the layer stack + */ bool visible() const; + + /** + * Set the visibility of the current node to @param visible + */ void setVisible(bool visible); /** * @brief pixelData reads the given rectangle from the Node's paintable pixels, if those * exist, and returns it as a byte array. The pixel data starts top-left, and is ordered row-first. * * The byte array can be interpreted as follows: 8 bits images have one byte per channel, * and as many bytes as there are channels. 16 bits integer images have two bytes per channel, * representing an unsigned short. 16 bits float images have two bytes per channel, representing * a half, or 16 bits float. 32 bits float images have four bytes per channel, representing a * float. * * You can read outside the node boundaries; those pixels will be transparent black. * * The order of channels is: * *
    *
  • Integer RGBA: Blue, Green, Red, Alpha *
  • Float RGBA: Red, Green, Blue, Alpha *
  • GrayA: Gray, Alpha *
  • Selection: selectedness *
  • LabA: L, a, b, Alpha *
  • CMYKA: Cyan, Magenta, Yellow, Key, Alpha *
  • XYZA: X, Y, Z, A *
  • YCbCrA: Y, Cb, Cr, Alpha *
* * The byte array is a copy of the original node data. In Python, you can use bytes, bytearray * and the struct module to interpret the data and construct, for instance, a Pillow Image object. * * If you read the pixeldata of a mask, a filter or generator layer, you get the selection bytes, * which is one channel with values in the range from 0..255. * * If you want to change the pixels of a node you can write the pixels back after manipulation * with setPixelData(). This will only succeed on nodes with writable pixel data, e.g not on groups * or file layers. * * @param x x position from where to start reading * @param y y position from where to start reading * @param w row length to read * @param h number of rows to read * @return a QByteArray with the pixel data. The byte array may be empty. */ QByteArray pixelData(int x, int y, int w, int h) const; /** * @brief projectionPixelData reads the given rectangle from the Node's projection (that is, what the node * looks like after all sub-Nodes (like layers in a group or masks on a layer) have been applied, * and returns it as a byte array. The pixel data starts top-left, and is ordered row-first. * * The byte array can be interpreted as follows: 8 bits images have one byte per channel, * and as many bytes as there are channels. 16 bits integer images have two bytes per channel, * representing an unsigned short. 16 bits float images have two bytes per channel, representing * a half, or 16 bits float. 32 bits float images have four bytes per channel, representing a * float. * * You can read outside the node boundaries; those pixels will be transparent black. * * The order of channels is: * *
    *
  • Integer RGBA: Blue, Green, Red, Alpha *
  • Float RGBA: Red, Green, Blue, Alpha *
  • GrayA: Gray, Alpha *
  • Selection: selectedness *
  • LabA: L, a, b, Alpha *
  • CMYKA: Cyan, Magenta, Yellow, Key, Alpha *
  • XYZA: X, Y, Z, A *
  • YCbCrA: Y, Cb, Cr, Alpha *
* * The byte array is a copy of the original node data. In Python, you can use bytes, bytearray * and the struct module to interpret the data and construct, for instance, a Pillow Image object. * * If you read the projection of a mask, you get the selection bytes, which is one channel with * values in the range from 0..255. * * If you want to change the pixels of a node you can write the pixels back after manipulation * with setPixelData(). This will only succeed on nodes with writable pixel data, e.g not on groups * or file layers. * * @param x x position from where to start reading * @param y y position from where to start reading * @param w row length to read * @param h number of rows to read * @return a QByteArray with the pixel data. The byte array may be empty. */ QByteArray projectionPixelData(int x, int y, int w, int h) const; /** * @brief setPixelData writes the given bytes, of which there must be enough, into the * Node, if the Node has writable pixel data: * *
    *
  • paint layer: the layer's original pixels are overwritten *
  • filter layer, generator layer, any mask: the embedded selection's pixels are overwritten. * Note: for these *
* * File layers, Group layers, Clone layers cannot be written to. Calling setPixelData on * those layer types will silently do nothing. * * @param value the byte array representing the pixels. There must be enough bytes available. * Krita will take the raw pointer from the QByteArray and start reading, not stopping before * (number of channels * size of channel * w * h) bytes are read. * * @param x the x position to start writing from * @param y the y position to start writing from * @param w the width of each row * @param h the number of rows to write */ void setPixelData(QByteArray value, int x, int y, int w, int h); /** * @brief bounds return the exact bounds of the node's paint device * @return the bounds, or an empty QRect if the node has no paint device or is empty. */ QRect bounds() const; /** * move the pixels to the given x, y location in the image coordinate space. */ void move(int x, int y); /** * @brief position returns the position of the paint device of this node * @return the top-left position of the node */ QPoint position() const; /** * @brief remove removes this node from its parent image. */ bool remove(); /** * @brief duplicate returns a full copy of the current node. The node is not inserted in the graphc * @return a valid Node object or 0 if the node couldn't be duplicated. */ Node* duplicate(); /** * @brief save exports the given node with this filename. The extension of the filename determins the filetype. * @param filename the filename including extension * @param xRes the horizontal resolution in pixels per pt (there are 72 pts in an inch) * @param yRes the horizontal resolution in pixels per pt (there are 72 pts in an inch) * @return true if saving succeeded, false if it failed. */ bool save(const QString &filename, double xRes, double yRes); /** * @brief mergeDown merges the given node with the first visible node underneath this node in the layerstack. * This will drop all per-layer metadata. * @param node the node to merge down; this node will be removed from the layer stack */ Node *mergeDown(); /** * @brief thumbnail create a thumbnail of the given dimensions. The thumbnail is sized according * to the layer dimensions, not the image dimensions. If the requested size is too big a null * QImage is created. If the current node cannot generate a thumbnail, a transparent QImage of the * requested size is generated. * @return a QImage representing the layer contents. */ QImage thumbnail(int w, int h); private: friend class Filter; friend class Document; friend class Selection; /** * @brief paintDevice gives access to the internal paint device of this Node * @return the paintdevice or 0 if the node does not have an editable paint device. */ KisPaintDeviceSP paintDevice() const; KisImageSP image() const; KisNodeSP node() const; struct Private; Private *const d; }; #endif // LIBKIS_NODE_H diff --git a/plugins/extensions/pykrita/plugin/plugin.cpp b/plugins/extensions/pykrita/plugin/plugin.cpp index ae7f31b714..0201a53601 100644 --- a/plugins/extensions/pykrita/plugin/plugin.cpp +++ b/plugins/extensions/pykrita/plugin/plugin.cpp @@ -1,93 +1,93 @@ /* * Copyright (c) 2014 Boudewijn Rempt (boud@valdyas.org) * * This program 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 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU 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 "plugin.h" #include "engine.h" #include "utilities.h" #include #include #include #include #include #include "pyqtpluginsettings.h" #include #include K_PLUGIN_FACTORY_WITH_JSON(KritaPyQtPluginFactory, "kritapykrita.json", registerPlugin();) KritaPyQtPlugin::KritaPyQtPlugin(QObject *parent, const QVariantList &) : KisViewPlugin(parent) , m_engineFailureReason(m_engine.tryInitializeGetFailureReason()) , m_autoReload(false) { qDebug() << "Loading Python plugin"; KisPreferenceSetRegistry *preferenceSetRegistry = KisPreferenceSetRegistry::instance(); PyQtPluginSettingsFactory* settingsFactory = new PyQtPluginSettingsFactory(&m_engine); QByteArray pythonPath = qgetenv("PYTHONPATH"); qDebug() << "\tPython path:" << pythonPath; QStringList pluginDirectories = KoResourcePaths::findDirs("pythonscripts"); qDebug() << "\tPython plugin directories" << pluginDirectories; Q_FOREACH(const QString pluginDir, pluginDirectories) { pythonPath.prepend(pluginDir.toUtf8() + ":"); } qputenv("PYTHONPATH", pythonPath); //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("PyQtPluginSettingsFactory", settingsFactory); // Try to import the `pykrita` module PyKrita::Python py = PyKrita::Python(); PyObject* pykritaPackage = py.moduleImport("pykrita"); pykritaPackage = py.moduleImport("krita"); if (pykritaPackage) { dbgScript << "Loaded pykrita, now load plugins"; m_engine.tryLoadEnabledPlugins(); //py.functionCall("_pykritaLoaded", PyKrita::Python::PYKRITA_ENGINE); } else { dbgScript << "Cannot load pykrita module"; m_engine.setBroken(); } - Q_FOREACH (Extension* ext, Krita::instance()->viewExtensions()) + Q_FOREACH (Extension* ext, Krita::instance()->extensions()) { ext->setup(); } } KritaPyQtPlugin::~KritaPyQtPlugin() { } #include "plugin.moc" diff --git a/plugins/extensions/pykrita/sip/krita/Action.sip b/plugins/extensions/pykrita/sip/krita/Action.sip index eb61ad6ad9..96eefc6183 100644 --- a/plugins/extensions/pykrita/sip/krita/Action.sip +++ b/plugins/extensions/pykrita/sip/krita/Action.sip @@ -1,31 +1,33 @@ class Action : QObject { %TypeHeaderCode #include "Action.h" %End public: Action(QObject* parent /TransferThis/ = 0); Action(const QString & name, QAction* action, QObject* parent /TransferThis/ = 0); virtual ~Action(); public Q_SLOTS: + QString text() const; + void settext(QString text); QString name() const; void setName(QString value); bool isCheckable() const; void setCheckable(bool value); bool isChecked() const; void setChecked(bool value); QString shortcut() const; void setShortcut(QString value); bool isVisible() const; void setVisible(bool value); bool isEnabled() const; void setEnabled(bool value); void setToolTip(QString tooltip); void trigger(); Q_SIGNALS: void triggered(bool); private: private: Action(const Action &); // Generated }; diff --git a/plugins/extensions/pykrita/sip/krita/DockWidget.sip b/plugins/extensions/pykrita/sip/krita/DockWidget.sip index 5a403be16e..18c42a8714 100644 --- a/plugins/extensions/pykrita/sip/krita/DockWidget.sip +++ b/plugins/extensions/pykrita/sip/krita/DockWidget.sip @@ -1,12 +1,13 @@ class DockWidget : public QDockWidget /NoDefaultCtors/ { %TypeHeaderCode #include "DockWidget.h" %End public: explicit DockWidget(); protected Q_SLOTS: + Canvas* canvas() const; virtual void canvasChanged(Canvas *canvas) = 0; }; diff --git a/plugins/extensions/pykrita/sip/krita/Document.sip b/plugins/extensions/pykrita/sip/krita/Document.sip index a36f4bfab8..b81d5c791a 100644 --- a/plugins/extensions/pykrita/sip/krita/Document.sip +++ b/plugins/extensions/pykrita/sip/krita/Document.sip @@ -1,53 +1,51 @@ class Document : QObject /NoDefaultCtors/ { %TypeHeaderCode #include "Document.h" %End Document(const Document & __0); public Q_SLOTS: Node * activeNode() const /Factory/; void setActiveNode(Node* value); QList toplevelNodes() const /Factory/; Node *nodeByName(const QString &node) const /Factory/; bool batchmode() const; void setBatchmode(bool value); QString colorDepth() const; QString colorModel() const; QString colorProfile() const; bool setColorProfile(const QString &colorProfile); void setColorSpace(const QString &value, const QString &colorDepth, const QString &colorProfile); QString documentInfo() const; void setDocumentInfo(const QString &document); QString fileName() const; void setFileName(QString value); int height() const; void setHeight(int value); QString name() const; void setName(QString value); int resolution() const; void setResolution(int value); Node * rootNode() const /Factory/; Selection * selection() const /Factory/; void setSelection(Selection* value); int width() const; void setWidth(int value); double xRes() const; void setXRes(double xRes) const; double yRes() const; void setyRes(double yRes) const; QByteArray pixelData(int x, int y, int w, int h) const; bool close(); void crop(int x, int y, int w, int h); bool exportImage(const QString &filename, const InfoObject & exportConfiguration); void flatten(); void resizeImage(int w, int h); bool save(); bool saveAs(const QString & filename); Node *createNode(const QString & name, const QString & nodeType) /Factory/; QImage projection(int x = 0, int y = 0, int w = 0, int h = 0) const; QImage thumbnail(int w, int h) const; -Q_SIGNALS: - void nodeCreated(Node *node); private: }; diff --git a/plugins/extensions/pykrita/sip/krita/Krita.sip b/plugins/extensions/pykrita/sip/krita/Krita.sip index 526dacbd35..07677e84ec 100644 --- a/plugins/extensions/pykrita/sip/krita/Krita.sip +++ b/plugins/extensions/pykrita/sip/krita/Krita.sip @@ -1,57 +1,57 @@ class Krita : QObject { %TypeHeaderCode #include "Krita.h" %End public: public Q_SLOTS: Krita(QObject* parent /TransferThis/ = 0); virtual ~Krita(); Document * activeDocument() const /Factory/; void setActiveDocument(Document* value); bool batchmode() const; void setBatchmode(bool value); QList actions() const /Factory/; Action * action(const QString & name) const; QList documents() const /Factory/; QStringList filters() const; Filter * filter(const QString &name) const /Factory/; QStringList profiles(const QString &colorModel, const QString &ColorDepth) const; bool addProfile(const QString &profilePath); Notifier * notifier() const; QString version() const; QList views() const /Factory/; Window * activeWindow() const /Factory/; QList windows() const /Factory/; QMap resources(const QString &type) const /Factory/; Document * createDocument(int width, int height, const QString &name, const QString &colorModel, const QString &colorDepth, const QString &profile) /Factory/; Document * openDocument(const QString &filename) /Factory/; Window * openWindow(); Action * createAction(const QString & text); - void addExtension(Extension* _viewExtension /GetWrapper/); + void addExtension(Extension* _extension /GetWrapper/); %MethodCode Py_BEGIN_ALLOW_THREADS sipCpp->addExtension(a0); Py_END_ALLOW_THREADS sipTransferTo(a0Wrapper, Py_None); %End void addDockWidgetFactory(DockWidgetFactoryBase* _factory /GetWrapper/); %MethodCode Py_BEGIN_ALLOW_THREADS sipCpp->addDockWidgetFactory(a0); Py_END_ALLOW_THREADS sipTransferTo(a0Wrapper, Py_None); %End void writeSetting(const QString &group, const QString &name, const QString &value); QString readSetting(const QString &group, const QString &name, const QString &defaultValue); static Krita * instance(); static QObject * fromVariant(const QVariant & v); private: Krita(const Krita &); // Generated };