diff --git a/libs/libkis/Document.h b/libs/libkis/Document.h index 8387205356..aed713c8d2 100644 --- a/libs/libkis/Document.h +++ b/libs/libkis/Document.h @@ -1,139 +1,143 @@ /* * 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; /** * Document */ class KRITALIBKIS_EXPORT Document : public QObject { Q_OBJECT Q_DISABLE_COPY(Document) public: explicit Document(KisDocument *document, bool ownsDocument = false, QObject *parent = 0); virtual ~Document(); bool batchmode() const; void setBatchmode(bool value); Node* activeNode() const; void setActiveNode(Node* value); ColorDepth* colorDepth() const; void setColorDepth(ColorDepth* value); ColorManager* colorManager() const; void setColorManager(ColorManager* value); ColorModel* colorModel() const; void setColorModel(ColorModel* value); ColorProfile* colorProfile() const; void setColorProfile(ColorProfile* value); InfoObject* documentInfo() const; void setDocumentInfo(InfoObject* value); QString fileName() const; void setFileName(QString value); int height() const; void setHeight(int value); InfoObject* metaData() const; void setMetaData(InfoObject* value); QString name() const; 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); Node* rootNode() const; Selection* selection() const; void setSelection(Selection* value); int width() const; 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; 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; void setyRes(double yRes) const; QByteArray pixelData() const; public Q_SLOTS: bool close(); bool convert(const QString &colorModel, const ColorProfile *profile); 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); void openView(); Node* createNode(const QString &name, const QString &nodeType); +Q_SIGNALS: + + void nodeCreated(Node *node); + private: friend class Krita; QPointer document() const; private: struct Private; Private *const d; }; #endif // LIBKIS_DOCUMENT_H diff --git a/libs/libkis/Krita.cpp b/libs/libkis/Krita.cpp index cedc18badd..ff63375672 100644 --- a/libs/libkis/Krita.cpp +++ b/libs/libkis/Krita.cpp @@ -1,338 +1,338 @@ /* * 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 "View.h" #include "Document.h" #include "Window.h" #include "ViewExtension.h" #include "DockWidgetFactoryBase.h" #include "Filter.h" #include "InfoObject.h" #include "Generator.h" Krita* Krita::s_instance = 0; struct Krita::Private { Private() {} QList viewExtensions; bool batchMode {false}; Notifier *notifier{new Notifier()}; }; Krita::Krita(QObject *parent) : QObject(parent) , d(new Private) { qRegisterMetaType(); } Krita::~Krita() { qDeleteAll(d->viewExtensions); 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(0); InfoObject *info = new InfoObject(fc); filter->setConfiguration(info); return filter; } QStringList Krita::generators() const { QStringList ls = KisGeneratorRegistry::instance()->keys(); qSort(ls); return ls; } Generator *Krita::generator(const QString &name) const { if (!generators().contains(name)) return 0; Generator *generator = new Generator(); - generator->setName(name); - KisGeneratorSP f = KisGeneratorRegistry::instance()->value(name); - KisGeneratorConfigurationSP fc = f->defaultConfiguration(0); - InfoObject *info = new InfoObject(fc); - generator->setConfiguration(info); +// generator->setName(name); +// KisGeneratorSP f = KisGeneratorRegistry::instance()->value(name); +// KisGeneratorConfigurationSP fc = f->defaultConfiguration(0); +// InfoObject *info = new InfoObject(fc); +// generator->setConfiguration(info); return generator; } Notifier* Krita::notifier() const { return d->notifier; } InfoObject* Krita::preferences() const { return 0; } void Krita::setPreferences(InfoObject* value) { } 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; } QList Krita::resources() const { return QList (); } void Krita::setResources(QList value) { } void Krita::addDockWidget(DockWidget *dockWidget) { } bool Krita::closeApplication() { qDebug() << "closeApplication called"; return false; } 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); QColor qc(Qt::white); qc.setAlpha(0); KoColor bgColor(qc, cs); document->newImage(name, width, height, cs, bgColor, true, 1, "", 100.0); return new Document(document, true); } 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() { return 0; } Action *Krita::createAction(const QString &text) { KisAction *action = new KisAction(text, this); KisPart::instance()->addScriptAction(action); return new Action(action->objectName(), action); } void Krita::addViewExtension(ViewExtension* viewExtension) { d->viewExtensions.append(viewExtension); } QList< ViewExtension* > Krita::viewExtensions() { return d->viewExtensions; } 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 1c868135a4..494da2a806 100644 --- a/libs/libkis/Krita.h +++ b/libs/libkis/Krita.h @@ -1,210 +1,224 @@ /* * 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 "ViewExtension.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; 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 Create a list of all available generator plugins. Generators are identified + * by an internal name; this name can be used to construct a Generator object. The + * Generator object can then be used to create a Node object representing a Fill Layer. + * @return the list of available generators. + */ QStringList generators() const; + + /** + * @brief generator construct a Generator object with a default configuration. + * @param name the name of the generator. Use Krita.instance().generators() to get + * a list of all possible filters. + * @return the generator or None if there is no such generator. + */ Generator *generator(const QString &name) const; Notifier* notifier() const; InfoObject* preferences() const; void setPreferences(InfoObject* value); /** * @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; QList resources() const; void setResources(QList value); -public Q_SLOTS: - void addDockWidget(DockWidget *dockWidget); bool closeApplication(); /** * @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); 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 QAction you can connect a slot to. */ Action *createAction(const QString &text); void addViewExtension(ViewExtension* viewExtension); QList viewExtensions(); void addDockWidgetFactory(DockWidgetFactoryBase* factory ); static Krita* instance(); 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/Notifier.cpp b/libs/libkis/Notifier.cpp index e6831f083a..a41035306a 100644 --- a/libs/libkis/Notifier.cpp +++ b/libs/libkis/Notifier.cpp @@ -1,50 +1,85 @@ /* * 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 "Notifier.h" +#include +#include +#include "View.h" +#include "Window.h" +#include "Document.h" struct Notifier::Private { Private() {} bool active {false}; }; Notifier::Notifier(QObject *parent) : QObject(parent) , d(new Private) { + connect(qApp, SIGNAL(aboutToQuit()), SIGNAL(applicationClosing())); + + connect(KisPart::instance(), SIGNAL(sigDocumentAdded(KisDocument*)), SLOT(imageCreated(KisDocument*))); + connect(KisPart::instance(), SIGNAL(sigDocumentSaved(QString)), SIGNAL(imageSaved(QString))); + connect(KisPart::instance(), SIGNAL(sigDocumentRemoved(QString)), SIGNAL(imageClosed(QString))); + + connect(KisPart::instance(), SIGNAL(sigViewAdded(KisView*)), SLOT(viewCreated(KisView*))); + connect(KisPart::instance(), SIGNAL(sigViewRemoved(KisView*)), SLOT(viewClosed(KisView*))); + + connect(KisPart::instance(), SIGNAL(sigWindowAdded(KisMainWindow*)), SLOT(WindowCreated(KisMainWindow*))); + } Notifier::~Notifier() { delete d; } bool Notifier::active() const { return d->active; } void Notifier::setActive(bool value) { d->active = value; } +void Notifier::imageCreated(KisDocument* document) +{ + Document *doc = new Document(document); + emit imageCreated(doc); +} +void Notifier::viewCreated(KisView *view) +{ + View *v = new View(view); + emit viewCreated(v); +} +void Notifier::viewClosed(KisView *view) +{ + View *v = new View(view); + emit viewClosed(v); +} - +void Notifier::windowCreated(KisMainWindow *window) +{ + Window *w = new Window(window); + emit windowCreated(w); +} diff --git a/libs/libkis/Notifier.h b/libs/libkis/Notifier.h index 45fe36a140..d3c83facb3 100644 --- a/libs/libkis/Notifier.h +++ b/libs/libkis/Notifier.h @@ -1,60 +1,109 @@ /* * 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_NOTIFIER_H #define LIBKIS_NOTIFIER_H #include #include "kritalibkis_export.h" +#include #include "libkis.h" +#include +#include +#include /** * Notifier */ class KRITALIBKIS_EXPORT Notifier : public QObject { Q_OBJECT Q_DISABLE_COPY(Notifier) Q_PROPERTY(bool Active READ active WRITE setActive) public: explicit Notifier(QObject *parent = 0); virtual ~Notifier(); bool active() const; void setActive(bool value); Q_SIGNALS: - void applicationStarted(); - void applicationClosed(); + /** + * @brief applicationClosing is emitted when the application is about to close. This + * happens after any documents and windows are closed. + */ + void applicationClosing(); + + /** + * @brief imageCreated is emitted whenever a new image is created and registered with + * the application. + */ void imageCreated(Document *image); - void imageLoaded(Document *image); - void imageSaved(Document *image); - void imageClosed(Document *image); - void nodeCreated(Document *node); + + /** + * @brief imageSaved is emitted whenever a document is saved. + * @param filename the filename of the document that has been saved. + */ + void imageSaved(const QString &filename); + + /** + * @brief imageClosed is emitted whenever the last view on an image is closed. The image + * does not exist anymore in Krita + * @param filename the filename of the image. + */ + void imageClosed(const QString &filename); + + /** + * @brief viewCreated is emitted whenever a new view is created. + * @param view the view + */ + void viewCreated(View *view); + + /** + * @brief viewClosed is emitted whenever a view is closed + * @param view the view + */ + void viewClosed(View *view); + + /** + * @brief windowCreated is emitted whenever a window is created + * @param window the window + */ + void windowCreated(Window *window); + + +private Q_SLOTS: + + void imageCreated(KisDocument *document); + + void viewCreated(KisView *view); + void viewClosed(KisView *view); + + void windowCreated(KisMainWindow *window); private: struct Private; Private *const d; }; #endif // LIBKIS_NOTIFIER_H diff --git a/libs/libkis/Window.cpp b/libs/libkis/Window.cpp index 31058fb5ca..da02bd0376 100644 --- a/libs/libkis/Window.cpp +++ b/libs/libkis/Window.cpp @@ -1,76 +1,77 @@ /* * 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 "Window.h" #include #include struct Window::Private { Private() {} QPointer window; }; Window::Window(KisMainWindow *window, QObject *parent) : QObject(parent) , d(new Private) { d->window = window; + connect(window, SIGNAL(destroyed(QObject*)), SIGNAL(windowClosed())); } Window::~Window() { delete d; } QList Window::views() const { return QList(); } void Window::setViews(QList value) { } QString Window::viewMode() const { return QString(); } void Window::setViewMode(QString value) { } void Window::activate() { if (!d->window) { d->window->activateWindow(); } } void Window::close() { if (d->window) { d->window->close(); } } diff --git a/libs/libkis/Window.h b/libs/libkis/Window.h index e8824605e1..8a4c060403 100644 --- a/libs/libkis/Window.h +++ b/libs/libkis/Window.h @@ -1,70 +1,74 @@ /* * 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_WINDOW_H #define LIBKIS_WINDOW_H #include #include "kritalibkis_export.h" #include "libkis.h" #include /** * Window */ class KRITALIBKIS_EXPORT Window : public QObject { Q_OBJECT Q_DISABLE_COPY(Window) Q_PROPERTY(QList Views READ views WRITE setViews) Q_PROPERTY(QString ViewMode READ viewMode WRITE setViewMode) public: explicit Window(KisMainWindow *window, QObject *parent = 0); virtual ~Window(); QList views() const; void setViews(QList value); QString viewMode() const; void setViewMode(QString value); public Q_SLOTS: /** * @brief activate activates this Window. */ void activate(); /** * @brief close the active window and all its Views. If there * are no Views left for a given Document, that Document will * also be closed. */ void close(); +Q_SIGNALS: + /// Emitted when the window is closed. + void windowClosed(); + private: struct Private; Private *const d; }; #endif // LIBKIS_WINDOW_H diff --git a/libs/ui/KisPart.cpp b/libs/ui/KisPart.cpp index 4eeaab3368..26d381b985 100644 --- a/libs/ui/KisPart.cpp +++ b/libs/ui/KisPart.cpp @@ -1,493 +1,501 @@ /* This file is part of the KDE project * Copyright (C) 1998-1999 Torben Weis * Copyright (C) 2000-2005 David Faure * Copyright (C) 2007-2008 Thorsten Zachmann * Copyright (C) 2010-2012 Boudewijn Rempt * Copyright (C) 2011 Inge Wallin * Copyright (C) 2015 Michael Abrahams * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public License * along with this library; see the file COPYING.LIB. If not, write to * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. */ #include "KisPart.h" #include "KoProgressProxy.h" #include #include #include #include #include #include #include #include #include "KisApplication.h" #include "KisDocument.h" #include "KisView.h" #include "KisViewManager.h" #include "KisImportExportManager.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "KisView.h" #include "KisDocument.h" #include "kis_config.h" #include "kis_shape_controller.h" #include "kis_resource_server_provider.h" #include "kis_animation_cache_populator.h" #include "kis_idle_watcher.h" #include "kis_image.h" #include "KisImportExportManager.h" #include "KisDocument.h" #include "KoToolManager.h" #include "KisViewManager.h" #include "kis_script_manager.h" #include "KisOpenPane.h" #include "kis_color_manager.h" #include "kis_debug.h" #include "kis_action.h" #include "kis_action_registry.h" Q_GLOBAL_STATIC(KisPart, s_instance) class Q_DECL_HIDDEN KisPart::Private { public: Private(KisPart *_part) : part(_part) , idleWatcher(2500) , animationCachePopulator(_part) { } ~Private() { } KisPart *part; QList > views; QList > mainWindows; QList > documents; QList scriptActions; KActionCollection *actionCollection{0}; KisIdleWatcher idleWatcher; KisAnimationCachePopulator animationCachePopulator; }; KisPart* KisPart::instance() { return s_instance; } KisPart::KisPart() : d(new Private(this)) { // Preload all the resources in the background Q_UNUSED(KoResourceServerProvider::instance()); Q_UNUSED(KisResourceServerProvider::instance()); Q_UNUSED(KisColorManager::instance()); connect(this, SIGNAL(documentOpened(QString)), this, SLOT(updateIdleWatcherConnections())); connect(this, SIGNAL(documentClosed(QString)), this, SLOT(updateIdleWatcherConnections())); connect(KisActionRegistry::instance(), SIGNAL(shortcutsUpdated()), this, SLOT(updateShortcuts())); connect(&d->idleWatcher, SIGNAL(startedIdleMode()), &d->animationCachePopulator, SLOT(slotRequestRegeneration())); d->animationCachePopulator.slotRequestRegeneration(); } KisPart::~KisPart() { while (!d->documents.isEmpty()) { delete d->documents.takeFirst(); } while (!d->views.isEmpty()) { delete d->views.takeFirst(); } while (!d->mainWindows.isEmpty()) { delete d->mainWindows.takeFirst(); } delete d; } void KisPart::updateIdleWatcherConnections() { QVector images; Q_FOREACH (QPointer document, documents()) { if (document->image()) { images << document->image(); } } d->idleWatcher.setTrackedImages(images); } void KisPart::addDocument(KisDocument *document) { //dbgUI << "Adding document to part list" << document; Q_ASSERT(document); if (!d->documents.contains(document)) { d->documents.append(document); emit documentOpened('/'+objectName()); + emit sigDocumentAdded(document); + connect(document, SIGNAL(sigSavingFinished()), SLOT(slotDocumentSaved())); } } QList > KisPart::documents() const { return d->documents; } KisDocument *KisPart::createDocument() const { KisDocument *doc = new KisDocument(); return doc; } int KisPart::documentCount() const { return d->documents.size(); } void KisPart::removeDocument(KisDocument *document) { d->documents.removeAll(document); emit documentClosed('/'+objectName()); + emit sigDocumentRemoved(document->url().toLocalFile()); document->deleteLater(); } KisMainWindow *KisPart::createMainWindow() { KisMainWindow *mw = new KisMainWindow(); Q_FOREACH(QAction *action, d->scriptActions) { mw->viewManager()->scriptManager()->addAction(action); } dbgUI <<"mainWindow" << (void*)mw << "added to view" << this; d->mainWindows.append(mw); - + emit sigWindowAdded(mw); return mw; } KisView *KisPart::createView(KisDocument *document, KoCanvasResourceManager *resourceManager, KActionCollection *actionCollection, QWidget *parent) { // If creating the canvas fails, record this and disable OpenGL next time KisConfig cfg; KConfigGroup grp( KSharedConfig::openConfig(), "crashprevention"); if (grp.readEntry("CreatingCanvas", false)) { cfg.setUseOpenGL(false); } if (cfg.canvasState() == "OPENGL_FAILED") { cfg.setUseOpenGL(false); } grp.writeEntry("CreatingCanvas", true); grp.sync(); QApplication::setOverrideCursor(Qt::WaitCursor); KisView *view = new KisView(document, resourceManager, actionCollection, parent); QApplication::restoreOverrideCursor(); // Record successful canvas creation grp.writeEntry("CreatingCanvas", false); grp.sync(); addView(view); return view; } void KisPart::addView(KisView *view) { if (!view) return; if (!d->views.contains(view)) { d->views.append(view); } connect(view, SIGNAL(destroyed()), this, SLOT(viewDestroyed())); emit sigViewAdded(view); } void KisPart::removeView(KisView *view) { if (!view) return; /** * HACK ALERT: we check here explicitly if the document (or main * window), is saving the stuff. If we close the * document *before* the saving is completed, a crash * will happen. */ if (view->mainWindow()->hackIsSaving()) { return; } emit sigViewRemoved(view); QPointer doc = view->document(); d->views.removeAll(view); if (doc) { bool found = false; Q_FOREACH (QPointer view, d->views) { if (view && view->document() == doc) { found = true; break; } } if (!found) { removeDocument(doc); } } } QList > KisPart::views() const { return d->views; } int KisPart::viewCount(KisDocument *doc) const { if (!doc) { return d->views.count(); } else { int count = 0; Q_FOREACH (QPointer view, d->views) { if (view && view->isVisible() && view->document() == doc) { count++; } } return count; } } +void KisPart::slotDocumentSaved() +{ + KisDocument *doc = qobject_cast(sender()); + emit sigDocumentSaved(doc->url().toLocalFile()); +} void KisPart::removeMainWindow(KisMainWindow *mainWindow) { dbgUI <<"mainWindow" << (void*)mainWindow <<"removed from doc" << this; if (mainWindow) { d->mainWindows.removeAll(mainWindow); } } const QList > &KisPart::mainWindows() const { return d->mainWindows; } int KisPart::mainwindowCount() const { return d->mainWindows.count(); } KisMainWindow *KisPart::currentMainwindow() const { QWidget *widget = qApp->activeWindow(); KisMainWindow *mainWindow = qobject_cast(widget); while (!mainWindow && widget) { widget = widget->parentWidget(); mainWindow = qobject_cast(widget); } if (!mainWindow && mainWindows().size() > 0) { mainWindow = mainWindows().first(); } return mainWindow; } void KisPart::addScriptAction(KisAction *action) { d->scriptActions << action; } KisIdleWatcher* KisPart::idleWatcher() const { return &d->idleWatcher; } KisAnimationCachePopulator* KisPart::cachePopulator() const { return &d->animationCachePopulator; } void KisPart::openExistingFile(const QUrl &url) { Q_ASSERT(url.isLocalFile()); qApp->setOverrideCursor(Qt::BusyCursor); KisDocument *document = createDocument(); if (!document->openUrl(url)) { delete document; return; } if (!document->image()) { delete document; return; } document->setModified(false); addDocument(document); KisMainWindow *mw = currentMainwindow(); mw->addViewAndNotifyLoadingCompleted(document); qApp->restoreOverrideCursor(); } void KisPart::updateShortcuts() { // Update any non-UI actionCollections. That includes: // - Shortcuts called inside of tools // - Perhaps other things? KoToolManager::instance()->updateToolShortcuts(); // Now update the UI actions. Q_FOREACH (KisMainWindow *mainWindow, d->mainWindows) { KActionCollection *ac = mainWindow->actionCollection(); ac->updateShortcuts(); // Loop through mainWindow->actionCollections() to modify tooltips // so that they list shortcuts at the end in parentheses Q_FOREACH ( QAction* action, ac->actions()) { // Remove any existing suffixes from the tooltips. // Note this regexp starts with a space, e.g. " (Ctrl-a)" QString strippedTooltip = action->toolTip().remove(QRegExp("\\s\\(.*\\)")); // Now update the tooltips with the new shortcut info. if(action->shortcut() == QKeySequence(0)) action->setToolTip(strippedTooltip); else action->setToolTip( strippedTooltip + " (" + action->shortcut().toString() + ")"); } } } void KisPart::openTemplate(const QUrl &url) { qApp->setOverrideCursor(Qt::BusyCursor); KisDocument *document = createDocument(); bool ok = document->loadNativeFormat(url.toLocalFile()); document->setModified(false); document->undoStack()->clear(); if (ok) { QString mimeType = KisMimeDatabase::mimeTypeForFile(url.toLocalFile()); // in case this is a open document template remove the -template from the end mimeType.remove( QRegExp( "-template$" ) ); document->setMimeTypeAfterLoading(mimeType); document->resetURL(); } else { if (document->errorMessage().isEmpty()) { QMessageBox::critical(0, i18nc("@title:window", "Krita"), i18n("Could not create document from template\n%1", document->localFilePath())); } else { QMessageBox::critical(0, i18nc("@title:window", "Krita"), i18n("Could not create document from template\n%1\nReason: %2", document->localFilePath(), document->errorMessage())); } delete document; return; } addDocument(document); KisMainWindow *mw = currentMainwindow(); mw->addViewAndNotifyLoadingCompleted(document); KisOpenPane *pane = qobject_cast(sender()); if (pane) { pane->hide(); pane->deleteLater(); } qApp->restoreOverrideCursor(); } void KisPart::viewDestroyed() { KisView *view = qobject_cast(sender()); if (view) { removeView(view); } } void KisPart::addRecentURLToAllMainWindows(QUrl url) { // Add to recent actions list in our mainWindows Q_FOREACH (KisMainWindow *mainWindow, d->mainWindows) { mainWindow->addRecentURL(url); } } void KisPart::startCustomDocument(KisDocument* doc) { addDocument(doc); KisMainWindow *mw = currentMainwindow(); KisOpenPane *pane = qobject_cast(sender()); if (pane) { pane->hide(); pane->deleteLater(); } mw->addViewAndNotifyLoadingCompleted(doc); } KisInputManager* KisPart::currentInputManager() { return instance()->currentMainwindow()->viewManager()->inputManager(); } diff --git a/libs/ui/KisPart.h b/libs/ui/KisPart.h index 390987d41b..a7e8b47d27 100644 --- a/libs/ui/KisPart.h +++ b/libs/ui/KisPart.h @@ -1,251 +1,261 @@ /* This file is part of the KDE project Copyright (C) 1998, 1999 Torben Weis Copyright (C) 2000-2005 David Faure Copyright (C) 2007 Thorsten Zachmann Copyright (C) 2010 Boudewijn Rempt Copyright (C) 2015 Michael Abrahams This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. */ #ifndef KIS_PART_H #define KIS_PART_H #include #include #include #include "kritaui_export.h" #include #include namespace KIO { } class KisAction; class KisDocument; class KisView; class KisDocument; class KisIdleWatcher; class KisAnimationCachePopulator; /** * KisPart is the Great Deku Tree of Krita. * * It is a singleton class which provides the main entry point to the application. * Krita supports multiple documents, multiple main windows, and multiple * components. KisPart manages these resources and provides them to the rest of * Krita. It manages lists of Actions and shortcuts as well. * * The terminology comes from KParts, which is a system allowing one KDE app * to be run from inside another, like pressing F4 inside dophin to run konsole. * * Needless to say, KisPart hasn't got much to do with KParts anymore. */ class KRITAUI_EXPORT KisPart : public QObject { Q_OBJECT public: static KisPart *instance(); /** * Constructor. * * @param parent may be another KisDocument, or anything else. * Usually passed by KPluginFactory::create. */ explicit KisPart(); /** * Destructor. * * The destructor does not delete any attached KisView objects and it does not * delete the attached widget as returned by widget(). */ ~KisPart(); // ----------------- Document management ----------------- /** * create an empty document. The document is not automatically registered with the part. */ KisDocument *createDocument() const; /** * Add the specified document to the list of documents this KisPart manages. */ void addDocument(KisDocument *document); /** * @return a list of all documents this part manages */ QList > documents() const; /** * @return number of documents this part manages. */ int documentCount() const; void removeDocument(KisDocument *document); // ----------------- MainWindow management ----------------- /** * Create a new main window. */ KisMainWindow *createMainWindow(); /** * Removes a main window from the list of managed windows. * * This is called by the MainWindow after it finishes its shutdown routine. */ void removeMainWindow(KisMainWindow *mainWindow); /** * @return the list of main windows. */ const QList >& mainWindows() const; /** * @return the number of shells for the main window */ int mainwindowCount() const; void addRecentURLToAllMainWindows(QUrl url); /** * @return the currently active main window. */ KisMainWindow *currentMainwindow() const; /** * Add a given action to the list of dynamically defined actions. On creating * a mainwindow, all these actions will be added to the script manager. */ void addScriptAction(KisAction *); /** * Load actions for currently active main window into KisActionRegistry. */ void loadActions(); /** * @return the application-wide KisIdleWatcher. */ KisIdleWatcher *idleWatcher() const; /** * @return the application-wide AnimationCachePopulator. */ KisAnimationCachePopulator *cachePopulator() const; public Q_SLOTS: /** * This slot loads an existing file. * @param url the file to load */ void openExistingFile(const QUrl &url); /** * This slot loads a template and deletes the sender. * @param url the template to load */ void openTemplate(const QUrl &url); /** * @brief startCustomDocument adds the given document to the document list and deletes the sender() * @param doc */ void startCustomDocument(KisDocument *doc); private Q_SLOTS: void viewDestroyed(); void updateIdleWatcherConnections(); void updateShortcuts(); Q_SIGNALS: /** - * emitted when a new document is opened. + * emitted when a new document is opened. (for the idle watcher) */ void documentOpened(const QString &ref); /** - * emitted when an old document is closed. + * emitted when an old document is closed. (for the idle watcher) */ void documentClosed(const QString &ref); + // These signals are for libkis or sketch void sigViewAdded(KisView *view); void sigViewRemoved(KisView *view); + void sigDocumentAdded(KisDocument *document); + void sigDocumentSaved(const QString &url); + void sigDocumentRemoved(const QString &filename); + void sigWindowAdded(KisMainWindow *window); public: static KisInputManager *currentInputManager(); //------------------ View management ------------------ /** * Create a new view for the document. The view is added to the list of * views, and if the document wasn't known yet, it's registered as well. */ KisView *createView(KisDocument *document, KoCanvasResourceManager *resourceManager, KActionCollection *actionCollection, QWidget *parent); /** * Adds a view to the document. If the part doesn't know yet about * the document, it is registered. * * This calls KisView::updateReadWrite to tell the new view * whether the document is readonly or not. */ void addView(KisView *view); /** * Removes a view of the document. */ void removeView(KisView *view); /** * @return a list of views this document is displayed in */ QList > views() const; /** * @return number of views this document is displayed in */ int viewCount(KisDocument *doc) const; + +private Q_SLOTS: + + void slotDocumentSaved(); + private: Q_DISABLE_COPY(KisPart) class Private; Private *const d; }; #endif diff --git a/plugins/extensions/pykrita/sip/krita/Document.sip b/plugins/extensions/pykrita/sip/krita/Document.sip index 639b05fdc5..1bb96a9e6d 100644 --- a/plugins/extensions/pykrita/sip/krita/Document.sip +++ b/plugins/extensions/pykrita/sip/krita/Document.sip @@ -1,56 +1,58 @@ class Document : QObject /NoDefaultCtors/ { %TypeHeaderCode #include "Document.h" %End Document(const Document & __0); public: Node * activeNode() const; void setActiveNode(Node* value); bool batchmode() const; void setBatchmode(bool value); ColorDepth * colorDepth() const; void setColorDepth(ColorDepth* value); ColorManager * colorManager() const; void setColorManager(ColorManager* value); ColorModel * colorModel() const; void setColorModel(ColorModel* value); ColorProfile * colorProfile() const; void setColorProfile(ColorProfile* value); InfoObject * documentInfo() const; void setDocumentInfo(InfoObject* value); QString fileName() const; void setFileName(QString value); int height() const; void setHeight(int value); InfoObject * metaData() const; void setMetaData(InfoObject* value); QString name() const; void setName(QString value); int resolution() const; void setResolution(int value); Node * rootNode() const; Selection * selection() const; 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() const; public Q_SLOTS: bool close(); bool convert(const QString & colorModel, const ColorProfile* profile); 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); void openView(); Node * createNode(const QString & name, const QString & nodeType); +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 ced71babea..03243e5dda 100644 --- a/plugins/extensions/pykrita/sip/krita/Krita.sip +++ b/plugins/extensions/pykrita/sip/krita/Krita.sip @@ -1,59 +1,59 @@ class Krita : QObject { %TypeHeaderCode #include "Krita.h" %End public: -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 generators() const /Factory/; Generator * generator(const QString &name) const /Factory/; - Notifier * notifier() const /Factory/; + Notifier * notifier() const; InfoObject * preferences() const /Factory/; void setPreferences(InfoObject* value); QString version() const; QList views() const /Factory/; Window * activeWindow() const /Factory/; QList windows() const /Factory/; QList resources() const /Factory/; void setResources(QList value); -public Q_SLOTS: + void addDockWidget(DockWidget* dockWidget); bool closeApplication(); 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 addViewExtension(ViewExtension* _viewExtension /GetWrapper/); %MethodCode Py_BEGIN_ALLOW_THREADS sipCpp->addViewExtension(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 static Krita * instance(); static QObject * fromVariant(const QVariant & v); private: Krita(const Krita &); // Generated }; diff --git a/plugins/extensions/pykrita/sip/krita/Notifier.sip b/plugins/extensions/pykrita/sip/krita/Notifier.sip index 0c0e492f09..9a2c16e861 100644 --- a/plugins/extensions/pykrita/sip/krita/Notifier.sip +++ b/plugins/extensions/pykrita/sip/krita/Notifier.sip @@ -1,21 +1,20 @@ class Notifier : QObject { %TypeHeaderCode #include "Notifier.h" %End Notifier(const Notifier & __0); public: Notifier(QObject* parent /TransferThis/ = 0); virtual ~Notifier(); bool active() const; void setActive(bool value); Q_SIGNALS: - void applicationStarted(); - void applicationClosed(); + void applicationClosing(); void imageCreated(Document* image); - void imageLoaded(Document* image); - void imageSaved(Document* image); - void imageClosed(Document* image); - void nodeCreated(Document* node); -private: + void imageSaved(const QString &filename); + void imageClosed(const QString &filename); + void viewCreated(View *view); + void viewClosed(View *view); + void windowCreated(Window *window); }; diff --git a/plugins/extensions/pykrita/sip/krita/Window.sip b/plugins/extensions/pykrita/sip/krita/Window.sip index be32f89617..040d079b01 100644 --- a/plugins/extensions/pykrita/sip/krita/Window.sip +++ b/plugins/extensions/pykrita/sip/krita/Window.sip @@ -1,16 +1,18 @@ class Window : QObject { %TypeHeaderCode #include "Window.h" %End Window(const Window & __0); public: QList views() const /Factory/; void setViews(QList value); QString viewMode() const; void setViewMode(QString value); public Q_SLOTS: void activate(); void close(); +Q_SIGNALS: + void windowClosed(); private: };