diff --git a/krita/krita4.xmlgui b/krita/krita4.xmlgui
index b933f80cf4..1e8ec06428 100644
--- a/krita/krita4.xmlgui
+++ b/krita/krita4.xmlgui
@@ -1,386 +1,386 @@
&View
&Canvas
&Snap To
&Image
&Rotate
&Layer
New
&Import/Export
Import
&Convert
&Select
&Group
&Transform
&Rotate
S&plit
S&plit Alpha
&Select
Filte&r
&Tools
-
+ Scripting
Recording
Macros
Setti&ngs
&Help
File
Brushes and Stuff
diff --git a/libs/libkis/Action.cpp b/libs/libkis/Action.cpp
index 75005dce79..faafc23113 100644
--- a/libs/libkis/Action.cpp
+++ b/libs/libkis/Action.cpp
@@ -1,169 +1,158 @@
/*
* 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);
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);
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->isVisible();
}
void Action::setVisible(bool value)
{
if (!d->action) return;
d->action->setVisible(value);
}
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);
}
QString Action::tooltip() const
{
return d->action->toolTip();
}
void Action::trigger()
{
d->action->trigger();
}
-
-
-void Action::setMenu(const QString menu)
-{
- d->action->setProperty("menu", menu);
-}
-
-QString Action::menu() const
-{
- return d->action->property("menu").toString();
-}
diff --git a/libs/libkis/Action.h b/libs/libkis/Action.h
index 3d8b470013..9546fc644d 100644
--- a/libs/libkis/Action.h
+++ b/libs/libkis/Action.h
@@ -1,165 +1,153 @@
/*
* 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);
~Action() override;
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);
/**
* @return the tooltip text
*/
QString tooltip() const;
/**
* Trigger this action
*/
void trigger();
- /**
- * @brief setMenu determines in which menu the action will be placed. The default is tools/scripts
- * @param menu the menu where the action should go, / -separated to drill down the hierarchy
- */
- void setMenu(const QString menu);
-
- /**
- * @return the menu in which this action is to be placed.
- */
- QString menu() const;
-
-
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/Extension.h b/libs/libkis/Extension.h
index fc9d76c47e..eb9502a953 100644
--- a/libs/libkis/Extension.h
+++ b/libs/libkis/Extension.h
@@ -1,78 +1,86 @@
/*
* 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_EXTENSION_H
#define LIBKIS_EXTENSION_H
#include "kritalibkis_export.h"
#include
+#include
/**
- * An Extension is the base for classes that extend Krita. An Extension
+ * An Extension is the base for classes that extend Krita. An Extension
* is loaded on startup, when the setup() method will be executed.
- *
- * The extension instance should be added to the Krita Application object
+ *
+ * The extension instance should be added to the Krita Application object
* using Krita.instance().addViewExtension or Application.addViewExtension
* or Scripter.addViewExtension.
- *
+ *
* Example:
- *
+ *
* @code
* import sys
* from PyQt5.QtGui import *
* from PyQt5.QtWidgets import *
* from krita import *
* class HelloExtension(Extension):
*
* def __init__(self, parent):
* super().__init__(parent)
*
* def hello(self):
* QMessageBox.information(QWidget(), "Test", "Hello! This is Krita " + Application.version())
- *
+ *
* def setup(self):
* qDebug("Hello Setup")
- * action = Krita.instance().createAction("hello")
+ *
+ * def createActions(self, window)
+ * action = window.createAction("hello")
* action.triggered.connect(self.hello)
*
* Scripter.addExtension(HelloExtension(Krita.instance()))
- *
+ *
* @endcode
*/
class KRITALIBKIS_EXPORT Extension : public QObject
{
Q_OBJECT
public:
-
+
/**
- * Create a new extension. The extension will be
+ * Create a new extension. The extension will be
* owned by @param parent.
*/
explicit Extension(QObject *parent = 0);
~Extension() override;
-
+
/**
- * Override this function to setup your Extension. You can use it to add
- * Actions to the action collection or integrate in any other way with
- * the application.
+ * Override this function to setup your Extension. You can use it to integrate
+ * with the Krita application instance.
*/
virtual void setup() = 0;
+
+ virtual void createActions(Window *window) = 0;
+
};
+
+
+
#endif
diff --git a/libs/libkis/Krita.cpp b/libs/libkis/Krita.cpp
index b9421a573e..a90f5ec0ea 100644
--- a/libs/libkis/Krita.cpp
+++ b/libs/libkis/Krita.cpp
@@ -1,433 +1,423 @@
/*
* 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
#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 extensions;
bool batchMode {false};
Notifier *notifier{new Notifier()};
};
Krita::Krita(QObject *parent)
: QObject(parent)
, d(new Private)
{
qRegisterMetaType();
+ connect(KisPart::instance(), SIGNAL(sigWindowAdded(KisMainWindow*)), SLOT(mainWindowAdded(KisMainWindow*)));
}
Krita::~Krita()
{
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();
std::sort(ls.begin(), ls.end());
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::colorModels() const
{
QSet colorModelsIds;
QList ids = KoColorSpaceRegistry::instance()->colorModelsList(KoColorSpaceRegistry::AllColorSpaces);
Q_FOREACH(KoID id, ids) {
colorModelsIds << id.id();
}
return colorModelsIds.toList();;
}
QStringList Krita::colorDepths(const QString &colorModel) const
{
QSet colorDepthsIds;
QList ids = KoColorSpaceRegistry::instance()->colorDepthList(colorModel, KoColorSpaceRegistry::AllColorSpaces);
Q_FOREACH(KoID id, ids) {
colorDepthsIds << id.id();
}
return colorDepthsIds.toList();;
}
QStringList Krita::filterStrategies() const
{
return KisFilterStrategyRegistry::instance()->keys();
}
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.toLower() == "pattern") {
KoResourceServer* server = KoResourceServerProvider::instance()->patternServer();
Q_FOREACH (KoResource *res, server->resources()) {
resources[res->name()] = new Resource(res);
}
}
else if (type.toLower() == "gradient") {
KoResourceServer* server = KoResourceServerProvider::instance()->gradientServer();
Q_FOREACH (KoResource *res, server->resources()) {
resources[res->name()] = new Resource(res);
}
}
else if (type.toLower() == "brush") {
KisBrushResourceServer* server = KisBrushServer::instance()->brushServer();
Q_FOREACH (KisBrushSP res, server->resources()) {
resources[res->name()] = new Resource(res.data());
}
}
else if (type.toLower() == "preset") {
KisPaintOpPresetResourceServer* server = KisResourceServerProvider::instance()->paintOpPresetServer();
Q_FOREACH (KisPaintOpPresetSP res, server->resources()) {
resources[res->name()] = new Resource(res.data());
}
}
else if (type.toLower() == "palette") {
KoResourceServer* server = KoResourceServerProvider::instance()->paletteServer();
Q_FOREACH (KoResource *res, server->resources()) {
resources[res->name()] = new Resource(res);
}
}
else if (type.toLower() == "workspace") {
KoResourceServer< KisWorkspaceResource >* server = KisResourceServerProvider::instance()->workspaceServer();
Q_FOREACH (KoResource *res, server->resources()) {
resources[res->name()] = new Resource(res);
}
}
return resources;
}
QStringList Krita::recentDocuments() const
{
KConfigGroup grp = KSharedConfig::openConfig()->group(QString("RecentFiles"));
QStringList keys = grp.keyList();
QStringList recentDocuments;
for(int i = 0; i <= keys.filter("File").count(); i++)
recentDocuments << grp.readEntry(QString("File%1").arg(i), QString(""));
return recentDocuments;
}
Document* Krita::createDocument(int width, int height, const QString &name, const QString &colorModel, const QString &colorDepth, const QString &profile, double resolution)
{
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, "", double(resolution / 72) )) {
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::DontAddToRecent);
return new Document(document);
}
Window* Krita::openWindow()
{
KisMainWindow *mw = KisPart::instance()->createMainWindow();
return new Window(mw);
}
-Action *Krita::createAction(const QString &id, const QString &text, bool addToScriptMenu)
-{
- KisAction *action = new KisAction(text, this);
- action->setObjectName(id);
-
- KisActionRegistry *actionRegistry = KisActionRegistry::instance();
- actionRegistry->propertizeAction(action->objectName(), action);
- bool ok; // We will skip this check
- int activationFlags = actionRegistry->getActionProperty(id, "activationFlags").toInt(&ok, 2);
- int activationConditions = actionRegistry->getActionProperty(id, "activationConditions").toInt(&ok, 2);
- action->setActivationFlags((KisAction::ActivationFlags) activationFlags);
- action->setActivationConditions((KisAction::ActivationConditions) activationConditions);
-
- if (addToScriptMenu) {
- KisPart::instance()->addScriptAction(action);
- }
- return new Action(action->objectName(), action);
-}
-
void Krita::addExtension(Extension* extension)
{
d->extensions.append(extension);
}
QList< Extension* > Krita::extensions()
{
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);
}
QIcon Krita::icon(QString &iconName) const
{
return KisIconUtils::loadIcon(iconName);
}
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;
}
+
+void Krita::mainWindowAdded(KisMainWindow *kisWindow)
+{
+ Q_FOREACH(Extension *extension, d->extensions) {
+ Window window(kisWindow);
+ extension->createActions(&window);
+ }
+}
diff --git a/libs/libkis/Krita.h b/libs/libkis/Krita.h
index fc4f5b6a36..5fd47153fb 100644
--- a/libs/libkis/Krita.h
+++ b/libs/libkis/Krita.h
@@ -1,350 +1,344 @@
/*
* 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);
~Krita() override;
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 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 colorModels creates a list with all color models id's registered.
* @return a list of all color models or a empty list if there is no such color models.
*/
QStringList colorModels() const;
/**
* @brief colorDepths creates a list with the names of all color depths
* compatible with the given color model.
* @param colorModel the id of a color model.
* @return a list of all color depths or a empty list if there is no such
* color depths.
*/
QStringList colorDepths(const QString &colorModel) const;
/**
* @brief filterStrategies Retrieves all installed filter strategies. A filter
* strategy is used when transforming (scaling, shearing, rotating) an image to
* calculate the value of the new pixels. You can use th
* @return the id's of all available filters.
*/
QStringList filterStrategies() 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 return all recent documents registered in the RecentFiles group of the kritarc
*/
QStringList recentDocuments() const;
/**
* @brief createDocument creates a new document and image and registers
* the document with the Krita application.
*
* Unless you explicitly call Document::close() the document wil remain
* known to the Krita document registry. The document and its image will
* only be deleted when Krita exits.
*
* The document will have one transparent layer.
*
* To create a new document and show it, do something like:
@code
from Krita import *
def add_document_to_window():
d = Application.createDocument(100, 100, "Test", "RGBA", "U8", "", 120.0)
Application.activeWindow().addView(d)
add_document_to_window()
@endcode
*
* @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.
* @param resolution the resolution in points per inch.
* @return the created document.
*/
Document *createDocument(int width, int height, const QString &name, const QString &colorModel, const QString &colorDepth, const QString &profile, double resolution);
/**
* @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. This means that actions need to be created in the
- * setup phase of the plugin, not on the fly.
- * @param id the unique id for this action
- * @param text the user-visible text
- * @return the Action you can connect a slot to.
- */
- Action *createAction(const QString &name, const QString &text, bool addToScriptMenu = true);
-
/**
* @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.
*/
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 icon
* This allows you to get icons from Krita's internal icons.
* @param iconName name of the icon.
* @return the icon related to this name.
*/
QIcon icon(QString &iconName) const;
/**
* @brief instance retrieve the singleton instance of the Application object.
*/
static Krita* instance();
// Internal only: for use with mikro.py
static QObject *fromVariant(const QVariant& v);
+private Q_SLOTS:
+
+ void mainWindowAdded(KisMainWindow *window);
+
private:
struct Private;
Private *const d;
static Krita* s_instance;
};
Q_DECLARE_METATYPE(Notifier*);
#endif // LIBKIS_KRITA_H
diff --git a/libs/libkis/Mainpage.dox b/libs/libkis/Mainpage.dox
index 03b09767d3..c98cbcf7c8 100644
--- a/libs/libkis/Mainpage.dox
+++ b/libs/libkis/Mainpage.dox
@@ -1,147 +1,150 @@
/*
* Copyright (C) 2016 Boudewijn Rempt
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
/**
\mainpage Krita Scripting and Plugin Wrapper Library: libkis
Libkis is a QObject-based wrapper around Krita's internal libraries.
The wrapper can be used from C++ plugins that do not need the
advanced and volatile internal libraries of Krita, or can be bound
to scripting languages like Python or Javascript.
All classes are based on QObject, so QMetaObject introspection can
be used to discover properties, slots and signals and automatically
expose all functionality to the client.
Note that all objects that are created are wrapper objects that are
owned by the scripting environment or the plugin.
Using the functionality in this library, either through a scripting
environment like Python or Javascript, or directly from C++, you can,
among other things achieve the following functionality:
- Open, save, export, rename files.
- Access the layers and masks in a file
- Read and write pixel data
- Add menu items, toolbar items and docker palettes
The reference implementation of scripting in Krita is implemented
in Python 3. All examples in the documentation for scripting will be
provided using Python, although the api documentation is generated
from C++ header files and shows c++ syntax for arguments.
Autostarting Scripts
====================
Autostarting scripts or script-based plugins are scripts that Krita
loads on startup. You can add autostarting scripts to Krita by placing
them in the pykrita folder in the resources folder: go to settings/
manage resources and press the Open Resources Folder to open your
local resources folder.
Scripts are identified by a file that ends in a `.desktop` extension
that contain information about the script itself. For example:
@code
[Desktop Entry]
Type=Service
ServiceTypes=Krita/PythonPlugin
X-KDE-Library=hello
X-Python-2-Compatible=false
Name=Hello World
Comment=Basic plugin to test PyKrita
@endcode
The Python code itself should be placed in the pykrita/hello folder.
Your Python plugin needs to be a module, so needs to have a `__init__.py`
file:
@code
# let's make a module
from .hello import *
@endcode
Krita is a Qt-based application. In principle, you can use any Python
binding to Qt as long as it's using exactly the same version of Qt
that Krita uses. In our examples we will be using [PyQt](https://www.riverbankcomputing.com/software/pyqt/intro).
The easiest access to the Krita api is by simply importing the "krita"
module. This automatically adds two built-ins: Scripter and Application.
This is an alias for Krita.instance(), which is the first place from
which to access the running Krita instance.
@code
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *
from krita import *
def hello():
QMessageBox.information(QWidget(), "Test", "Hello World")
class HelloExtension(Extension):
def __init__(self, parent):
super().__init__(parent)
- def setup(self, viewManager):
- action = viewManager.createAction("Hello")
+ def setup(self):
+ pass
+
+ def createActions(self, window):
+ action = window.createAction("Hello")
action.triggered.connect(hello)
Krita.instance().addExtension(HelloExtension(Krita.instance()))
@endcode
The Krita Object Model
======================
The starting point is the @see Krita class, which provides a singleton
object for easy reference. From the Krita class, a hierarchy is provided
where you can access windows, lviews, documents, nodes and channels.
You can access the Krita class as
* Krita.instance()
* Application
* Scripter
For ease of use.
The Document class is provided to allow access to the images Krita has
loaded. *Note*: internally, Krita distinguishes between images and documents.
A document contains an image and knows the filename of the image, the image
itself only knows about the layers and masks it contains. The generic
name for layers and masks is *node*.
A Node can be a group layer, a file layer, a vector layer, a filter layer,
a generator layer, a clone layer, a paint layer or a transform mask, a selection
mask, a transparency mask or a colorize mask. You can change some properties
of Nodes, but not all of them.
The Window class is provided to allow access to the windows and views Krita
has open. A given Document can be shown in more than one View, and in more than
one Window. You can open and close windows and views.
*/
// DOXYGEN_SET_PROJECT_NAME = Krita
// DOXYGEN_SET_IGNORE_PREFIX = Kis Ko K
diff --git a/libs/libkis/Window.cpp b/libs/libkis/Window.cpp
index e5b2189e77..59d273e1b1 100644
--- a/libs/libkis/Window.cpp
+++ b/libs/libkis/Window.cpp
@@ -1,117 +1,151 @@
/*
* 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
+
#include
#include
#include
+#include
+#include
#include
#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;
}
bool Window::operator==(const Window &other) const
{
return (d->window == other.d->window);
}
bool Window::operator!=(const Window &other) const
{
return !(operator==(other));
}
QMainWindow *Window::qwindow() const
{
return d->window;
}
QList Window::views() const
{
QList ret;
if (d->window) {
foreach(QPointer view, KisPart::instance()->views()) {
if (view->mainWindow() == d->window) {
ret << new View(view);
}
}
}
return ret;
}
View *Window::addView(Document *document)
{
if (d->window) {
KisView *view = d->window->newView(document->document());
return new View(view);
}
return 0;
}
void Window::showView(View *view)
{
if (views().contains(view)) {
KisView *v = view->view();
d->window->showView(v);
}
}
View *Window::activeView() const
{
if (d->window) {
return new View(d->window->activeView());
}
return 0;
}
void Window::activate()
{
if (d->window) {
d->window->activateWindow();
}
}
void Window::close()
{
if (d->window) {
KisPart::instance()->removeMainWindow(d->window);
d->window->close();
}
}
+Action *Window::createAction(const QString &id, const QString &text, const QString &menuLocation)
+{
+ KisAction *action = d->window->viewManager()->actionManager()->createAction(id);
+ action->setText(text);
+ action->setObjectName(id);
+ if (!menuLocation.isEmpty()) {
+ QAction *found = 0;
+ QList candidates = d->window->menuBar()->actions();
+ Q_FOREACH(const QString &name, menuLocation.split("/")) {
+ Q_FOREACH(QAction *candidate, candidates) {
+ if (candidate->objectName() == name) {
+ found = candidate;
+ candidates = candidate->menu()->actions();
+ break;
+ }
+ }
+ if (candidates.isEmpty()) {
+ break;
+ }
+ }
+
+ if (found && found->menu()) {
+ found->menu()->addAction(action);
+ }
+ }
+ return new Action(action->objectName(), action);
+}
+
+
diff --git a/libs/libkis/Window.h b/libs/libkis/Window.h
index f6a5b0eac4..53c5f13942 100644
--- a/libs/libkis/Window.h
+++ b/libs/libkis/Window.h
@@ -1,95 +1,112 @@
/*
* 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
#include
#include "kritalibkis_export.h"
#include "libkis.h"
#include
+
+class Action;
+
/**
* Window represents one Krita mainwindow. A window can have any number
* of views open on any number of documents.
*/
class KRITALIBKIS_EXPORT Window : public QObject
{
Q_OBJECT
public:
explicit Window(KisMainWindow *window, QObject *parent = 0);
~Window() override;
bool operator==(const Window &other) const;
bool operator!=(const Window &other) const;
public Q_SLOTS:
/**
* Return a handle to the QMainWindow widget. This is useful
* to e.g. parent dialog boxes and message box.
*/
QMainWindow *qwindow() const;
/**
* @return a list of open views in this window
*/
QList views() const;
/**
* Open a new view on the given document in this window
*/
View *addView(Document *document);
/**
* Make the given view active in this window. If the view
* does not belong to this window, nothing happens.
*/
void showView(View *view);
/**
* @return the currently active view or 0 if no view is active
*/
View *activeView() const;
/**
* @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();
+ /**
+ * @brief createAction creates an Action object and adds it to the action
+ * manager for this Window.
+ * @param id The unique id for the action. This will be used to
+ * propertize the action if any .action file is present
+ * @param text The user-visible text of the action. If empty, the text from the
+ * .action file is used.
+ * @param menu a /-separated string that describes which menu the action should
+ * be places in. Default is "tools/scripts"
+ * @return the new action.
+ */
+ Action *createAction(const QString &id, const QString &text = QString(), const QString &menuLocation = QString("tools/scripts"));
+
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/CMakeLists.txt b/libs/ui/CMakeLists.txt
index e1fa6a93e2..6d69cf303a 100644
--- a/libs/ui/CMakeLists.txt
+++ b/libs/ui/CMakeLists.txt
@@ -1,577 +1,576 @@
include_directories(
${CMAKE_CURRENT_SOURCE_DIR}/qtlockedfile
${EXIV2_INCLUDE_DIR}
)
include_directories(SYSTEM
${EIGEN3_INCLUDE_DIR}
${OCIO_INCLUDE_DIR}
)
add_subdirectory( tests )
if (APPLE)
find_library(FOUNDATION_LIBRARY Foundation)
find_library(APPKIT_LIBRARY AppKit)
endif ()
set(kritaui_LIB_SRCS
canvas/kis_canvas_widget_base.cpp
canvas/kis_canvas2.cpp
canvas/kis_canvas_updates_compressor.cpp
canvas/kis_canvas_controller.cpp
canvas/kis_paintop_transformation_connector.cpp
canvas/kis_display_color_converter.cpp
canvas/kis_display_filter.cpp
canvas/kis_exposure_gamma_correction_interface.cpp
canvas/kis_tool_proxy.cpp
canvas/kis_canvas_decoration.cc
canvas/kis_coordinates_converter.cpp
canvas/kis_grid_manager.cpp
canvas/kis_grid_decoration.cpp
canvas/kis_grid_config.cpp
canvas/kis_prescaled_projection.cpp
canvas/kis_qpainter_canvas.cpp
canvas/kis_projection_backend.cpp
canvas/kis_update_info.cpp
canvas/kis_image_patch.cpp
canvas/kis_image_pyramid.cpp
canvas/kis_infinity_manager.cpp
canvas/kis_change_guides_command.cpp
canvas/kis_guides_decoration.cpp
canvas/kis_guides_manager.cpp
canvas/kis_guides_config.cpp
canvas/kis_snap_config.cpp
canvas/kis_snap_line_strategy.cpp
canvas/KisSnapPointStrategy.cpp
dialogs/kis_about_application.cpp
dialogs/kis_dlg_adj_layer_props.cc
dialogs/kis_dlg_adjustment_layer.cc
dialogs/kis_dlg_filter.cpp
dialogs/kis_dlg_generator_layer.cpp
dialogs/kis_dlg_file_layer.cpp
dialogs/kis_dlg_filter.cpp
dialogs/kis_dlg_stroke_selection_properties.cpp
dialogs/kis_dlg_image_properties.cc
dialogs/kis_dlg_layer_properties.cc
dialogs/kis_dlg_preferences.cc
dialogs/slider_and_spin_box_sync.cpp
dialogs/kis_dlg_blacklist_cleanup.cpp
dialogs/kis_dlg_layer_style.cpp
dialogs/kis_dlg_png_import.cpp
dialogs/kis_dlg_import_image_sequence.cpp
dialogs/kis_delayed_save_dialog.cpp
dialogs/kis_dlg_internal_color_selector.cpp
flake/kis_node_dummies_graph.cpp
flake/kis_dummies_facade_base.cpp
flake/kis_dummies_facade.cpp
flake/kis_node_shapes_graph.cpp
flake/kis_node_shape.cpp
flake/kis_shape_controller.cpp
flake/kis_shape_layer.cc
flake/kis_shape_layer_canvas.cpp
flake/kis_shape_selection.cpp
flake/kis_shape_selection_canvas.cpp
flake/kis_shape_selection_model.cpp
flake/kis_take_all_shapes_command.cpp
brushhud/kis_uniform_paintop_property_widget.cpp
brushhud/kis_brush_hud.cpp
brushhud/kis_round_hud_button.cpp
brushhud/kis_dlg_brush_hud_config.cpp
brushhud/kis_brush_hud_properties_list.cpp
brushhud/kis_brush_hud_properties_config.cpp
kis_aspect_ratio_locker.cpp
kis_autogradient.cc
kis_bookmarked_configurations_editor.cc
kis_bookmarked_configurations_model.cc
kis_bookmarked_filter_configurations_model.cc
kis_base_option.cpp
kis_canvas_resource_provider.cpp
kis_derived_resources.cpp
kis_categories_mapper.cpp
kis_categorized_list_model.cpp
kis_categorized_item_delegate.cpp
kis_clipboard.cc
kis_config.cc
kis_config_notifier.cpp
kis_control_frame.cpp
kis_composite_ops_model.cc
kis_paint_ops_model.cpp
kis_cursor.cc
kis_cursor_cache.cpp
kis_custom_pattern.cc
kis_file_layer.cpp
kis_change_file_layer_command.h
kis_safe_document_loader.cpp
kis_splash_screen.cpp
kis_filter_manager.cc
kis_filters_model.cc
kis_histogram_view.cc
KisImageBarrierLockerWithFeedback.cpp
kis_image_manager.cc
kis_image_view_converter.cpp
kis_import_catcher.cc
kis_layer_manager.cc
kis_mask_manager.cc
kis_mimedata.cpp
kis_node_commands_adapter.cpp
kis_node_manager.cpp
kis_node_juggler_compressed.cpp
kis_node_selection_adapter.cpp
kis_node_insertion_adapter.cpp
kis_node_model.cpp
kis_node_filter_proxy_model.cpp
kis_model_index_converter_base.cpp
kis_model_index_converter.cpp
kis_model_index_converter_show_all.cpp
kis_painting_assistant.cc
kis_painting_assistants_decoration.cpp
kis_painting_assistants_manager.cpp
kis_paintop_box.cc
kis_paintop_option.cpp
kis_paintop_options_model.cpp
kis_paintop_settings_widget.cpp
kis_popup_palette.cpp
kis_png_converter.cpp
kis_preference_set_registry.cpp
- kis_script_manager.cpp
kis_resource_server_provider.cpp
KisSelectedShapesProxy.cpp
kis_selection_decoration.cc
kis_selection_manager.cc
kis_statusbar.cc
kis_zoom_manager.cc
kis_favorite_resource_manager.cpp
kis_workspace_resource.cpp
kis_action.cpp
kis_action_manager.cpp
KisActionPlugin.cpp
kis_canvas_controls_manager.cpp
kis_tooltip_manager.cpp
kis_multinode_property.cpp
kis_stopgradient_editor.cpp
kisexiv2/kis_exif_io.cpp
kisexiv2/kis_exiv2.cpp
kisexiv2/kis_iptc_io.cpp
kisexiv2/kis_xmp_io.cpp
opengl/kis_opengl.cpp
opengl/kis_opengl_canvas2.cpp
opengl/kis_opengl_canvas_debugger.cpp
opengl/kis_opengl_image_textures.cpp
opengl/kis_texture_tile.cpp
opengl/kis_opengl_shader_loader.cpp
opengl/kis_texture_tile_info_pool.cpp
kis_fps_decoration.cpp
recorder/kis_node_query_path_editor.cc
recorder/kis_recorded_action_creator.cc
recorder/kis_recorded_action_creator_factory.cc
recorder/kis_recorded_action_creator_factory_registry.cc
recorder/kis_recorded_action_editor_factory.cc
recorder/kis_recorded_action_editor_factory_registry.cc
recorder/kis_recorded_filter_action_editor.cc
recorder/kis_recorded_filter_action_creator.cpp
recorder/kis_recorded_paint_action_editor.cc
tool/kis_selection_tool_helper.cpp
tool/kis_selection_tool_config_widget_helper.cpp
tool/kis_rectangle_constraint_widget.cpp
tool/kis_shape_tool_helper.cpp
tool/kis_tool.cc
tool/kis_delegated_tool_policies.cpp
tool/kis_tool_freehand.cc
tool/kis_speed_smoother.cpp
tool/kis_painting_information_builder.cpp
tool/kis_stabilized_events_sampler.cpp
tool/kis_tool_freehand_helper.cpp
tool/kis_tool_multihand_helper.cpp
tool/kis_figure_painting_tool_helper.cpp
tool/kis_recording_adapter.cpp
tool/kis_tool_paint.cc
tool/kis_tool_shape.cc
tool/kis_tool_ellipse_base.cpp
tool/kis_tool_rectangle_base.cpp
tool/kis_tool_polyline_base.cpp
tool/kis_tool_utils.cpp
tool/kis_resources_snapshot.cpp
tool/kis_smoothing_options.cpp
tool/KisStabilizerDelayedPaintHelper.cpp
tool/KisStrokeSpeedMonitor.cpp
tool/strokes/freehand_stroke.cpp
tool/strokes/KisStrokeEfficiencyMeasurer.cpp
tool/strokes/kis_painter_based_stroke_strategy.cpp
tool/strokes/kis_filter_stroke_strategy.cpp
tool/strokes/kis_color_picker_stroke_strategy.cpp
tool/strokes/KisFreehandStrokeInfo.cpp
tool/strokes/KisMaskedFreehandStrokePainter.cpp
tool/strokes/KisMaskingBrushRenderer.cpp
tool/strokes/KisMaskingBrushCompositeOpFactory.cpp
widgets/kis_cmb_composite.cc
widgets/kis_cmb_contour.cpp
widgets/kis_cmb_gradient.cpp
widgets/kis_paintop_list_widget.cpp
widgets/kis_cmb_idlist.cc
widgets/kis_color_space_selector.cc
widgets/kis_advanced_color_space_selector.cc
widgets/kis_cie_tongue_widget.cpp
widgets/kis_tone_curve_widget.cpp
widgets/kis_curve_widget.cpp
widgets/kis_custom_image_widget.cc
widgets/kis_image_from_clipboard_widget.cpp
widgets/kis_double_widget.cc
widgets/kis_filter_selector_widget.cc
widgets/kis_gradient_chooser.cc
widgets/kis_gradient_slider_widget.cc
widgets/kis_gradient_slider.cpp
widgets/kis_iconwidget.cc
widgets/kis_mask_widgets.cpp
widgets/kis_meta_data_merge_strategy_chooser_widget.cc
widgets/kis_multi_bool_filter_widget.cc
widgets/kis_multi_double_filter_widget.cc
widgets/kis_multi_integer_filter_widget.cc
widgets/kis_multipliers_double_slider_spinbox.cpp
widgets/kis_paintop_presets_popup.cpp
widgets/kis_tool_options_popup.cpp
widgets/kis_paintop_presets_chooser_popup.cpp
widgets/kis_paintop_presets_save.cpp
widgets/kis_paintop_preset_icon_library.cpp
widgets/kis_pattern_chooser.cc
widgets/kis_popup_button.cc
widgets/kis_preset_chooser.cpp
widgets/kis_progress_widget.cpp
widgets/kis_selection_options.cc
widgets/kis_scratch_pad.cpp
widgets/kis_scratch_pad_event_filter.cpp
widgets/kis_preset_selector_strip.cpp
widgets/kis_slider_spin_box.cpp
widgets/kis_size_group.cpp
widgets/kis_size_group_p.cpp
widgets/kis_wdg_generator.cpp
widgets/kis_workspace_chooser.cpp
widgets/kis_categorized_list_view.cpp
widgets/kis_widget_chooser.cpp
widgets/kis_tool_button.cpp
widgets/kis_floating_message.cpp
widgets/kis_lod_availability_widget.cpp
widgets/kis_color_label_selector_widget.cpp
widgets/kis_color_filter_combo.cpp
widgets/kis_elided_label.cpp
widgets/kis_stopgradient_slider_widget.cpp
widgets/kis_spinbox_color_selector.cpp
widgets/kis_screen_color_picker.cpp
widgets/kis_preset_live_preview_view.cpp
widgets/KoDualColorButton.cpp
widgets/kis_color_input.cpp
widgets/kis_color_button.cpp
widgets/KisVisualColorSelector.cpp
widgets/KisVisualColorSelectorShape.cpp
widgets/KisVisualEllipticalSelectorShape.cpp
widgets/KisVisualRectangleSelectorShape.cpp
widgets/KisVisualTriangleSelectorShape.cpp
widgets/KoStrokeConfigWidget.cpp
widgets/KoFillConfigWidget.cpp
utils/kis_document_aware_spin_box_unit_manager.cpp
input/kis_input_manager.cpp
input/kis_input_manager_p.cpp
input/kis_extended_modifiers_mapper.cpp
input/kis_abstract_input_action.cpp
input/kis_tool_invocation_action.cpp
input/kis_pan_action.cpp
input/kis_alternate_invocation_action.cpp
input/kis_rotate_canvas_action.cpp
input/kis_zoom_action.cpp
input/kis_change_frame_action.cpp
input/kis_gamma_exposure_action.cpp
input/kis_show_palette_action.cpp
input/kis_change_primary_setting_action.cpp
input/kis_abstract_shortcut.cpp
input/kis_native_gesture_shortcut.cpp
input/kis_single_action_shortcut.cpp
input/kis_stroke_shortcut.cpp
input/kis_shortcut_matcher.cpp
input/kis_select_layer_action.cpp
input/KisQtWidgetsTweaker.cpp
input/KisInputActionGroup.cpp
operations/kis_operation.cpp
operations/kis_operation_configuration.cpp
operations/kis_operation_registry.cpp
operations/kis_operation_ui_factory.cpp
operations/kis_operation_ui_widget.cpp
operations/kis_filter_selection_operation.cpp
actions/kis_selection_action_factories.cpp
actions/KisPasteActionFactory.cpp
input/kis_touch_shortcut.cpp
kis_document_undo_store.cpp
kis_transaction_based_command.cpp
kis_gui_context_command.cpp
kis_gui_context_command_p.cpp
input/kis_tablet_debugger.cpp
input/kis_input_profile_manager.cpp
input/kis_input_profile.cpp
input/kis_shortcut_configuration.cpp
input/config/kis_input_configuration_page.cpp
input/config/kis_edit_profiles_dialog.cpp
input/config/kis_input_profile_model.cpp
input/config/kis_input_configuration_page_item.cpp
input/config/kis_action_shortcuts_model.cpp
input/config/kis_input_type_delegate.cpp
input/config/kis_input_mode_delegate.cpp
input/config/kis_input_button.cpp
input/config/kis_input_editor_delegate.cpp
input/config/kis_mouse_input_editor.cpp
input/config/kis_wheel_input_editor.cpp
input/config/kis_key_input_editor.cpp
processing/fill_processing_visitor.cpp
kis_asl_layer_style_serializer.cpp
kis_psd_layer_style_resource.cpp
canvas/kis_mirror_axis.cpp
kis_abstract_perspective_grid.cpp
KisApplication.cpp
KisAutoSaveRecoveryDialog.cpp
KisDetailsPane.cpp
KisDocument.cpp
KisNodeDelegate.cpp
kis_node_view_visibility_delegate.cpp
KisNodeToolTip.cpp
KisNodeView.cpp
kis_node_view_color_scheme.cpp
KisImportExportFilter.cpp
KisFilterEntry.cpp
KisImportExportManager.cpp
KisImportExportUtils.cpp
kis_async_action_feedback.cpp
KisMainWindow.cpp
KisOpenPane.cpp
KisPart.cpp
KisPrintJob.cpp
KisTemplate.cpp
KisTemplateCreateDia.cpp
KisTemplateGroup.cpp
KisTemplates.cpp
KisTemplatesPane.cpp
KisTemplateTree.cpp
KisUndoStackAction.cpp
KisView.cpp
thememanager.cpp
kis_mainwindow_observer.cpp
KisViewManager.cpp
kis_mirror_manager.cpp
qtlockedfile/qtlockedfile.cpp
qtsingleapplication/qtlocalpeer.cpp
qtsingleapplication/qtsingleapplication.cpp
KisResourceBundle.cpp
KisResourceBundleManifest.cpp
kis_md5_generator.cpp
KisApplicationArguments.cpp
KisNetworkAccessManager.cpp
KisMultiFeedRSSModel.cpp
KisRemoteFileFetcher.cpp
KisPaletteModel.cpp
kis_palette_delegate.cpp
kis_palette_view.cpp
KisColorsetChooser.cpp
KisSaveGroupVisitor.cpp
)
if(WIN32)
set(kritaui_LIB_SRCS
${kritaui_LIB_SRCS}
input/kis_tablet_event.cpp
input/wintab/kis_tablet_support_win.cpp
input/wintab/kis_screen_size_choice_dialog.cpp
qtlockedfile/qtlockedfile_win.cpp
input/wintab/kis_tablet_support_win8.cpp
opengl/kis_opengl_win.cpp
)
endif()
set(kritaui_LIB_SRCS
${kritaui_LIB_SRCS}
kis_animation_frame_cache.cpp
kis_animation_cache_populator.cpp
KisAsyncAnimationRendererBase.cpp
KisAsyncAnimationCacheRenderer.cpp
KisAsyncAnimationFramesSavingRenderer.cpp
dialogs/KisAsyncAnimationRenderDialogBase.cpp
dialogs/KisAsyncAnimationCacheRenderDialog.cpp
dialogs/KisAsyncAnimationFramesSaveDialog.cpp
canvas/kis_animation_player.cpp
kis_animation_importer.cpp
KisSyncedAudioPlayback.cpp
)
if(UNIX)
set(kritaui_LIB_SRCS
${kritaui_LIB_SRCS}
input/kis_tablet_event.cpp
input/wintab/kis_tablet_support.cpp
qtlockedfile/qtlockedfile_unix.cpp
)
if(NOT APPLE)
set(kritaui_LIB_SRCS
${kritaui_LIB_SRCS}
input/wintab/qxcbconnection_xi2.cpp
input/wintab/qxcbconnection.cpp
input/wintab/kis_xi2_event_filter.cpp
)
endif()
endif()
if(APPLE)
set(kritaui_LIB_SRCS
${kritaui_LIB_SRCS}
osx.mm
)
endif()
ki18n_wrap_ui(kritaui_LIB_SRCS
widgets/KoFillConfigWidget.ui
widgets/KoStrokeConfigWidget.ui
forms/wdgdlgpngimport.ui
forms/wdgfullscreensettings.ui
forms/wdgautogradient.ui
forms/wdggeneralsettings.ui
forms/wdgperformancesettings.ui
forms/wdggenerators.ui
forms/wdgbookmarkedconfigurationseditor.ui
forms/wdgapplyprofile.ui
forms/wdgcustompattern.ui
forms/wdglayerproperties.ui
forms/wdgcolorsettings.ui
forms/wdgtabletsettings.ui
forms/wdgcolorspaceselector.ui
forms/wdgcolorspaceselectoradvanced.ui
forms/wdgdisplaysettings.ui
forms/kis_previewwidgetbase.ui
forms/kis_matrix_widget.ui
forms/wdgselectionoptions.ui
forms/wdggeometryoptions.ui
forms/wdgnewimage.ui
forms/wdgimageproperties.ui
forms/wdgmaskfromselection.ui
forms/wdgmasksource.ui
forms/wdgfilterdialog.ui
forms/wdgmetadatamergestrategychooser.ui
forms/wdgpaintoppresets.ui
forms/wdgpaintopsettings.ui
forms/wdgdlggeneratorlayer.ui
forms/wdgdlgfilelayer.ui
forms/wdgfilterselector.ui
forms/wdgfilternodecreation.ui
forms/wdgpaintactioneditor.ui
forms/wdgmultipliersdoublesliderspinbox.ui
forms/wdgnodequerypatheditor.ui
forms/wdgpresetselectorstrip.ui
forms/wdgsavebrushpreset.ui
forms/wdgpreseticonlibrary.ui
forms/wdgdlgblacklistcleanup.ui
forms/wdgrectangleconstraints.ui
forms/wdgimportimagesequence.ui
forms/wdgstrokeselectionproperties.ui
forms/KisDetailsPaneBase.ui
forms/KisOpenPaneBase.ui
forms/wdgstopgradienteditor.ui
brushhud/kis_dlg_brush_hud_config.ui
forms/wdgdlginternalcolorselector.ui
dialogs/kis_delayed_save_dialog.ui
input/config/kis_input_configuration_page.ui
input/config/kis_edit_profiles_dialog.ui
input/config/kis_input_configuration_page_item.ui
input/config/kis_mouse_input_editor.ui
input/config/kis_wheel_input_editor.ui
input/config/kis_key_input_editor.ui
layerstyles/wdgBevelAndEmboss.ui
layerstyles/wdgblendingoptions.ui
layerstyles/WdgColorOverlay.ui
layerstyles/wdgContour.ui
layerstyles/wdgdropshadow.ui
layerstyles/WdgGradientOverlay.ui
layerstyles/wdgInnerGlow.ui
layerstyles/wdglayerstyles.ui
layerstyles/WdgPatternOverlay.ui
layerstyles/WdgSatin.ui
layerstyles/WdgStroke.ui
layerstyles/wdgstylesselector.ui
layerstyles/wdgTexture.ui
wdgsplash.ui
input/wintab/kis_screen_size_choice_dialog.ui
)
QT5_WRAP_CPP(kritaui_HEADERS_MOC KisNodePropertyAction_p.h)
add_library(kritaui SHARED ${kritaui_HEADERS_MOC} ${kritaui_LIB_SRCS} )
generate_export_header(kritaui BASE_NAME kritaui)
target_link_libraries(kritaui KF5::CoreAddons KF5::Completion KF5::I18n KF5::ItemViews Qt5::Network
kritaimpex kritacolor kritaimage kritalibbrush kritawidgets kritawidgetutils ${PNG_LIBRARIES} ${EXIV2_LIBRARIES}
)
if (HAVE_QT_MULTIMEDIA)
target_link_libraries(kritaui Qt5::Multimedia)
endif()
if (HAVE_KIO)
target_link_libraries(kritaui KF5::KIOCore)
endif()
if (NOT WIN32 AND NOT APPLE)
target_link_libraries(kritaui ${X11_X11_LIB}
${X11_Xinput_LIB}
${XCB_LIBRARIES})
endif()
if(APPLE)
target_link_libraries(kritaui ${FOUNDATION_LIBRARY})
target_link_libraries(kritaui ${APPKIT_LIBRARY})
endif ()
target_link_libraries(kritaui ${OPENEXR_LIBRARIES})
# Add VSync disable workaround
if(NOT WIN32 AND NOT APPLE)
target_link_libraries(kritaui ${CMAKE_DL_LIBS} Qt5::X11Extras)
endif()
if(X11_FOUND)
target_link_libraries(kritaui Qt5::X11Extras ${X11_LIBRARIES})
endif()
target_include_directories(kritaui
PUBLIC
$
$
$
$
$
$
$
)
set_target_properties(kritaui
PROPERTIES VERSION ${GENERIC_KRITA_LIB_VERSION} SOVERSION ${GENERIC_KRITA_LIB_SOVERSION}
)
install(TARGETS kritaui ${INSTALL_TARGETS_DEFAULT_ARGS})
if (APPLE)
install(FILES osx.stylesheet DESTINATION ${DATA_INSTALL_DIR}/krita)
endif ()
diff --git a/libs/ui/KisPart.cpp b/libs/ui/KisPart.cpp
index 645991d798..cf34bffca3 100644
--- a/libs/ui/KisPart.cpp
+++ b/libs/ui/KisPart.cpp
@@ -1,479 +1,468 @@
/* 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(KisAction *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);
}
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.
*/
KIS_ASSERT_RECOVER_RETURN(!view->mainWindow()->hackIsSaving());
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)
{
// TODO: refactor out this method!
KisMainWindow *mw = currentMainwindow();
KIS_SAFE_ASSERT_RECOVER_RETURN(mw);
mw->openDocument(url, KisMainWindow::None);
}
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::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()
{
KisMainWindow *mw = currentMainwindow();
KisViewManager *manager = mw ? mw->viewManager() : 0;
return manager ? manager->inputManager() : 0;
}
diff --git a/libs/ui/KisPart.h b/libs/ui/KisPart.h
index b0c71af228..434792e2da 100644
--- a/libs/ui/KisPart.h
+++ b/libs/ui/KisPart.h
@@ -1,259 +1,248 @@
/* 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() override;
// ----------------- 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 updateIdleWatcherConnections();
void updateShortcuts();
Q_SIGNALS:
/**
* emitted when a new document is opened. (for the idle watcher)
*/
void documentOpened(const QString &ref);
/**
* 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:
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/libs/ui/KisViewManager.cpp b/libs/ui/KisViewManager.cpp
index 3a129a4536..643857bd6f 100644
--- a/libs/ui/KisViewManager.cpp
+++ b/libs/ui/KisViewManager.cpp
@@ -1,1417 +1,1407 @@
/*
* This file is part of KimageShop^WKrayon^WKrita
*
* Copyright (c) 1999 Matthias Elter
* 1999 Michael Koch
* 1999 Carsten Pfeiffer
* 2002 Patrick Julien
* 2003-2011 Boudewijn Rempt
* 2004 Clarence Dang
* 2011 José Luis Vergara
* 2017 L. E. Segovia
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#include
#include "KisViewManager.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
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include "input/kis_input_manager.h"
#include "canvas/kis_canvas2.h"
#include "canvas/kis_canvas_controller.h"
#include "canvas/kis_grid_manager.h"
#include "dialogs/kis_dlg_blacklist_cleanup.h"
#include "input/kis_input_profile_manager.h"
#include "kis_action_manager.h"
#include "kis_action.h"
#include "kis_canvas_controls_manager.h"
#include "kis_canvas_resource_provider.h"
#include "kis_composite_progress_proxy.h"
#include
#include "kis_config.h"
#include "kis_config_notifier.h"
#include "kis_control_frame.h"
#include "kis_coordinates_converter.h"
#include "KisDocument.h"
#include "kis_favorite_resource_manager.h"
#include "kis_filter_manager.h"
#include "kis_group_layer.h"
#include
#include
#include "kis_image_manager.h"
#include
#include "kis_mainwindow_observer.h"
#include "kis_mask_manager.h"
#include "kis_mimedata.h"
#include "kis_mirror_manager.h"
#include "kis_node_commands_adapter.h"
#include "kis_node.h"
#include "kis_node_manager.h"
#include "kis_painting_assistants_manager.h"
#include
#include "kis_paintop_box.h"
#include
#include "KisPart.h"
#include "KisPrintJob.h"
#include
#include "kis_resource_server_provider.h"
#include "kis_selection.h"
#include "kis_selection_manager.h"
#include "kis_shape_controller.h"
#include "kis_shape_layer.h"
#include
#include "kis_statusbar.h"
#include
#include
#include "kis_tooltip_manager.h"
#include
#include "KisView.h"
#include "kis_zoom_manager.h"
#include "widgets/kis_floating_message.h"
#include "kis_signal_auto_connection.h"
-#include "kis_script_manager.h"
#include "kis_icon_utils.h"
#include "kis_guides_manager.h"
#include "kis_derived_resources.h"
#include "dialogs/kis_delayed_save_dialog.h"
#include
#include
#include "kis_signals_blocker.h"
class BlockingUserInputEventFilter : public QObject
{
bool eventFilter(QObject *watched, QEvent *event) override
{
Q_UNUSED(watched);
if(dynamic_cast(event)
|| dynamic_cast(event)
|| dynamic_cast(event)) {
return true;
}
else {
return false;
}
}
};
class KisViewManager::KisViewManagerPrivate
{
public:
KisViewManagerPrivate(KisViewManager *_q, KActionCollection *_actionCollection, QWidget *_q_parent)
: filterManager(_q)
, createTemplate(0)
, saveIncremental(0)
, saveIncrementalBackup(0)
, openResourcesDirectory(0)
, rotateCanvasRight(0)
, rotateCanvasLeft(0)
, resetCanvasRotation(0)
, wrapAroundAction(0)
, levelOfDetailAction(0)
, showRulersAction(0)
, rulersTrackMouseAction(0)
, zoomTo100pct(0)
, zoomIn(0)
, zoomOut(0)
, selectionManager(_q)
, statusBar(_q)
, controlFrame(_q, _q_parent)
, nodeManager(_q)
, imageManager(_q)
, gridManager(_q)
, canvasControlsManager(_q)
, paintingAssistantsManager(_q)
, actionManager(_q, _actionCollection)
, mainWindow(0)
, showFloatingMessage(true)
, currentImageView(0)
, canvasResourceProvider(_q)
, canvasResourceManager()
, guiUpdateCompressor(30, KisSignalCompressor::POSTPONE, _q)
, actionCollection(_actionCollection)
, mirrorManager(_q)
, inputManager(_q)
- , scriptManager(_q)
, actionAuthor(0)
, showPixelGrid(0)
{
KisViewManager::initializeResourceManager(&canvasResourceManager);
}
public:
KisFilterManager filterManager;
KisAction *createTemplate;
KisAction *createCopy;
KisAction *saveIncremental;
KisAction *saveIncrementalBackup;
KisAction *openResourcesDirectory;
KisAction *rotateCanvasRight;
KisAction *rotateCanvasLeft;
KisAction *resetCanvasRotation;
KisAction *wrapAroundAction;
KisAction *levelOfDetailAction;
KisAction *showRulersAction;
KisAction *rulersTrackMouseAction;
KisAction *zoomTo100pct;
KisAction *zoomIn;
KisAction *zoomOut;
KisAction *softProof;
KisAction *gamutCheck;
KisSelectionManager selectionManager;
KisGuidesManager guidesManager;
KisStatusBar statusBar;
QPointer persistentImageProgressUpdater;
QScopedPointer persistentUnthreadedProgressUpdaterRouter;
QPointer persistentUnthreadedProgressUpdater;
KisControlFrame controlFrame;
KisNodeManager nodeManager;
KisImageManager imageManager;
KisGridManager gridManager;
KisCanvasControlsManager canvasControlsManager;
KisPaintingAssistantsManager paintingAssistantsManager;
BlockingUserInputEventFilter blockingEventFilter;
KisActionManager actionManager;
QMainWindow* mainWindow;
QPointer savedFloatingMessage;
bool showFloatingMessage;
QPointer currentImageView;
KisCanvasResourceProvider canvasResourceProvider;
KoCanvasResourceManager canvasResourceManager;
KisSignalCompressor guiUpdateCompressor;
KActionCollection *actionCollection;
KisMirrorManager mirrorManager;
KisInputManager inputManager;
KisSignalAutoConnectionsStore viewConnections;
- KisScriptManager scriptManager;
KSelectAction *actionAuthor; // Select action for author profile.
KisAction *showPixelGrid;
QByteArray canvasState;
#if QT_VERSION < QT_VERSION_CHECK(5, 10, 0)
QFlags windowFlags;
#endif
bool blockUntilOperationsFinishedImpl(KisImageSP image, bool force);
};
KisViewManager::KisViewManager(QWidget *parent, KActionCollection *_actionCollection)
: d(new KisViewManagerPrivate(this, _actionCollection, parent))
{
d->actionCollection = _actionCollection;
d->mainWindow = dynamic_cast(parent);
d->canvasResourceProvider.setResourceManager(&d->canvasResourceManager);
connect(&d->guiUpdateCompressor, SIGNAL(timeout()), this, SLOT(guiUpdateTimeout()));
createActions();
setupManagers();
// These initialization functions must wait until KisViewManager ctor is complete.
d->statusBar.setup();
d->persistentImageProgressUpdater =
d->statusBar.progressUpdater()->startSubtask(1, "", true);
// reset state to "completed"
d->persistentImageProgressUpdater->setRange(0,100);
d->persistentImageProgressUpdater->setValue(100);
d->persistentUnthreadedProgressUpdater =
d->statusBar.progressUpdater()->startSubtask(1, "", true);
// reset state to "completed"
d->persistentUnthreadedProgressUpdater->setRange(0,100);
d->persistentUnthreadedProgressUpdater->setValue(100);
d->persistentUnthreadedProgressUpdaterRouter.reset(
new KoProgressUpdater(d->persistentUnthreadedProgressUpdater,
KoProgressUpdater::Unthreaded));
d->persistentUnthreadedProgressUpdaterRouter->setAutoNestNames(true);
d->controlFrame.setup(parent);
//Check to draw scrollbars after "Canvas only mode" toggle is created.
this->showHideScrollbars();
QScopedPointer dummy(new KoDummyCanvasController(actionCollection()));
KoToolManager::instance()->registerToolActions(actionCollection(), dummy.data());
QTimer::singleShot(0, this, SLOT(initializeStatusBarVisibility()));
connect(KoToolManager::instance(), SIGNAL(inputDeviceChanged(KoInputDevice)),
d->controlFrame.paintopBox(), SLOT(slotInputDeviceChanged(KoInputDevice)));
connect(KoToolManager::instance(), SIGNAL(changedTool(KoCanvasController*,int)),
d->controlFrame.paintopBox(), SLOT(slotToolChanged(KoCanvasController*,int)));
connect(&d->nodeManager, SIGNAL(sigNodeActivated(KisNodeSP)),
resourceProvider(), SLOT(slotNodeActivated(KisNodeSP)));
connect(resourceProvider()->resourceManager(), SIGNAL(canvasResourceChanged(int,QVariant)),
d->controlFrame.paintopBox(), SLOT(slotCanvasResourceChanged(int,QVariant)));
connect(KisPart::instance(), SIGNAL(sigViewAdded(KisView*)), SLOT(slotViewAdded(KisView*)));
connect(KisPart::instance(), SIGNAL(sigViewRemoved(KisView*)), SLOT(slotViewRemoved(KisView*)));
connect(KisConfigNotifier::instance(), SIGNAL(configChanged()), SLOT(slotUpdateAuthorProfileActions()));
connect(KisConfigNotifier::instance(), SIGNAL(pixelGridModeChanged()), SLOT(slotUpdatePixelGridAction()));
KisInputProfileManager::instance()->loadProfiles();
KisConfig cfg;
d->showFloatingMessage = cfg.showCanvasMessages();
}
KisViewManager::~KisViewManager()
{
KisConfig cfg;
if (resourceProvider() && resourceProvider()->currentPreset()) {
cfg.writeEntry("LastPreset", resourceProvider()->currentPreset()->name());
cfg.writeKoColor("LastForeGroundColor",resourceProvider()->fgColor());
cfg.writeKoColor("LastBackGroundColor",resourceProvider()->bgColor());
}
cfg.writeEntry("baseLength", KoResourceItemChooserSync::instance()->baseLength());
delete d;
}
void KisViewManager::initializeResourceManager(KoCanvasResourceManager *resourceManager)
{
resourceManager->addDerivedResourceConverter(toQShared(new KisCompositeOpResourceConverter));
resourceManager->addDerivedResourceConverter(toQShared(new KisEffectiveCompositeOpResourceConverter));
resourceManager->addDerivedResourceConverter(toQShared(new KisOpacityResourceConverter));
resourceManager->addDerivedResourceConverter(toQShared(new KisFlowResourceConverter));
resourceManager->addDerivedResourceConverter(toQShared(new KisSizeResourceConverter));
resourceManager->addDerivedResourceConverter(toQShared(new KisLodAvailabilityResourceConverter));
resourceManager->addDerivedResourceConverter(toQShared(new KisLodSizeThresholdResourceConverter));
resourceManager->addDerivedResourceConverter(toQShared(new KisLodSizeThresholdSupportedResourceConverter));
resourceManager->addDerivedResourceConverter(toQShared(new KisEraserModeResourceConverter));
resourceManager->addResourceUpdateMediator(toQShared(new KisPresetUpdateMediator));
}
KActionCollection *KisViewManager::actionCollection() const
{
return d->actionCollection;
}
void KisViewManager::slotViewAdded(KisView *view)
{
// WARNING: this slot is called even when a view from another main windows is added!
// Don't expect \p view be a child of this view manager!
Q_UNUSED(view);
if (viewCount() == 0) {
d->statusBar.showAllStatusBarItems();
}
}
void KisViewManager::slotViewRemoved(KisView *view)
{
// WARNING: this slot is called even when a view from another main windows is removed!
// Don't expect \p view be a child of this view manager!
Q_UNUSED(view);
if (viewCount() == 0) {
d->statusBar.hideAllStatusBarItems();
}
}
void KisViewManager::setCurrentView(KisView *view)
{
bool first = true;
if (d->currentImageView) {
d->currentImageView->notifyCurrentStateChanged(false);
d->currentImageView->canvasBase()->setCursor(QCursor(Qt::ArrowCursor));
first = false;
KisDocument* doc = d->currentImageView->document();
if (doc) {
doc->image()->compositeProgressProxy()->removeProxy(d->persistentImageProgressUpdater);
doc->disconnect(this);
}
d->currentImageView->canvasController()->proxyObject->disconnect(&d->statusBar);
d->viewConnections.clear();
}
QPointer imageView = qobject_cast(view);
d->currentImageView = imageView;
if (imageView) {
d->softProof->setChecked(imageView->softProofing());
d->gamutCheck->setChecked(imageView->gamutCheck());
// Wait for the async image to have loaded
KisDocument* doc = view->document();
// connect(canvasController()->proxyObject, SIGNAL(documentMousePositionChanged(QPointF)), d->statusBar, SLOT(documentMousePositionChanged(QPointF)));
// Restore the last used brush preset, color and background color.
if (first) {
KisConfig cfg;
KisPaintOpPresetResourceServer * rserver = KisResourceServerProvider::instance()->paintOpPresetServer();
QString defaultPresetName = "basic_tip_default";
bool foundTip = false;
for (int i=0; iresourceCount(); i++) {
KisPaintOpPresetSP resource = rserver->resources().at(i);
if (resource->name().toLower().contains("basic_tip_default")) {
defaultPresetName = resource->name();
foundTip = true;
} else if (foundTip == false && (resource->name().toLower().contains("default") ||
resource->filename().toLower().contains("default"))) {
defaultPresetName = resource->name();
foundTip = true;
}
}
QString lastPreset = cfg.readEntry("LastPreset", defaultPresetName);
KisPaintOpPresetSP preset = rserver->resourceByName(lastPreset);
if (!preset) {
preset = rserver->resourceByName(defaultPresetName);
}
if (!preset) {
preset = rserver->resources().first();
}
if (preset) {
paintOpBox()->restoreResource(preset.data());
}
const KoColorSpace *cs = KoColorSpaceRegistry::instance()->rgb8();
KoColor foreground(Qt::black, cs);
d->canvasResourceProvider.setFGColor(cfg.readKoColor("LastForeGroundColor",foreground));
KoColor background(Qt::white, cs);
d->canvasResourceProvider.setBGColor(cfg.readKoColor("LastBackGroundColor",background));
}
KisCanvasController *canvasController = dynamic_cast(d->currentImageView->canvasController());
d->viewConnections.addUniqueConnection(&d->nodeManager, SIGNAL(sigNodeActivated(KisNodeSP)), doc->image(), SLOT(requestStrokeEndActiveNode()));
d->viewConnections.addUniqueConnection(d->rotateCanvasRight, SIGNAL(triggered()), canvasController, SLOT(rotateCanvasRight15()));
d->viewConnections.addUniqueConnection(d->rotateCanvasLeft, SIGNAL(triggered()),canvasController, SLOT(rotateCanvasLeft15()));
d->viewConnections.addUniqueConnection(d->resetCanvasRotation, SIGNAL(triggered()),canvasController, SLOT(resetCanvasRotation()));
d->viewConnections.addUniqueConnection(d->wrapAroundAction, SIGNAL(toggled(bool)), canvasController, SLOT(slotToggleWrapAroundMode(bool)));
d->wrapAroundAction->setChecked(canvasController->wrapAroundMode());
d->viewConnections.addUniqueConnection(d->levelOfDetailAction, SIGNAL(toggled(bool)), canvasController, SLOT(slotToggleLevelOfDetailMode(bool)));
d->levelOfDetailAction->setChecked(canvasController->levelOfDetailMode());
d->viewConnections.addUniqueConnection(d->currentImageView->image(), SIGNAL(sigColorSpaceChanged(const KoColorSpace*)), d->controlFrame.paintopBox(), SLOT(slotColorSpaceChanged(const KoColorSpace*)));
d->viewConnections.addUniqueConnection(d->showRulersAction, SIGNAL(toggled(bool)), imageView->zoomManager(), SLOT(setShowRulers(bool)));
d->viewConnections.addUniqueConnection(d->rulersTrackMouseAction, SIGNAL(toggled(bool)), imageView->zoomManager(), SLOT(setRulersTrackMouse(bool)));
d->viewConnections.addUniqueConnection(d->zoomTo100pct, SIGNAL(triggered()), imageView->zoomManager(), SLOT(zoomTo100()));
d->viewConnections.addUniqueConnection(d->zoomIn, SIGNAL(triggered()), imageView->zoomController()->zoomAction(), SLOT(zoomIn()));
d->viewConnections.addUniqueConnection(d->zoomOut, SIGNAL(triggered()), imageView->zoomController()->zoomAction(), SLOT(zoomOut()));
d->viewConnections.addUniqueConnection(d->softProof, SIGNAL(toggled(bool)), view, SLOT(slotSoftProofing(bool)) );
d->viewConnections.addUniqueConnection(d->gamutCheck, SIGNAL(toggled(bool)), view, SLOT(slotGamutCheck(bool)) );
// set up progrress reporting
doc->image()->compositeProgressProxy()->addProxy(d->persistentImageProgressUpdater);
d->viewConnections.addUniqueConnection(&d->statusBar, SIGNAL(sigCancellationRequested()), doc->image(), SLOT(requestStrokeCancellation()));
d->viewConnections.addUniqueConnection(d->showPixelGrid, SIGNAL(toggled(bool)), canvasController, SLOT(slotTogglePixelGrid(bool)));
imageView->zoomManager()->setShowRulers(d->showRulersAction->isChecked());
imageView->zoomManager()->setRulersTrackMouse(d->rulersTrackMouseAction->isChecked());
showHideScrollbars();
}
d->filterManager.setView(imageView);
d->selectionManager.setView(imageView);
d->guidesManager.setView(imageView);
d->nodeManager.setView(imageView);
d->imageManager.setView(imageView);
d->canvasControlsManager.setView(imageView);
d->actionManager.setView(imageView);
d->gridManager.setView(imageView);
d->statusBar.setView(imageView);
d->paintingAssistantsManager.setView(imageView);
d->mirrorManager.setView(imageView);
if (d->currentImageView) {
d->currentImageView->notifyCurrentStateChanged(true);
d->currentImageView->canvasController()->activate();
d->currentImageView->canvasController()->setFocus();
d->viewConnections.addUniqueConnection(
image(), SIGNAL(sigSizeChanged(const QPointF&, const QPointF&)),
resourceProvider(), SLOT(slotImageSizeChanged()));
d->viewConnections.addUniqueConnection(
image(), SIGNAL(sigResolutionChanged(double,double)),
resourceProvider(), SLOT(slotOnScreenResolutionChanged()));
d->viewConnections.addUniqueConnection(
image(), SIGNAL(sigNodeChanged(KisNodeSP)),
this, SLOT(updateGUI()));
d->viewConnections.addUniqueConnection(
d->currentImageView->zoomManager()->zoomController(),
SIGNAL(zoomChanged(KoZoomMode::Mode,qreal)),
resourceProvider(), SLOT(slotOnScreenResolutionChanged()));
}
d->actionManager.updateGUI();
resourceProvider()->slotImageSizeChanged();
resourceProvider()->slotOnScreenResolutionChanged();
Q_EMIT viewChanged();
}
KoZoomController *KisViewManager::zoomController() const
{
if (d->currentImageView) {
return d->currentImageView->zoomController();
}
return 0;
}
KisImageWSP KisViewManager::image() const
{
if (document()) {
return document()->image();
}
return 0;
}
KisCanvasResourceProvider * KisViewManager::resourceProvider()
{
return &d->canvasResourceProvider;
}
KisCanvas2 * KisViewManager::canvasBase() const
{
if (d && d->currentImageView) {
return d->currentImageView->canvasBase();
}
return 0;
}
QWidget* KisViewManager::canvas() const
{
if (d && d->currentImageView && d->currentImageView->canvasBase()->canvasWidget()) {
return d->currentImageView->canvasBase()->canvasWidget();
}
return 0;
}
KisStatusBar * KisViewManager::statusBar() const
{
return &d->statusBar;
}
void KisViewManager::addStatusBarItem(QWidget *widget, int stretch, bool permanent)
{
d->statusBar.addStatusBarItem(widget, stretch, permanent);
}
void KisViewManager::removeStatusBarItem(QWidget *widget)
{
d->statusBar.removeStatusBarItem(widget);
}
KisPaintopBox* KisViewManager::paintOpBox() const
{
return d->controlFrame.paintopBox();
}
QPointer KisViewManager::createUnthreadedUpdater(const QString &name)
{
return d->persistentUnthreadedProgressUpdaterRouter->startSubtask(1, name, false);
}
QPointer KisViewManager::createThreadedUpdater(const QString &name)
{
return d->statusBar.progressUpdater()->startSubtask(1, name, false);
}
KisSelectionManager * KisViewManager::selectionManager()
{
return &d->selectionManager;
}
KisNodeSP KisViewManager::activeNode()
{
return d->nodeManager.activeNode();
}
KisLayerSP KisViewManager::activeLayer()
{
return d->nodeManager.activeLayer();
}
KisPaintDeviceSP KisViewManager::activeDevice()
{
return d->nodeManager.activePaintDevice();
}
KisZoomManager * KisViewManager::zoomManager()
{
if (d->currentImageView) {
return d->currentImageView->zoomManager();
}
return 0;
}
KisFilterManager * KisViewManager::filterManager()
{
return &d->filterManager;
}
KisImageManager * KisViewManager::imageManager()
{
return &d->imageManager;
}
KisInputManager* KisViewManager::inputManager() const
{
return &d->inputManager;
}
KisSelectionSP KisViewManager::selection()
{
if (d->currentImageView) {
return d->currentImageView->selection();
}
return 0;
}
bool KisViewManager::selectionEditable()
{
KisLayerSP layer = activeLayer();
if (layer) {
KoProperties properties;
QList masks = layer->childNodes(QStringList("KisSelectionMask"), properties);
if (masks.size() == 1) {
return masks[0]->isEditable();
}
}
// global selection is always editable
return true;
}
KisUndoAdapter * KisViewManager::undoAdapter()
{
if (!document()) return 0;
KisImageWSP image = document()->image();
Q_ASSERT(image);
return image->undoAdapter();
}
void KisViewManager::createActions()
{
KisConfig cfg;
d->saveIncremental = actionManager()->createAction("save_incremental_version");
connect(d->saveIncremental, SIGNAL(triggered()), this, SLOT(slotSaveIncremental()));
d->saveIncrementalBackup = actionManager()->createAction("save_incremental_backup");
connect(d->saveIncrementalBackup, SIGNAL(triggered()), this, SLOT(slotSaveIncrementalBackup()));
connect(mainWindow(), SIGNAL(documentSaved()), this, SLOT(slotDocumentSaved()));
d->saveIncremental->setEnabled(false);
d->saveIncrementalBackup->setEnabled(false);
KisAction *tabletDebugger = actionManager()->createAction("tablet_debugger");
connect(tabletDebugger, SIGNAL(triggered()), this, SLOT(toggleTabletLogger()));
d->createTemplate = actionManager()->createAction("create_template");
connect(d->createTemplate, SIGNAL(triggered()), this, SLOT(slotCreateTemplate()));
d->createCopy = actionManager()->createAction("create_copy");
connect(d->createCopy, SIGNAL(triggered()), this, SLOT(slotCreateCopy()));
d->openResourcesDirectory = actionManager()->createAction("open_resources_directory");
connect(d->openResourcesDirectory, SIGNAL(triggered()), SLOT(openResourcesDirectory()));
d->rotateCanvasRight = actionManager()->createAction("rotate_canvas_right");
d->rotateCanvasLeft = actionManager()->createAction("rotate_canvas_left");
d->resetCanvasRotation = actionManager()->createAction("reset_canvas_rotation");
d->wrapAroundAction = actionManager()->createAction("wrap_around_mode");
d->levelOfDetailAction = actionManager()->createAction("level_of_detail_mode");
d->softProof = actionManager()->createAction("softProof");
d->gamutCheck = actionManager()->createAction("gamutCheck");
KisAction *tAction = actionManager()->createAction("showStatusBar");
tAction->setChecked(cfg.showStatusBar());
connect(tAction, SIGNAL(toggled(bool)), this, SLOT(showStatusBar(bool)));
tAction = actionManager()->createAction("view_show_canvas_only");
tAction->setChecked(false);
connect(tAction, SIGNAL(toggled(bool)), this, SLOT(switchCanvasOnly(bool)));
//Workaround, by default has the same shortcut as mirrorCanvas
KisAction *a = dynamic_cast(actionCollection()->action("format_italic"));
if (a) {
a->setDefaultShortcut(QKeySequence());
}
a = actionManager()->createAction("edit_blacklist_cleanup");
connect(a, SIGNAL(triggered()), this, SLOT(slotBlacklistCleanup()));
actionManager()->createAction("ruler_pixel_multiple2");
d->showRulersAction = actionManager()->createAction("view_ruler");
d->showRulersAction->setChecked(cfg.showRulers());
connect(d->showRulersAction, SIGNAL(toggled(bool)), SLOT(slotSaveShowRulersState(bool)));
d->rulersTrackMouseAction = actionManager()->createAction("rulers_track_mouse");
d->rulersTrackMouseAction->setChecked(cfg.rulersTrackMouse());
connect(d->rulersTrackMouseAction, SIGNAL(toggled(bool)), SLOT(slotSaveRulersTrackMouseState(bool)));
d->zoomTo100pct = actionManager()->createAction("zoom_to_100pct");
d->zoomIn = actionManager()->createStandardAction(KStandardAction::ZoomIn, 0, "");
d->zoomOut = actionManager()->createStandardAction(KStandardAction::ZoomOut, 0, "");
d->actionAuthor = new KSelectAction(KisIconUtils::loadIcon("im-user"), i18n("Active Author Profile"), this);
connect(d->actionAuthor, SIGNAL(triggered(const QString &)), this, SLOT(changeAuthorProfile(const QString &)));
actionCollection()->addAction("settings_active_author", d->actionAuthor);
slotUpdateAuthorProfileActions();
d->showPixelGrid = actionManager()->createAction("view_pixel_grid");
slotUpdatePixelGridAction();
}
void KisViewManager::setupManagers()
{
// Create the managers for filters, selections, layers etc.
// XXX: When the currentlayer changes, call updateGUI on all
// managers
d->filterManager.setup(actionCollection(), actionManager());
d->selectionManager.setup(actionManager());
d->guidesManager.setup(actionManager());
d->nodeManager.setup(actionCollection(), actionManager());
d->imageManager.setup(actionManager());
d->gridManager.setup(actionManager());
d->paintingAssistantsManager.setup(actionManager());
d->canvasControlsManager.setup(actionManager());
d->mirrorManager.setup(actionCollection());
-
- d->scriptManager.setup(actionCollection(), actionManager());
}
void KisViewManager::updateGUI()
{
d->guiUpdateCompressor.start();
}
void KisViewManager::slotBlacklistCleanup()
{
KisDlgBlacklistCleanup dialog;
dialog.exec();
}
KisNodeManager * KisViewManager::nodeManager() const
{
return &d->nodeManager;
}
KisActionManager* KisViewManager::actionManager() const
{
return &d->actionManager;
}
KisGridManager * KisViewManager::gridManager() const
{
return &d->gridManager;
}
KisGuidesManager * KisViewManager::guidesManager() const
{
return &d->guidesManager;
}
KisDocument *KisViewManager::document() const
{
if (d->currentImageView && d->currentImageView->document()) {
return d->currentImageView->document();
}
return 0;
}
-KisScriptManager *KisViewManager::scriptManager() const
-{
- return &d->scriptManager;
-}
-
int KisViewManager::viewCount() const
{
KisMainWindow *mw = qobject_cast(d->mainWindow);
if (mw) {
return mw->viewCount();
}
return 0;
}
bool KisViewManager::KisViewManagerPrivate::blockUntilOperationsFinishedImpl(KisImageSP image, bool force)
{
const int busyWaitDelay = 1000;
KisDelayedSaveDialog dialog(image, !force ? KisDelayedSaveDialog::GeneralDialog : KisDelayedSaveDialog::ForcedDialog, busyWaitDelay, mainWindow);
dialog.blockIfImageIsBusy();
return dialog.result() == QDialog::Accepted;
}
bool KisViewManager::blockUntilOperationsFinished(KisImageSP image)
{
return d->blockUntilOperationsFinishedImpl(image, false);
}
void KisViewManager::blockUntilOperationsFinishedForced(KisImageSP image)
{
d->blockUntilOperationsFinishedImpl(image, true);
}
void KisViewManager::slotCreateTemplate()
{
if (!document()) return;
KisTemplateCreateDia::createTemplate( QStringLiteral("templates/"), ".kra", document(), mainWindow());
}
void KisViewManager::slotCreateCopy()
{
KisDocument *srcDoc = document();
if (!srcDoc) return;
if (!this->blockUntilOperationsFinished(srcDoc->image())) return;
KisDocument *doc = 0;
{
KisImageBarrierLocker l(srcDoc->image());
doc = srcDoc->clone();
}
KIS_SAFE_ASSERT_RECOVER_RETURN(doc);
QString name = srcDoc->documentInfo()->aboutInfo("name");
if (name.isEmpty()) {
name = document()->url().toLocalFile();
}
name = i18n("%1 (Copy)", name);
doc->documentInfo()->setAboutInfo("title", name);
KisPart::instance()->addDocument(doc);
KisMainWindow *mw = qobject_cast(d->mainWindow);
mw->addViewAndNotifyLoadingCompleted(doc);
}
QMainWindow* KisViewManager::qtMainWindow() const
{
if (d->mainWindow)
return d->mainWindow;
//Fallback for when we have not yet set the main window.
QMainWindow* w = qobject_cast(qApp->activeWindow());
if(w)
return w;
return mainWindow();
}
void KisViewManager::setQtMainWindow(QMainWindow* newMainWindow)
{
d->mainWindow = newMainWindow;
}
void KisViewManager::slotDocumentSaved()
{
d->saveIncremental->setEnabled(true);
d->saveIncrementalBackup->setEnabled(true);
}
void KisViewManager::slotSaveIncremental()
{
if (!document()) return;
if (document()->url().isEmpty()) {
KisMainWindow *mw = qobject_cast(d->mainWindow);
mw->saveDocument(document(), true, false);
return;
}
bool foundVersion;
bool fileAlreadyExists;
bool isBackup;
QString version = "000";
QString newVersion;
QString letter;
QString fileName = document()->localFilePath();
// Find current version filenames
// v v Regexp to find incremental versions in the filename, taking our backup scheme into account as well
// Considering our incremental version and backup scheme, format is filename_001~001.ext
QRegExp regex("_\\d{1,4}[.]|_\\d{1,4}[a-z][.]|_\\d{1,4}[~]|_\\d{1,4}[a-z][~]");
regex.indexIn(fileName); // Perform the search
QStringList matches = regex.capturedTexts();
foundVersion = matches.at(0).isEmpty() ? false : true;
// Ensure compatibility with Save Incremental Backup
// If this regex is not kept separate, the entire algorithm needs modification;
// It's simpler to just add this.
QRegExp regexAux("_\\d{1,4}[~]|_\\d{1,4}[a-z][~]");
regexAux.indexIn(fileName); // Perform the search
QStringList matchesAux = regexAux.capturedTexts();
isBackup = matchesAux.at(0).isEmpty() ? false : true;
// If the filename has a version, prepare it for incrementation
if (foundVersion) {
version = matches.at(matches.count() - 1); // Look at the last index, we don't care about other matches
if (version.contains(QRegExp("[a-z]"))) {
version.chop(1); // Trim "."
letter = version.right(1); // Save letter
version.chop(1); // Trim letter
} else {
version.chop(1); // Trim "."
}
version.remove(0, 1); // Trim "_"
} else {
// TODO: this will not work with files extensions like jp2
// ...else, simply add a version to it so the next loop works
QRegExp regex2("[.][a-z]{2,4}$"); // Heuristic to find file extension
regex2.indexIn(fileName);
QStringList matches2 = regex2.capturedTexts();
QString extensionPlusVersion = matches2.at(0);
extensionPlusVersion.prepend(version);
extensionPlusVersion.prepend("_");
fileName.replace(regex2, extensionPlusVersion);
}
// Prepare the base for new version filename
int intVersion = version.toInt(0);
++intVersion;
QString baseNewVersion = QString::number(intVersion);
while (baseNewVersion.length() < version.length()) {
baseNewVersion.prepend("0");
}
// Check if the file exists under the new name and search until options are exhausted (test appending a to z)
do {
newVersion = baseNewVersion;
newVersion.prepend("_");
if (!letter.isNull()) newVersion.append(letter);
if (isBackup) {
newVersion.append("~");
} else {
newVersion.append(".");
}
fileName.replace(regex, newVersion);
fileAlreadyExists = QFile(fileName).exists();
if (fileAlreadyExists) {
if (!letter.isNull()) {
char letterCh = letter.at(0).toLatin1();
++letterCh;
letter = QString(QChar(letterCh));
} else {
letter = 'a';
}
}
} while (fileAlreadyExists && letter != "{"); // x, y, z, {...
if (letter == "{") {
QMessageBox::critical(mainWindow(), i18nc("@title:window", "Couldn't save incremental version"), i18n("Alternative names exhausted, try manually saving with a higher number"));
return;
}
document()->setFileBatchMode(true);
document()->saveAs(QUrl::fromUserInput(fileName), document()->mimeType(), true);
document()->setFileBatchMode(false);
if (mainWindow()) {
mainWindow()->updateCaption();
}
}
void KisViewManager::slotSaveIncrementalBackup()
{
if (!document()) return;
if (document()->url().isEmpty()) {
KisMainWindow *mw = qobject_cast(d->mainWindow);
mw->saveDocument(document(), true, false);
return;
}
bool workingOnBackup;
bool fileAlreadyExists;
QString version = "000";
QString newVersion;
QString letter;
QString fileName = document()->localFilePath();
// First, discover if working on a backup file, or a normal file
QRegExp regex("~\\d{1,4}[.]|~\\d{1,4}[a-z][.]");
regex.indexIn(fileName); // Perform the search
QStringList matches = regex.capturedTexts();
workingOnBackup = matches.at(0).isEmpty() ? false : true;
if (workingOnBackup) {
// Try to save incremental version (of backup), use letter for alt versions
version = matches.at(matches.count() - 1); // Look at the last index, we don't care about other matches
if (version.contains(QRegExp("[a-z]"))) {
version.chop(1); // Trim "."
letter = version.right(1); // Save letter
version.chop(1); // Trim letter
} else {
version.chop(1); // Trim "."
}
version.remove(0, 1); // Trim "~"
// Prepare the base for new version filename
int intVersion = version.toInt(0);
++intVersion;
QString baseNewVersion = QString::number(intVersion);
QString backupFileName = document()->localFilePath();
while (baseNewVersion.length() < version.length()) {
baseNewVersion.prepend("0");
}
// Check if the file exists under the new name and search until options are exhausted (test appending a to z)
do {
newVersion = baseNewVersion;
newVersion.prepend("~");
if (!letter.isNull()) newVersion.append(letter);
newVersion.append(".");
backupFileName.replace(regex, newVersion);
fileAlreadyExists = QFile(backupFileName).exists();
if (fileAlreadyExists) {
if (!letter.isNull()) {
char letterCh = letter.at(0).toLatin1();
++letterCh;
letter = QString(QChar(letterCh));
} else {
letter = 'a';
}
}
} while (fileAlreadyExists && letter != "{"); // x, y, z, {...
if (letter == "{") {
QMessageBox::critical(mainWindow(), i18nc("@title:window", "Couldn't save incremental backup"), i18n("Alternative names exhausted, try manually saving with a higher number"));
return;
}
QFile::copy(fileName, backupFileName);
document()->saveAs(QUrl::fromUserInput(fileName), document()->mimeType(), true);
if (mainWindow()) mainWindow()->updateCaption();
}
else { // if NOT working on a backup...
// Navigate directory searching for latest backup version, ignore letters
const quint8 HARDCODED_DIGIT_COUNT = 3;
QString baseNewVersion = "000";
QString backupFileName = document()->localFilePath();
QRegExp regex2("[.][a-z]{2,4}$"); // Heuristic to find file extension
regex2.indexIn(backupFileName);
QStringList matches2 = regex2.capturedTexts();
QString extensionPlusVersion = matches2.at(0);
extensionPlusVersion.prepend(baseNewVersion);
extensionPlusVersion.prepend("~");
backupFileName.replace(regex2, extensionPlusVersion);
// Save version with 1 number higher than the highest version found ignoring letters
do {
newVersion = baseNewVersion;
newVersion.prepend("~");
newVersion.append(".");
backupFileName.replace(regex, newVersion);
fileAlreadyExists = QFile(backupFileName).exists();
if (fileAlreadyExists) {
// Prepare the base for new version filename, increment by 1
int intVersion = baseNewVersion.toInt(0);
++intVersion;
baseNewVersion = QString::number(intVersion);
while (baseNewVersion.length() < HARDCODED_DIGIT_COUNT) {
baseNewVersion.prepend("0");
}
}
} while (fileAlreadyExists);
// Save both as backup and on current file for interapplication workflow
document()->setFileBatchMode(true);
QFile::copy(fileName, backupFileName);
document()->saveAs(QUrl::fromUserInput(fileName), document()->mimeType(), true);
document()->setFileBatchMode(false);
if (mainWindow()) mainWindow()->updateCaption();
}
}
void KisViewManager::disableControls()
{
// prevents possible crashes, if somebody changes the paintop during dragging by using the mousewheel
// this is for Bug 250944
// the solution blocks all wheel, mouse and key event, while dragging with the freehand tool
// see KisToolFreehand::initPaint() and endPaint()
d->controlFrame.paintopBox()->installEventFilter(&d->blockingEventFilter);
Q_FOREACH (QObject* child, d->controlFrame.paintopBox()->children()) {
child->installEventFilter(&d->blockingEventFilter);
}
}
void KisViewManager::enableControls()
{
d->controlFrame.paintopBox()->removeEventFilter(&d->blockingEventFilter);
Q_FOREACH (QObject* child, d->controlFrame.paintopBox()->children()) {
child->removeEventFilter(&d->blockingEventFilter);
}
}
void KisViewManager::showStatusBar(bool toggled)
{
KisMainWindow *mw = mainWindow();
if(mw && mw->statusBar()) {
mw->statusBar()->setVisible(toggled);
KisConfig cfg;
cfg.setShowStatusBar(toggled);
}
}
void KisViewManager::switchCanvasOnly(bool toggled)
{
KisConfig cfg;
KisMainWindow* main = mainWindow();
if(!main) {
dbgUI << "Unable to switch to canvas-only mode, main window not found";
return;
}
if (toggled) {
d->canvasState = qtMainWindow()->saveState();
#if QT_VERSION < QT_VERSION_CHECK(5, 10, 0)
d->windowFlags = main->windowState();
#endif
}
if (cfg.hideStatusbarFullscreen()) {
if (main->statusBar()) {
if (!toggled) {
if (main->statusBar()->dynamicPropertyNames().contains("wasvisible")) {
if (main->statusBar()->property("wasvisible").toBool()) {
main->statusBar()->setVisible(true);
}
}
}
else {
main->statusBar()->setProperty("wasvisible", main->statusBar()->isVisible());
main->statusBar()->setVisible(false);
}
}
}
if (cfg.hideDockersFullscreen()) {
KisAction* action = qobject_cast(main->actionCollection()->action("view_toggledockers"));
if (action) {
action->setCheckable(true);
if (toggled) {
if (action->isChecked()) {
cfg.setShowDockers(action->isChecked());
action->setChecked(false);
} else {
cfg.setShowDockers(false);
}
} else {
action->setChecked(cfg.showDockers());
}
}
}
// QT in windows does not return to maximized upon 4th tab in a row
// https://bugreports.qt.io/browse/QTBUG-57882, https://bugreports.qt.io/browse/QTBUG-52555, https://codereview.qt-project.org/#/c/185016/
if (cfg.hideTitlebarFullscreen() && !cfg.fullscreenMode()) {
if(toggled) {
main->setWindowState( main->windowState() | Qt::WindowFullScreen);
} else {
main->setWindowState( main->windowState() & ~Qt::WindowFullScreen);
#if QT_VERSION < QT_VERSION_CHECK(5, 10, 0)
// If window was maximized prior to fullscreen, restore that
if (d->windowFlags & Qt::WindowMaximized) {
main->setWindowState( main->windowState() | Qt::WindowMaximized);
}
#endif
}
}
if (cfg.hideMenuFullscreen()) {
if (!toggled) {
if (main->menuBar()->dynamicPropertyNames().contains("wasvisible")) {
if (main->menuBar()->property("wasvisible").toBool()) {
main->menuBar()->setVisible(true);
}
}
}
else {
main->menuBar()->setProperty("wasvisible", main->menuBar()->isVisible());
main->menuBar()->setVisible(false);
}
}
if (cfg.hideToolbarFullscreen()) {
QList toolBars = main->findChildren