diff --git a/libs/libkis/Krita.cpp b/libs/libkis/Krita.cpp
index 48df9ca5c1..7b0e90723d 100644
--- a/libs/libkis/Krita.cpp
+++ b/libs/libkis/Krita.cpp
@@ -1,423 +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
{
KisMainWindow *mainWindow = KisPart::instance()->currentMainwindow();
if (!mainWindow) {
return QList();
}
KActionCollection *actionCollection = mainWindow->actionCollection();
return actionCollection->actions();
}
QAction *Krita::action(const QString &name) const
{
KisMainWindow *mainWindow = KisPart::instance()->currentMainwindow();
if (!mainWindow) {
return 0;
}
KActionCollection *actionCollection = mainWindow->actionCollection();
QAction *action = actionCollection->action(name);
return action;
}
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();
}
QStringList r = profileNames.toList();
r.sort();
return r;
}
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) )) {
+ if (!document->newImage(name, width, height, cs, bgColor, KisConfig::RASTER_LAYER, 1, "", double(resolution / 72) )) {
return 0;
}
Q_ASSERT(document->image());
return new Document(document);
}
Document* Krita::openDocument(const QString &filename)
{
KisDocument *document = KisPart::instance()->createDocument();
document->setFileBatchMode(this->batchmode());
KisPart::instance()->addDocument(document);
document->openUrl(QUrl::fromLocalFile(filename), KisDocument::DontAddToRecent);
document->setFileBatchMode(false);
return new Document(document);
}
Window* Krita::openWindow()
{
KisMainWindow *mw = KisPart::instance()->createMainWindow();
return new Window(mw);
}
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;
}
QString Krita::krita_i18n(const QString &text)
{
return i18n(text.toUtf8().constData());
}
void Krita::mainWindowAdded(KisMainWindow *kisWindow)
{
Q_FOREACH(Extension *extension, d->extensions) {
Window window(kisWindow);
extension->createActions(&window);
}
}
diff --git a/libs/libqml/DocumentManager.cpp b/libs/libqml/DocumentManager.cpp
index 9df83a5680..c53b148800 100644
--- a/libs/libqml/DocumentManager.cpp
+++ b/libs/libqml/DocumentManager.cpp
@@ -1,311 +1,311 @@
/* This file is part of the KDE project
* Copyright (C) 2012 Arjen Hiemstra
*
* 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 "DocumentManager.h"
#include "ProgressProxy.h"
#include "Settings.h"
#include "RecentFileManager.h"
#include
#include
#include
#include
#include
#include
#include
class DocumentManager::Private
{
public:
Private()
: proxy(0)
, document(0)
, settingsManager(0)
, recentFileManager(0)
, newDocWidth(0)
, newDocHeight(0)
, newDocResolution(0)
, importingDocument(false)
, temporaryFile(false)
{ }
ProgressProxy* proxy;
QPointer document;
Settings* settingsManager;
RecentFileManager* recentFileManager;
QString saveAsFilename;
QString openDocumentFilename;
int newDocWidth, newDocHeight; float newDocResolution;
bool importingDocument;
QVariantMap newDocOptions;
bool temporaryFile;
};
DocumentManager *DocumentManager::sm_instance = 0;
KisDocument* DocumentManager::document() const
{
return d->document;
}
ProgressProxy* DocumentManager::progressProxy() const
{
return d->proxy;
}
Settings* DocumentManager::settingsManager() const
{
return d->settingsManager;
}
void DocumentManager::setSettingsManager(Settings* newManager)
{
d->settingsManager = newManager;
}
RecentFileManager* DocumentManager::recentFileManager() const
{
return d->recentFileManager;
}
bool DocumentManager::isTemporaryFile() const
{
return d->temporaryFile;
}
void DocumentManager::newDocument(int width, int height, float resolution)
{
closeDocument();
d->newDocWidth = width;
d->newDocHeight = height;
d->newDocResolution = resolution;
QTimer::singleShot(300, this, SLOT(delayedNewDocument()));
}
void DocumentManager::newDocument(const QVariantMap& options)
{
closeDocument();
d->newDocOptions = options;
QTimer::singleShot(300, this, SLOT(delayedNewDocument()));
}
void DocumentManager::delayedNewDocument()
{
d->document = KisPart::instance()->createDocument();
if (qAppName().contains("sketch")) {
d->document->setFileBatchMode(true);
}
if (d->newDocOptions.isEmpty())
{
const KoColorSpace *cs = KoColorSpaceRegistry::instance()->rgb8(0);
QColor qc(Qt::white);
qc.setAlpha(0);
KoColor bgColor(qc, cs);
- d->document->newImage("New Image", d->newDocWidth, d->newDocHeight, KoColorSpaceRegistry::instance()->rgb8(), bgColor, true, 2, "", d->newDocResolution);
+ d->document->newImage("New Image", d->newDocWidth, d->newDocHeight, KoColorSpaceRegistry::instance()->rgb8(), bgColor, KisConfig::RASTER_LAYER, 2, "", d->newDocResolution);
d->document->resetURL();
}
else if (d->newDocOptions.contains("template")) {
QUrl url(d->newDocOptions.value("template").toString().remove("template://"));
bool ok = d->document->loadNativeFormat(url.toLocalFile());
d->document->setModified(false);
d->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$" ) );
d->document->setMimeTypeAfterLoading(mimeType);
d->document->resetURL();
}
}
else
{
QString name = d->newDocOptions.value("name", "New Image").toString();
int width = d->newDocOptions.value("width").toInt();
int height = d->newDocOptions.value("height").toInt();
// internal resolution is pixels per point, not ppi
float res = d->newDocOptions.value("resolution", 72.0f).toFloat() / 72.0f;
QString colorModelId = d->newDocOptions.value("colorModelId").toString();
QString colorDepthId = d->newDocOptions.value("colorDepthId").toString();
QString colorProfileId = d->newDocOptions.value("colorProfileId").toString();
const KoColorSpace* cs;
if(colorModelId.isEmpty() || colorDepthId.isEmpty() || colorProfileId.isEmpty()) {
cs = KoColorSpaceRegistry::instance()->rgb8();
}
else
{
cs = KoColorSpaceRegistry::instance()->colorSpace(colorModelId, colorDepthId, colorProfileId);
}
QColor background = d->newDocOptions.value("backgroundColor", QColor("white")).value();
background.setAlphaF(d->newDocOptions.value("backgroundOpacity", 1.0f).toFloat());
KoColor bg(background, cs);
- d->document->newImage(name, width, height, cs, bg, true, 1, "", res);
+ d->document->newImage(name, width, height, cs, bg, KisConfig::RASTER_LAYER, 1, "", res);
d->document->resetURL();
}
KisPart::instance()->addDocument(d->document);
d->temporaryFile = true;
emit documentChanged();
}
void DocumentManager::openDocument(const QString& document, bool import)
{
closeDocument();
d->openDocumentFilename = document;
d->importingDocument = import;
QTimer::singleShot(300, this, SLOT(delayedOpenDocument()));
}
void DocumentManager::delayedOpenDocument()
{
d->document = KisPart::instance()->createDocument();
if (qAppName().contains("sketch")) {
d->document->setFileBatchMode(true);
}
connect(d->document, SIGNAL(completed()), this, SLOT(onLoadCompleted()));
connect(d->document, SIGNAL(canceled(QString)), this, SLOT(onLoadCanceled(QString)));
// TODO: still needed?
d->document->setModified(false);
if (d->importingDocument)
d->document->importDocument(QUrl::fromLocalFile(d->openDocumentFilename));
else
d->document->openUrl(QUrl::fromLocalFile(d->openDocumentFilename));
// TODO: handle fail of open/import
d->recentFileManager->addRecent(d->openDocumentFilename);
KisPart::instance()->addDocument(d->document);
d->temporaryFile = false;
}
// Separate from openDocument to handle async loading (remote URLs)
void DocumentManager::onLoadCompleted()
{
KisDocument *newdoc = qobject_cast(sender());
disconnect(newdoc, SIGNAL(completed()), this, SLOT(onLoadCompleted()));
disconnect(newdoc, SIGNAL(canceled(QString)), this, SLOT(onLoadCanceled(QString)));
emit documentChanged();
}
void DocumentManager::onLoadCanceled(const QString &/*errMsg*/)
{
// if (!errMsg.isEmpty()) // empty when canceled by user
// QMessageBox::critical(this, i18nc("@title:window", "Krita"), errMsg);
// ... can't delete the document, it's the one who emitted the signal...
KisDocument* newdoc = qobject_cast(sender());
Q_ASSERT(newdoc);
disconnect(newdoc, SIGNAL(completed()), this, SLOT(onLoadCompleted()));
disconnect(newdoc, SIGNAL(canceled(QString)), this, SLOT(onLoadCanceled(QString)));
}
void DocumentManager::closeDocument()
{
if (d->document) {
emit aboutToDeleteDocument();
d->document->closeUrl(false);
//d->document->deleteLater();
d->document = 0;
}
}
bool DocumentManager::save()
{
// if (d->document->save())
// {
// d->recentFileManager->addRecent(d->document->url().toLocalFile());
// d->settingsManager->setCurrentFile(d->document->url().toLocalFile());
// emit documentSaved();
// return true;
// }
return false;
}
void DocumentManager::saveAs(const QString &filename, const QString &mimetype)
{
d->document->setMimeType(mimetype.toLatin1());
d->saveAsFilename = filename;
// Yes. This is a massive hack. Basically, we need to wait a little while, to ensure
// the save call happens late enough for a variety of UI things to happen first.
// A second seems like a long time, but well, we do have file system interaction here,
// so for now, we can get away with it.
QTimer::singleShot(300, this, SLOT(delayedSaveAs()));
}
void DocumentManager::delayedSaveAs()
{
//d->document->saveAs(QUrl::fromLocalFile(d->saveAsFilename));
d->settingsManager->setCurrentFile(d->saveAsFilename);
d->recentFileManager->addRecent(d->saveAsFilename);
emit documentSaved();
}
void DocumentManager::reload()
{
QUrl url = d->document->url();
closeDocument();
d->openDocumentFilename = url.toLocalFile();
QTimer::singleShot(0, this, SLOT(delayedOpenDocument()));
}
void DocumentManager::setTemporaryFile(bool temp)
{
d->temporaryFile = temp;
emit documentSaved();
}
DocumentManager* DocumentManager::instance()
{
if (!sm_instance) {
sm_instance = new DocumentManager(QCoreApplication::instance());
}
return sm_instance;
}
DocumentManager::DocumentManager(QObject* parent)
: QObject(parent), d(new Private)
{
d->proxy = new ProgressProxy(this);
d->recentFileManager = new RecentFileManager(this);
}
DocumentManager::~DocumentManager()
{
delete d;
}
diff --git a/libs/ui/KisApplicationArguments.cpp b/libs/ui/KisApplicationArguments.cpp
index df58592699..a2029e0f9e 100644
--- a/libs/ui/KisApplicationArguments.cpp
+++ b/libs/ui/KisApplicationArguments.cpp
@@ -1,336 +1,336 @@
/*
* Copyright (c) 2015 Boudewijn Rempt
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this 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 "KisApplicationArguments.h"
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
struct Q_DECL_HIDDEN KisApplicationArguments::Private
{
Private()
{
}
QStringList filenames;
int dpiX {72};
int dpiY {72};
bool doTemplate {false};
bool exportAs {false};
QString exportFileName;
QString workspace;
QString windowLayout;
QString session;
bool canvasOnly {false};
bool noSplash {false};
bool fullScreen {false};
bool newImage {false};
QString colorModel {"RGBA"};
QString colorDepth {"U8"};
int width {2000};
int height {5000};
};
KisApplicationArguments::KisApplicationArguments()
: d(new Private)
{
}
KisApplicationArguments::~KisApplicationArguments()
{
}
KisApplicationArguments::KisApplicationArguments(const QApplication &app)
: d(new Private)
{
QCommandLineParser parser;
parser.addVersionOption();
parser.addHelpOption();
parser.addOption(QCommandLineOption(QStringList() << QLatin1String("template"), i18n("Open a new document with a template")));
parser.addOption(QCommandLineOption(QStringList() << QLatin1String("new-image"), i18n("Create a new image on startup.\n"
"Possible colorspace values are:\n"
" * RGBA\n"
" * XYZA\n"
" * LABA\n"
" * CMYKA\n"
" * GRAY\n"
" * YCbCrA\n"
"Possible channel depth arguments are\n"
" * U8 (8 bits integer)\n"
" * U16 (16 bits integer)\n"
" * F16 (16 bits floating point)\n"
" * F32 (32 bits floating point)\n"),
QLatin1String("colorspace,depth,width,height")));
parser.addOption(QCommandLineOption(QStringList() << QLatin1String("workspace"), i18n("The name of the workspace to open Krita with"), QLatin1String("workspace")));
parser.addOption(QCommandLineOption(QStringList() << QLatin1String("windowlayout"), i18n("The name of the window layout to open Krita with"), QLatin1String("windowlayout")));
parser.addOption(QCommandLineOption(QStringList() << QLatin1String("load-session"), i18n("The name of the session to open Krita with"), QLatin1String("load-session"))); // NB: the argument "session" is already used by QGuiApplication
parser.addOption(QCommandLineOption(QStringList() << QLatin1String("canvasonly"), i18n("Start Krita in canvas-only mode")));
parser.addOption(QCommandLineOption(QStringList() << QLatin1String("nosplash"), i18n("Do not show the splash screen")));
parser.addOption(QCommandLineOption(QStringList() << QLatin1String("fullscreen"), i18n("Start Krita in full-screen mode")));
parser.addOption(QCommandLineOption(QStringList() << QLatin1String("dpi"), i18n("Override display DPI"), QLatin1String("dpiX,dpiY")));
parser.addOption(QCommandLineOption(QStringList() << QLatin1String("export"), i18n("Export to the given filename and exit")));
parser.addOption(QCommandLineOption(QStringList() << QLatin1String("export-filename"), i18n("Filename for export"), QLatin1String("filename")));
parser.addPositionalArgument(QLatin1String("[file(s)]"), i18n("File(s) or URL(s) to open"));
parser.process(app);
QString dpiValues = parser.value("dpi");
if (!dpiValues.isEmpty()) {
int sep = dpiValues.indexOf(QRegExp("[x, ]"));
bool ok = true;
if (sep != -1) {
d->dpiY = dpiValues.mid(sep + 1).toInt(&ok);
dpiValues.truncate(sep);
}
if (ok) {
d->dpiX = dpiValues.toInt(&ok);
if (ok) {
if (!d->dpiY)
d->dpiY = d->dpiX;
}
}
}
QString newImageValues = parser.value("new-image");
d->newImage = !newImageValues.isEmpty();
if (d->newImage) {
QStringList v = newImageValues.split(",");
if (v.size() != 4) {
d->newImage = false;
qWarning() << "Cannot create a new image: please specify colormodel, depth, width and height.";
}
d->colorModel = v[0].toUpper();
d->colorDepth = v[1].toUpper();
d->width = v[2].toInt();
d->height = v[3].toInt();
}
d->exportFileName = parser.value("export-filename");
d->workspace = parser.value("workspace");
d->windowLayout = parser.value("windowlayout");
d->session = parser.value("load-session");
d->doTemplate = parser.isSet("template");
d->exportAs = parser.isSet("export");
d->canvasOnly = parser.isSet("canvasonly");
d->noSplash = parser.isSet("nosplash");
d->fullScreen = parser.isSet("fullscreen");
const QDir currentDir = QDir::current();
Q_FOREACH (const QString &filename, parser.positionalArguments()) {
d->filenames << currentDir.absoluteFilePath(filename);
}
}
KisApplicationArguments::KisApplicationArguments(const KisApplicationArguments &rhs)
: d(new Private)
{
d->filenames = rhs.filenames();
d->dpiX = rhs.dpiX();
d->dpiY = rhs.dpiY();
d->doTemplate = rhs.doTemplate();
d->exportAs = rhs.exportAs();
d->exportFileName = rhs.exportFileName();
d->canvasOnly = rhs.canvasOnly();
d->workspace = rhs.workspace();
d->windowLayout = rhs.windowLayout();
d->session = rhs.session();
d->noSplash = rhs.noSplash();
d->fullScreen = rhs.fullScreen();
}
void KisApplicationArguments::operator=(const KisApplicationArguments &rhs)
{
d->filenames = rhs.filenames();
d->dpiX = rhs.dpiX();
d->dpiY = rhs.dpiY();
d->doTemplate = rhs.doTemplate();
d->exportAs = rhs.exportAs();
d->exportFileName = rhs.exportFileName();
d->canvasOnly = rhs.canvasOnly();
d->workspace = rhs.workspace();
d->windowLayout = rhs.windowLayout();
d->session = rhs.session();
d->noSplash = rhs.noSplash();
d->fullScreen = rhs.fullScreen();
}
QByteArray KisApplicationArguments::serialize()
{
QByteArray ba;
QBuffer buf(&ba);
buf.open(QIODevice::WriteOnly);
QDataStream ds(&buf);
ds.setVersion(QDataStream::Qt_5_0);
ds << d->filenames.count();
Q_FOREACH (const QString &filename, d->filenames) {
ds << filename;
}
ds << d->dpiX;
ds << d->dpiY;
ds << d->doTemplate;
ds << d->exportAs;
ds << d->exportFileName;
ds << d->workspace;
ds << d->windowLayout;
ds << d->session;
ds << d->canvasOnly;
ds << d->noSplash;
ds << d->fullScreen;
ds << d->newImage;
ds << d->height;
ds << d->width;
ds << d->height;
ds << d->colorModel;
ds << d->colorDepth;
buf.close();
return ba;
}
KisApplicationArguments KisApplicationArguments::deserialize(QByteArray &serialized)
{
KisApplicationArguments args;
QBuffer buf(&serialized);
buf.open(QIODevice::ReadOnly);
QDataStream ds(&buf);
ds.setVersion(QDataStream::Qt_5_0);
int count;
ds >> count;
for(int i = 0; i < count; ++i) {
QString s;
ds >> s;
args.d->filenames << s;
}
ds >> args.d->dpiX;
ds >> args.d->dpiY;
ds >> args.d->doTemplate;
ds >> args.d->exportAs;
ds >> args.d->exportFileName;
ds >> args.d->workspace;
ds >> args.d->windowLayout;
ds >> args.d->session;
ds >> args.d->canvasOnly;
ds >> args.d->noSplash;
ds >> args.d->fullScreen;
ds >> args.d->newImage;
ds >> args.d->height;
ds >> args.d->width;
ds >> args.d->height;
ds >> args.d->colorModel;
ds >> args.d->colorDepth;
buf.close();
return args;
}
QStringList KisApplicationArguments::filenames() const
{
return d->filenames;
}
int KisApplicationArguments::dpiX() const
{
return d->dpiX;
}
int KisApplicationArguments::dpiY() const
{
return d->dpiY;
}
bool KisApplicationArguments::doTemplate() const
{
return d->doTemplate;
}
bool KisApplicationArguments::exportAs() const
{
return d->exportAs;
}
QString KisApplicationArguments::exportFileName() const
{
return d->exportFileName;
}
QString KisApplicationArguments::workspace() const
{
return d->workspace;
}
QString KisApplicationArguments::windowLayout() const
{
return d->windowLayout;
}
QString KisApplicationArguments::session() const
{
return d->session;
}
bool KisApplicationArguments::canvasOnly() const
{
return d->canvasOnly;
}
bool KisApplicationArguments::noSplash() const
{
return d->noSplash;
}
bool KisApplicationArguments::fullScreen() const
{
return d->fullScreen;
}
bool KisApplicationArguments::doNewImage() const
{
return d->newImage;
}
KisDocument *KisApplicationArguments::image() const
{
KisDocument *doc = KisPart::instance()->createDocument();
const KoColorSpace *cs = KoColorSpaceRegistry::instance()->colorSpace(d->colorModel, d->colorDepth, "");
if (!cs) {
qWarning() << "Could not create the colorspace for the new image. Check the colorspace and depth arguments.";
return 0;
}
- doc->newImage(i18n("Unnamed"), d->width, d->height, cs, KoColor(QColor(Qt::white), cs), false, 1, "", 100.0);
+ doc->newImage(i18n("Unnamed"), d->width, d->height, cs, KoColor(QColor(Qt::white), cs), KisConfig::CANVAS_COLOR, 1, "", 100.0);
return doc;
}
diff --git a/libs/ui/KisDocument.cpp b/libs/ui/KisDocument.cpp
index 41c2809bb5..ab95fd2a29 100644
--- a/libs/ui/KisDocument.cpp
+++ b/libs/ui/KisDocument.cpp
@@ -1,1856 +1,1867 @@
/* This file is part of the Krita project
*
* Copyright (C) 2014 Boudewijn Rempt
*
* 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 "KisMainWindow.h" // XXX: remove
#include // XXX: remove
#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
#include
#include
#include
#include
#include
#include
#include
#include
// Krita Image
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include "kis_layer_utils.h"
// Local
#include "KisViewManager.h"
#include "kis_clipboard.h"
#include "widgets/kis_custom_image_widget.h"
#include "canvas/kis_canvas2.h"
#include "flake/kis_shape_controller.h"
#include "kis_statusbar.h"
#include "widgets/kis_progress_widget.h"
#include "kis_canvas_resource_provider.h"
#include "KisResourceServerProvider.h"
#include "kis_node_manager.h"
#include "KisPart.h"
#include "KisApplication.h"
#include "KisDocument.h"
#include "KisImportExportManager.h"
#include "KisView.h"
#include "kis_grid_config.h"
#include "kis_guides_config.h"
#include "kis_image_barrier_lock_adapter.h"
#include "KisReferenceImagesLayer.h"
#include
#include "kis_config_notifier.h"
#include "kis_async_action_feedback.h"
#include "KisCloneDocumentStroke.h"
// Define the protocol used here for embedded documents' URL
// This used to "store" but QUrl didn't like it,
// so let's simply make it "tar" !
#define STORE_PROTOCOL "tar"
// The internal path is a hack to make QUrl happy and for document children
#define INTERNAL_PROTOCOL "intern"
#define INTERNAL_PREFIX "intern:/"
// Warning, keep it sync in koStore.cc
#include
using namespace std;
namespace {
constexpr int errorMessageTimeout = 5000;
constexpr int successMessageTimeout = 1000;
}
/**********************************************************
*
* KisDocument
*
**********************************************************/
//static
QString KisDocument::newObjectName()
{
static int s_docIFNumber = 0;
QString name; name.setNum(s_docIFNumber++); name.prepend("document_");
return name;
}
class UndoStack : public KUndo2Stack
{
public:
UndoStack(KisDocument *doc)
: KUndo2Stack(doc),
m_doc(doc)
{
}
void setIndex(int idx) override {
KisImageWSP image = this->image();
image->requestStrokeCancellation();
if(image->tryBarrierLock()) {
KUndo2Stack::setIndex(idx);
image->unlock();
}
}
void notifySetIndexChangedOneCommand() override {
KisImageWSP image = this->image();
image->unlock();
/**
* Some very weird commands may emit blocking signals to
* the GUI (e.g. KisGuiContextCommand). Here is the best thing
* we can do to avoid the deadlock
*/
while(!image->tryBarrierLock()) {
QApplication::processEvents();
}
}
void undo() override {
KisImageWSP image = this->image();
image->requestUndoDuringStroke();
if (image->tryUndoUnfinishedLod0Stroke() == UNDO_OK) {
return;
}
if(image->tryBarrierLock()) {
KUndo2Stack::undo();
image->unlock();
}
}
void redo() override {
KisImageWSP image = this->image();
if(image->tryBarrierLock()) {
KUndo2Stack::redo();
image->unlock();
}
}
private:
KisImageWSP image() {
KisImageWSP currentImage = m_doc->image();
Q_ASSERT(currentImage);
return currentImage;
}
private:
KisDocument *m_doc;
};
class Q_DECL_HIDDEN KisDocument::Private
{
public:
Private(KisDocument *q)
: docInfo(new KoDocumentInfo(q)) // deleted by QObject
, importExportManager(new KisImportExportManager(q)) // deleted manually
, autoSaveTimer(new QTimer(q))
, undoStack(new UndoStack(q)) // deleted by QObject
, m_bAutoDetectedMime(false)
, modified(false)
, readwrite(true)
, firstMod(QDateTime::currentDateTime())
, lastMod(firstMod)
, nserver(new KisNameServer(1))
, imageIdleWatcher(2000 /*ms*/)
, globalAssistantsColor(KisConfig(true).defaultAssistantsColor())
, savingLock(&savingMutex)
, batchMode(false)
{
if (QLocale().measurementSystem() == QLocale::ImperialSystem) {
unit = KoUnit::Inch;
} else {
unit = KoUnit::Centimeter;
}
}
Private(const Private &rhs, KisDocument *q)
: docInfo(new KoDocumentInfo(*rhs.docInfo, q))
, unit(rhs.unit)
, importExportManager(new KisImportExportManager(q))
, mimeType(rhs.mimeType)
, outputMimeType(rhs.outputMimeType)
, autoSaveTimer(new QTimer(q))
, undoStack(new UndoStack(q))
, guidesConfig(rhs.guidesConfig)
, m_bAutoDetectedMime(rhs.m_bAutoDetectedMime)
, m_url(rhs.m_url)
, m_file(rhs.m_file)
, modified(rhs.modified)
, readwrite(rhs.readwrite)
, firstMod(rhs.firstMod)
, lastMod(rhs.lastMod)
, nserver(new KisNameServer(*rhs.nserver))
, preActivatedNode(0) // the node is from another hierarchy!
, imageIdleWatcher(2000 /*ms*/)
, assistants(rhs.assistants) // WARNING: assistants should not store pointers to the document!
, globalAssistantsColor(rhs.globalAssistantsColor)
, paletteList(rhs.paletteList)
, gridConfig(rhs.gridConfig)
, savingLock(&savingMutex)
, batchMode(rhs.batchMode)
{
// TODO: clone assistants
}
~Private() {
// Don't delete m_d->shapeController because it's in a QObject hierarchy.
delete nserver;
}
KoDocumentInfo *docInfo = 0;
KoUnit unit;
KisImportExportManager *importExportManager = 0; // The filter-manager to use when loading/saving [for the options]
QByteArray mimeType; // The actual mimetype of the document
QByteArray outputMimeType; // The mimetype to use when saving
QTimer *autoSaveTimer;
QString lastErrorMessage; // see openFile()
QString lastWarningMessage;
int autoSaveDelay = 300; // in seconds, 0 to disable.
bool modifiedAfterAutosave = false;
bool isAutosaving = false;
bool disregardAutosaveFailure = false;
int autoSaveFailureCount = 0;
KUndo2Stack *undoStack = 0;
KisGuidesConfig guidesConfig;
bool m_bAutoDetectedMime = false; // whether the mimetype in the arguments was detected by the part itself
QUrl m_url; // local url - the one displayed to the user.
QString m_file; // Local file - the only one the part implementation should deal with.
QMutex savingMutex;
bool modified = false;
bool readwrite = false;
QDateTime firstMod;
QDateTime lastMod;
KisNameServer *nserver;
KisImageSP image;
KisImageSP savingImage;
KisNodeWSP preActivatedNode;
KisShapeController* shapeController = 0;
KoShapeController* koShapeController = 0;
KisIdleWatcher imageIdleWatcher;
QScopedPointer imageIdleConnection;
QList assistants;
QColor globalAssistantsColor;
KisSharedPtr referenceImagesLayer;
QList paletteList;
KisGridConfig gridConfig;
StdLockableWrapper savingLock;
bool modifiedWhileSaving = false;
QScopedPointer backgroundSaveDocument;
QPointer savingUpdater;
QFuture childSavingFuture;
KritaUtils::ExportFileJob backgroundSaveJob;
bool isRecovered = false;
bool batchMode { false };
void setImageAndInitIdleWatcher(KisImageSP _image) {
image = _image;
imageIdleWatcher.setTrackedImage(image);
if (image) {
imageIdleConnection.reset(
new KisSignalAutoConnection(
&imageIdleWatcher, SIGNAL(startedIdleMode()),
image.data(), SLOT(explicitRegenerateLevelOfDetail())));
}
}
class StrippedSafeSavingLocker;
};
class KisDocument::Private::StrippedSafeSavingLocker {
public:
StrippedSafeSavingLocker(QMutex *savingMutex, KisImageSP image)
: m_locked(false)
, m_image(image)
, m_savingLock(savingMutex)
, m_imageLock(image, true)
{
/**
* Initial try to lock both objects. Locking the image guards
* us from any image composition threads running in the
* background, while savingMutex guards us from entering the
* saving code twice by autosave and main threads.
*
* Since we are trying to lock multiple objects, so we should
* do it in a safe manner.
*/
m_locked = std::try_lock(m_imageLock, m_savingLock) < 0;
if (!m_locked) {
m_image->requestStrokeEnd();
QApplication::processEvents();
// one more try...
m_locked = std::try_lock(m_imageLock, m_savingLock) < 0;
}
}
~StrippedSafeSavingLocker() {
if (m_locked) {
m_imageLock.unlock();
m_savingLock.unlock();
}
}
bool successfullyLocked() const {
return m_locked;
}
private:
bool m_locked;
KisImageSP m_image;
StdLockableWrapper m_savingLock;
KisImageBarrierLockAdapter m_imageLock;
};
KisDocument::KisDocument()
: d(new Private(this))
{
connect(KisConfigNotifier::instance(), SIGNAL(configChanged()), SLOT(slotConfigChanged()));
connect(d->undoStack, SIGNAL(cleanChanged(bool)), this, SLOT(slotUndoStackCleanChanged(bool)));
connect(d->autoSaveTimer, SIGNAL(timeout()), this, SLOT(slotAutoSave()));
setObjectName(newObjectName());
// preload the krita resources
KisResourceServerProvider::instance();
d->shapeController = new KisShapeController(this, d->nserver),
d->koShapeController = new KoShapeController(0, d->shapeController),
slotConfigChanged();
}
KisDocument::KisDocument(const KisDocument &rhs)
: QObject(),
d(new Private(*rhs.d, this))
{
connect(KisConfigNotifier::instance(), SIGNAL(configChanged()), SLOT(slotConfigChanged()));
connect(d->undoStack, SIGNAL(cleanChanged(bool)), this, SLOT(slotUndoStackCleanChanged(bool)));
connect(d->autoSaveTimer, SIGNAL(timeout()), this, SLOT(slotAutoSave()));
setObjectName(rhs.objectName());
d->shapeController = new KisShapeController(this, d->nserver),
d->koShapeController = new KoShapeController(0, d->shapeController),
slotConfigChanged();
// clone the image with keeping the GUIDs of the layers intact
// NOTE: we expect the image to be locked!
setCurrentImage(rhs.image()->clone(true), false);
if (rhs.d->preActivatedNode) {
// since we clone uuid's, we can use them for lacating new
// nodes. Otherwise we would need to use findSymmetricClone()
d->preActivatedNode =
KisLayerUtils::findNodeByUuid(d->image->root(), rhs.d->preActivatedNode->uuid());
}
}
KisDocument::~KisDocument()
{
// wait until all the pending operations are in progress
waitForSavingToComplete();
/**
* Push a timebomb, which will try to release the memory after
* the document has been deleted
*/
KisPaintDevice::createMemoryReleaseObject()->deleteLater();
d->autoSaveTimer->disconnect(this);
d->autoSaveTimer->stop();
delete d->importExportManager;
// Despite being QObject they needs to be deleted before the image
delete d->shapeController;
delete d->koShapeController;
if (d->image) {
d->image->notifyAboutToBeDeleted();
/**
* WARNING: We should wait for all the internal image jobs to
* finish before entering KisImage's destructor. The problem is,
* while execution of KisImage::~KisImage, all the weak shared
* pointers pointing to the image enter an inconsistent
* state(!). The shared counter is already zero and destruction
* has started, but the weak reference doesn't know about it,
* because KisShared::~KisShared hasn't been executed yet. So all
* the threads running in background and having weak pointers will
* enter the KisImage's destructor as well.
*/
d->image->requestStrokeCancellation();
d->image->waitForDone();
// clear undo commands that can still point to the image
d->undoStack->clear();
d->image->waitForDone();
KisImageWSP sanityCheckPointer = d->image;
Q_UNUSED(sanityCheckPointer);
// The following line trigger the deletion of the image
d->image.clear();
// check if the image has actually been deleted
KIS_SAFE_ASSERT_RECOVER_NOOP(!sanityCheckPointer.isValid());
}
delete d;
}
bool KisDocument::reload()
{
// XXX: reimplement!
return false;
}
KisDocument *KisDocument::clone()
{
return new KisDocument(*this);
}
bool KisDocument::exportDocumentImpl(const KritaUtils::ExportFileJob &job, KisPropertiesConfigurationSP exportConfiguration)
{
QFileInfo filePathInfo(job.filePath);
if (filePathInfo.exists() && !filePathInfo.isWritable()) {
slotCompleteSavingDocument(job,
KisImportExportFilter::CreationError,
i18n("%1 cannot be written to. Please save under a different name.", job.filePath));
return false;
}
KisConfig cfg(true);
if (cfg.backupFile() && filePathInfo.exists()) {
KBackup::backupFile(job.filePath);
}
KIS_SAFE_ASSERT_RECOVER_RETURN_VALUE(!job.mimeType.isEmpty(), false);
const QString actionName =
job.flags & KritaUtils::SaveIsExporting ?
i18n("Exporting Document...") :
i18n("Saving Document...");
bool started =
initiateSavingInBackground(actionName,
this, SLOT(slotCompleteSavingDocument(KritaUtils::ExportFileJob,KisImportExportFilter::ConversionStatus,QString)),
job, exportConfiguration);
if (!started) {
emit canceled(QString());
}
return started;
}
bool KisDocument::exportDocument(const QUrl &url, const QByteArray &mimeType, bool showWarnings, KisPropertiesConfigurationSP exportConfiguration)
{
using namespace KritaUtils;
SaveFlags flags = SaveIsExporting;
if (showWarnings) {
flags |= SaveShowWarnings;
}
return exportDocumentImpl(KritaUtils::ExportFileJob(url.toLocalFile(),
mimeType,
flags),
exportConfiguration);
}
bool KisDocument::saveAs(const QUrl &url, const QByteArray &mimeType, bool showWarnings, KisPropertiesConfigurationSP exportConfiguration)
{
using namespace KritaUtils;
return exportDocumentImpl(ExportFileJob(url.toLocalFile(),
mimeType,
showWarnings ? SaveShowWarnings : SaveNone),
exportConfiguration);
}
bool KisDocument::save(bool showWarnings, KisPropertiesConfigurationSP exportConfiguration)
{
return saveAs(url(), mimeType(), showWarnings, exportConfiguration);
}
QByteArray KisDocument::serializeToNativeByteArray()
{
QByteArray byteArray;
QBuffer buffer(&byteArray);
QScopedPointer filter(KisImportExportManager::filterForMimeType(nativeFormatMimeType(), KisImportExportManager::Export));
filter->setBatchMode(true);
filter->setMimeType(nativeFormatMimeType());
Private::StrippedSafeSavingLocker locker(&d->savingMutex, d->image);
if (!locker.successfullyLocked()) {
return byteArray;
}
d->savingImage = d->image;
if (filter->convert(this, &buffer) != KisImportExportFilter::OK) {
qWarning() << "serializeToByteArray():: Could not export to our native format";
}
return byteArray;
}
void KisDocument::slotCompleteSavingDocument(const KritaUtils::ExportFileJob &job, KisImportExportFilter::ConversionStatus status, const QString &errorMessage)
{
if (status == KisImportExportFilter::UserCancelled)
return;
const QString fileName = QFileInfo(job.filePath).fileName();
if (status != KisImportExportFilter::OK) {
emit statusBarMessage(i18nc("%1 --- failing file name, %2 --- error message",
"Error during saving %1: %2",
fileName,
exportErrorToUserMessage(status, errorMessage)), errorMessageTimeout);
if (!fileBatchMode()) {
const QString filePath = job.filePath;
QMessageBox::critical(0, i18nc("@title:window", "Krita"), i18n("Could not save %1\nReason: %2", filePath, exportErrorToUserMessage(status, errorMessage)));
}
} else {
if (!(job.flags & KritaUtils::SaveIsExporting)) {
const QString existingAutoSaveBaseName = localFilePath();
const bool wasRecovered = isRecovered();
setUrl(QUrl::fromLocalFile(job.filePath));
setLocalFilePath(job.filePath);
setMimeType(job.mimeType);
updateEditingTime(true);
if (!d->modifiedWhileSaving) {
/**
* If undo stack is already clean/empty, it doesn't emit any
* signals, so we might forget update document modified state
* (which was set, e.g. while recovering an autosave file)
*/
if (d->undoStack->isClean()) {
setModified(false);
} else {
d->undoStack->setClean();
}
}
setRecovered(false);
removeAutoSaveFiles(existingAutoSaveBaseName, wasRecovered);
}
emit completed();
emit sigSavingFinished();
emit statusBarMessage(i18n("Finished saving %1", fileName), successMessageTimeout);
}
}
QByteArray KisDocument::mimeType() const
{
return d->mimeType;
}
void KisDocument::setMimeType(const QByteArray & mimeType)
{
d->mimeType = mimeType;
}
bool KisDocument::fileBatchMode() const
{
return d->batchMode;
}
void KisDocument::setFileBatchMode(const bool batchMode)
{
d->batchMode = batchMode;
}
KisDocument* KisDocument::lockAndCloneForSaving()
{
// force update of all the asynchronous nodes before cloning
QApplication::processEvents();
KisLayerUtils::forceAllDelayedNodesUpdate(d->image->root());
KisMainWindow *window = KisPart::instance()->currentMainwindow();
if (window) {
if (window->viewManager()) {
if (!window->viewManager()->blockUntilOperationsFinished(d->image)) {
return 0;
}
}
}
Private::StrippedSafeSavingLocker locker(&d->savingMutex, d->image);
if (!locker.successfullyLocked()) {
return 0;
}
return new KisDocument(*this);
}
bool KisDocument::exportDocumentSync(const QUrl &url, const QByteArray &mimeType, KisPropertiesConfigurationSP exportConfiguration)
{
Private::StrippedSafeSavingLocker locker(&d->savingMutex, d->image);
if (!locker.successfullyLocked()) {
return false;
}
d->savingImage = d->image;
const QString fileName = url.toLocalFile();
KisImportExportFilter::ConversionStatus status =
d->importExportManager->
exportDocument(fileName, fileName, mimeType, false, exportConfiguration);
d->savingImage = 0;
return status == KisImportExportFilter::OK;
}
bool KisDocument::initiateSavingInBackground(const QString actionName,
const QObject *receiverObject, const char *receiverMethod,
const KritaUtils::ExportFileJob &job,
KisPropertiesConfigurationSP exportConfiguration)
{
return initiateSavingInBackground(actionName, receiverObject, receiverMethod,
job, exportConfiguration, std::unique_ptr());
}
bool KisDocument::initiateSavingInBackground(const QString actionName,
const QObject *receiverObject, const char *receiverMethod,
const KritaUtils::ExportFileJob &job,
KisPropertiesConfigurationSP exportConfiguration,
std::unique_ptr &&optionalClonedDocument)
{
KIS_ASSERT_RECOVER_RETURN_VALUE(job.isValid(), false);
QScopedPointer clonedDocument;
if (!optionalClonedDocument) {
clonedDocument.reset(lockAndCloneForSaving());
} else {
clonedDocument.reset(optionalClonedDocument.release());
}
// we block saving until the current saving is finished!
if (!clonedDocument || !d->savingMutex.tryLock()) {
return false;
}
KIS_ASSERT_RECOVER_RETURN_VALUE(!d->backgroundSaveDocument, false);
KIS_ASSERT_RECOVER_RETURN_VALUE(!d->backgroundSaveJob.isValid(), false);
d->backgroundSaveDocument.reset(clonedDocument.take());
d->backgroundSaveJob = job;
d->modifiedWhileSaving = false;
if (d->backgroundSaveJob.flags & KritaUtils::SaveInAutosaveMode) {
d->backgroundSaveDocument->d->isAutosaving = true;
}
connect(d->backgroundSaveDocument.data(),
SIGNAL(sigBackgroundSavingFinished(KisImportExportFilter::ConversionStatus,QString)),
this,
SLOT(slotChildCompletedSavingInBackground(KisImportExportFilter::ConversionStatus,QString)));
connect(this, SIGNAL(sigCompleteBackgroundSaving(KritaUtils::ExportFileJob,KisImportExportFilter::ConversionStatus,QString)),
receiverObject, receiverMethod, Qt::UniqueConnection);
bool started =
d->backgroundSaveDocument->startExportInBackground(actionName,
job.filePath,
job.filePath,
job.mimeType,
job.flags & KritaUtils::SaveShowWarnings,
exportConfiguration);
if (!started) {
// the state should have been deinitialized in slotChildCompletedSavingInBackground()
KIS_SAFE_ASSERT_RECOVER (!d->backgroundSaveDocument && !d->backgroundSaveJob.isValid()) {
d->backgroundSaveDocument.take()->deleteLater();
d->savingMutex.unlock();
d->backgroundSaveJob = KritaUtils::ExportFileJob();
}
}
return started;
}
void KisDocument::slotChildCompletedSavingInBackground(KisImportExportFilter::ConversionStatus status, const QString &errorMessage)
{
KIS_SAFE_ASSERT_RECOVER(!d->savingMutex.tryLock()) {
d->savingMutex.unlock();
return;
}
KIS_SAFE_ASSERT_RECOVER_RETURN(d->backgroundSaveDocument);
if (d->backgroundSaveJob.flags & KritaUtils::SaveInAutosaveMode) {
d->backgroundSaveDocument->d->isAutosaving = false;
}
d->backgroundSaveDocument.take()->deleteLater();
d->savingMutex.unlock();
KIS_SAFE_ASSERT_RECOVER_RETURN(d->backgroundSaveJob.isValid());
const KritaUtils::ExportFileJob job = d->backgroundSaveJob;
d->backgroundSaveJob = KritaUtils::ExportFileJob();
emit sigCompleteBackgroundSaving(job, status, errorMessage);
}
void KisDocument::slotAutoSaveImpl(std::unique_ptr &&optionalClonedDocument)
{
if (!d->modified || !d->modifiedAfterAutosave) return;
const QString autoSaveFileName = generateAutoSaveFileName(localFilePath());
emit statusBarMessage(i18n("Autosaving... %1", autoSaveFileName), successMessageTimeout);
const bool hadClonedDocument = bool(optionalClonedDocument);
bool started = false;
if (d->image->isIdle() || hadClonedDocument) {
started = initiateSavingInBackground(i18n("Autosaving..."),
this, SLOT(slotCompleteAutoSaving(KritaUtils::ExportFileJob,KisImportExportFilter::ConversionStatus,QString)),
KritaUtils::ExportFileJob(autoSaveFileName, nativeFormatMimeType(), KritaUtils::SaveIsExporting | KritaUtils::SaveInAutosaveMode),
0,
std::move(optionalClonedDocument));
} else {
emit statusBarMessage(i18n("Autosaving postponed: document is busy..."), errorMessageTimeout);
}
if (!started && !hadClonedDocument && d->autoSaveFailureCount >= 3) {
KisCloneDocumentStroke *stroke = new KisCloneDocumentStroke(this);
connect(stroke, SIGNAL(sigDocumentCloned(KisDocument*)),
this, SLOT(slotInitiateAsyncAutosaving(KisDocument*)),
Qt::BlockingQueuedConnection);
KisStrokeId strokeId = d->image->startStroke(stroke);
d->image->endStroke(strokeId);
setInfiniteAutoSaveInterval();
} else if (!started) {
setEmergencyAutoSaveInterval();
} else {
d->modifiedAfterAutosave = false;
}
}
void KisDocument::slotAutoSave()
{
slotAutoSaveImpl(std::unique_ptr());
}
void KisDocument::slotInitiateAsyncAutosaving(KisDocument *clonedDocument)
{
slotAutoSaveImpl(std::unique_ptr(clonedDocument));
}
void KisDocument::slotCompleteAutoSaving(const KritaUtils::ExportFileJob &job, KisImportExportFilter::ConversionStatus status, const QString &errorMessage)
{
Q_UNUSED(job);
const QString fileName = QFileInfo(job.filePath).fileName();
if (status != KisImportExportFilter::OK) {
setEmergencyAutoSaveInterval();
emit statusBarMessage(i18nc("%1 --- failing file name, %2 --- error message",
"Error during autosaving %1: %2",
fileName,
exportErrorToUserMessage(status, errorMessage)), errorMessageTimeout);
} else {
KisConfig cfg(true);
d->autoSaveDelay = cfg.autoSaveInterval();
if (!d->modifiedWhileSaving) {
d->autoSaveTimer->stop(); // until the next change
d->autoSaveFailureCount = 0;
} else {
setNormalAutoSaveInterval();
}
emit statusBarMessage(i18n("Finished autosaving %1", fileName), successMessageTimeout);
}
}
bool KisDocument::startExportInBackground(const QString &actionName,
const QString &location,
const QString &realLocation,
const QByteArray &mimeType,
bool showWarnings,
KisPropertiesConfigurationSP exportConfiguration)
{
d->savingImage = d->image;
KisMainWindow *window = KisPart::instance()->currentMainwindow();
if (window) {
if (window->viewManager()) {
d->savingUpdater = window->viewManager()->createThreadedUpdater(actionName);
d->importExportManager->setUpdater(d->savingUpdater);
}
}
KisImportExportFilter::ConversionStatus initializationStatus;
d->childSavingFuture =
d->importExportManager->exportDocumentAsyc(location,
realLocation,
mimeType,
initializationStatus,
showWarnings,
exportConfiguration);
if (initializationStatus != KisImportExportFilter::ConversionStatus::OK) {
if (d->savingUpdater) {
d->savingUpdater->cancel();
}
d->savingImage.clear();
emit sigBackgroundSavingFinished(initializationStatus, this->errorMessage());
return false;
}
typedef QFutureWatcher StatusWatcher;
StatusWatcher *watcher = new StatusWatcher();
watcher->setFuture(d->childSavingFuture);
connect(watcher, SIGNAL(finished()), SLOT(finishExportInBackground()));
connect(watcher, SIGNAL(finished()), watcher, SLOT(deleteLater()));
return true;
}
void KisDocument::finishExportInBackground()
{
KIS_SAFE_ASSERT_RECOVER(d->childSavingFuture.isFinished()) {
emit sigBackgroundSavingFinished(KisImportExportFilter::InternalError, "");
return;
}
KisImportExportFilter::ConversionStatus status =
d->childSavingFuture.result();
const QString errorMessage = this->errorMessage();
d->savingImage.clear();
d->childSavingFuture = QFuture();
d->lastErrorMessage.clear();
if (d->savingUpdater) {
d->savingUpdater->setProgress(100);
}
emit sigBackgroundSavingFinished(status, errorMessage);
}
void KisDocument::setReadWrite(bool readwrite)
{
d->readwrite = readwrite;
setNormalAutoSaveInterval();
Q_FOREACH (KisMainWindow *mainWindow, KisPart::instance()->mainWindows()) {
mainWindow->setReadWrite(readwrite);
}
}
void KisDocument::setAutoSaveDelay(int delay)
{
if (isReadWrite() && delay > 0) {
d->autoSaveTimer->start(delay * 1000);
} else {
d->autoSaveTimer->stop();
}
}
void KisDocument::setNormalAutoSaveInterval()
{
setAutoSaveDelay(d->autoSaveDelay);
d->autoSaveFailureCount = 0;
}
void KisDocument::setEmergencyAutoSaveInterval()
{
const int emergencyAutoSaveInterval = 10; /* sec */
setAutoSaveDelay(emergencyAutoSaveInterval);
d->autoSaveFailureCount++;
}
void KisDocument::setInfiniteAutoSaveInterval()
{
setAutoSaveDelay(-1);
}
KoDocumentInfo *KisDocument::documentInfo() const
{
return d->docInfo;
}
bool KisDocument::isModified() const
{
return d->modified;
}
QPixmap KisDocument::generatePreview(const QSize& size)
{
KisImageSP image = d->image;
if (d->savingImage) image = d->savingImage;
if (image) {
QRect bounds = image->bounds();
QSize newSize = bounds.size();
newSize.scale(size, Qt::KeepAspectRatio);
QPixmap px = QPixmap::fromImage(image->convertToQImage(newSize, 0));
if (px.size() == QSize(0,0)) {
px = QPixmap(newSize);
QPainter gc(&px);
QBrush checkBrush = QBrush(KisCanvasWidgetBase::createCheckersImage(newSize.width() / 5));
gc.fillRect(px.rect(), checkBrush);
gc.end();
}
return px;
}
return QPixmap(size);
}
QString KisDocument::generateAutoSaveFileName(const QString & path) const
{
QString retval;
// Using the extension allows to avoid relying on the mime magic when opening
const QString extension (".kra");
QRegularExpression autosavePattern("^\\..+-autosave.kra$");
QFileInfo fi(path);
QString dir = fi.absolutePath();
QString filename = fi.fileName();
if (path.isEmpty() || autosavePattern.match(filename).hasMatch()) {
// Never saved?
#ifdef Q_OS_WIN
// On Windows, use the temp location (https://bugs.kde.org/show_bug.cgi?id=314921)
retval = QString("%1%2.%3-%4-%5-autosave%6").arg(QDir::tempPath()).arg(QDir::separator()).arg("krita").arg(qApp->applicationPid()).arg(objectName()).arg(extension);
#else
// On Linux, use a temp file in $HOME then. Mark it with the pid so two instances don't overwrite each other's autosave file
retval = QString("%1%2.%3-%4-%5-autosave%6").arg(QDir::homePath()).arg(QDir::separator()).arg("krita").arg(qApp->applicationPid()).arg(objectName()).arg(extension);
#endif
} else {
retval = QString("%1%2.%3-autosave%4").arg(dir).arg(QDir::separator()).arg(filename).arg(extension);
}
//qDebug() << "generateAutoSaveFileName() for path" << path << ":" << retval;
return retval;
}
bool KisDocument::importDocument(const QUrl &_url)
{
bool ret;
dbgUI << "url=" << _url.url();
// open...
ret = openUrl(_url);
// reset url & m_file (kindly? set by KisParts::openUrl()) to simulate a
// File --> Import
if (ret) {
dbgUI << "success, resetting url";
resetURL();
setTitleModified();
}
return ret;
}
bool KisDocument::openUrl(const QUrl &_url, OpenFlags flags)
{
if (!_url.isLocalFile()) {
return false;
}
dbgUI << "url=" << _url.url();
d->lastErrorMessage.clear();
// Reimplemented, to add a check for autosave files and to improve error reporting
if (!_url.isValid()) {
d->lastErrorMessage = i18n("Malformed URL\n%1", _url.url()); // ## used anywhere ?
return false;
}
QUrl url(_url);
bool autosaveOpened = false;
if (url.isLocalFile() && !fileBatchMode()) {
QString file = url.toLocalFile();
QString asf = generateAutoSaveFileName(file);
if (QFile::exists(asf)) {
KisApplication *kisApp = static_cast(qApp);
kisApp->hideSplashScreen();
//dbgUI <<"asf=" << asf;
// ## TODO compare timestamps ?
int res = QMessageBox::warning(0,
i18nc("@title:window", "Krita"),
i18n("An autosaved file exists for this document.\nDo you want to open the autosaved file instead?"),
QMessageBox::Yes | QMessageBox::No | QMessageBox::Cancel, QMessageBox::Yes);
switch (res) {
case QMessageBox::Yes :
url.setPath(asf);
autosaveOpened = true;
break;
case QMessageBox::No :
QFile::remove(asf);
break;
default: // Cancel
return false;
}
}
}
bool ret = openUrlInternal(url);
if (autosaveOpened || flags & RecoveryFile) {
setReadWrite(true); // enable save button
setModified(true);
setRecovered(true);
}
else {
if (!(flags & DontAddToRecent)) {
KisPart::instance()->addRecentURLToAllMainWindows(_url);
}
if (ret) {
// Detect readonly local-files; remote files are assumed to be writable
QFileInfo fi(url.toLocalFile());
setReadWrite(fi.isWritable());
}
setRecovered(false);
}
return ret;
}
class DlgLoadMessages : public KoDialog {
public:
DlgLoadMessages(const QString &title, const QString &message, const QStringList &warnings) {
setWindowTitle(title);
setWindowIcon(KisIconUtils::loadIcon("warning"));
QWidget *page = new QWidget(this);
QVBoxLayout *layout = new QVBoxLayout(page);
QHBoxLayout *hlayout = new QHBoxLayout();
QLabel *labelWarning= new QLabel();
labelWarning->setPixmap(KisIconUtils::loadIcon("warning").pixmap(32, 32));
hlayout->addWidget(labelWarning);
hlayout->addWidget(new QLabel(message));
layout->addLayout(hlayout);
QTextBrowser *browser = new QTextBrowser();
QString warning = "";
if (warnings.size() == 1) {
warning += " Reason:
";
}
else {
warning += " Reasons:
";
}
warning += "";
Q_FOREACH(const QString &w, warnings) {
warning += "\n- " + w + "
";
}
warning += "
";
browser->setHtml(warning);
browser->setMinimumHeight(200);
browser->setMinimumWidth(400);
layout->addWidget(browser);
setMainWidget(page);
setButtons(KoDialog::Ok);
resize(minimumSize());
}
};
bool KisDocument::openFile()
{
//dbgUI <<"for" << localFilePath();
if (!QFile::exists(localFilePath())) {
QMessageBox::critical(0, i18nc("@title:window", "Krita"), i18n("File %1 does not exist.", localFilePath()));
return false;
}
QString filename = localFilePath();
QString typeName = mimeType();
if (typeName.isEmpty()) {
typeName = KisMimeDatabase::mimeTypeForFile(filename);
}
//qDebug() << "mimetypes 4:" << typeName;
// Allow to open backup files, don't keep the mimetype application/x-trash.
if (typeName == "application/x-trash") {
QString path = filename;
while (path.length() > 0) {
path.chop(1);
typeName = KisMimeDatabase::mimeTypeForFile(path);
//qDebug() << "\t" << path << typeName;
if (!typeName.isEmpty()) {
break;
}
}
//qDebug() << "chopped" << filename << "to" << path << "Was trash, is" << typeName;
}
dbgUI << localFilePath() << "type:" << typeName;
KisMainWindow *window = KisPart::instance()->currentMainwindow();
if (window && window->viewManager()) {
KoUpdaterPtr updater = window->viewManager()->createUnthreadedUpdater(i18n("Opening document"));
d->importExportManager->setUpdater(updater);
}
KisImportExportFilter::ConversionStatus status;
status = d->importExportManager->importDocument(localFilePath(), typeName);
if (status != KisImportExportFilter::OK) {
QString msg = KisImportExportFilter::conversionStatusString(status);
if (!msg.isEmpty()) {
DlgLoadMessages dlg(i18nc("@title:window", "Krita"),
i18n("Could not open %2.\nReason: %1.", msg, prettyPathOrUrl()),
errorMessage().split("\n") + warningMessage().split("\n"));
dlg.exec();
}
return false;
}
else if (!warningMessage().isEmpty()) {
DlgLoadMessages dlg(i18nc("@title:window", "Krita"),
i18n("There were problems opening %1.", prettyPathOrUrl()),
warningMessage().split("\n"));
dlg.exec();
setUrl(QUrl());
}
setMimeTypeAfterLoading(typeName);
emit sigLoadingFinished();
undoStack()->clear();
return true;
}
// shared between openFile and koMainWindow's "create new empty document" code
void KisDocument::setMimeTypeAfterLoading(const QString& mimeType)
{
d->mimeType = mimeType.toLatin1();
d->outputMimeType = d->mimeType;
}
bool KisDocument::loadNativeFormat(const QString & file_)
{
return openUrl(QUrl::fromLocalFile(file_));
}
void KisDocument::setModified(bool mod)
{
if (mod) {
updateEditingTime(false);
}
if (d->isAutosaving) // ignore setModified calls due to autosaving
return;
if ( !d->readwrite && d->modified ) {
errKrita << "Can't set a read-only document to 'modified' !" << endl;
return;
}
//dbgUI<<" url:" << url.path();
//dbgUI<<" mod="<docInfo->aboutInfo("editing-time").toInt() + d->firstMod.secsTo(d->lastMod)));
d->firstMod = now;
} else if (firstModDelta > 60 || forceStoreElapsed) {
d->docInfo->setAboutInfo("editing-time", QString::number(d->docInfo->aboutInfo("editing-time").toInt() + firstModDelta));
d->firstMod = now;
}
d->lastMod = now;
}
QString KisDocument::prettyPathOrUrl() const
{
QString _url(url().toDisplayString());
#ifdef Q_OS_WIN
if (url().isLocalFile()) {
_url = QDir::toNativeSeparators(_url);
}
#endif
return _url;
}
// Get caption from document info (title(), in about page)
QString KisDocument::caption() const
{
QString c;
const QString _url(url().fileName());
// if URL is empty...it is probably an unsaved file
if (_url.isEmpty()) {
c = " [" + i18n("Not Saved") + "] ";
} else {
c = _url; // Fall back to document URL
}
return c;
}
void KisDocument::setTitleModified()
{
emit titleModified(caption(), isModified());
}
QDomDocument KisDocument::createDomDocument(const QString& tagName, const QString& version) const
{
return createDomDocument("krita", tagName, version);
}
//static
QDomDocument KisDocument::createDomDocument(const QString& appName, const QString& tagName, const QString& version)
{
QDomImplementation impl;
QString url = QString("http://www.calligra.org/DTD/%1-%2.dtd").arg(appName).arg(version);
QDomDocumentType dtype = impl.createDocumentType(tagName,
QString("-//KDE//DTD %1 %2//EN").arg(appName).arg(version),
url);
// The namespace URN doesn't need to include the version number.
QString namespaceURN = QString("http://www.calligra.org/DTD/%1").arg(appName);
QDomDocument doc = impl.createDocument(namespaceURN, tagName, dtype);
doc.insertBefore(doc.createProcessingInstruction("xml", "version=\"1.0\" encoding=\"UTF-8\""), doc.documentElement());
return doc;
}
bool KisDocument::isNativeFormat(const QByteArray& mimetype) const
{
if (mimetype == nativeFormatMimeType())
return true;
return extraNativeMimeTypes().contains(mimetype);
}
void KisDocument::setErrorMessage(const QString& errMsg)
{
d->lastErrorMessage = errMsg;
}
QString KisDocument::errorMessage() const
{
return d->lastErrorMessage;
}
void KisDocument::setWarningMessage(const QString& warningMsg)
{
d->lastWarningMessage = warningMsg;
}
QString KisDocument::warningMessage() const
{
return d->lastWarningMessage;
}
void KisDocument::removeAutoSaveFiles(const QString &autosaveBaseName, bool wasRecovered)
{
//qDebug() << "removeAutoSaveFiles";
// Eliminate any auto-save file
QString asf = generateAutoSaveFileName(autosaveBaseName); // the one in the current dir
//qDebug() << "\tfilename:" << asf << "exists:" << QFile::exists(asf);
if (QFile::exists(asf)) {
//qDebug() << "\tremoving autosavefile" << asf;
QFile::remove(asf);
}
asf = generateAutoSaveFileName(QString()); // and the one in $HOME
//qDebug() << "Autsavefile in $home" << asf;
if (QFile::exists(asf)) {
//qDebug() << "\tremoving autsavefile 2" << asf;
QFile::remove(asf);
}
QRegularExpression autosavePattern("^\\..+-autosave.kra$");
if (wasRecovered &&
!autosaveBaseName.isEmpty() &&
autosavePattern.match(QFileInfo(autosaveBaseName).fileName()).hasMatch() &&
QFile::exists(autosaveBaseName)) {
QFile::remove(autosaveBaseName);
}
}
KoUnit KisDocument::unit() const
{
return d->unit;
}
void KisDocument::setUnit(const KoUnit &unit)
{
if (d->unit != unit) {
d->unit = unit;
emit unitChanged(unit);
}
}
KUndo2Stack *KisDocument::undoStack()
{
return d->undoStack;
}
KisImportExportManager *KisDocument::importExportManager() const
{
return d->importExportManager;
}
void KisDocument::addCommand(KUndo2Command *command)
{
if (command)
d->undoStack->push(command);
}
void KisDocument::beginMacro(const KUndo2MagicString & text)
{
d->undoStack->beginMacro(text);
}
void KisDocument::endMacro()
{
d->undoStack->endMacro();
}
void KisDocument::slotUndoStackCleanChanged(bool value)
{
setModified(!value);
}
void KisDocument::slotConfigChanged()
{
KisConfig cfg(true);
d->undoStack->setUndoLimit(cfg.undoStackLimit());
d->autoSaveDelay = cfg.autoSaveInterval();
setNormalAutoSaveInterval();
}
void KisDocument::clearUndoHistory()
{
d->undoStack->clear();
}
KisGridConfig KisDocument::gridConfig() const
{
return d->gridConfig;
}
void KisDocument::setGridConfig(const KisGridConfig &config)
{
d->gridConfig = config;
}
QList &KisDocument::paletteList()
{
return d->paletteList;
}
void KisDocument::setPaletteList(const QList &paletteList)
{
d->paletteList = paletteList;
}
const KisGuidesConfig& KisDocument::guidesConfig() const
{
return d->guidesConfig;
}
void KisDocument::setGuidesConfig(const KisGuidesConfig &data)
{
if (d->guidesConfig == data) return;
d->guidesConfig = data;
emit sigGuidesConfigChanged(d->guidesConfig);
}
void KisDocument::resetURL() {
setUrl(QUrl());
setLocalFilePath(QString());
}
KoDocumentInfoDlg *KisDocument::createDocumentInfoDialog(QWidget *parent, KoDocumentInfo *docInfo) const
{
return new KoDocumentInfoDlg(parent, docInfo);
}
bool KisDocument::isReadWrite() const
{
return d->readwrite;
}
QUrl KisDocument::url() const
{
return d->m_url;
}
bool KisDocument::closeUrl(bool promptToSave)
{
if (promptToSave) {
if ( isReadWrite() && isModified()) {
Q_FOREACH (KisView *view, KisPart::instance()->views()) {
if (view && view->document() == this) {
if (!view->queryClose()) {
return false;
}
}
}
}
}
// Not modified => ok and delete temp file.
d->mimeType = QByteArray();
// It always succeeds for a read-only part,
// but the return value exists for reimplementations
// (e.g. pressing cancel for a modified read-write part)
return true;
}
void KisDocument::setUrl(const QUrl &url)
{
d->m_url = url;
}
QString KisDocument::localFilePath() const
{
return d->m_file;
}
void KisDocument::setLocalFilePath( const QString &localFilePath )
{
d->m_file = localFilePath;
}
bool KisDocument::openUrlInternal(const QUrl &url)
{
if ( !url.isValid() )
return false;
if (d->m_bAutoDetectedMime) {
d->mimeType = QByteArray();
d->m_bAutoDetectedMime = false;
}
QByteArray mimetype = d->mimeType;
if ( !closeUrl() )
return false;
d->mimeType = mimetype;
setUrl(url);
d->m_file.clear();
if (d->m_url.isLocalFile()) {
d->m_file = d->m_url.toLocalFile();
bool ret;
// set the mimetype only if it was not already set (for example, by the host application)
if (d->mimeType.isEmpty()) {
// get the mimetype of the file
// using findByUrl() to avoid another string -> url conversion
QString mime = KisMimeDatabase::mimeTypeForFile(d->m_url.toLocalFile());
d->mimeType = mime.toLocal8Bit();
d->m_bAutoDetectedMime = true;
}
setUrl(d->m_url);
ret = openFile();
if (ret) {
emit completed();
} else {
emit canceled(QString());
}
return ret;
}
return false;
}
bool KisDocument::newImage(const QString& name,
qint32 width, qint32 height,
const KoColorSpace* cs,
- const KoColor &bgColor, bool backgroundAsLayer,
+ const KoColor &bgColor, KisConfig::BackgroundStyle bgStyle,
int numberOfLayers,
const QString &description, const double imageResolution)
{
Q_ASSERT(cs);
KisImageSP image;
- KisPaintLayerSP layer;
if (!cs) return false;
QApplication::setOverrideCursor(Qt::BusyCursor);
image = new KisImage(createUndoStore(), width, height, cs, name);
Q_CHECK_PTR(image);
connect(image, SIGNAL(sigImageModified()), this, SLOT(setImageModified()), Qt::UniqueConnection);
image->setResolution(imageResolution, imageResolution);
image->assignImageProfile(cs->profile());
documentInfo()->setAboutInfo("title", name);
documentInfo()->setAboutInfo("abstract", description);
- layer = new KisPaintLayer(image.data(), image->nextLayerName(), OPACITY_OPAQUE_U8, cs);
- Q_CHECK_PTR(layer);
+ KisLayerSP layer;
+ if (bgStyle == KisConfig::RASTER_LAYER || bgStyle == KisConfig::FILL_LAYER) {
+ KoColor strippedAlpha = bgColor;
+ strippedAlpha.setOpacity(OPACITY_OPAQUE_U8);
+
+ if (bgStyle == KisConfig::RASTER_LAYER) {
+ layer = new KisPaintLayer(image.data(), "Background", OPACITY_OPAQUE_U8, cs);;
+ layer->paintDevice()->setDefaultPixel(strippedAlpha);
+ } else if (bgStyle == KisConfig::FILL_LAYER) {
+ KisFilterConfigurationSP filter_config = KisGeneratorRegistry::instance()->get("color")->defaultConfiguration();
+ filter_config->setProperty("color", strippedAlpha.toQColor());
+ layer = new KisGeneratorLayer(image.data(), "Background Fill", filter_config, image->globalSelection());
+ }
- if (backgroundAsLayer) {
- image->setDefaultProjectionColor(KoColor(cs));
+ layer->setOpacity(bgColor.opacityU8());
- if (bgColor.opacityU8() == OPACITY_OPAQUE_U8) {
- layer->paintDevice()->setDefaultPixel(bgColor);
- } else {
- // Hack: with a semi-transparent background color, the projection isn't composited right if we just set the default pixel
- KisFillPainter painter;
- painter.begin(layer->paintDevice());
- painter.fillRect(0, 0, width, height, bgColor, bgColor.opacityU8());
+ if (numberOfLayers > 1) {
+ //Lock bg layer if others are present.
+ layer->setUserLocked(true);
}
- } else {
+ }
+ else { // KisConfig::CANVAS_COLOR (needs an unlocked starting layer).
image->setDefaultProjectionColor(bgColor);
+ layer = new KisPaintLayer(image.data(), image->nextLayerName(), OPACITY_OPAQUE_U8, cs);
}
- layer->setDirty(QRect(0, 0, width, height));
+ Q_CHECK_PTR(layer);
image->addNode(layer.data(), image->rootLayer().data());
+ layer->setDirty(QRect(0, 0, width, height));
+
setCurrentImage(image);
for(int i = 1; i < numberOfLayers; ++i) {
KisPaintLayerSP layer = new KisPaintLayer(image, image->nextLayerName(), OPACITY_OPAQUE_U8, cs);
image->addNode(layer, image->root(), i);
layer->setDirty(QRect(0, 0, width, height));
}
KisConfig cfg(false);
cfg.defImageWidth(width);
cfg.defImageHeight(height);
cfg.defImageResolution(imageResolution);
cfg.defColorModel(image->colorSpace()->colorModelId().id());
cfg.setDefaultColorDepth(image->colorSpace()->colorDepthId().id());
cfg.defColorProfile(image->colorSpace()->profile()->name());
QApplication::restoreOverrideCursor();
return true;
}
bool KisDocument::isSaving() const
{
const bool result = d->savingMutex.tryLock();
if (result) {
d->savingMutex.unlock();
}
return !result;
}
void KisDocument::waitForSavingToComplete()
{
if (isSaving()) {
KisAsyncActionFeedback f(i18nc("progress dialog message when the user closes the document that is being saved", "Waiting for saving to complete..."), 0);
f.waitForMutex(&d->savingMutex);
}
}
KoShapeControllerBase *KisDocument::shapeController() const
{
return d->shapeController;
}
KoShapeLayer* KisDocument::shapeForNode(KisNodeSP layer) const
{
return d->shapeController->shapeForNode(layer);
}
QList KisDocument::assistants() const
{
return d->assistants;
}
void KisDocument::setAssistants(const QList &value)
{
d->assistants = value;
}
KisSharedPtr KisDocument::referenceImagesLayer() const
{
return d->referenceImagesLayer.data();
}
void KisDocument::setReferenceImagesLayer(KisSharedPtr layer, bool updateImage)
{
if (d->referenceImagesLayer) {
d->referenceImagesLayer->disconnect(this);
}
if (updateImage) {
if (layer) {
d->image->addNode(layer);
} else {
d->image->removeNode(d->referenceImagesLayer);
}
}
d->referenceImagesLayer = layer;
if (d->referenceImagesLayer) {
connect(d->referenceImagesLayer, SIGNAL(sigUpdateCanvas(QRectF)),
this, SIGNAL(sigReferenceImagesChanged()));
}
}
void KisDocument::setPreActivatedNode(KisNodeSP activatedNode)
{
d->preActivatedNode = activatedNode;
}
KisNodeSP KisDocument::preActivatedNode() const
{
return d->preActivatedNode;
}
KisImageWSP KisDocument::image() const
{
return d->image;
}
KisImageSP KisDocument::savingImage() const
{
return d->savingImage;
}
void KisDocument::setCurrentImage(KisImageSP image, bool forceInitialUpdate)
{
if (d->image) {
// Disconnect existing sig/slot connections
d->image->setUndoStore(new KisDumbUndoStore());
d->image->disconnect(this);
d->shapeController->setImage(0);
d->image = 0;
}
if (!image) return;
d->setImageAndInitIdleWatcher(image);
d->image->setUndoStore(new KisDocumentUndoStore(this));
d->shapeController->setImage(image);
setModified(false);
connect(d->image, SIGNAL(sigImageModified()), this, SLOT(setImageModified()), Qt::UniqueConnection);
if (forceInitialUpdate) {
d->image->initialRefreshGraph();
}
}
void KisDocument::hackPreliminarySetImage(KisImageSP image)
{
KIS_SAFE_ASSERT_RECOVER_RETURN(!d->image);
d->setImageAndInitIdleWatcher(image);
d->shapeController->setImage(image);
}
void KisDocument::setImageModified()
{
setModified(true);
}
KisUndoStore* KisDocument::createUndoStore()
{
return new KisDocumentUndoStore(this);
}
bool KisDocument::isAutosaving() const
{
return d->isAutosaving;
}
QString KisDocument::exportErrorToUserMessage(KisImportExportFilter::ConversionStatus status, const QString &errorMessage)
{
return errorMessage.isEmpty() ? KisImportExportFilter::conversionStatusString(status) : errorMessage;
}
void KisDocument::setAssistantsGlobalColor(QColor color)
{
d->globalAssistantsColor = color;
}
QColor KisDocument::assistantsGlobalColor()
{
return d->globalAssistantsColor;
}
QRectF KisDocument::documentBounds() const
{
QRectF bounds = d->image->bounds();
if (d->referenceImagesLayer) {
bounds |= d->referenceImagesLayer->boundingImageRect();
}
return bounds;
}
diff --git a/libs/ui/KisDocument.h b/libs/ui/KisDocument.h
index 11f80ba458..eebc152d32 100644
--- a/libs/ui/KisDocument.h
+++ b/libs/ui/KisDocument.h
@@ -1,655 +1,656 @@
/* This file is part of the Krita project
*
* Copyright (C) 2014 Boudewijn Rempt
*
* 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 KISDOCUMENT_H
#define KISDOCUMENT_H
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
+#include
#include "kritaui_export.h"
#include
class QString;
class KUndo2Command;
class KoUnit;
class KoColor;
class KoColorSpace;
class KoShapeControllerBase;
class KoShapeLayer;
class KoStore;
class KoOdfReadStore;
class KoDocumentInfo;
class KoDocumentInfoDlg;
class KisImportExportManager;
class KisUndoStore;
class KisPart;
class KisGridConfig;
class KisGuidesConfig;
class QDomDocument;
class KisReferenceImagesLayer;
#define KIS_MIME_TYPE "application/x-krita"
/**
* The %Calligra document class
*
* This class provides some functionality each %Calligra document should have.
*
* @short The %Calligra document class
*/
class KRITAUI_EXPORT KisDocument : public QObject, public KoDocumentBase
{
Q_OBJECT
protected:
explicit KisDocument();
/**
* @brief KisDocument makes a deep copy of the document \p rhs.
* The caller *must* ensure that the image is properly
* locked and is in consistent state before asking for
* cloning.
* @param rhs the source document to copy from
*/
explicit KisDocument(const KisDocument &rhs);
public:
enum OpenFlag {
None = 0,
DontAddToRecent = 0x1,
RecoveryFile = 0x2
};
Q_DECLARE_FLAGS(OpenFlags, OpenFlag)
/**
* Destructor.
*
* The destructor does not delete any attached KisView objects and it does not
* delete the attached widget as returned by widget().
*/
~KisDocument() override;
/**
* @brief reload Reloads the document from the original url
* @return the result of loading the document
*/
bool reload();
/**
* @brief creates a clone of the document and returns it. Please make sure that you
* hold all the necessary locks on the image before asking for a clone!
*/
KisDocument* clone();
/**
* @brief openUrl Open an URL
* @param url The URL to open
* @param flags Control specific behavior
* @return success status
*/
bool openUrl(const QUrl &url, OpenFlags flags = None);
/**
* Opens the document given by @p url, without storing the URL
* in the KisDocument.
* Call this instead of openUrl() to implement KisMainWindow's
* File --> Import feature.
*
* @note This will call openUrl(). To differentiate this from an ordinary
* Open operation (in any reimplementation of openUrl() or openFile())
* call isImporting().
*/
bool importDocument(const QUrl &url);
/**
* Saves the document as @p url without changing the state of the
* KisDocument (URL, modified flag etc.). Call this instead of
* KisParts::ReadWritePart::saveAs() to implement KisMainWindow's
* File --> Export feature.
*/
bool exportDocument(const QUrl &url, const QByteArray &mimeType, bool showWarnings = false, KisPropertiesConfigurationSP exportConfiguration = 0);
bool exportDocumentSync(const QUrl &url, const QByteArray &mimeType, KisPropertiesConfigurationSP exportConfiguration = 0);
private:
bool exportDocumentImpl(const KritaUtils::ExportFileJob &job, KisPropertiesConfigurationSP exportConfiguration);
public:
/**
* @brief Sets whether the document can be edited or is read only.
*
* This recursively applied to all child documents and
* KisView::updateReadWrite is called for every attached
* view.
*/
void setReadWrite(bool readwrite = true);
/**
* To be preferred when a document exists. It is fast when calling
* it multiple times since it caches the result that readNativeFormatMimeType()
* delivers.
* This comes from the X-KDE-NativeMimeType key in the .desktop file.
*/
static QByteArray nativeFormatMimeType() { return KIS_MIME_TYPE; }
/// Checks whether a given mimetype can be handled natively.
bool isNativeFormat(const QByteArray& mimetype) const;
/// Returns a list of the mimetypes considered "native", i.e. which can
/// be saved by KisDocument without a filter, in *addition* to the main one
static QStringList extraNativeMimeTypes() { return QStringList() << KIS_MIME_TYPE; }
/**
* Returns the actual mimetype of the document
*/
QByteArray mimeType() const override;
/**
* @brief Sets the mime type for the document.
*
* When choosing "save as" this is also the mime type
* selected by default.
*/
void setMimeType(const QByteArray & mimeType) override;
/**
* @return true if file operations should inhibit the option dialog
*/
bool fileBatchMode() const;
/**
* @param batchMode if true, do not show the option dialog for file operations.
*/
void setFileBatchMode(const bool batchMode);
/**
* Sets the error message to be shown to the user (use i18n()!)
* when loading or saving fails.
* If you asked the user about something and they chose "Cancel",
*/
void setErrorMessage(const QString& errMsg);
/**
* Return the last error message. Usually KisDocument takes care of
* showing it; this method is mostly provided for non-interactive use.
*/
QString errorMessage() const;
/**
* Sets the warning message to be shown to the user (use i18n()!)
* when loading or saving fails.
*/
void setWarningMessage(const QString& warningMsg);
/**
* Return the last warning message set by loading or saving. Warnings
* mean that the document could not be completely loaded, but the errors
* were not absolutely fatal.
*/
QString warningMessage() const;
/**
* @brief Generates a preview picture of the document
* @note The preview is used in the File Dialog and also to create the Thumbnail
*/
QPixmap generatePreview(const QSize& size);
/**
* Tells the document that its title has been modified, either because
* the modified status changes (this is done by setModified() ) or
* because the URL or the document-info's title changed.
*/
void setTitleModified();
/**
* @brief Sets the document to empty.
*
* Used after loading a template
* (which is not empty, but not the user's input).
*
* @see isEmpty()
*/
void setEmpty(bool empty = true);
/**
* Return a correctly created QDomDocument for this KisDocument,
* including processing instruction, complete DOCTYPE tag (with systemId and publicId), and root element.
* @param tagName the name of the tag for the root element
* @param version the DTD version (usually the application's version).
*/
QDomDocument createDomDocument(const QString& tagName, const QString& version) const;
/**
* Return a correctly created QDomDocument for an old (1.3-style) %Calligra document,
* including processing instruction, complete DOCTYPE tag (with systemId and publicId), and root element.
* This static method can be used e.g. by filters.
* @param appName the app's instance name, e.g. words, kspread, kpresenter etc.
* @param tagName the name of the tag for the root element, e.g. DOC for words/kpresenter.
* @param version the DTD version (usually the application's version).
*/
static QDomDocument createDomDocument(const QString& appName, const QString& tagName, const QString& version);
/**
* Loads a document in the native format from a given URL.
* Reimplement if your native format isn't XML.
*
* @param file the file to load - usually KReadOnlyPart::m_file or the result of a filter
*/
bool loadNativeFormat(const QString & file);
/**
* Set standard autosave interval that is set by a config file
*/
void setNormalAutoSaveInterval();
/**
* Set emergency interval that autosave uses when the image is busy,
* by default it is 10 sec
*/
void setEmergencyAutoSaveInterval();
/**
* Disable autosave
*/
void setInfiniteAutoSaveInterval();
/**
* @return the information concerning this document.
* @see KoDocumentInfo
*/
KoDocumentInfo *documentInfo() const;
/**
* Performs a cleanup of unneeded backup files
*/
void removeAutoSaveFiles(const QString &autosaveBaseName, bool wasRecovered);
/**
* Returns true if this document or any of its internal child documents are modified.
*/
bool isModified() const override;
/**
* @return caption of the document
*
* Caption is of the form "[title] - [url]",
* built out of the document info (title) and pretty-printed
* document URL.
* If the title is not present, only the URL it returned.
*/
QString caption() const;
/**
* Sets the document URL to empty URL
* KParts doesn't allow this, but %Calligra apps have e.g. templates
* After using loadNativeFormat on a template, one wants
* to set the url to QUrl()
*/
void resetURL();
/**
* @internal (public for KisMainWindow)
*/
void setMimeTypeAfterLoading(const QString& mimeType);
/**
* Returns the unit used to display all measures/distances.
*/
KoUnit unit() const;
/**
* Sets the unit used to display all measures/distances.
*/
void setUnit(const KoUnit &unit);
KisGridConfig gridConfig() const;
void setGridConfig(const KisGridConfig &config);
/// returns the guides data for this document.
const KisGuidesConfig& guidesConfig() const;
void setGuidesConfig(const KisGuidesConfig &data);
QList &paletteList();
void setPaletteList(const QList &paletteList);
void clearUndoHistory();
/**
* Sets the modified flag on the document. This means that it has
* to be saved or not before deleting it.
*/
void setModified(bool _mod);
void setRecovered(bool value);
bool isRecovered() const;
void updateEditingTime(bool forceStoreElapsed);
/**
* Returns the global undo stack
*/
KUndo2Stack *undoStack();
/**
* @brief importExportManager gives access to the internal import/export manager
* @return the document's import/export manager
*/
KisImportExportManager *importExportManager() const;
/**
* @brief serializeToNativeByteArray daves the document into a .kra file wtitten
* to a memory-based byte-array
* @return a byte array containing the .kra file
*/
QByteArray serializeToNativeByteArray();
/**
* @brief isInSaving shown if the document has any (background) saving process or not
* @return true if there is some saving in action
*/
bool isInSaving() const;
public Q_SLOTS:
/**
* Adds a command to the undo stack and executes it by calling the redo() function.
* @param command command to add to the undo stack
*/
void addCommand(KUndo2Command *command);
/**
* Begins recording of a macro command. At the end endMacro needs to be called.
* @param text command description
*/
void beginMacro(const KUndo2MagicString &text);
/**
* Ends the recording of a macro command.
*/
void endMacro();
Q_SIGNALS:
/**
* This signal is emitted when the unit is changed by setUnit().
* It is common to connect views to it, in order to change the displayed units
* (e.g. in the rulers)
*/
void unitChanged(const KoUnit &unit);
/**
* Emitted e.g. at the beginning of a save operation
* This is emitted by KisDocument and used by KisView to display a statusbar message
*/
void statusBarMessage(const QString& text, int timeout = 0);
/**
* Emitted e.g. at the end of a save operation
* This is emitted by KisDocument and used by KisView to clear the statusbar message
*/
void clearStatusBarMessage();
/**
* Emitted when the document is modified
*/
void modified(bool);
void titleModified(const QString &caption, bool isModified);
void sigLoadingFinished();
void sigSavingFinished();
void sigGuidesConfigChanged(const KisGuidesConfig &config);
void sigBackgroundSavingFinished(KisImportExportFilter::ConversionStatus status, const QString &errorMessage);
void sigCompleteBackgroundSaving(const KritaUtils::ExportFileJob &job, KisImportExportFilter::ConversionStatus status, const QString &errorMessage);
void sigReferenceImagesChanged();
private Q_SLOTS:
void finishExportInBackground();
void slotChildCompletedSavingInBackground(KisImportExportFilter::ConversionStatus status, const QString &errorMessage);
void slotCompleteAutoSaving(const KritaUtils::ExportFileJob &job, KisImportExportFilter::ConversionStatus status, const QString &errorMessage);
void slotCompleteSavingDocument(const KritaUtils::ExportFileJob &job, KisImportExportFilter::ConversionStatus status, const QString &errorMessage);
void slotInitiateAsyncAutosaving(KisDocument *clonedDocument);
private:
friend class KisPart;
friend class SafeSavingLocker;
bool initiateSavingInBackground(const QString actionName,
const QObject *receiverObject, const char *receiverMethod,
const KritaUtils::ExportFileJob &job,
KisPropertiesConfigurationSP exportConfiguration,
std::unique_ptr &&optionalClonedDocument);
bool initiateSavingInBackground(const QString actionName,
const QObject *receiverObject, const char *receiverMethod,
const KritaUtils::ExportFileJob &job,
KisPropertiesConfigurationSP exportConfiguration);
bool startExportInBackground(const QString &actionName, const QString &location,
const QString &realLocation,
const QByteArray &mimeType,
bool showWarnings,
KisPropertiesConfigurationSP exportConfiguration);
/**
* Activate/deactivate/configure the autosave feature.
* @param delay in seconds, 0 to disable
*/
void setAutoSaveDelay(int delay);
/**
* Generate a name for the document.
*/
QString newObjectName();
QString generateAutoSaveFileName(const QString & path) const;
/**
* Loads a document
*
* Applies a filter if necessary, and calls loadNativeFormat in any case
* You should not have to reimplement, except for very special cases.
*
* NOTE: this method also creates a new KisView instance!
*
* This method is called from the KReadOnlyPart::openUrl method.
*/
bool openFile();
public:
bool isAutosaving() const override;
public:
QString localFilePath() const override;
void setLocalFilePath( const QString &localFilePath );
KoDocumentInfoDlg* createDocumentInfoDialog(QWidget *parent, KoDocumentInfo *docInfo) const;
bool isReadWrite() const;
QUrl url() const override;
void setUrl(const QUrl &url) override;
bool closeUrl(bool promptToSave = true);
bool saveAs(const QUrl &url, const QByteArray &mimeType, bool showWarnings, KisPropertiesConfigurationSP exportConfigration = 0);
/**
* Create a new image that has this document as a parent and
* replace the current image with this image.
*/
- bool newImage(const QString& name, qint32 width, qint32 height, const KoColorSpace * cs, const KoColor &bgColor, bool backgroundAsLayer,
+ bool newImage(const QString& name, qint32 width, qint32 height, const KoColorSpace * cs, const KoColor &bgColor, KisConfig::BackgroundStyle bgStyle,
int numberOfLayers, const QString &imageDescription, const double imageResolution);
bool isSaving() const;
void waitForSavingToComplete();
KisImageWSP image() const;
/**
* @brief savingImage provides a detached, shallow copy of the original image that must be used when saving.
* Any strokes in progress will not be applied to this image, so the result might be missing some data. On
* the other hand, it won't block.
*
* @return a shallow copy of the original image, or 0 is saving is not in progress
*/
KisImageSP savingImage() const;
/**
* Set the current image to the specified image and turn undo on.
*/
void setCurrentImage(KisImageSP image, bool forceInitialUpdate = true);
/**
* Set the image of the document preliminary, before the document
* has completed loading. Some of the document items (shapes) may want
* to access image properties (bounds and resolution), so we should provide
* it to them even before the entire image is loaded.
*
* Right now, the only use by KoShapeRegistry::createShapeFromOdf(), remove
* after it is deprecated.
*/
void hackPreliminarySetImage(KisImageSP image);
KisUndoStore* createUndoStore();
/**
* The shape controller matches internal krita image layers with
* the flake shape hierarchy.
*/
KoShapeControllerBase * shapeController() const;
KoShapeLayer* shapeForNode(KisNodeSP layer) const;
/**
* Set the list of nodes that was marked as currently active. Used *only*
* for saving loading. Never use it for tools or processing.
*/
void setPreActivatedNode(KisNodeSP activatedNode);
/**
* @return the node that was set as active during loading. Used *only*
* for saving loading. Never use it for tools or processing.
*/
KisNodeSP preActivatedNode() const;
/// @return the list of assistants associated with this document
QList assistants() const;
/// @replace the current list of assistants with @param value
void setAssistants(const QList &value);
void setAssistantsGlobalColor(QColor color);
QColor assistantsGlobalColor();
/**
* Get existing reference images layer or null if none exists.
*/
KisSharedPtr referenceImagesLayer() const;
void setReferenceImagesLayer(KisSharedPtr layer, bool updateImage);
bool save(bool showWarnings, KisPropertiesConfigurationSP exportConfiguration);
/**
* Return the bounding box of the image and associated elements (e.g. reference images)
*/
QRectF documentBounds() const;
Q_SIGNALS:
void completed();
void canceled(const QString &);
private Q_SLOTS:
void setImageModified();
void slotAutoSave();
void slotUndoStackCleanChanged(bool value);
void slotConfigChanged();
private:
/**
* @brief try to clone the image. This method handles all the locking for you. If locking
* has failed, no cloning happens
* @return cloned document on success, null otherwise
*/
KisDocument *lockAndCloneForSaving();
QString exportErrorToUserMessage(KisImportExportFilter::ConversionStatus status, const QString &errorMessage);
QString prettyPathOrUrl() const;
bool openUrlInternal(const QUrl &url);
void slotAutoSaveImpl(std::unique_ptr &&optionalClonedDocument);
class Private;
Private *const d;
};
Q_DECLARE_OPERATORS_FOR_FLAGS(KisDocument::OpenFlags)
Q_DECLARE_METATYPE(KisDocument*)
#endif
diff --git a/libs/ui/forms/wdgnewimage.ui b/libs/ui/forms/wdgnewimage.ui
index 4aca85cf9b..8ae7a727e9 100644
--- a/libs/ui/forms/wdgnewimage.ui
+++ b/libs/ui/forms/wdgnewimage.ui
@@ -1,663 +1,685 @@
WdgNewImage
0
0
600
- 462
+ 491
0
0
600
0
16777215
16777215
New Image
-
0
0
- 0
+ 1
0
0
Dimensions
-
0
0
Color
-
-
-
0
140
16777215
16777215
Image Size
Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter
false
false
-
-
P&redefined:
Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
cmbPredefined
-
0
0
-
Save As:
-
0
0
-
Save the current dimensions
&Save
-
-
-
Landscape
...
true
true
true
-
2
1.000000000000000
100000000.000000000000000
-
&Height:
Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
doubleHeight
-
0
1.000000000000000
9999.000000000000000
-
Resolution:
-
1.000000000000000
100000000.000000000000000
-
-
-
pixels-per-inch
ppi
-
W&idth:
Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
doubleWidth
-
Portrait
...
true
true
true
true
-
-
Qt::Horizontal
QSizePolicy::Expanding
191
61
-
Clipboard
-
75
75
250
250
QFrame::StyledPanel
TextLabel
-
Qt::Vertical
20
40
0
0
Content
-
Layers:
Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
-
- Ima&ge Background Opacity:
+ Background Opacity:
Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
sliderOpacity
-
0
0
+
+ Number of layers that the image will start with, including optional background layer.
+
1
200
2
-
- Image Bac&kground Color:
+ Bac&kground Color:
Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
cmbColor
-
Background:
Qt::AlignRight|Qt::AlignTop|Qt::AlignTrailing
-
&Description:
Qt::AlignRight|Qt::AlignTop|Qt::AlignTrailing
txtDescription
-
0
0
16777215
100
-
-
-
+
+
+ Use background color and opacity to create a background raster layer.
+
- As fi&rst layer
+ As &raster layer
-
+
+ Use background color and opacity as the base canvas color. This can be reconfigured in `Image > Properties.`
+
As can&vas color
+ -
+
+
+ Use background color and opacity to create a background fill layer. The color for this layer can be reconfigured in the layer's properties.
+
+
+ As &fill layer
+
+
+
-
0
0
50
0
- Reset the image background color in the Image Properties dialog
+
-
QFrame::NoFrame
QFrame::Plain
0
0
0
0
-
-
Qt::Vertical
20
40
-
&Name:
Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
txtName
-
+
+
+
untitled-1
label_4
lblBackgroundStyle
txtDescription
lblDescription
intNumLayers
opacityPanel
lblColor
cmbColor
lblOpacity
lblName
txtName
-
Qt::Vertical
QSizePolicy::Expanding
10
10
-
This document...
true
-
QDialogButtonBox::Cancel|QDialogButtonBox::Ok
KisIntParseSpinBox
QSpinBox
KisColorButton
QPushButton
KisDoubleSliderSpinBox
QWidget
1
KisColorSpaceSelector
QWidget
widgets/kis_color_space_selector.h
1
KisDoubleParseSpinBox
QDoubleSpinBox
kis_double_parse_spin_box.h
tabWidget
cmbPredefined
txtPredefinedName
bnSaveAsPredefined
doubleWidth
doubleHeight
doubleResolution
cmbWidthUnit
cmbHeightUnit
bnLandscape
bnPortrait
intNumLayers
cmbColor
- radioBackgroundAsLayer
+ radioBackgroundAsRaster
radioBackgroundAsProjection
txtDescription
diff --git a/libs/ui/kis_config.cc b/libs/ui/kis_config.cc
index 0eba622a79..9551c4678e 100644
--- a/libs/ui/kis_config.cc
+++ b/libs/ui/kis_config.cc
@@ -1,2035 +1,2035 @@
/*
* Copyright (c) 2002 Patrick Julien
*
* 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 "kis_config.h"
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include "kis_canvas_resource_provider.h"
#include "kis_config_notifier.h"
#include "kis_snap_config.h"
#include
#include
KisConfig::KisConfig(bool readOnly)
: m_cfg( KSharedConfig::openConfig()->group(""))
, m_readOnly(readOnly)
{
if (!readOnly) {
KIS_SAFE_ASSERT_RECOVER_RETURN(qApp->thread() == QThread::currentThread());
}
}
KisConfig::~KisConfig()
{
if (m_readOnly) return;
if (qApp->thread() != QThread::currentThread()) {
dbgKrita << "WARNING: KisConfig: requested config synchronization from nonGUI thread! Called from:" << kisBacktrace();
return;
}
m_cfg.sync();
}
bool KisConfig::disableTouchOnCanvas(bool defaultValue) const
{
return (defaultValue ? false : m_cfg.readEntry("disableTouchOnCanvas", false));
}
void KisConfig::setDisableTouchOnCanvas(bool value) const
{
m_cfg.writeEntry("disableTouchOnCanvas", value);
}
bool KisConfig::useProjections(bool defaultValue) const
{
return (defaultValue ? true : m_cfg.readEntry("useProjections", true));
}
void KisConfig::setUseProjections(bool useProj) const
{
m_cfg.writeEntry("useProjections", useProj);
}
bool KisConfig::undoEnabled(bool defaultValue) const
{
return (defaultValue ? true : m_cfg.readEntry("undoEnabled", true));
}
void KisConfig::setUndoEnabled(bool undo) const
{
m_cfg.writeEntry("undoEnabled", undo);
}
int KisConfig::undoStackLimit(bool defaultValue) const
{
return (defaultValue ? 30 : m_cfg.readEntry("undoStackLimit", 30));
}
void KisConfig::setUndoStackLimit(int limit) const
{
m_cfg.writeEntry("undoStackLimit", limit);
}
bool KisConfig::useCumulativeUndoRedo(bool defaultValue) const
{
return (defaultValue ? false : m_cfg.readEntry("useCumulativeUndoRedo",false));
}
void KisConfig::setCumulativeUndoRedo(bool value)
{
m_cfg.writeEntry("useCumulativeUndoRedo", value);
}
qreal KisConfig::stackT1(bool defaultValue) const
{
return (defaultValue ? 5 : m_cfg.readEntry("stackT1",5));
}
void KisConfig::setStackT1(int T1)
{
m_cfg.writeEntry("stackT1", T1);
}
qreal KisConfig::stackT2(bool defaultValue) const
{
return (defaultValue ? 1 : m_cfg.readEntry("stackT2",1));
}
void KisConfig::setStackT2(int T2)
{
m_cfg.writeEntry("stackT2", T2);
}
int KisConfig::stackN(bool defaultValue) const
{
return (defaultValue ? 5 : m_cfg.readEntry("stackN",5));
}
void KisConfig::setStackN(int N)
{
m_cfg.writeEntry("stackN", N);
}
qint32 KisConfig::defImageWidth(bool defaultValue) const
{
return (defaultValue ? 1600 : m_cfg.readEntry("imageWidthDef", 1600));
}
qint32 KisConfig::defImageHeight(bool defaultValue) const
{
return (defaultValue ? 1200 : m_cfg.readEntry("imageHeightDef", 1200));
}
qreal KisConfig::defImageResolution(bool defaultValue) const
{
return (defaultValue ? 100.0 : m_cfg.readEntry("imageResolutionDef", 100.0)) / 72.0;
}
QString KisConfig::defColorModel(bool defaultValue) const
{
return (defaultValue ? KoColorSpaceRegistry::instance()->rgb8()->colorModelId().id()
: m_cfg.readEntry("colorModelDef", KoColorSpaceRegistry::instance()->rgb8()->colorModelId().id()));
}
void KisConfig::defColorModel(const QString & model) const
{
m_cfg.writeEntry("colorModelDef", model);
}
QString KisConfig::defaultColorDepth(bool defaultValue) const
{
return (defaultValue ? KoColorSpaceRegistry::instance()->rgb8()->colorDepthId().id()
: m_cfg.readEntry("colorDepthDef", KoColorSpaceRegistry::instance()->rgb8()->colorDepthId().id()));
}
void KisConfig::setDefaultColorDepth(const QString & depth) const
{
m_cfg.writeEntry("colorDepthDef", depth);
}
QString KisConfig::defColorProfile(bool defaultValue) const
{
return (defaultValue ? KoColorSpaceRegistry::instance()->rgb8()->profile()->name() :
m_cfg.readEntry("colorProfileDef",
KoColorSpaceRegistry::instance()->rgb8()->profile()->name()));
}
void KisConfig::defColorProfile(const QString & profile) const
{
m_cfg.writeEntry("colorProfileDef", profile);
}
void KisConfig::defImageWidth(qint32 width) const
{
m_cfg.writeEntry("imageWidthDef", width);
}
void KisConfig::defImageHeight(qint32 height) const
{
m_cfg.writeEntry("imageHeightDef", height);
}
void KisConfig::defImageResolution(qreal res) const
{
m_cfg.writeEntry("imageResolutionDef", res*72.0);
}
int KisConfig::preferredVectorImportResolutionPPI(bool defaultValue) const
{
return defaultValue ? 100.0 : m_cfg.readEntry("preferredVectorImportResolution", 100.0);
}
void KisConfig::setPreferredVectorImportResolutionPPI(int value) const
{
m_cfg.writeEntry("preferredVectorImportResolution", value);
}
void cleanOldCursorStyleKeys(KConfigGroup &cfg)
{
if (cfg.hasKey("newCursorStyle") &&
cfg.hasKey("newOutlineStyle")) {
cfg.deleteEntry("cursorStyleDef");
}
}
CursorStyle KisConfig::newCursorStyle(bool defaultValue) const
{
if (defaultValue) {
return CURSOR_STYLE_NO_CURSOR;
}
int style = m_cfg.readEntry("newCursorStyle", int(-1));
if (style < 0) {
// old style format
style = m_cfg.readEntry("cursorStyleDef", int(OLD_CURSOR_STYLE_OUTLINE));
switch (style) {
case OLD_CURSOR_STYLE_TOOLICON:
style = CURSOR_STYLE_TOOLICON;
break;
case OLD_CURSOR_STYLE_CROSSHAIR:
case OLD_CURSOR_STYLE_OUTLINE_CENTER_CROSS:
style = CURSOR_STYLE_CROSSHAIR;
break;
case OLD_CURSOR_STYLE_POINTER:
style = CURSOR_STYLE_POINTER;
break;
case OLD_CURSOR_STYLE_OUTLINE:
case OLD_CURSOR_STYLE_NO_CURSOR:
style = CURSOR_STYLE_NO_CURSOR;
break;
case OLD_CURSOR_STYLE_SMALL_ROUND:
case OLD_CURSOR_STYLE_OUTLINE_CENTER_DOT:
style = CURSOR_STYLE_SMALL_ROUND;
break;
case OLD_CURSOR_STYLE_TRIANGLE_RIGHTHANDED:
case OLD_CURSOR_STYLE_OUTLINE_TRIANGLE_RIGHTHANDED:
style = CURSOR_STYLE_TRIANGLE_RIGHTHANDED;
break;
case OLD_CURSOR_STYLE_TRIANGLE_LEFTHANDED:
case OLD_CURSOR_STYLE_OUTLINE_TRIANGLE_LEFTHANDED:
style = CURSOR_STYLE_TRIANGLE_LEFTHANDED;
break;
default:
style = -1;
}
}
cleanOldCursorStyleKeys(m_cfg);
// compatibility with future versions
if (style < 0 || style >= N_CURSOR_STYLE_SIZE) {
style = CURSOR_STYLE_NO_CURSOR;
}
return (CursorStyle) style;
}
void KisConfig::setNewCursorStyle(CursorStyle style)
{
m_cfg.writeEntry("newCursorStyle", (int)style);
}
QColor KisConfig::getCursorMainColor(bool defaultValue) const
{
QColor col;
col.setRgbF(0.501961, 1.0, 0.501961);
return (defaultValue ? col : m_cfg.readEntry("cursorMaincColor", col));
}
void KisConfig::setCursorMainColor(const QColor &v) const
{
m_cfg.writeEntry("cursorMaincColor", v);
}
OutlineStyle KisConfig::newOutlineStyle(bool defaultValue) const
{
if (defaultValue) {
return OUTLINE_FULL;
}
int style = m_cfg.readEntry("newOutlineStyle", int(-1));
if (style < 0) {
// old style format
style = m_cfg.readEntry("cursorStyleDef", int(OLD_CURSOR_STYLE_OUTLINE));
switch (style) {
case OLD_CURSOR_STYLE_TOOLICON:
case OLD_CURSOR_STYLE_CROSSHAIR:
case OLD_CURSOR_STYLE_POINTER:
case OLD_CURSOR_STYLE_NO_CURSOR:
case OLD_CURSOR_STYLE_SMALL_ROUND:
case OLD_CURSOR_STYLE_TRIANGLE_RIGHTHANDED:
case OLD_CURSOR_STYLE_TRIANGLE_LEFTHANDED:
style = OUTLINE_NONE;
break;
case OLD_CURSOR_STYLE_OUTLINE:
case OLD_CURSOR_STYLE_OUTLINE_CENTER_DOT:
case OLD_CURSOR_STYLE_OUTLINE_CENTER_CROSS:
case OLD_CURSOR_STYLE_OUTLINE_TRIANGLE_RIGHTHANDED:
case OLD_CURSOR_STYLE_OUTLINE_TRIANGLE_LEFTHANDED:
style = OUTLINE_FULL;
break;
default:
style = -1;
}
}
cleanOldCursorStyleKeys(m_cfg);
// compatibility with future versions
if (style < 0 || style >= N_OUTLINE_STYLE_SIZE) {
style = OUTLINE_FULL;
}
return (OutlineStyle) style;
}
void KisConfig::setNewOutlineStyle(OutlineStyle style)
{
m_cfg.writeEntry("newOutlineStyle", (int)style);
}
QRect KisConfig::colorPreviewRect() const
{
return m_cfg.readEntry("colorPreviewRect", QVariant(QRect(32, 32, 48, 48))).toRect();
}
void KisConfig::setColorPreviewRect(const QRect &rect)
{
m_cfg.writeEntry("colorPreviewRect", QVariant(rect));
}
bool KisConfig::useDirtyPresets(bool defaultValue) const
{
return (defaultValue ? false : m_cfg.readEntry("useDirtyPresets",false));
}
void KisConfig::setUseDirtyPresets(bool value)
{
m_cfg.writeEntry("useDirtyPresets",value);
KisConfigNotifier::instance()->notifyConfigChanged();
}
bool KisConfig::useEraserBrushSize(bool defaultValue) const
{
return (defaultValue ? false : m_cfg.readEntry("useEraserBrushSize",false));
}
void KisConfig::setUseEraserBrushSize(bool value)
{
m_cfg.writeEntry("useEraserBrushSize",value);
KisConfigNotifier::instance()->notifyConfigChanged();
}
bool KisConfig::useEraserBrushOpacity(bool defaultValue) const
{
return (defaultValue ? false : m_cfg.readEntry("useEraserBrushOpacity",false));
}
void KisConfig::setUseEraserBrushOpacity(bool value)
{
m_cfg.writeEntry("useEraserBrushOpacity",value);
KisConfigNotifier::instance()->notifyConfigChanged();
}
QColor KisConfig::getMDIBackgroundColor(bool defaultValue) const
{
QColor col(77, 77, 77);
return (defaultValue ? col : m_cfg.readEntry("mdiBackgroundColor", col));
}
void KisConfig::setMDIBackgroundColor(const QColor &v) const
{
m_cfg.writeEntry("mdiBackgroundColor", v);
}
QString KisConfig::getMDIBackgroundImage(bool defaultValue) const
{
return (defaultValue ? "" : m_cfg.readEntry("mdiBackgroundImage", ""));
}
void KisConfig::setMDIBackgroundImage(const QString &filename) const
{
m_cfg.writeEntry("mdiBackgroundImage", filename);
}
QString KisConfig::monitorProfile(int screen) const
{
// Note: keep this in sync with the default profile for the RGB colorspaces!
QString profile = m_cfg.readEntry("monitorProfile" + QString(screen == 0 ? "": QString("_%1").arg(screen)), "sRGB-elle-V2-srgbtrc.icc");
//dbgKrita << "KisConfig::monitorProfile()" << profile;
return profile;
}
QString KisConfig::monitorForScreen(int screen, const QString &defaultMonitor, bool defaultValue) const
{
return (defaultValue ? defaultMonitor
: m_cfg.readEntry(QString("monitor_for_screen_%1").arg(screen), defaultMonitor));
}
void KisConfig::setMonitorForScreen(int screen, const QString& monitor)
{
m_cfg.writeEntry(QString("monitor_for_screen_%1").arg(screen), monitor);
}
void KisConfig::setMonitorProfile(int screen, const QString & monitorProfile, bool override) const
{
m_cfg.writeEntry("monitorProfile/OverrideX11", override);
m_cfg.writeEntry("monitorProfile" + QString(screen == 0 ? "": QString("_%1").arg(screen)), monitorProfile);
}
const KoColorProfile *KisConfig::getScreenProfile(int screen)
{
if (screen < 0) return 0;
KisConfig cfg(true);
QString monitorId;
if (KisColorManager::instance()->devices().size() > screen) {
monitorId = cfg.monitorForScreen(screen, KisColorManager::instance()->devices()[screen]);
}
//dbgKrita << "getScreenProfile(). Screen" << screen << "monitor id" << monitorId;
if (monitorId.isEmpty()) {
return 0;
}
QByteArray bytes = KisColorManager::instance()->displayProfile(monitorId);
//dbgKrita << "\tgetScreenProfile()" << bytes.size();
if (bytes.length() > 0) {
const KoColorProfile *profile = KoColorSpaceRegistry::instance()->createColorProfile(RGBAColorModelID.id(), Integer8BitsColorDepthID.id(), bytes);
//dbgKrita << "\tKisConfig::getScreenProfile for screen" << screen << profile->name();
return profile;
}
else {
//dbgKrita << "\tCould not get a system monitor profile";
return 0;
}
}
const KoColorProfile *KisConfig::displayProfile(int screen) const
{
if (screen < 0) return 0;
// if the user plays with the settings, they can override the display profile, in which case
// we don't want the system setting.
bool override = useSystemMonitorProfile();
//dbgKrita << "KisConfig::displayProfile(). Override X11:" << override;
const KoColorProfile *profile = 0;
if (override) {
//dbgKrita << "\tGoing to get the screen profile";
profile = KisConfig::getScreenProfile(screen);
}
// if it fails. check the configuration
if (!profile || !profile->isSuitableForDisplay()) {
//dbgKrita << "\tGoing to get the monitor profile";
QString monitorProfileName = monitorProfile(screen);
//dbgKrita << "\t\tmonitorProfileName:" << monitorProfileName;
if (!monitorProfileName.isEmpty()) {
profile = KoColorSpaceRegistry::instance()->profileByName(monitorProfileName);
}
if (profile) {
//dbgKrita << "\t\tsuitable for display" << profile->isSuitableForDisplay();
}
else {
//dbgKrita << "\t\tstill no profile";
}
}
// if we still don't have a profile, or the profile isn't suitable for display,
// we need to get a last-resort profile. the built-in sRGB is a good choice then.
if (!profile || !profile->isSuitableForDisplay()) {
//dbgKrita << "\tnothing worked, going to get sRGB built-in";
profile = KoColorSpaceRegistry::instance()->profileByName("sRGB Built-in");
}
if (profile) {
//dbgKrita << "\tKisConfig::displayProfile for screen" << screen << "is" << profile->name();
}
else {
//dbgKrita << "\tCouldn't get a display profile at all";
}
return profile;
}
QString KisConfig::workingColorSpace(bool defaultValue) const
{
return (defaultValue ? "RGBA" : m_cfg.readEntry("workingColorSpace", "RGBA"));
}
void KisConfig::setWorkingColorSpace(const QString & workingColorSpace) const
{
m_cfg.writeEntry("workingColorSpace", workingColorSpace);
}
QString KisConfig::printerColorSpace(bool /*defaultValue*/) const
{
//TODO currently only rgb8 is supported
//return (defaultValue ? "RGBA" : m_cfg.readEntry("printerColorSpace", "RGBA"));
return QString("RGBA");
}
void KisConfig::setPrinterColorSpace(const QString & printerColorSpace) const
{
m_cfg.writeEntry("printerColorSpace", printerColorSpace);
}
QString KisConfig::printerProfile(bool defaultValue) const
{
return (defaultValue ? "" : m_cfg.readEntry("printerProfile", ""));
}
void KisConfig::setPrinterProfile(const QString & printerProfile) const
{
m_cfg.writeEntry("printerProfile", printerProfile);
}
bool KisConfig::useBlackPointCompensation(bool defaultValue) const
{
return (defaultValue ? true : m_cfg.readEntry("useBlackPointCompensation", true));
}
void KisConfig::setUseBlackPointCompensation(bool useBlackPointCompensation) const
{
m_cfg.writeEntry("useBlackPointCompensation", useBlackPointCompensation);
}
bool KisConfig::allowLCMSOptimization(bool defaultValue) const
{
return (defaultValue ? true : m_cfg.readEntry("allowLCMSOptimization", true));
}
void KisConfig::setAllowLCMSOptimization(bool allowLCMSOptimization)
{
m_cfg.writeEntry("allowLCMSOptimization", allowLCMSOptimization);
}
bool KisConfig::forcePaletteColors(bool defaultValue) const
{
return (defaultValue ? false : m_cfg.readEntry("colorsettings/forcepalettecolors", false));
}
void KisConfig::setForcePaletteColors(bool forcePaletteColors)
{
m_cfg.writeEntry("colorsettings/forcepalettecolors", forcePaletteColors);
}
bool KisConfig::showRulers(bool defaultValue) const
{
return (defaultValue ? false : m_cfg.readEntry("showrulers", false));
}
void KisConfig::setShowRulers(bool rulers) const
{
m_cfg.writeEntry("showrulers", rulers);
}
bool KisConfig::forceShowSaveMessages(bool defaultValue) const
{
return (defaultValue ? false : m_cfg.readEntry("forceShowSaveMessages", false));
}
void KisConfig::setForceShowSaveMessages(bool value) const
{
m_cfg.writeEntry("forceShowSaveMessages", value);
}
bool KisConfig::forceShowAutosaveMessages(bool defaultValue) const
{
return (defaultValue ? false : m_cfg.readEntry("forceShowAutosaveMessages", false));
}
void KisConfig::setForceShowAutosaveMessages(bool value) const
{
m_cfg.writeEntry("forceShowAutosaveMessages", value);
}
bool KisConfig::rulersTrackMouse(bool defaultValue) const
{
return (defaultValue ? true : m_cfg.readEntry("rulersTrackMouse", true));
}
void KisConfig::setRulersTrackMouse(bool value) const
{
m_cfg.writeEntry("rulersTrackMouse", value);
}
qint32 KisConfig::pasteBehaviour(bool defaultValue) const
{
return (defaultValue ? 2 : m_cfg.readEntry("pasteBehaviour", 2));
}
void KisConfig::setPasteBehaviour(qint32 renderIntent) const
{
m_cfg.writeEntry("pasteBehaviour", renderIntent);
}
qint32 KisConfig::monitorRenderIntent(bool defaultValue) const
{
qint32 intent = m_cfg.readEntry("renderIntent", INTENT_PERCEPTUAL);
if (intent > 3) intent = 3;
if (intent < 0) intent = 0;
return (defaultValue ? INTENT_PERCEPTUAL : intent);
}
void KisConfig::setRenderIntent(qint32 renderIntent) const
{
if (renderIntent > 3) renderIntent = 3;
if (renderIntent < 0) renderIntent = 0;
m_cfg.writeEntry("renderIntent", renderIntent);
}
bool KisConfig::useOpenGL(bool defaultValue) const
{
if (defaultValue) {
return true;
}
//dbgKrita << "use opengl" << m_cfg.readEntry("useOpenGL", true) << "success" << m_cfg.readEntry("canvasState", "OPENGL_SUCCESS");
QString cs = canvasState();
#ifdef Q_OS_WIN
return (m_cfg.readEntry("useOpenGLWindows", true) && (cs == "OPENGL_SUCCESS" || cs == "TRY_OPENGL"));
#else
return (m_cfg.readEntry("useOpenGL", true) && (cs == "OPENGL_SUCCESS" || cs == "TRY_OPENGL"));
#endif
}
void KisConfig::setUseOpenGL(bool useOpenGL) const
{
#ifdef Q_OS_WIN
m_cfg.writeEntry("useOpenGLWindows", useOpenGL);
#else
m_cfg.writeEntry("useOpenGL", useOpenGL);
#endif
}
int KisConfig::openGLFilteringMode(bool defaultValue) const
{
return (defaultValue ? 3 : m_cfg.readEntry("OpenGLFilterMode", 3));
}
void KisConfig::setOpenGLFilteringMode(int filteringMode)
{
m_cfg.writeEntry("OpenGLFilterMode", filteringMode);
}
bool KisConfig::useOpenGLTextureBuffer(bool defaultValue) const
{
return (defaultValue ? true : m_cfg.readEntry("useOpenGLTextureBuffer", true));
}
void KisConfig::setUseOpenGLTextureBuffer(bool useBuffer)
{
m_cfg.writeEntry("useOpenGLTextureBuffer", useBuffer);
}
int KisConfig::openGLTextureSize(bool defaultValue) const
{
return (defaultValue ? 256 : m_cfg.readEntry("textureSize", 256));
}
bool KisConfig::disableVSync(bool defaultValue) const
{
return (defaultValue ? true : m_cfg.readEntry("disableVSync", true));
}
void KisConfig::setDisableVSync(bool disableVSync)
{
m_cfg.writeEntry("disableVSync", disableVSync);
}
bool KisConfig::showAdvancedOpenGLSettings(bool defaultValue) const
{
return (defaultValue ? false : m_cfg.readEntry("showAdvancedOpenGLSettings", false));
}
bool KisConfig::forceOpenGLFenceWorkaround(bool defaultValue) const
{
return (defaultValue ? false : m_cfg.readEntry("forceOpenGLFenceWorkaround", false));
}
int KisConfig::numMipmapLevels(bool defaultValue) const
{
return (defaultValue ? 4 : m_cfg.readEntry("numMipmapLevels", 4));
}
int KisConfig::textureOverlapBorder() const
{
return 1 << qMax(0, numMipmapLevels());
}
quint32 KisConfig::getGridMainStyle(bool defaultValue) const
{
int v = m_cfg.readEntry("gridmainstyle", 0);
v = qBound(0, v, 2);
return (defaultValue ? 0 : v);
}
void KisConfig::setGridMainStyle(quint32 v) const
{
m_cfg.writeEntry("gridmainstyle", v);
}
quint32 KisConfig::getGridSubdivisionStyle(bool defaultValue) const
{
quint32 v = m_cfg.readEntry("gridsubdivisionstyle", 1);
if (v > 2) v = 2;
return (defaultValue ? 1 : v);
}
void KisConfig::setGridSubdivisionStyle(quint32 v) const
{
m_cfg.writeEntry("gridsubdivisionstyle", v);
}
QColor KisConfig::getGridMainColor(bool defaultValue) const
{
QColor col(99, 99, 99);
return (defaultValue ? col : m_cfg.readEntry("gridmaincolor", col));
}
void KisConfig::setGridMainColor(const QColor & v) const
{
m_cfg.writeEntry("gridmaincolor", v);
}
QColor KisConfig::getGridSubdivisionColor(bool defaultValue) const
{
QColor col(150, 150, 150);
return (defaultValue ? col : m_cfg.readEntry("gridsubdivisioncolor", col));
}
void KisConfig::setGridSubdivisionColor(const QColor & v) const
{
m_cfg.writeEntry("gridsubdivisioncolor", v);
}
QColor KisConfig::getPixelGridColor(bool defaultValue) const
{
QColor col(255, 255, 255);
return (defaultValue ? col : m_cfg.readEntry("pixelGridColor", col));
}
void KisConfig::setPixelGridColor(const QColor & v) const
{
m_cfg.writeEntry("pixelGridColor", v);
}
qreal KisConfig::getPixelGridDrawingThreshold(bool defaultValue) const
{
qreal border = 24.0f;
return (defaultValue ? border : m_cfg.readEntry("pixelGridDrawingThreshold", border));
}
void KisConfig::setPixelGridDrawingThreshold(qreal v) const
{
m_cfg.writeEntry("pixelGridDrawingThreshold", v);
}
bool KisConfig::pixelGridEnabled(bool defaultValue) const
{
bool enabled = true;
return (defaultValue ? enabled : m_cfg.readEntry("pixelGridEnabled", enabled));
}
void KisConfig::enablePixelGrid(bool v) const
{
m_cfg.writeEntry("pixelGridEnabled", v);
}
quint32 KisConfig::guidesLineStyle(bool defaultValue) const
{
int v = m_cfg.readEntry("guidesLineStyle", 0);
v = qBound(0, v, 2);
return (defaultValue ? 0 : v);
}
void KisConfig::setGuidesLineStyle(quint32 v) const
{
m_cfg.writeEntry("guidesLineStyle", v);
}
QColor KisConfig::guidesColor(bool defaultValue) const
{
QColor col(99, 99, 99);
return (defaultValue ? col : m_cfg.readEntry("guidesColor", col));
}
void KisConfig::setGuidesColor(const QColor & v) const
{
m_cfg.writeEntry("guidesColor", v);
}
void KisConfig::loadSnapConfig(KisSnapConfig *config, bool defaultValue) const
{
KisSnapConfig defaultConfig(false);
if (defaultValue) {
*config = defaultConfig;
return;
}
config->setOrthogonal(m_cfg.readEntry("globalSnapOrthogonal", defaultConfig.orthogonal()));
config->setNode(m_cfg.readEntry("globalSnapNode", defaultConfig.node()));
config->setExtension(m_cfg.readEntry("globalSnapExtension", defaultConfig.extension()));
config->setIntersection(m_cfg.readEntry("globalSnapIntersection", defaultConfig.intersection()));
config->setBoundingBox(m_cfg.readEntry("globalSnapBoundingBox", defaultConfig.boundingBox()));
config->setImageBounds(m_cfg.readEntry("globalSnapImageBounds", defaultConfig.imageBounds()));
config->setImageCenter(m_cfg.readEntry("globalSnapImageCenter", defaultConfig.imageCenter()));
}
void KisConfig::saveSnapConfig(const KisSnapConfig &config)
{
m_cfg.writeEntry("globalSnapOrthogonal", config.orthogonal());
m_cfg.writeEntry("globalSnapNode", config.node());
m_cfg.writeEntry("globalSnapExtension", config.extension());
m_cfg.writeEntry("globalSnapIntersection", config.intersection());
m_cfg.writeEntry("globalSnapBoundingBox", config.boundingBox());
m_cfg.writeEntry("globalSnapImageBounds", config.imageBounds());
m_cfg.writeEntry("globalSnapImageCenter", config.imageCenter());
}
qint32 KisConfig::checkSize(bool defaultValue) const
{
return (defaultValue ? 32 : m_cfg.readEntry("checksize", 32));
}
void KisConfig::setCheckSize(qint32 checksize) const
{
m_cfg.writeEntry("checksize", checksize);
}
bool KisConfig::scrollCheckers(bool defaultValue) const
{
return (defaultValue ? false : m_cfg.readEntry("scrollingcheckers", false));
}
void KisConfig::setScrollingCheckers(bool sc) const
{
m_cfg.writeEntry("scrollingcheckers", sc);
}
QColor KisConfig::canvasBorderColor(bool defaultValue) const
{
QColor color(QColor(128,128,128));
return (defaultValue ? color : m_cfg.readEntry("canvasBorderColor", color));
}
void KisConfig::setCanvasBorderColor(const QColor& color) const
{
m_cfg.writeEntry("canvasBorderColor", color);
}
bool KisConfig::hideScrollbars(bool defaultValue) const
{
return (defaultValue ? false : m_cfg.readEntry("hideScrollbars", false));
}
void KisConfig::setHideScrollbars(bool value) const
{
m_cfg.writeEntry("hideScrollbars", value);
}
QColor KisConfig::checkersColor1(bool defaultValue) const
{
QColor col(220, 220, 220);
return (defaultValue ? col : m_cfg.readEntry("checkerscolor", col));
}
void KisConfig::setCheckersColor1(const QColor & v) const
{
m_cfg.writeEntry("checkerscolor", v);
}
QColor KisConfig::checkersColor2(bool defaultValue) const
{
return (defaultValue ? QColor(Qt::white) : m_cfg.readEntry("checkerscolor2", QColor(Qt::white)));
}
void KisConfig::setCheckersColor2(const QColor & v) const
{
m_cfg.writeEntry("checkerscolor2", v);
}
bool KisConfig::antialiasCurves(bool defaultValue) const
{
return (defaultValue ? true : m_cfg.readEntry("antialiascurves", true));
}
void KisConfig::setAntialiasCurves(bool v) const
{
m_cfg.writeEntry("antialiascurves", v);
}
bool KisConfig::antialiasSelectionOutline(bool defaultValue) const
{
return (defaultValue ? false : m_cfg.readEntry("AntialiasSelectionOutline", false));
}
void KisConfig::setAntialiasSelectionOutline(bool v) const
{
m_cfg.writeEntry("AntialiasSelectionOutline", v);
}
bool KisConfig::showRootLayer(bool defaultValue) const
{
return (defaultValue ? false : m_cfg.readEntry("ShowRootLayer", false));
}
void KisConfig::setShowRootLayer(bool showRootLayer) const
{
m_cfg.writeEntry("ShowRootLayer", showRootLayer);
}
bool KisConfig::showGlobalSelection(bool defaultValue) const
{
return (defaultValue ? false : m_cfg.readEntry("ShowGlobalSelection", false));
}
void KisConfig::setShowGlobalSelection(bool showGlobalSelection) const
{
m_cfg.writeEntry("ShowGlobalSelection", showGlobalSelection);
}
bool KisConfig::showOutlineWhilePainting(bool defaultValue) const
{
return (defaultValue ? true : m_cfg.readEntry("ShowOutlineWhilePainting", true));
}
void KisConfig::setShowOutlineWhilePainting(bool showOutlineWhilePainting) const
{
m_cfg.writeEntry("ShowOutlineWhilePainting", showOutlineWhilePainting);
}
bool KisConfig::forceAlwaysFullSizedOutline(bool defaultValue) const
{
return (defaultValue ? false : m_cfg.readEntry("forceAlwaysFullSizedOutline", false));
}
void KisConfig::setForceAlwaysFullSizedOutline(bool value) const
{
m_cfg.writeEntry("forceAlwaysFullSizedOutline", value);
}
KisConfig::SessionOnStartup KisConfig::sessionOnStartup(bool defaultValue) const
{
int value = defaultValue ? SOS_BlankSession : m_cfg.readEntry("sessionOnStartup", (int)SOS_BlankSession);
return (KisConfig::SessionOnStartup)value;
}
void KisConfig::setSessionOnStartup(SessionOnStartup value)
{
m_cfg.writeEntry("sessionOnStartup", (int)value);
}
bool KisConfig::saveSessionOnQuit(bool defaultValue) const
{
return defaultValue ? false : m_cfg.readEntry("saveSessionOnQuit", false);
}
void KisConfig::setSaveSessionOnQuit(bool value)
{
m_cfg.writeEntry("saveSessionOnQuit", value);
}
qreal KisConfig::outlineSizeMinimum(bool defaultValue) const
{
return (defaultValue ? 1.0 : m_cfg.readEntry("OutlineSizeMinimum", 1.0));
}
void KisConfig::setOutlineSizeMinimum(qreal outlineSizeMinimum) const
{
m_cfg.writeEntry("OutlineSizeMinimum", outlineSizeMinimum);
}
qreal KisConfig::selectionViewSizeMinimum(bool defaultValue) const
{
return (defaultValue ? 5.0 : m_cfg.readEntry("SelectionViewSizeMinimum", 5.0));
}
void KisConfig::setSelectionViewSizeMinimum(qreal outlineSizeMinimum) const
{
m_cfg.writeEntry("SelectionViewSizeMinimum", outlineSizeMinimum);
}
int KisConfig::autoSaveInterval(bool defaultValue) const
{
return (defaultValue ? 15 * 60 : m_cfg.readEntry("AutoSaveInterval", 15 * 60));
}
void KisConfig::setAutoSaveInterval(int seconds) const
{
return m_cfg.writeEntry("AutoSaveInterval", seconds);
}
bool KisConfig::backupFile(bool defaultValue) const
{
return (defaultValue ? true : m_cfg.readEntry("CreateBackupFile", true));
}
void KisConfig::setBackupFile(bool backupFile) const
{
m_cfg.writeEntry("CreateBackupFile", backupFile);
}
bool KisConfig::showFilterGallery(bool defaultValue) const
{
return (defaultValue ? false : m_cfg.readEntry("showFilterGallery", false));
}
void KisConfig::setShowFilterGallery(bool showFilterGallery) const
{
m_cfg.writeEntry("showFilterGallery", showFilterGallery);
}
bool KisConfig::showFilterGalleryLayerMaskDialog(bool defaultValue) const
{
return (defaultValue ? true : m_cfg.readEntry("showFilterGalleryLayerMaskDialog", true));
}
void KisConfig::setShowFilterGalleryLayerMaskDialog(bool showFilterGallery) const
{
m_cfg.writeEntry("setShowFilterGalleryLayerMaskDialog", showFilterGallery);
}
QString KisConfig::canvasState(bool defaultValue) const
{
const QString configPath = QStandardPaths::writableLocation(QStandardPaths::GenericConfigLocation);
QSettings kritarc(configPath + QStringLiteral("/kritadisplayrc"), QSettings::IniFormat);
return (defaultValue ? "OPENGL_NOT_TRIED" : kritarc.value("canvasState", "OPENGL_NOT_TRIED").toString());
}
void KisConfig::setCanvasState(const QString& state) const
{
static QStringList acceptableStates;
if (acceptableStates.isEmpty()) {
acceptableStates << "OPENGL_SUCCESS" << "TRY_OPENGL" << "OPENGL_NOT_TRIED" << "OPENGL_FAILED";
}
if (acceptableStates.contains(state)) {
const QString configPath = QStandardPaths::writableLocation(QStandardPaths::GenericConfigLocation);
QSettings kritarc(configPath + QStringLiteral("/kritadisplayrc"), QSettings::IniFormat);
kritarc.setValue("canvasState", state);
}
}
bool KisConfig::toolOptionsPopupDetached(bool defaultValue) const
{
return (defaultValue ? false : m_cfg.readEntry("ToolOptionsPopupDetached", false));
}
void KisConfig::setToolOptionsPopupDetached(bool detached) const
{
m_cfg.writeEntry("ToolOptionsPopupDetached", detached);
}
bool KisConfig::paintopPopupDetached(bool defaultValue) const
{
return (defaultValue ? false : m_cfg.readEntry("PaintopPopupDetached", false));
}
void KisConfig::setPaintopPopupDetached(bool detached) const
{
m_cfg.writeEntry("PaintopPopupDetached", detached);
}
QString KisConfig::pressureTabletCurve(bool defaultValue) const
{
return (defaultValue ? "0,0;1,1" : m_cfg.readEntry("tabletPressureCurve","0,0;1,1;"));
}
void KisConfig::setPressureTabletCurve(const QString& curveString) const
{
m_cfg.writeEntry("tabletPressureCurve", curveString);
}
bool KisConfig::useWin8PointerInput(bool defaultValue) const
{
#ifdef Q_OS_WIN
return (defaultValue ? false : m_cfg.readEntry("useWin8PointerInput", false));
#else
Q_UNUSED(defaultValue);
return false;
#endif
}
void KisConfig::setUseWin8PointerInput(bool value) const
{
#ifdef Q_OS_WIN
// Special handling: Only set value if changed
// I don't want it to be set if the user hasn't touched it
if (useWin8PointerInput() != value) {
m_cfg.writeEntry("useWin8PointerInput", value);
}
#else
Q_UNUSED(value)
#endif
}
qreal KisConfig::vastScrolling(bool defaultValue) const
{
return (defaultValue ? 0.9 : m_cfg.readEntry("vastScrolling", 0.9));
}
void KisConfig::setVastScrolling(const qreal factor) const
{
m_cfg.writeEntry("vastScrolling", factor);
}
int KisConfig::presetChooserViewMode(bool defaultValue) const
{
return (defaultValue ? 0 : m_cfg.readEntry("presetChooserViewMode", 0));
}
void KisConfig::setPresetChooserViewMode(const int mode) const
{
m_cfg.writeEntry("presetChooserViewMode", mode);
}
int KisConfig::presetIconSize(bool defaultValue) const
{
return (defaultValue ? 60 : m_cfg.readEntry("presetIconSize", 60));
}
void KisConfig::setPresetIconSize(const int value) const
{
m_cfg.writeEntry("presetIconSize", value);
}
bool KisConfig::firstRun(bool defaultValue) const
{
return (defaultValue ? true : m_cfg.readEntry("firstRun", true));
}
void KisConfig::setFirstRun(const bool first) const
{
m_cfg.writeEntry("firstRun", first);
}
int KisConfig::horizontalSplitLines(bool defaultValue) const
{
return (defaultValue ? 1 : m_cfg.readEntry("horizontalSplitLines", 1));
}
void KisConfig::setHorizontalSplitLines(const int numberLines) const
{
m_cfg.writeEntry("horizontalSplitLines", numberLines);
}
int KisConfig::verticalSplitLines(bool defaultValue) const
{
return (defaultValue ? 1 : m_cfg.readEntry("verticalSplitLines", 1));
}
void KisConfig::setVerticalSplitLines(const int numberLines) const
{
m_cfg.writeEntry("verticalSplitLines", numberLines);
}
bool KisConfig::clicklessSpacePan(bool defaultValue) const
{
return (defaultValue ? true : m_cfg.readEntry("clicklessSpacePan", true));
}
void KisConfig::setClicklessSpacePan(const bool toggle) const
{
m_cfg.writeEntry("clicklessSpacePan", toggle);
}
bool KisConfig::hideDockersFullscreen(bool defaultValue) const
{
return (defaultValue ? true : m_cfg.readEntry("hideDockersFullScreen", true));
}
void KisConfig::setHideDockersFullscreen(const bool value) const
{
m_cfg.writeEntry("hideDockersFullScreen", value);
}
bool KisConfig::showDockers(bool defaultValue) const
{
return (defaultValue ? true : m_cfg.readEntry("showDockers", true));
}
void KisConfig::setShowDockers(const bool value) const
{
m_cfg.writeEntry("showDockers", value);
}
bool KisConfig::showStatusBar(bool defaultValue) const
{
return (defaultValue ? true : m_cfg.readEntry("showStatusBar", true));
}
void KisConfig::setShowStatusBar(const bool value) const
{
m_cfg.writeEntry("showStatusBar", value);
}
bool KisConfig::hideMenuFullscreen(bool defaultValue) const
{
return (defaultValue ? true: m_cfg.readEntry("hideMenuFullScreen", true));
}
void KisConfig::setHideMenuFullscreen(const bool value) const
{
m_cfg.writeEntry("hideMenuFullScreen", value);
}
bool KisConfig::hideScrollbarsFullscreen(bool defaultValue) const
{
return (defaultValue ? true : m_cfg.readEntry("hideScrollbarsFullScreen", true));
}
void KisConfig::setHideScrollbarsFullscreen(const bool value) const
{
m_cfg.writeEntry("hideScrollbarsFullScreen", value);
}
bool KisConfig::hideStatusbarFullscreen(bool defaultValue) const
{
return (defaultValue ? true: m_cfg.readEntry("hideStatusbarFullScreen", true));
}
void KisConfig::setHideStatusbarFullscreen(const bool value) const
{
m_cfg.writeEntry("hideStatusbarFullScreen", value);
}
bool KisConfig::hideTitlebarFullscreen(bool defaultValue) const
{
return (defaultValue ? true : m_cfg.readEntry("hideTitleBarFullscreen", true));
}
void KisConfig::setHideTitlebarFullscreen(const bool value) const
{
m_cfg.writeEntry("hideTitleBarFullscreen", value);
}
bool KisConfig::hideToolbarFullscreen(bool defaultValue) const
{
return (defaultValue ? true : m_cfg.readEntry("hideToolbarFullscreen", true));
}
void KisConfig::setHideToolbarFullscreen(const bool value) const
{
m_cfg.writeEntry("hideToolbarFullscreen", value);
}
bool KisConfig::fullscreenMode(bool defaultValue) const
{
return (defaultValue ? true : m_cfg.readEntry("fullscreenMode", true));
}
void KisConfig::setFullscreenMode(const bool value) const
{
m_cfg.writeEntry("fullscreenMode", value);
}
QStringList KisConfig::favoriteCompositeOps(bool defaultValue) const
{
return (defaultValue ? QStringList() : m_cfg.readEntry("favoriteCompositeOps", QStringList()));
}
void KisConfig::setFavoriteCompositeOps(const QStringList& compositeOps) const
{
m_cfg.writeEntry("favoriteCompositeOps", compositeOps);
}
QString KisConfig::exportConfiguration(const QString &filterId, bool defaultValue) const
{
return (defaultValue ? QString() : m_cfg.readEntry("ExportConfiguration-" + filterId, QString()));
}
void KisConfig::setExportConfiguration(const QString &filterId, KisPropertiesConfigurationSP properties) const
{
QString exportConfig = properties->toXML();
m_cfg.writeEntry("ExportConfiguration-" + filterId, exportConfig);
}
QString KisConfig::importConfiguration(const QString &filterId, bool defaultValue) const
{
return (defaultValue ? QString() : m_cfg.readEntry("ImportConfiguration-" + filterId, QString()));
}
void KisConfig::setImportConfiguration(const QString &filterId, KisPropertiesConfigurationSP properties) const
{
QString importConfig = properties->toXML();
m_cfg.writeEntry("ImportConfiguration-" + filterId, importConfig);
}
bool KisConfig::useOcio(bool defaultValue) const
{
#ifdef HAVE_OCIO
return (defaultValue ? false : m_cfg.readEntry("Krita/Ocio/UseOcio", false));
#else
Q_UNUSED(defaultValue);
return false;
#endif
}
void KisConfig::setUseOcio(bool useOCIO) const
{
m_cfg.writeEntry("Krita/Ocio/UseOcio", useOCIO);
}
int KisConfig::favoritePresets(bool defaultValue) const
{
return (defaultValue ? 10 : m_cfg.readEntry("numFavoritePresets", 10));
}
void KisConfig::setFavoritePresets(const int value)
{
m_cfg.writeEntry("numFavoritePresets", value);
}
bool KisConfig::levelOfDetailEnabled(bool defaultValue) const
{
return (defaultValue ? false : m_cfg.readEntry("levelOfDetailEnabled", false));
}
void KisConfig::setLevelOfDetailEnabled(bool value)
{
m_cfg.writeEntry("levelOfDetailEnabled", value);
}
KisConfig::OcioColorManagementMode
KisConfig::ocioColorManagementMode(bool defaultValue) const
{
return (OcioColorManagementMode)(defaultValue ? INTERNAL
: m_cfg.readEntry("Krita/Ocio/OcioColorManagementMode", (int) INTERNAL));
}
void KisConfig::setOcioColorManagementMode(OcioColorManagementMode mode) const
{
m_cfg.writeEntry("Krita/Ocio/OcioColorManagementMode", (int) mode);
}
QString KisConfig::ocioConfigurationPath(bool defaultValue) const
{
return (defaultValue ? QString() : m_cfg.readEntry("Krita/Ocio/OcioConfigPath", QString()));
}
void KisConfig::setOcioConfigurationPath(const QString &path) const
{
m_cfg.writeEntry("Krita/Ocio/OcioConfigPath", path);
}
QString KisConfig::ocioLutPath(bool defaultValue) const
{
return (defaultValue ? QString() : m_cfg.readEntry("Krita/Ocio/OcioLutPath", QString()));
}
void KisConfig::setOcioLutPath(const QString &path) const
{
m_cfg.writeEntry("Krita/Ocio/OcioLutPath", path);
}
int KisConfig::ocioLutEdgeSize(bool defaultValue) const
{
return (defaultValue ? 64 : m_cfg.readEntry("Krita/Ocio/LutEdgeSize", 64));
}
void KisConfig::setOcioLutEdgeSize(int value)
{
m_cfg.writeEntry("Krita/Ocio/LutEdgeSize", value);
}
bool KisConfig::ocioLockColorVisualRepresentation(bool defaultValue) const
{
return (defaultValue ? false : m_cfg.readEntry("Krita/Ocio/OcioLockColorVisualRepresentation", false));
}
void KisConfig::setOcioLockColorVisualRepresentation(bool value)
{
m_cfg.writeEntry("Krita/Ocio/OcioLockColorVisualRepresentation", value);
}
QString KisConfig::defaultPalette(bool defaultValue) const
{
return (defaultValue ? QString() : m_cfg.readEntry("defaultPalette", "Default"));
}
void KisConfig::setDefaultPalette(const QString& name) const
{
m_cfg.writeEntry("defaultPalette", name);
}
QString KisConfig::toolbarSlider(int sliderNumber, bool defaultValue) const
{
QString def = "flow";
if (sliderNumber == 1) {
def = "opacity";
}
if (sliderNumber == 2) {
def = "size";
}
return (defaultValue ? def : m_cfg.readEntry(QString("toolbarslider_%1").arg(sliderNumber), def));
}
void KisConfig::setToolbarSlider(int sliderNumber, const QString &slider)
{
m_cfg.writeEntry(QString("toolbarslider_%1").arg(sliderNumber), slider);
}
int KisConfig::layerThumbnailSize(bool defaultValue) const
{
return (defaultValue ? 20 : m_cfg.readEntry("layerThumbnailSize", 20));
}
void KisConfig::setLayerThumbnailSize(int size)
{
m_cfg.writeEntry("layerThumbnailSize", size);
}
bool KisConfig::sliderLabels(bool defaultValue) const
{
return (defaultValue ? true : m_cfg.readEntry("sliderLabels", true));
}
void KisConfig::setSliderLabels(bool enabled)
{
m_cfg.writeEntry("sliderLabels", enabled);
}
QString KisConfig::currentInputProfile(bool defaultValue) const
{
return (defaultValue ? QString() : m_cfg.readEntry("currentInputProfile", QString()));
}
void KisConfig::setCurrentInputProfile(const QString& name)
{
m_cfg.writeEntry("currentInputProfile", name);
}
bool KisConfig::useSystemMonitorProfile(bool defaultValue) const
{
return (defaultValue ? false : m_cfg.readEntry("ColorManagement/UseSystemMonitorProfile", false));
}
void KisConfig::setUseSystemMonitorProfile(bool _useSystemMonitorProfile) const
{
m_cfg.writeEntry("ColorManagement/UseSystemMonitorProfile", _useSystemMonitorProfile);
}
bool KisConfig::presetStripVisible(bool defaultValue) const
{
return (defaultValue ? true : m_cfg.readEntry("presetStripVisible", true));
}
void KisConfig::setPresetStripVisible(bool visible)
{
m_cfg.writeEntry("presetStripVisible", visible);
}
bool KisConfig::scratchpadVisible(bool defaultValue) const
{
return (defaultValue ? true : m_cfg.readEntry("scratchpadVisible", true));
}
void KisConfig::setScratchpadVisible(bool visible)
{
m_cfg.writeEntry("scratchpadVisible", visible);
}
bool KisConfig::showSingleChannelAsColor(bool defaultValue) const
{
return (defaultValue ? false : m_cfg.readEntry("showSingleChannelAsColor", false));
}
void KisConfig::setShowSingleChannelAsColor(bool asColor)
{
m_cfg.writeEntry("showSingleChannelAsColor", asColor);
}
bool KisConfig::hidePopups(bool defaultValue) const
{
return (defaultValue ? false : m_cfg.readEntry("hidePopups", false));
}
void KisConfig::setHidePopups(bool hidepopups)
{
m_cfg.writeEntry("hidePopups", hidepopups);
}
int KisConfig::numDefaultLayers(bool defaultValue) const
{
return (defaultValue ? 2 : m_cfg.readEntry("NumberOfLayersForNewImage", 2));
}
void KisConfig::setNumDefaultLayers(int num)
{
m_cfg.writeEntry("NumberOfLayersForNewImage", num);
}
quint8 KisConfig::defaultBackgroundOpacity(bool defaultValue) const
{
return (defaultValue ? (int)OPACITY_OPAQUE_U8 : m_cfg.readEntry("BackgroundOpacityForNewImage", (int)OPACITY_OPAQUE_U8));
}
void KisConfig::setDefaultBackgroundOpacity(quint8 value)
{
m_cfg.writeEntry("BackgroundOpacityForNewImage", (int)value);
}
QColor KisConfig::defaultBackgroundColor(bool defaultValue) const
{
return (defaultValue ? QColor(Qt::white) : m_cfg.readEntry("BackgroundColorForNewImage", QColor(Qt::white)));
}
void KisConfig::setDefaultBackgroundColor(QColor value)
{
m_cfg.writeEntry("BackgroundColorForNewImage", value);
}
KisConfig::BackgroundStyle KisConfig::defaultBackgroundStyle(bool defaultValue) const
{
- return (KisConfig::BackgroundStyle)(defaultValue ? LAYER : m_cfg.readEntry("BackgroundStyleForNewImage", (int)LAYER));
+ return (KisConfig::BackgroundStyle)(defaultValue ? RASTER_LAYER : m_cfg.readEntry("BackgroundStyleForNewImage", (int)RASTER_LAYER));
}
void KisConfig::setDefaultBackgroundStyle(KisConfig::BackgroundStyle value)
{
m_cfg.writeEntry("BackgroundStyleForNewImage", (int)value);
}
int KisConfig::lineSmoothingType(bool defaultValue) const
{
return (defaultValue ? 1 : m_cfg.readEntry("LineSmoothingType", 1));
}
void KisConfig::setLineSmoothingType(int value)
{
m_cfg.writeEntry("LineSmoothingType", value);
}
qreal KisConfig::lineSmoothingDistance(bool defaultValue) const
{
return (defaultValue ? 50.0 : m_cfg.readEntry("LineSmoothingDistance", 50.0));
}
void KisConfig::setLineSmoothingDistance(qreal value)
{
m_cfg.writeEntry("LineSmoothingDistance", value);
}
qreal KisConfig::lineSmoothingTailAggressiveness(bool defaultValue) const
{
return (defaultValue ? 0.15 : m_cfg.readEntry("LineSmoothingTailAggressiveness", 0.15));
}
void KisConfig::setLineSmoothingTailAggressiveness(qreal value)
{
m_cfg.writeEntry("LineSmoothingTailAggressiveness", value);
}
bool KisConfig::lineSmoothingSmoothPressure(bool defaultValue) const
{
return (defaultValue ? false : m_cfg.readEntry("LineSmoothingSmoothPressure", false));
}
void KisConfig::setLineSmoothingSmoothPressure(bool value)
{
m_cfg.writeEntry("LineSmoothingSmoothPressure", value);
}
bool KisConfig::lineSmoothingScalableDistance(bool defaultValue) const
{
return (defaultValue ? true : m_cfg.readEntry("LineSmoothingScalableDistance", true));
}
void KisConfig::setLineSmoothingScalableDistance(bool value)
{
m_cfg.writeEntry("LineSmoothingScalableDistance", value);
}
qreal KisConfig::lineSmoothingDelayDistance(bool defaultValue) const
{
return (defaultValue ? 50.0 : m_cfg.readEntry("LineSmoothingDelayDistance", 50.0));
}
void KisConfig::setLineSmoothingDelayDistance(qreal value)
{
m_cfg.writeEntry("LineSmoothingDelayDistance", value);
}
bool KisConfig::lineSmoothingUseDelayDistance(bool defaultValue) const
{
return (defaultValue ? true : m_cfg.readEntry("LineSmoothingUseDelayDistance", true));
}
void KisConfig::setLineSmoothingUseDelayDistance(bool value)
{
m_cfg.writeEntry("LineSmoothingUseDelayDistance", value);
}
bool KisConfig::lineSmoothingFinishStabilizedCurve(bool defaultValue) const
{
return (defaultValue ? true : m_cfg.readEntry("LineSmoothingFinishStabilizedCurve", true));
}
void KisConfig::setLineSmoothingFinishStabilizedCurve(bool value)
{
m_cfg.writeEntry("LineSmoothingFinishStabilizedCurve", value);
}
bool KisConfig::lineSmoothingStabilizeSensors(bool defaultValue) const
{
return (defaultValue ? true : m_cfg.readEntry("LineSmoothingStabilizeSensors", true));
}
void KisConfig::setLineSmoothingStabilizeSensors(bool value)
{
m_cfg.writeEntry("LineSmoothingStabilizeSensors", value);
}
int KisConfig::tabletEventsDelay(bool defaultValue) const
{
return (defaultValue ? 10 : m_cfg.readEntry("tabletEventsDelay", 10));
}
void KisConfig::setTabletEventsDelay(int value)
{
m_cfg.writeEntry("tabletEventsDelay", value);
}
bool KisConfig::trackTabletEventLatency(bool defaultValue) const
{
return (defaultValue ? false : m_cfg.readEntry("trackTabletEventLatency", false));
}
void KisConfig::setTrackTabletEventLatency(bool value)
{
m_cfg.writeEntry("trackTabletEventLatency", value);
}
bool KisConfig::testingAcceptCompressedTabletEvents(bool defaultValue) const
{
return (defaultValue ? false : m_cfg.readEntry("testingAcceptCompressedTabletEvents", false));
}
void KisConfig::setTestingAcceptCompressedTabletEvents(bool value)
{
m_cfg.writeEntry("testingAcceptCompressedTabletEvents", value);
}
bool KisConfig::shouldEatDriverShortcuts(bool defaultValue) const
{
return (defaultValue ? false : m_cfg.readEntry("shouldEatDriverShortcuts", false));
}
bool KisConfig::testingCompressBrushEvents(bool defaultValue) const
{
return (defaultValue ? false : m_cfg.readEntry("testingCompressBrushEvents", false));
}
void KisConfig::setTestingCompressBrushEvents(bool value)
{
m_cfg.writeEntry("testingCompressBrushEvents", value);
}
int KisConfig::workaroundX11SmoothPressureSteps(bool defaultValue) const
{
return (defaultValue ? 0 : m_cfg.readEntry("workaroundX11SmoothPressureSteps", 0));
}
bool KisConfig::showCanvasMessages(bool defaultValue) const
{
return (defaultValue ? true : m_cfg.readEntry("showOnCanvasMessages", true));
}
void KisConfig::setShowCanvasMessages(bool show)
{
m_cfg.writeEntry("showOnCanvasMessages", show);
}
bool KisConfig::compressKra(bool defaultValue) const
{
return (defaultValue ? false : m_cfg.readEntry("compressLayersInKra", false));
}
void KisConfig::setCompressKra(bool compress)
{
m_cfg.writeEntry("compressLayersInKra", compress);
}
bool KisConfig::toolOptionsInDocker(bool defaultValue) const
{
return (defaultValue ? true : m_cfg.readEntry("ToolOptionsInDocker", true));
}
void KisConfig::setToolOptionsInDocker(bool inDocker)
{
m_cfg.writeEntry("ToolOptionsInDocker", inDocker);
}
bool KisConfig::kineticScrollingEnabled(bool defaultValue) const
{
return (defaultValue ? true : m_cfg.readEntry("KineticScrollingEnabled", true));
}
void KisConfig::setKineticScrollingEnabled(bool value)
{
m_cfg.writeEntry("KineticScrollingEnabled", value);
}
int KisConfig::kineticScrollingGesture(bool defaultValue) const
{
return (defaultValue ? 2 : m_cfg.readEntry("KineticScrollingGesture", 2));
}
void KisConfig::setKineticScrollingGesture(int gesture)
{
m_cfg.writeEntry("KineticScrollingGesture", gesture);
}
int KisConfig::kineticScrollingSensitivity(bool defaultValue) const
{
return (defaultValue ? 75 : m_cfg.readEntry("KineticScrollingSensitivity", 75));
}
void KisConfig::setKineticScrollingSensitivity(int sensitivity)
{
m_cfg.writeEntry("KineticScrollingSensitivity", sensitivity);
}
bool KisConfig::kineticScrollingHiddenScrollbars(bool defaultValue) const
{
return (defaultValue ? false : m_cfg.readEntry("KineticScrollingHideScrollbar", false));
}
void KisConfig::setKineticScrollingHideScrollbars(bool scrollbar)
{
m_cfg.writeEntry("KineticScrollingHideScrollbar", scrollbar);
}
const KoColorSpace* KisConfig::customColorSelectorColorSpace(bool defaultValue) const
{
const KoColorSpace *cs = 0;
KConfigGroup cfg = KSharedConfig::openConfig()->group("advancedColorSelector");
if (defaultValue || cfg.readEntry("useCustomColorSpace", true)) {
KoColorSpaceRegistry* csr = KoColorSpaceRegistry::instance();
QString modelID = cfg.readEntry("customColorSpaceModel", "RGBA");
QString depthID = cfg.readEntry("customColorSpaceDepthID", "U8");
QString profile = cfg.readEntry("customColorSpaceProfile", "sRGB built-in - (lcms internal)");
if (profile == "default") {
// qDebug() << "Falling back to default color profile.";
profile = "sRGB built-in - (lcms internal)";
}
cs = csr->colorSpace(modelID, depthID, profile);
}
return cs;
}
void KisConfig::setCustomColorSelectorColorSpace(const KoColorSpace *cs)
{
KConfigGroup cfg = KSharedConfig::openConfig()->group("advancedColorSelector");
cfg.writeEntry("useCustomColorSpace", bool(cs));
if(cs) {
cfg.writeEntry("customColorSpaceModel", cs->colorModelId().id());
cfg.writeEntry("customColorSpaceDepthID", cs->colorDepthId().id());
cfg.writeEntry("customColorSpaceProfile", cs->profile()->name());
}
KisConfigNotifier::instance()->notifyConfigChanged();
}
bool KisConfig::enableOpenGLFramerateLogging(bool defaultValue) const
{
return (defaultValue ? false : m_cfg.readEntry("enableOpenGLFramerateLogging", false));
}
void KisConfig::setEnableOpenGLFramerateLogging(bool value) const
{
m_cfg.writeEntry("enableOpenGLFramerateLogging", value);
}
bool KisConfig::enableBrushSpeedLogging(bool defaultValue) const
{
return (defaultValue ? false : m_cfg.readEntry("enableBrushSpeedLogging", false));
}
void KisConfig::setEnableBrushSpeedLogging(bool value) const
{
m_cfg.writeEntry("enableBrushSpeedLogging", value);
}
void KisConfig::setEnableAmdVectorizationWorkaround(bool value)
{
m_cfg.writeEntry("amdDisableVectorWorkaround", value);
}
bool KisConfig::enableAmdVectorizationWorkaround(bool defaultValue) const
{
return (defaultValue ? false : m_cfg.readEntry("amdDisableVectorWorkaround", false));
}
void KisConfig::setAnimationDropFrames(bool value)
{
bool oldValue = animationDropFrames();
if (value == oldValue) return;
m_cfg.writeEntry("animationDropFrames", value);
KisConfigNotifier::instance()->notifyDropFramesModeChanged();
}
bool KisConfig::animationDropFrames(bool defaultValue) const
{
return (defaultValue ? true : m_cfg.readEntry("animationDropFrames", true));
}
int KisConfig::scrubbingUpdatesDelay(bool defaultValue) const
{
return (defaultValue ? 30 : m_cfg.readEntry("scrubbingUpdatesDelay", 30));
}
void KisConfig::setScrubbingUpdatesDelay(int value)
{
m_cfg.writeEntry("scrubbingUpdatesDelay", value);
}
int KisConfig::scrubbingAudioUpdatesDelay(bool defaultValue) const
{
return (defaultValue ? -1 : m_cfg.readEntry("scrubbingAudioUpdatesDelay", -1));
}
void KisConfig::setScrubbingAudioUpdatesDelay(int value)
{
m_cfg.writeEntry("scrubbingAudioUpdatesDelay", value);
}
int KisConfig::audioOffsetTolerance(bool defaultValue) const
{
return (defaultValue ? -1 : m_cfg.readEntry("audioOffsetTolerance", -1));
}
void KisConfig::setAudioOffsetTolerance(int value)
{
m_cfg.writeEntry("audioOffsetTolerance", value);
}
bool KisConfig::switchSelectionCtrlAlt(bool defaultValue) const
{
return defaultValue ? false : m_cfg.readEntry("switchSelectionCtrlAlt", false);
}
void KisConfig::setSwitchSelectionCtrlAlt(bool value)
{
m_cfg.writeEntry("switchSelectionCtrlAlt", value);
KisConfigNotifier::instance()->notifyConfigChanged();
}
bool KisConfig::convertToImageColorspaceOnImport(bool defaultValue) const
{
return defaultValue ? false : m_cfg.readEntry("ConvertToImageColorSpaceOnImport", false);
}
void KisConfig::setConvertToImageColorspaceOnImport(bool value)
{
m_cfg.writeEntry("ConvertToImageColorSpaceOnImport", value);
}
int KisConfig::stabilizerSampleSize(bool defaultValue) const
{
#ifdef Q_OS_WIN
const int defaultSampleSize = 50;
#else
const int defaultSampleSize = 15;
#endif
return defaultValue ?
defaultSampleSize : m_cfg.readEntry("stabilizerSampleSize", defaultSampleSize);
}
void KisConfig::setStabilizerSampleSize(int value)
{
m_cfg.writeEntry("stabilizerSampleSize", value);
}
bool KisConfig::stabilizerDelayedPaint(bool defaultValue) const
{
const bool defaultEnabled = true;
return defaultValue ?
defaultEnabled : m_cfg.readEntry("stabilizerDelayedPaint", defaultEnabled);
}
void KisConfig::setStabilizerDelayedPaint(bool value)
{
m_cfg.writeEntry("stabilizerDelayedPaint", value);
}
QString KisConfig::customFFMpegPath(bool defaultValue) const
{
return defaultValue ? QString() : m_cfg.readEntry("ffmpegExecutablePath", QString());
}
void KisConfig::setCustomFFMpegPath(const QString &value) const
{
m_cfg.writeEntry("ffmpegExecutablePath", value);
}
bool KisConfig::showBrushHud(bool defaultValue) const
{
return defaultValue ? false : m_cfg.readEntry("showBrushHud", false);
}
void KisConfig::setShowBrushHud(bool value)
{
m_cfg.writeEntry("showBrushHud", value);
}
QString KisConfig::brushHudSetting(bool defaultValue) const
{
QString defaultDoc = "\n\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n\n";
return defaultValue ? defaultDoc : m_cfg.readEntry("brushHudSettings", defaultDoc);
}
void KisConfig::setBrushHudSetting(const QString &value) const
{
m_cfg.writeEntry("brushHudSettings", value);
}
bool KisConfig::calculateAnimationCacheInBackground(bool defaultValue) const
{
return defaultValue ? true : m_cfg.readEntry("calculateAnimationCacheInBackground", true);
}
void KisConfig::setCalculateAnimationCacheInBackground(bool value)
{
m_cfg.writeEntry("calculateAnimationCacheInBackground", value);
}
QColor KisConfig::defaultAssistantsColor(bool defaultValue) const
{
static const QColor defaultColor = QColor(176, 176, 176, 255);
return defaultValue ? defaultColor : m_cfg.readEntry("defaultAssistantsColor", defaultColor);
}
void KisConfig::setDefaultAssistantsColor(const QColor &color) const
{
m_cfg.writeEntry("defaultAssistantsColor", color);
}
bool KisConfig::autoSmoothBezierCurves(bool defaultValue) const
{
return defaultValue ? false : m_cfg.readEntry("autoSmoothBezierCurves", false);
}
void KisConfig::setAutoSmoothBezierCurves(bool value)
{
m_cfg.writeEntry("autoSmoothBezierCurves", value);
}
bool KisConfig::activateTransformToolAfterPaste(bool defaultValue) const
{
return defaultValue ? false : m_cfg.readEntry("activateTransformToolAfterPaste", false);
}
void KisConfig::setActivateTransformToolAfterPaste(bool value)
{
m_cfg.writeEntry("activateTransformToolAfterPaste", value);
}
#include
#include
void KisConfig::writeKoColor(const QString& name, const KoColor& color) const
{
QDomDocument doc = QDomDocument(name);
QDomElement el = doc.createElement(name);
doc.appendChild(el);
color.toXML(doc, el);
m_cfg.writeEntry(name, doc.toString());
}
//ported from kispropertiesconfig.
KoColor KisConfig::readKoColor(const QString& name, const KoColor& color) const
{
QDomDocument doc;
if (!m_cfg.readEntry(name).isNull()) {
doc.setContent(m_cfg.readEntry(name));
QDomElement e = doc.documentElement().firstChild().toElement();
return KoColor::fromXML(e, Integer16BitsColorDepthID.id());
} else {
QString blackColor = "\n\n \n\n";
doc.setContent(blackColor);
QDomElement e = doc.documentElement().firstChild().toElement();
return KoColor::fromXML(e, Integer16BitsColorDepthID.id());
}
return color;
}
diff --git a/libs/ui/kis_config.h b/libs/ui/kis_config.h
index eb7aa92606..dbc8d05056 100644
--- a/libs/ui/kis_config.h
+++ b/libs/ui/kis_config.h
@@ -1,616 +1,617 @@
/*
* Copyright (c) 2002 Patrick Julien
*
* 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.
*/
#ifndef KIS_CONFIG_H_
#define KIS_CONFIG_H_
#include
#include
#include
#include
#include
#include
#include
#include
#include "kritaui_export.h"
class KoColorProfile;
class KoColorSpace;
class KisSnapConfig;
class KRITAUI_EXPORT KisConfig
{
public:
/**
* @brief KisConfig create a kisconfig object
* @param readOnly if true, there will be no call to sync when the object is deleted.
* Any KisConfig object created in a thread must be read-only.
*/
KisConfig(bool readOnly);
~KisConfig();
bool disableTouchOnCanvas(bool defaultValue = false) const;
void setDisableTouchOnCanvas(bool value) const;
bool useProjections(bool defaultValue = false) const;
void setUseProjections(bool useProj) const;
bool undoEnabled(bool defaultValue = false) const;
void setUndoEnabled(bool undo) const;
int undoStackLimit(bool defaultValue = false) const;
void setUndoStackLimit(int limit) const;
bool useCumulativeUndoRedo(bool defaultValue = false) const;
void setCumulativeUndoRedo(bool value);
double stackT1(bool defaultValue = false) const;
void setStackT1(int T1);
double stackT2(bool defaultValue = false) const;
void setStackT2(int T2);
int stackN(bool defaultValue = false) const;
void setStackN(int N);
qint32 defImageWidth(bool defaultValue = false) const;
void defImageWidth(qint32 width) const;
qint32 defImageHeight(bool defaultValue = false) const;
void defImageHeight(qint32 height) const;
qreal defImageResolution(bool defaultValue = false) const;
void defImageResolution(qreal res) const;
int preferredVectorImportResolutionPPI(bool defaultValue = false) const;
void setPreferredVectorImportResolutionPPI(int value) const;
/**
* @return the id of the default color model used for creating new images.
*/
QString defColorModel(bool defaultValue = false) const;
/**
* set the id of the default color model used for creating new images.
*/
void defColorModel(const QString & model) const;
/**
* @return the id of the default color depth used for creating new images.
*/
QString defaultColorDepth(bool defaultValue = false) const;
/**
* set the id of the default color depth used for creating new images.
*/
void setDefaultColorDepth(const QString & depth) const;
/**
* @return the id of the default color profile used for creating new images.
*/
QString defColorProfile(bool defaultValue = false) const;
/**
* set the id of the default color profile used for creating new images.
*/
void defColorProfile(const QString & depth) const;
CursorStyle newCursorStyle(bool defaultValue = false) const;
void setNewCursorStyle(CursorStyle style);
QColor getCursorMainColor(bool defaultValue = false) const;
void setCursorMainColor(const QColor& v) const;
OutlineStyle newOutlineStyle(bool defaultValue = false) const;
void setNewOutlineStyle(OutlineStyle style);
QRect colorPreviewRect() const;
void setColorPreviewRect(const QRect &rect);
/// get the profile the user has selected for the given screen
QString monitorProfile(int screen) const;
void setMonitorProfile(int screen, const QString & monitorProfile, bool override) const;
QString monitorForScreen(int screen, const QString &defaultMonitor, bool defaultValue = true) const;
void setMonitorForScreen(int screen, const QString& monitor);
/// Get the actual profile to be used for the given screen, which is
/// either the screen profile set by the color management system or
/// the custom monitor profile set by the user, depending on the configuration
const KoColorProfile *displayProfile(int screen) const;
QString workingColorSpace(bool defaultValue = false) const;
void setWorkingColorSpace(const QString & workingColorSpace) const;
QString importProfile(bool defaultValue = false) const;
void setImportProfile(const QString & importProfile) const;
QString printerColorSpace(bool defaultValue = false) const;
void setPrinterColorSpace(const QString & printerColorSpace) const;
QString printerProfile(bool defaultValue = false) const;
void setPrinterProfile(const QString & printerProfile) const;
bool useBlackPointCompensation(bool defaultValue = false) const;
void setUseBlackPointCompensation(bool useBlackPointCompensation) const;
bool allowLCMSOptimization(bool defaultValue = false) const;
void setAllowLCMSOptimization(bool allowLCMSOptimization);
bool forcePaletteColors(bool defaultValue = false) const;
void setForcePaletteColors(bool forcePaletteColors);
void writeKoColor(const QString& name, const KoColor& color) const;
KoColor readKoColor(const QString& name, const KoColor& color = KoColor()) const;
bool showRulers(bool defaultValue = false) const;
void setShowRulers(bool rulers) const;
bool forceShowSaveMessages(bool defaultValue = true) const;
void setForceShowSaveMessages(bool value) const;
bool forceShowAutosaveMessages(bool defaultValue = true) const;
void setForceShowAutosaveMessages(bool ShowAutosaveMessages) const;
bool rulersTrackMouse(bool defaultValue = false) const;
void setRulersTrackMouse(bool value) const;
qint32 pasteBehaviour(bool defaultValue = false) const;
void setPasteBehaviour(qint32 behaviour) const;
qint32 monitorRenderIntent(bool defaultValue = false) const;
void setRenderIntent(qint32 monitorRenderIntent) const;
bool useOpenGL(bool defaultValue = false) const;
void setUseOpenGL(bool useOpenGL) const;
int openGLFilteringMode(bool defaultValue = false) const;
void setOpenGLFilteringMode(int filteringMode);
bool useOpenGLTextureBuffer(bool defaultValue = false) const;
void setUseOpenGLTextureBuffer(bool useBuffer);
bool disableVSync(bool defaultValue = false) const;
void setDisableVSync(bool disableVSync);
bool showAdvancedOpenGLSettings(bool defaultValue = false) const;
bool forceOpenGLFenceWorkaround(bool defaultValue = false) const;
int numMipmapLevels(bool defaultValue = false) const;
int openGLTextureSize(bool defaultValue = false) const;
int textureOverlapBorder() const;
quint32 getGridMainStyle(bool defaultValue = false) const;
void setGridMainStyle(quint32 v) const;
quint32 getGridSubdivisionStyle(bool defaultValue = false) const;
void setGridSubdivisionStyle(quint32 v) const;
QColor getGridMainColor(bool defaultValue = false) const;
void setGridMainColor(const QColor & v) const;
QColor getGridSubdivisionColor(bool defaultValue = false) const;
void setGridSubdivisionColor(const QColor & v) const;
QColor getPixelGridColor(bool defaultValue = false) const;
void setPixelGridColor(const QColor & v) const;
qreal getPixelGridDrawingThreshold(bool defaultValue = false) const;
void setPixelGridDrawingThreshold(qreal v) const;
bool pixelGridEnabled(bool defaultValue = false) const;
void enablePixelGrid(bool v) const;
quint32 guidesLineStyle(bool defaultValue = false) const;
void setGuidesLineStyle(quint32 v) const;
QColor guidesColor(bool defaultValue = false) const;
void setGuidesColor(const QColor & v) const;
void loadSnapConfig(KisSnapConfig *config, bool defaultValue = false) const;
void saveSnapConfig(const KisSnapConfig &config);
qint32 checkSize(bool defaultValue = false) const;
void setCheckSize(qint32 checkSize) const;
bool scrollCheckers(bool defaultValue = false) const;
void setScrollingCheckers(bool scollCheckers) const;
QColor checkersColor1(bool defaultValue = false) const;
void setCheckersColor1(const QColor & v) const;
QColor checkersColor2(bool defaultValue = false) const;
void setCheckersColor2(const QColor & v) const;
QColor canvasBorderColor(bool defaultValue = false) const;
void setCanvasBorderColor(const QColor &color) const;
bool hideScrollbars(bool defaultValue = false) const;
void setHideScrollbars(bool value) const;
bool antialiasCurves(bool defaultValue = false) const;
void setAntialiasCurves(bool v) const;
bool antialiasSelectionOutline(bool defaultValue = false) const;
void setAntialiasSelectionOutline(bool v) const;
bool showRootLayer(bool defaultValue = false) const;
void setShowRootLayer(bool showRootLayer) const;
bool showGlobalSelection(bool defaultValue = false) const;
void setShowGlobalSelection(bool showGlobalSelection) const;
bool showOutlineWhilePainting(bool defaultValue = false) const;
void setShowOutlineWhilePainting(bool showOutlineWhilePainting) const;
bool forceAlwaysFullSizedOutline(bool defaultValue = false) const;
void setForceAlwaysFullSizedOutline(bool value) const;
enum SessionOnStartup {
SOS_BlankSession,
SOS_PreviousSession,
SOS_ShowSessionManager
};
SessionOnStartup sessionOnStartup(bool defaultValue = false) const;
void setSessionOnStartup(SessionOnStartup value);
bool saveSessionOnQuit(bool defaultValue) const;
void setSaveSessionOnQuit(bool value);
qreal outlineSizeMinimum(bool defaultValue = false) const;
void setOutlineSizeMinimum(qreal outlineSizeMinimum) const;
qreal selectionViewSizeMinimum(bool defaultValue = false) const;
void setSelectionViewSizeMinimum(qreal outlineSizeMinimum) const;
int autoSaveInterval(bool defaultValue = false) const;
void setAutoSaveInterval(int seconds) const;
bool backupFile(bool defaultValue = false) const;
void setBackupFile(bool backupFile) const;
bool showFilterGallery(bool defaultValue = false) const;
void setShowFilterGallery(bool showFilterGallery) const;
bool showFilterGalleryLayerMaskDialog(bool defaultValue = false) const;
void setShowFilterGalleryLayerMaskDialog(bool showFilterGallery) const;
// OPENGL_SUCCESS, TRY_OPENGL, OPENGL_NOT_TRIED, OPENGL_FAILED
QString canvasState(bool defaultValue = false) const;
void setCanvasState(const QString& state) const;
bool toolOptionsPopupDetached(bool defaultValue = false) const;
void setToolOptionsPopupDetached(bool detached) const;
bool paintopPopupDetached(bool defaultValue = false) const;
void setPaintopPopupDetached(bool detached) const;
QString pressureTabletCurve(bool defaultValue = false) const;
void setPressureTabletCurve(const QString& curveString) const;
bool useWin8PointerInput(bool defaultValue = false) const;
void setUseWin8PointerInput(bool value) const;
qreal vastScrolling(bool defaultValue = false) const;
void setVastScrolling(const qreal factor) const;
int presetChooserViewMode(bool defaultValue = false) const;
void setPresetChooserViewMode(const int mode) const;
int presetIconSize(bool defaultValue = false) const;
void setPresetIconSize(const int value) const;
bool firstRun(bool defaultValue = false) const;
void setFirstRun(const bool firstRun) const;
bool clicklessSpacePan(bool defaultValue = false) const;
void setClicklessSpacePan(const bool toggle) const;
int horizontalSplitLines(bool defaultValue = false) const;
void setHorizontalSplitLines(const int numberLines) const;
int verticalSplitLines(bool defaultValue = false) const;
void setVerticalSplitLines(const int numberLines) const;
bool hideDockersFullscreen(bool defaultValue = false) const;
void setHideDockersFullscreen(const bool value) const;
bool showDockers(bool defaultValue = false) const;
void setShowDockers(const bool value) const;
bool showStatusBar(bool defaultValue = false) const;
void setShowStatusBar(const bool value) const;
bool hideMenuFullscreen(bool defaultValue = false) const;
void setHideMenuFullscreen(const bool value) const;
bool hideScrollbarsFullscreen(bool defaultValue = false) const;
void setHideScrollbarsFullscreen(const bool value) const;
bool hideStatusbarFullscreen(bool defaultValue = false) const;
void setHideStatusbarFullscreen(const bool value) const;
bool hideTitlebarFullscreen(bool defaultValue = false) const;
void setHideTitlebarFullscreen(const bool value) const;
bool hideToolbarFullscreen(bool defaultValue = false) const;
void setHideToolbarFullscreen(const bool value) const;
bool fullscreenMode(bool defaultValue = false) const;
void setFullscreenMode(const bool value) const;
QStringList favoriteCompositeOps(bool defaultValue = false) const;
void setFavoriteCompositeOps(const QStringList& compositeOps) const;
QString exportConfiguration(const QString &filterId, bool defaultValue = false) const;
void setExportConfiguration(const QString &filterId, KisPropertiesConfigurationSP properties) const;
QString importConfiguration(const QString &filterId, bool defaultValue = false) const;
void setImportConfiguration(const QString &filterId, KisPropertiesConfigurationSP properties) const;
bool useOcio(bool defaultValue = false) const;
void setUseOcio(bool useOCIO) const;
int favoritePresets(bool defaultValue = false) const;
void setFavoritePresets(const int value);
bool levelOfDetailEnabled(bool defaultValue = false) const;
void setLevelOfDetailEnabled(bool value);
enum OcioColorManagementMode {
INTERNAL = 0,
OCIO_CONFIG,
OCIO_ENVIRONMENT
};
OcioColorManagementMode ocioColorManagementMode(bool defaultValue = false) const;
void setOcioColorManagementMode(OcioColorManagementMode mode) const;
QString ocioConfigurationPath(bool defaultValue = false) const;
void setOcioConfigurationPath(const QString &path) const;
QString ocioLutPath(bool defaultValue = false) const;
void setOcioLutPath(const QString &path) const;
int ocioLutEdgeSize(bool defaultValue = false) const;
void setOcioLutEdgeSize(int value);
bool ocioLockColorVisualRepresentation(bool defaultValue = false) const;
void setOcioLockColorVisualRepresentation(bool value);
bool useSystemMonitorProfile(bool defaultValue = false) const;
void setUseSystemMonitorProfile(bool _useSystemMonitorProfile) const;
QString defaultPalette(bool defaultValue = false) const;
void setDefaultPalette(const QString& name) const;
QString toolbarSlider(int sliderNumber, bool defaultValue = false) const;
void setToolbarSlider(int sliderNumber, const QString &slider);
int layerThumbnailSize(bool defaultValue = false) const;
void setLayerThumbnailSize(int size);
bool sliderLabels(bool defaultValue = false) const;
void setSliderLabels(bool enabled);
QString currentInputProfile(bool defaultValue = false) const;
void setCurrentInputProfile(const QString& name);
bool presetStripVisible(bool defaultValue = false) const;
void setPresetStripVisible(bool visible);
bool scratchpadVisible(bool defaultValue = false) const;
void setScratchpadVisible(bool visible);
bool showSingleChannelAsColor(bool defaultValue = false) const;
void setShowSingleChannelAsColor(bool asColor);
bool hidePopups(bool defaultValue = false) const;
void setHidePopups(bool hidepopups);
int numDefaultLayers(bool defaultValue = false) const;
void setNumDefaultLayers(int num);
quint8 defaultBackgroundOpacity(bool defaultValue = false) const;
void setDefaultBackgroundOpacity(quint8 value);
QColor defaultBackgroundColor(bool defaultValue = false) const;
void setDefaultBackgroundColor(QColor value);
enum BackgroundStyle {
- LAYER = 0,
- PROJECTION = 1
+ RASTER_LAYER = 0,
+ CANVAS_COLOR = 1,
+ FILL_LAYER = 2
};
BackgroundStyle defaultBackgroundStyle(bool defaultValue = false) const;
void setDefaultBackgroundStyle(BackgroundStyle value);
int lineSmoothingType(bool defaultValue = false) const;
void setLineSmoothingType(int value);
qreal lineSmoothingDistance(bool defaultValue = false) const;
void setLineSmoothingDistance(qreal value);
qreal lineSmoothingTailAggressiveness(bool defaultValue = false) const;
void setLineSmoothingTailAggressiveness(qreal value);
bool lineSmoothingSmoothPressure(bool defaultValue = false) const;
void setLineSmoothingSmoothPressure(bool value);
bool lineSmoothingScalableDistance(bool defaultValue = false) const;
void setLineSmoothingScalableDistance(bool value);
qreal lineSmoothingDelayDistance(bool defaultValue = false) const;
void setLineSmoothingDelayDistance(qreal value);
bool lineSmoothingUseDelayDistance(bool defaultValue = false) const;
void setLineSmoothingUseDelayDistance(bool value);
bool lineSmoothingFinishStabilizedCurve(bool defaultValue = false) const;
void setLineSmoothingFinishStabilizedCurve(bool value);
bool lineSmoothingStabilizeSensors(bool defaultValue = false) const;
void setLineSmoothingStabilizeSensors(bool value);
int tabletEventsDelay(bool defaultValue = false) const;
void setTabletEventsDelay(int value);
bool trackTabletEventLatency(bool defaultValue = false) const;
void setTrackTabletEventLatency(bool value);
bool testingAcceptCompressedTabletEvents(bool defaultValue = false) const;
void setTestingAcceptCompressedTabletEvents(bool value);
bool shouldEatDriverShortcuts(bool defaultValue = false) const;
bool testingCompressBrushEvents(bool defaultValue = false) const;
void setTestingCompressBrushEvents(bool value);
const KoColorSpace* customColorSelectorColorSpace(bool defaultValue = false) const;
void setCustomColorSelectorColorSpace(const KoColorSpace *cs);
bool useDirtyPresets(bool defaultValue = false) const;
void setUseDirtyPresets(bool value);
bool useEraserBrushSize(bool defaultValue = false) const;
void setUseEraserBrushSize(bool value);
bool useEraserBrushOpacity(bool defaultValue = false) const;
void setUseEraserBrushOpacity(bool value);
QColor getMDIBackgroundColor(bool defaultValue = false) const;
void setMDIBackgroundColor(const QColor & v) const;
QString getMDIBackgroundImage(bool defaultValue = false) const;
void setMDIBackgroundImage(const QString & fileName) const;
int workaroundX11SmoothPressureSteps(bool defaultValue = false) const;
bool showCanvasMessages(bool defaultValue = false) const;
void setShowCanvasMessages(bool show);
bool compressKra(bool defaultValue = false) const;
void setCompressKra(bool compress);
bool toolOptionsInDocker(bool defaultValue = false) const;
void setToolOptionsInDocker(bool inDocker);
bool kineticScrollingEnabled(bool defaultValue = false) const;
void setKineticScrollingEnabled(bool enabled);
int kineticScrollingGesture(bool defaultValue = false) const;
void setKineticScrollingGesture(int kineticScroll);
int kineticScrollingSensitivity(bool defaultValue = false) const;
void setKineticScrollingSensitivity(int sensitivity);
bool kineticScrollingHiddenScrollbars(bool defaultValue = false) const;
void setKineticScrollingHideScrollbars(bool scrollbar);
void setEnableOpenGLFramerateLogging(bool value) const;
bool enableOpenGLFramerateLogging(bool defaultValue = false) const;
void setEnableBrushSpeedLogging(bool value) const;
bool enableBrushSpeedLogging(bool defaultValue = false) const;
void setEnableAmdVectorizationWorkaround(bool value);
bool enableAmdVectorizationWorkaround(bool defaultValue = false) const;
bool animationDropFrames(bool defaultValue = false) const;
void setAnimationDropFrames(bool value);
int scrubbingUpdatesDelay(bool defaultValue = false) const;
void setScrubbingUpdatesDelay(int value);
int scrubbingAudioUpdatesDelay(bool defaultValue = false) const;
void setScrubbingAudioUpdatesDelay(int value);
int audioOffsetTolerance(bool defaultValue = false) const;
void setAudioOffsetTolerance(int value);
bool switchSelectionCtrlAlt(bool defaultValue = false) const;
void setSwitchSelectionCtrlAlt(bool value);
bool convertToImageColorspaceOnImport(bool defaultValue = false) const;
void setConvertToImageColorspaceOnImport(bool value);
int stabilizerSampleSize(bool defaultValue = false) const;
void setStabilizerSampleSize(int value);
bool stabilizerDelayedPaint(bool defaultValue = false) const;
void setStabilizerDelayedPaint(bool value);
QString customFFMpegPath(bool defaultValue = false) const;
void setCustomFFMpegPath(const QString &value) const;
bool showBrushHud(bool defaultValue = false) const;
void setShowBrushHud(bool value);
QString brushHudSetting(bool defaultValue = false) const;
void setBrushHudSetting(const QString &value) const;
bool calculateAnimationCacheInBackground(bool defaultValue = false) const;
void setCalculateAnimationCacheInBackground(bool value);
QColor defaultAssistantsColor(bool defaultValue = false) const;
void setDefaultAssistantsColor(const QColor &color) const;
bool autoSmoothBezierCurves(bool defaultValue = false) const;
void setAutoSmoothBezierCurves(bool value);
bool activateTransformToolAfterPaste(bool defaultValue = false) const;
void setActivateTransformToolAfterPaste(bool value);
template
void writeEntry(const QString& name, const T& value) {
m_cfg.writeEntry(name, value);
}
template
void writeList(const QString& name, const QList& value) {
m_cfg.writeEntry(name, value);
}
template
T readEntry(const QString& name, const T& defaultValue=T()) {
return m_cfg.readEntry(name, defaultValue);
}
template
QList readList(const QString& name, const QList& defaultValue=QList()) {
return m_cfg.readEntry(name, defaultValue);
}
/// get the profile the color management system has stored for the given screen
static const KoColorProfile* getScreenProfile(int screen);
private:
KisConfig(const KisConfig&);
KisConfig& operator=(const KisConfig&) const;
private:
mutable KConfigGroup m_cfg;
bool m_readOnly;
};
#endif // KIS_CONFIG_H_
diff --git a/libs/ui/tests/kis_shape_selection_test.cpp b/libs/ui/tests/kis_shape_selection_test.cpp
index e4637deaff..880825468b 100644
--- a/libs/ui/tests/kis_shape_selection_test.cpp
+++ b/libs/ui/tests/kis_shape_selection_test.cpp
@@ -1,85 +1,85 @@
/*
* Copyright (c) 2008 Sven Langkamp
*
* 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 "kis_shape_selection_test.h"
#include
#include
#include
#include
#include
#include
#include "kis_selection.h"
#include "kis_pixel_selection.h"
#include "flake/kis_shape_selection.h"
#include "kis_image.h"
#include "testutil.h"
#include "kistest.h"
#include
#include
void KisShapeSelectionTest::testAddChild()
{
const KoColorSpace * cs = KoColorSpaceRegistry::instance()->rgb8();
QScopedPointer doc(KisPart::instance()->createDocument());
QColor qc(Qt::white);
qc.setAlpha(0);
KoColor bgColor(qc, cs);
- doc->newImage("test", 300, 300, cs, bgColor, true, 1, "test", 100);
+ doc->newImage("test", 300, 300, cs, bgColor, KisConfig::CANVAS_COLOR, 1, "test", 100);
KisImageSP image = doc->image();
KisSelectionSP selection = new KisSelection();
QVERIFY(selection->hasPixelSelection() == false);
QVERIFY(selection->hasShapeSelection() == false);
KisPixelSelectionSP pixelSelection = selection->pixelSelection();
pixelSelection->select(QRect(0, 0, 100, 100));
QCOMPARE(TestUtil::alphaDevicePixel(pixelSelection, 25, 25), MAX_SELECTED);
QCOMPARE(selection->selectedExactRect(), QRect(0, 0, 100, 100));
QRectF rect(50, 50, 100, 100);
QTransform matrix;
matrix.scale(1 / image->xRes(), 1 / image->yRes());
rect = matrix.mapRect(rect);
KoPathShape* shape = new KoPathShape();
shape->setShapeId(KoPathShapeId);
shape->moveTo(rect.topLeft());
shape->lineTo(rect.topRight());
shape->lineTo(rect.bottomRight());
shape->lineTo(rect.bottomLeft());
shape->close();
KisShapeSelection * shapeSelection = new KisShapeSelection(doc->shapeController(), image, selection);
selection->setShapeSelection(shapeSelection);
shapeSelection->addShape(shape);
QVERIFY(selection->hasShapeSelection());
selection->updateProjection();
image->waitForDone();
QCOMPARE(selection->selectedExactRect(), QRect(50, 50, 100, 100));
}
KISTEST_MAIN(KisShapeSelectionTest)
diff --git a/libs/ui/widgets/kis_custom_image_widget.cc b/libs/ui/widgets/kis_custom_image_widget.cc
index 5ee1eaf17e..b8be9165ff 100644
--- a/libs/ui/widgets/kis_custom_image_widget.cc
+++ b/libs/ui/widgets/kis_custom_image_widget.cc
@@ -1,512 +1,518 @@
/* This file is part of the Calligra project
* Copyright (C) 2005 Thomas Zander
* Copyright (C) 2005 C. Boemann
* Copyright (C) 2007 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.
*/
#include "widgets/kis_custom_image_widget.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 "kis_config.h"
#include "KisPart.h"
#include "kis_clipboard.h"
#include "KisDocument.h"
#include "widgets/kis_cmb_idlist.h"
#include
KisCustomImageWidget::KisCustomImageWidget(QWidget* parent, qint32 defWidth, qint32 defHeight, double resolution, const QString& defColorModel, const QString& defColorDepth, const QString& defColorProfile, const QString& imageName)
: WdgNewImage(parent)
{
setObjectName("KisCustomImageWidget");
m_openPane = qobject_cast(parent);
Q_ASSERT(m_openPane);
txtName->setText(imageName);
m_widthUnit = KoUnit(KoUnit::Pixel, resolution);
doubleWidth->setValue(defWidth);
doubleWidth->setDecimals(0);
m_width = m_widthUnit.fromUserValue(defWidth);
cmbWidthUnit->addItems(KoUnit::listOfUnitNameForUi(KoUnit::ListAll));
cmbWidthUnit->setCurrentIndex(m_widthUnit.indexInListForUi(KoUnit::ListAll));
m_heightUnit = KoUnit(KoUnit::Pixel, resolution);
doubleHeight->setValue(defHeight);
doubleHeight->setDecimals(0);
m_height = m_heightUnit.fromUserValue(defHeight);
cmbHeightUnit->addItems(KoUnit::listOfUnitNameForUi(KoUnit::ListAll));
cmbHeightUnit->setCurrentIndex(m_heightUnit.indexInListForUi(KoUnit::ListAll));
doubleResolution->setValue(72.0 * resolution);
doubleResolution->setDecimals(0);
imageGroupSpacer->changeSize(0, 0, QSizePolicy::Fixed, QSizePolicy::Fixed);
grpClipboard->hide();
sliderOpacity->setRange(0, 100, 0);
sliderOpacity->setValue(100);
sliderOpacity->setSuffix("%");
connect(cmbPredefined, SIGNAL(activated(int)), SLOT(predefinedClicked(int)));
connect(doubleResolution, SIGNAL(valueChanged(double)),
this, SLOT(resolutionChanged(double)));
connect(cmbWidthUnit, SIGNAL(activated(int)),
this, SLOT(widthUnitChanged(int)));
connect(doubleWidth, SIGNAL(valueChanged(double)),
this, SLOT(widthChanged(double)));
connect(cmbHeightUnit, SIGNAL(activated(int)),
this, SLOT(heightUnitChanged(int)));
connect(doubleHeight, SIGNAL(valueChanged(double)),
this, SLOT(heightChanged(double)));
// Create image
newDialogConfirmationButtonBox->button(QDialogButtonBox::Ok)->setText(i18n("&Create"));
connect(newDialogConfirmationButtonBox, SIGNAL(accepted()), this, SLOT(createImage()));
// Cancel Create image button
connect(newDialogConfirmationButtonBox, SIGNAL(rejected()), this->parentWidget(), SLOT(close()));
connect(newDialogConfirmationButtonBox, SIGNAL(rejected()), this->parentWidget(), SLOT(deleteLater()));
bnPortrait->setIcon(KisIconUtils::loadIcon("portrait"));
connect(bnPortrait, SIGNAL(clicked()), SLOT(setPortrait()));
connect(bnLandscape, SIGNAL(clicked()), SLOT(setLandscape()));
bnLandscape->setIcon(KisIconUtils::loadIcon("landscape"));
connect(doubleWidth, SIGNAL(valueChanged(double)), this, SLOT(switchPortraitLandscape()));
connect(doubleHeight, SIGNAL(valueChanged(double)), this, SLOT(switchPortraitLandscape()));
connect(bnSaveAsPredefined, SIGNAL(clicked()), this, SLOT(saveAsPredefined()));
colorSpaceSelector->setCurrentColorModel(KoID(defColorModel));
colorSpaceSelector->setCurrentColorDepth(KoID(defColorDepth));
colorSpaceSelector->setCurrentProfile(defColorProfile);
connect(colorSpaceSelector, SIGNAL(colorSpaceChanged(const KoColorSpace*)), this, SLOT(changeDocumentInfoLabel()));
//connect(chkFromClipboard,SIGNAL(stateChanged(int)),this,SLOT(clipboardDataChanged()));
connect(QApplication::clipboard(), SIGNAL(dataChanged()), this, SLOT(clipboardDataChanged()));
connect(QApplication::clipboard(), SIGNAL(selectionChanged()), this, SLOT(clipboardDataChanged()));
connect(QApplication::clipboard(), SIGNAL(changed(QClipboard::Mode)), this, SLOT(clipboardDataChanged()));
connect(colorSpaceSelector, SIGNAL(selectionChanged(bool)), newDialogConfirmationButtonBox->button(QDialogButtonBox::Ok), SLOT(setEnabled(bool)));
KisConfig cfg(true);
intNumLayers->setValue(cfg.numDefaultLayers());
KoColor bcol(KoColorSpaceRegistry::instance()->rgb8());
bcol.fromQColor(cfg.defaultBackgroundColor());
cmbColor->setColor(bcol);
setBackgroundOpacity(cfg.defaultBackgroundOpacity());
KisConfig::BackgroundStyle bgStyle = cfg.defaultBackgroundStyle();
- if (bgStyle == KisConfig::LAYER) {
- radioBackgroundAsLayer->setChecked(true);
+ if (bgStyle == KisConfig::RASTER_LAYER) {
+ radioBackgroundAsRaster->setChecked(true);
+ } else if (bgStyle == KisConfig::FILL_LAYER) {
+ radioBackgroundAsFill->setChecked(true);
} else {
radioBackgroundAsProjection->setChecked(true);
}
fillPredefined();
switchPortraitLandscape();
// this makes the portrait and landscape buttons more
// obvious what is selected by changing the highlight color
QPalette p = QApplication::palette();
QPalette palette_highlight(p );
QColor c = p.color(QPalette::Highlight);
palette_highlight.setColor(QPalette::Button, c);
bnLandscape->setPalette(palette_highlight);
bnPortrait->setPalette(palette_highlight);
changeDocumentInfoLabel();
}
void KisCustomImageWidget::showEvent(QShowEvent *)
{
fillPredefined();
newDialogConfirmationButtonBox->button(QDialogButtonBox::Ok)->setFocus();
newDialogConfirmationButtonBox->button(QDialogButtonBox::Ok)->setEnabled(true);
}
KisCustomImageWidget::~KisCustomImageWidget()
{
m_predefined.clear();
}
void KisCustomImageWidget::resolutionChanged(double res)
{
if (m_widthUnit.type() == KoUnit::Pixel) {
m_widthUnit.setFactor(res / 72.0);
m_width = m_widthUnit.fromUserValue(doubleWidth->value());
}
if (m_heightUnit.type() == KoUnit::Pixel) {
m_heightUnit.setFactor(res / 72.0);
m_height = m_heightUnit.fromUserValue(doubleHeight->value());
}
changeDocumentInfoLabel();
}
void KisCustomImageWidget::widthUnitChanged(int index)
{
doubleWidth->blockSignals(true);
m_widthUnit = KoUnit::fromListForUi(index, KoUnit::ListAll);
if (m_widthUnit.type() == KoUnit::Pixel) {
doubleWidth->setDecimals(0);
m_widthUnit.setFactor(doubleResolution->value() / 72.0);
} else {
doubleWidth->setDecimals(2);
}
doubleWidth->setValue(KoUnit::ptToUnit(m_width, m_widthUnit));
doubleWidth->blockSignals(false);
changeDocumentInfoLabel();
}
void KisCustomImageWidget::widthChanged(double value)
{
m_width = m_widthUnit.fromUserValue(value);
changeDocumentInfoLabel();
}
void KisCustomImageWidget::heightUnitChanged(int index)
{
doubleHeight->blockSignals(true);
m_heightUnit = KoUnit::fromListForUi(index, KoUnit::ListAll);
if (m_heightUnit.type() == KoUnit::Pixel) {
doubleHeight->setDecimals(0);
m_heightUnit.setFactor(doubleResolution->value() / 72.0);
} else {
doubleHeight->setDecimals(2);
}
doubleHeight->setValue(KoUnit::ptToUnit(m_height, m_heightUnit));
doubleHeight->blockSignals(false);
changeDocumentInfoLabel();
}
void KisCustomImageWidget::heightChanged(double value)
{
m_height = m_heightUnit.fromUserValue(value);
changeDocumentInfoLabel();
}
void KisCustomImageWidget::createImage()
{
newDialogConfirmationButtonBox->button(QDialogButtonBox::Ok)->setEnabled(false);
KisDocument *doc = createNewImage();
if (doc) {
doc->setModified(false);
emit m_openPane->documentSelected(doc);
}
}
KisDocument* KisCustomImageWidget::createNewImage()
{
-
const KoColorSpace * cs = colorSpaceSelector->currentColorSpace();
if (cs->colorModelId() == RGBAColorModelID &&
cs->colorDepthId() == Integer8BitsColorDepthID) {
const KoColorProfile *profile = cs->profile();
if (profile->name().contains("linear") ||
profile->name().contains("scRGB") ||
profile->info().contains("linear") ||
profile->info().contains("scRGB")) {
int result =
QMessageBox::warning(this,
i18nc("@title:window", "Krita"),
i18n("Linear gamma RGB color spaces are not supposed to be used "
"in 8-bit integer modes. It is suggested to use 16-bit integer "
"or any floating point colorspace for linear profiles.\n\n"
"Press \"Ok\" to create a 8-bit integer linear RGB color space "
"or \"Cancel\" to return to the settings dialog."),
QMessageBox::Ok | QMessageBox::Cancel, QMessageBox::Cancel);
if (result == QMessageBox::Cancel) {
dbgKrita << "Model RGB8" << "NOT SUPPORTED";
dbgKrita << ppVar(cs->name());
dbgKrita << ppVar(cs->profile()->name());
dbgKrita << ppVar(cs->profile()->info());
return 0;
}
}
}
KisDocument *doc = static_cast(KisPart::instance()->createDocument());
qint32 width, height;
double resolution;
resolution = doubleResolution->value() / 72.0; // internal resolution is in pixels per pt
width = static_cast(0.5 + KoUnit::ptToUnit(m_width, KoUnit(KoUnit::Pixel, resolution)));
height = static_cast(0.5 + KoUnit::ptToUnit(m_height, KoUnit(KoUnit::Pixel, resolution)));
QColor qc = cmbColor->color().toQColor();
qc.setAlpha(backgroundOpacity());
KoColor bgColor(qc, cs);
- bool backgroundAsLayer = radioBackgroundAsLayer->isChecked();
+ KisConfig::BackgroundStyle bgStyle = KisConfig::CANVAS_COLOR;
+ if( radioBackgroundAsRaster->isChecked() ){
+ bgStyle = KisConfig::RASTER_LAYER;
+ } else if( radioBackgroundAsFill->isChecked() ){
+ bgStyle = KisConfig::FILL_LAYER;
+ }
- doc->newImage(txtName->text(), width, height, cs, bgColor, backgroundAsLayer, intNumLayers->value(), txtDescription->toPlainText(), resolution);
+ doc->newImage(txtName->text(), width, height, cs, bgColor, bgStyle, intNumLayers->value(), txtDescription->toPlainText(), resolution);
KisConfig cfg(true);
cfg.setNumDefaultLayers(intNumLayers->value());
cfg.setDefaultBackgroundOpacity(backgroundOpacity());
cfg.setDefaultBackgroundColor(cmbColor->color().toQColor());
- cfg.setDefaultBackgroundStyle(backgroundAsLayer ? KisConfig::LAYER : KisConfig::PROJECTION);
+ cfg.setDefaultBackgroundStyle(bgStyle);
return doc;
}
void KisCustomImageWidget::setNumberOfLayers(int layers)
{
intNumLayers->setValue(layers);
}
quint8 KisCustomImageWidget::backgroundOpacity() const
{
qint32 opacity = sliderOpacity->value();
if (!opacity)
return 0;
return (opacity * 255) / 100;
}
void KisCustomImageWidget::setBackgroundOpacity(quint8 value) {
sliderOpacity->setValue((value * 100) / 255);
}
void KisCustomImageWidget::clipboardDataChanged()
{
}
void KisCustomImageWidget::fillPredefined()
{
cmbPredefined->clear();
m_predefined.clear();
cmbPredefined->addItem("");
QStringList definitions = KoResourcePaths::findAllResources("data", "predefined_image_sizes/*.predefinedimage", KoResourcePaths::Recursive);
definitions.sort();
if (!definitions.empty()) {
Q_FOREACH (const QString &definition, definitions) {
QFile f(definition);
f.open(QIODevice::ReadOnly);
if (f.exists()) {
QString xml = QString::fromUtf8(f.readAll());
KisPropertiesConfigurationSP predefined = new KisPropertiesConfiguration;
predefined->fromXML(xml);
if (predefined->hasProperty("name")
&& predefined->hasProperty("width")
&& predefined->hasProperty("height")
&& predefined->hasProperty("resolution")
&& predefined->hasProperty("x-unit")
&& predefined->hasProperty("y-unit")) {
m_predefined << predefined;
cmbPredefined->addItem(predefined->getString("name"));
}
}
}
}
cmbPredefined->setCurrentIndex(0);
}
void KisCustomImageWidget::predefinedClicked(int index)
{
if (index < 1 || index > m_predefined.size()) return;
KisPropertiesConfigurationSP predefined = m_predefined[index - 1];
txtPredefinedName->setText(predefined->getString("name"));
doubleResolution->setValue(predefined->getDouble("resolution"));
cmbWidthUnit->setCurrentIndex(predefined->getInt("x-unit"));
cmbHeightUnit->setCurrentIndex(predefined->getInt("y-unit"));
widthUnitChanged(cmbWidthUnit->currentIndex());
heightUnitChanged(cmbHeightUnit->currentIndex());
doubleWidth->setValue(predefined->getDouble("width"));
doubleHeight->setValue(predefined->getDouble("height"));
changeDocumentInfoLabel();
}
void KisCustomImageWidget::saveAsPredefined()
{
QString fileName = txtPredefinedName->text();
if (fileName.isEmpty()) {
return;
}
QString saveLocation = KoResourcePaths::saveLocation("data", "predefined_image_sizes/", true);
QFile f(saveLocation + '/' + fileName.replace(' ', '_').replace('(', '_').replace(')', '_').replace(':', '_') + ".predefinedimage");
f.open(QIODevice::WriteOnly | QIODevice::Truncate);
KisPropertiesConfigurationSP predefined = new KisPropertiesConfiguration();
predefined->setProperty("name", txtPredefinedName->text());
predefined->setProperty("width", doubleWidth->value());
predefined->setProperty("height", doubleHeight->value());
predefined->setProperty("resolution", doubleResolution->value());
predefined->setProperty("x-unit", cmbWidthUnit->currentIndex());
predefined->setProperty("y-unit", cmbHeightUnit->currentIndex());
QString xml = predefined->toXML();
f.write(xml.toUtf8());
f.flush();
f.close();
int i = 0;
bool found = false;
Q_FOREACH (KisPropertiesConfigurationSP pr, m_predefined) {
if (pr->getString("name") == txtPredefinedName->text()) {
found = true;
break;
}
++i;
}
if (found) {
m_predefined[i] = predefined;
}
else {
m_predefined.append(predefined);
cmbPredefined->addItem(txtPredefinedName->text());
}
}
void KisCustomImageWidget::setLandscape()
{
if (doubleWidth->value() < doubleHeight->value()) {
switchWidthHeight();
}
}
void KisCustomImageWidget::setPortrait()
{
if (doubleWidth->value() > doubleHeight->value()) {
switchWidthHeight();
}
}
void KisCustomImageWidget::switchWidthHeight()
{
double width = doubleWidth->value();
double height = doubleHeight->value();
doubleHeight->blockSignals(true);
doubleWidth->blockSignals(true);
cmbWidthUnit->blockSignals(true);
cmbHeightUnit->blockSignals(true);
doubleWidth->setValue(height);
doubleHeight->setValue(width);
cmbWidthUnit->setCurrentIndex(m_heightUnit.indexInListForUi(KoUnit::ListAll));
cmbHeightUnit->setCurrentIndex(m_widthUnit.indexInListForUi(KoUnit::ListAll));
doubleHeight->blockSignals(false);
doubleWidth->blockSignals(false);
cmbWidthUnit->blockSignals(false);
cmbHeightUnit->blockSignals(false);
switchPortraitLandscape();
widthChanged(doubleWidth->value());
heightChanged(doubleHeight->value());
changeDocumentInfoLabel();
}
void KisCustomImageWidget::switchPortraitLandscape()
{
if(doubleWidth->value() > doubleHeight->value())
bnLandscape->setChecked(true);
else
bnPortrait->setChecked(true);
}
void KisCustomImageWidget::changeDocumentInfoLabel()
{
qint64 width, height;
double resolution;
resolution = doubleResolution->value() / 72.0; // internal resolution is in pixels per pt
width = static_cast(0.5 + KoUnit::ptToUnit(m_width, KoUnit(KoUnit::Pixel, resolution)));
height = static_cast(0.5 + KoUnit::ptToUnit(m_height, KoUnit(KoUnit::Pixel, resolution)));
qint64 layerSize = width * height;
const KoColorSpace *cs = colorSpaceSelector->currentColorSpace();
int bitSize = 8 * cs->pixelSize(); //pixelsize is in bytes.
layerSize = layerSize * cs->pixelSize();
QString text = i18nc("arg1: width. arg2: height. arg3: colorspace name. arg4: size of a channel in bits. arg5: image size",
"This document will be %1 pixels by %2 pixels in %3, which means the pixel size is %4 bit. A single paint layer will thus take up %5 of RAM.",
width,
height,
cs->name(),
bitSize,
KFormat().formatByteSize(layerSize));
lblDocumentInfo->setText(text);
}