Commit 505fa128 authored by Boudewijn Rempt's avatar Boudewijn Rempt

Add libkis: the Krita scripting wrapper library

libkis offers a QObject-introspectalbe wrapper around Krita's messy
internals. Some notes:

* Functions that return a pointer to a wrapper objectare factories:
the caller is responsible for deleting the wrapper object
* In principle, the library is meant to be low-level. Not a set of
macro commands, but an programming API
* Bindings in other languages are welcome
* Extensions are welcome.
parent 7a974cdc
......@@ -16,3 +16,4 @@ add_subdirectory( image )
add_subdirectory( ui )
add_subdirectory( vectorimage )
add_subdirectory( impex )
add_subdirectory( libkis )
/*
* Copyright (c) 2016 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; 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;
}
bool Action::operator==(const Action &other) const
{
return (d->action == other.d->action);
}
bool Action::operator!=(const Action &other) const
{
return !(operator==(other));
}
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();
}
/*
* Copyright (c) 2016 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; 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 <kis_action.h>
#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();
bool operator==(const Action &other) const;
bool operator!=(const Action &other) const;
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
set(kritalibkis_LIB_SRCS
Action.cpp
Canvas.cpp
Channel.cpp
DockWidget.cpp
DockWidgetFactoryBase.cpp
Document.cpp
Filter.cpp
InfoObject.cpp
Krita.cpp
Node.cpp
Notifier.cpp
PresetChooser
Resource.cpp
Selection.cpp
View.cpp
Extension.cpp
Window.cpp
)
add_library(kritalibkis SHARED ${kritalibkis_LIB_SRCS} )
generate_export_header(kritalibkis)
target_link_libraries(kritalibkis kritaui kritaimage kritaversion)
target_link_libraries(kritalibkis LINK_INTERFACE_LIBRARIES kritaimage kritaui)
set_target_properties(kritalibkis PROPERTIES
VERSION ${GENERIC_KRITA_LIB_VERSION} SOVERSION ${GENERIC_KRITA_LIB_SOVERSION}
)
install(TARGETS kritalibkis ${INSTALL_TARGETS_DEFAULT_ARGS})
add_subdirectory(tests)
/*
* Copyright (c) 2016 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; 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 <KoCanvasBase.h>
#include <kis_canvas2.h>
#include <KisView.h>
#include <KoCanvasController.h>
#include <kis_canvas_controller.h>
#include <kis_zoom_manager.h>
#include <QPointer>
#include <View.h>
struct Canvas::Private {
Private() {}
KisCanvas2 *canvas;
};
Canvas::Canvas(KoCanvasBase *canvas, QObject *parent)
: QObject(parent)
, d(new Private)
{
d->canvas = static_cast<KisCanvas2*>(canvas);
}
Canvas::~Canvas()
{
delete d;
}
bool Canvas::operator==(const Canvas &other) const
{
return (d->canvas == other.d->canvas);
}
bool Canvas::operator!=(const Canvas &other) const
{
return !(operator==(other));
}
qreal Canvas::zoomLevel() const
{
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()->wrapAroundMode();
}
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);
}
/*
* Copyright (c) 2016 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; 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 <QObject>
#include "kritalibkis_export.h"
#include "libkis.h"
class KoCanvasBase;
/**
* 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
public:
explicit Canvas(KoCanvasBase *canvas, QObject *parent = 0);
virtual ~Canvas();
bool operator==(const Canvas &other) const;
bool operator!=(const Canvas &other) const;
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();
/**
* @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
/*
* Copyright (c) 2016 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; 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 "Channel.h"
#include <QByteArray>
#include <QDataStream>
#include <KoColorModelStandardIds.h>
#include <KoConfig.h>
#include <KoColorSpaceRegistry.h>
#include <KoColorSpace.h>
#include <kis_sequential_iterator.h>
#include <kis_layer.h>
#ifdef HAVE_OPENEXR
#include <half.h>
#endif
struct Channel::Private {
Private() {}
KisNodeSP node;
KoChannelInfo *channel;
};
Channel::Channel(KisNodeSP node, KoChannelInfo *channel, QObject *parent)
: QObject(parent)
, d(new Private)
{
d->node = node;
d->channel = channel;
}
Channel::~Channel()
{
delete d;
}
bool Channel::operator==(const Channel &other) const
{
return (d->node == other.d->node
&& d->channel == other.d->channel);
}
bool Channel::operator!=(const Channel &other) const
{
return !(operator==(other));
}
bool Channel::visible() const
{
if (!d->node || !d->channel) return false;
if (!d->node->inherits("KisLayer")) return false;
for (uint i = 0; i < d->node->colorSpace()->channelCount(); ++i) {
if (d->node->colorSpace()->channels()[i] == d->channel) {
KisLayerSP layer = qobject_cast<KisLayer*>(d->node.data());
QBitArray flags = layer->channelFlags();
return flags.testBit(i);
}
}
return false;
}
void Channel::setVisible(bool value)
{
if (!d->node || !d->channel) return;
if (!d->node->inherits("KisLayer")) return;
for (uint i = 0; i < d->node->colorSpace()->channelCount(); ++i) {
if (d->node->colorSpace()->channels()[i] == d->channel) {
QBitArray flags = d->node->colorSpace()->channelFlags(true, true);
flags.setBit(i, value);
KisLayerSP layer = qobject_cast<KisLayer*>(d->node.data());
layer->setChannelFlags(flags);
break;
}
}
}
QString Channel::name() const
{
return d->channel->name();
}
int Channel::position() const
{
return d->channel->pos();
}
int Channel::channelSize() const
{
return d->channel->size();
}
QRect Channel::bounds() const
{
if (!d->node || !d->channel) return QRect();
QRect rect = d->node->exactBounds();
KisPaintDeviceSP dev;
if (d->node->colorSpace()->colorDepthId() == Integer8BitsColorDepthID) {
dev = new KisPaintDevice(KoColorSpaceRegistry::instance()->alpha8());
}
else if (d->node->colorSpace()->colorDepthId() == Integer16BitsColorDepthID) {
dev = new KisPaintDevice(KoColorSpaceRegistry::instance()->alpha16());
}
#ifdef HAVE_OPENEXR
else if (d->node->colorSpace()->colorDepthId