File indexing completed on 2024-05-19 04:26:56

0001 /*
0002  *  SPDX-FileCopyrightText: 2016 Boudewijn Rempt <boud@valdyas.org>
0003  *
0004  *  SPDX-License-Identifier: LGPL-2.0-or-later
0005  */
0006 #include "Krita.h"
0007 
0008 #include <QPointer>
0009 #include <QVariant>
0010 #include <QStringList>
0011 
0012 #include <ksharedconfig.h>
0013 #include <kconfiggroup.h>
0014 #include <klocalizedstring.h>
0015 
0016 #include <KoColorSpaceRegistry.h>
0017 #include <KoColorProfile.h>
0018 #include <KoColorSpace.h>
0019 #include <KoDockRegistry.h>
0020 #include <KoColorSpaceEngine.h>
0021 #include <KoColorModelStandardIds.h>
0022 #include <KoID.h>
0023 
0024 #include <kis_filter_strategy.h>
0025 #include <kactioncollection.h>
0026 #include <KisPart.h>
0027 #include <KisMainWindow.h>
0028 #include <KisDocument.h>
0029 #include <kis_image.h>
0030 #include <kis_action.h>
0031 #include <KisViewManager.h>
0032 #include <KritaVersionWrapper.h>
0033 #include <kis_filter_registry.h>
0034 #include <kis_filter.h>
0035 #include <kis_filter_configuration.h>
0036 #include <kis_properties_configuration.h>
0037 #include <kis_config.h>
0038 #include <kis_workspace_resource.h>
0039 #include <brushengine/kis_paintop_preset.h>
0040 #include <KisBrushServerProvider.h>
0041 #include <KoResourceServerProvider.h>
0042 #include <KisResourceServerProvider.h>
0043 #include <KisBrushServerProvider.h>
0044 #include <kis_action_registry.h>
0045 #include <kis_icon_utils.h>
0046 
0047 #include <KisResourceModel.h>
0048 #include <KisGlobalResourcesInterface.h>
0049 
0050 #include "View.h"
0051 #include "Document.h"
0052 #include "Window.h"
0053 #include "Extension.h"
0054 #include "DockWidgetFactoryBase.h"
0055 #include "Filter.h"
0056 #include "InfoObject.h"
0057 #include "Resource.h"
0058 
0059 Krita* Krita::s_instance = 0;
0060 
0061 struct Krita::Private {
0062     Private() {}
0063     QList<Extension*> extensions;
0064     bool batchMode {false};
0065     Notifier *notifier{new Notifier()};
0066 };
0067 
0068 Krita::Krita(QObject *parent)
0069     : QObject(parent)
0070     , d(new Private)
0071 {
0072     qRegisterMetaType<Notifier*>();
0073     connect(KisPart::instance(), SIGNAL(sigMainWindowIsBeingCreated(KisMainWindow*)), SLOT(mainWindowIsBeingCreated(KisMainWindow*)));
0074 }
0075 
0076 Krita::~Krita()
0077 {
0078     qDeleteAll(d->extensions);
0079     delete d->notifier;
0080     delete d;
0081 }
0082 
0083 QList<QAction *> Krita::actions() const
0084 {
0085     KisMainWindow *mainWindow = KisPart::instance()->currentMainwindow();
0086     if (!mainWindow) {
0087         return QList<QAction*>();
0088     }
0089     KisKActionCollection *actionCollection = mainWindow->actionCollection();
0090     return actionCollection->actions();
0091 }
0092 
0093 QAction *Krita::action(const QString &name) const
0094 {
0095     KisMainWindow *mainWindow = KisPart::instance()->currentMainwindow();
0096     if (!mainWindow) {
0097         return 0;
0098     }
0099     KisKActionCollection *actionCollection = mainWindow->actionCollection();
0100     QAction *action = actionCollection->action(name);
0101     return action;
0102 }
0103 
0104 Document* Krita::activeDocument() const
0105 {
0106     KisMainWindow *mainWindow = KisPart::instance()->currentMainwindow();
0107     if (!mainWindow) {
0108         return 0;
0109     }
0110     KisView *view = mainWindow->activeView();
0111     if (!view) {
0112         return 0;
0113     }
0114     KisDocument *document = view->document();
0115     Document *d = new Document(document, false);
0116     return d;
0117 }
0118 
0119 void Krita::setActiveDocument(Document* value)
0120 {
0121     Q_FOREACH(KisView *view, KisPart::instance()->views()) {
0122         if (view->document() == value->document().data()) {
0123             view->activateWindow();
0124             break;
0125         }
0126     }
0127 }
0128 
0129 bool Krita::batchmode() const
0130 {
0131     return d->batchMode;
0132 }
0133 
0134 void Krita::setBatchmode(bool value)
0135 {
0136     d->batchMode = value;
0137 }
0138 
0139 
0140 QList<Document *> Krita::documents() const
0141 {
0142     QList<Document *> ret;
0143     foreach(QPointer<KisDocument> doc, KisPart::instance()->documents()) {
0144         ret << new Document(doc, false);
0145     }
0146     return ret;
0147 }
0148 
0149 QStringList Krita::filters() const
0150 {
0151     QStringList ls = KisFilterRegistry::instance()->keys();
0152     std::sort(ls.begin(), ls.end());
0153     return ls;
0154 }
0155 
0156 Filter *Krita::filter(const QString &name) const
0157 {
0158     if (!filters().contains(name)) return 0;
0159 
0160     Filter *filter = new Filter();
0161     filter->setName(name);
0162     KisFilterSP f = KisFilterRegistry::instance()->value(name);
0163     KisFilterConfigurationSP fc = f->defaultConfiguration(KisGlobalResourcesInterface::instance());
0164     InfoObject *info = new InfoObject(fc);
0165     filter->setConfiguration(info);
0166     return filter;
0167 }
0168 
0169 QStringList Krita::colorModels() const
0170 {
0171     QSet<QString> colorModelsIds;
0172     QList<KoID> ids = KoColorSpaceRegistry::instance()->colorModelsList(KoColorSpaceRegistry::AllColorSpaces);
0173     Q_FOREACH(KoID id, ids) {
0174         colorModelsIds << id.id();
0175     }
0176 #if QT_VERSION >= QT_VERSION_CHECK(5,14,0)
0177     return QStringList(colorModelsIds.begin(), colorModelsIds.end());
0178 #else
0179     return QStringList::fromSet(colorModelsIds);
0180 #endif
0181 }
0182 
0183 QStringList Krita::colorDepths(const QString &colorModel) const
0184 {
0185     QSet<QString> colorDepthsIds;
0186     QList<KoID> ids = KoColorSpaceRegistry::instance()->colorDepthList(colorModel, KoColorSpaceRegistry::AllColorSpaces);
0187     Q_FOREACH(KoID id, ids) {
0188         colorDepthsIds << id.id();
0189     }
0190 #if QT_VERSION >= QT_VERSION_CHECK(5,14,0)
0191     return QStringList(colorDepthsIds.begin(), colorDepthsIds.end());
0192 #else
0193     return QStringList::fromSet(colorDepthsIds);
0194 #endif
0195 }
0196 
0197 QStringList Krita::filterStrategies() const
0198 {
0199     return KisFilterStrategyRegistry::instance()->keys();
0200 }
0201 
0202 QStringList Krita::profiles(const QString &colorModel, const QString &colorDepth) const
0203 {
0204     QSet<QString> profileNames;
0205     QString id = KoColorSpaceRegistry::instance()->colorSpaceId(colorModel, colorDepth);
0206     QList<const KoColorProfile *> profiles = KoColorSpaceRegistry::instance()->profilesFor(id);
0207     Q_FOREACH(const KoColorProfile *profile, profiles) {
0208         profileNames << profile->name();
0209     }
0210 #if QT_VERSION >= QT_VERSION_CHECK(5,14,0)
0211     QStringList r(profileNames.begin(), profileNames.end());
0212 #else
0213     QStringList r = QStringList::fromSet(profileNames);
0214 #endif
0215     r.sort();
0216     return r;
0217 }
0218 
0219 bool Krita::addProfile(const QString &profilePath)
0220 {
0221     KoColorSpaceEngine *iccEngine = KoColorSpaceEngineRegistry::instance()->get("icc");
0222     KIS_ASSERT(iccEngine);
0223     return iccEngine->addProfile(profilePath);
0224 }
0225 
0226 Notifier* Krita::notifier() const
0227 {
0228     return d->notifier;
0229 }
0230 
0231 QString Krita::version() const
0232 {
0233     return KritaVersionWrapper::versionString(true);
0234 }
0235 
0236 QList<View *> Krita::views() const
0237 {
0238     QList<View *> ret;
0239     foreach(QPointer<KisView> view, KisPart::instance()->views()) {
0240         ret << new View(view);
0241     }
0242     return ret;
0243 }
0244 
0245 Window *Krita::activeWindow() const
0246 {
0247     KisMainWindow *mainWindow = KisPart::instance()->currentMainwindow();
0248     if (!mainWindow) {
0249         return 0;
0250     }
0251     return new Window(mainWindow);
0252 }
0253 
0254 QList<Window*>  Krita::windows() const
0255 {
0256     QList<Window*> ret;
0257     foreach(QPointer<KisMainWindow> mainWin, KisPart::instance()->mainWindows()) {
0258         ret << new Window(mainWin);
0259     }
0260     return ret;
0261 }
0262 
0263 QMap<QString, Resource*> Krita::resources(QString &type) const
0264 {
0265     QMap<QString, Resource*> resources;
0266     KisResourceModel *resourceModel = 0;
0267     if (type == "pattern") {
0268         resourceModel = KoResourceServerProvider::instance()->patternServer()->resourceModel();
0269         type = ResourceType::Patterns;
0270     }
0271     else if (type == "gradient") {
0272         type = ResourceType::Gradients;
0273         resourceModel = KoResourceServerProvider::instance()->gradientServer()->resourceModel();
0274     }
0275     else if (type == "brush") {
0276         resourceModel = KisBrushServerProvider::instance()->brushServer()->resourceModel();
0277         type = ResourceType::Brushes;
0278     }
0279     else if (type == "palette") {
0280         resourceModel = KoResourceServerProvider::instance()->paletteServer()->resourceModel();
0281         type = ResourceType::Palettes;
0282     }
0283     else if (type == "workspace") {
0284         resourceModel = KisResourceServerProvider::instance()->workspaceServer()->resourceModel();
0285         type = ResourceType::Workspaces;
0286     }
0287     else if (type == "preset") {
0288         resourceModel = KisResourceServerProvider::instance()->paintOpPresetServer()->resourceModel();
0289     }
0290 
0291     if (resourceModel) {
0292         for (int i = 0; i < resourceModel->rowCount(); ++i) {
0293 
0294             QModelIndex idx = resourceModel->index(i, 0);
0295             int id = resourceModel->data(idx, Qt::UserRole + KisAbstractResourceModel::Id).toInt();
0296             QString name  = resourceModel->data(idx, Qt::UserRole + KisAbstractResourceModel::Name).toString();
0297             QString filename  = resourceModel->data(idx, Qt::UserRole + KisAbstractResourceModel::Filename).toString();
0298             QImage image = resourceModel->data(idx, Qt::UserRole + KisAbstractResourceModel::Thumbnail).value<QImage>();
0299 
0300             resources[name] = new Resource(id, type, name, filename, image, 0);
0301         }
0302     }
0303 
0304     return resources;
0305 }
0306 
0307 
0308 QList<QDockWidget*> Krita::dockers() const
0309 {
0310     KisMainWindow *mainWindow = KisPart::instance()->currentMainwindow();
0311 
0312     if (!mainWindow) return {};
0313     return mainWindow->dockWidgets();
0314 }
0315 
0316 
0317 QStringList Krita::recentDocuments() const
0318 {
0319     KConfigGroup grp = KSharedConfig::openConfig()->group(QString("RecentFiles"));
0320     QStringList keys = grp.keyList();
0321     QStringList recentDocuments;
0322 
0323     for(int i = 0; i <= keys.filter("File").count(); i++)
0324         recentDocuments << grp.readEntry(QString("File%1").arg(i), QString(""));
0325 
0326     return recentDocuments;
0327 }
0328 
0329 Document* Krita::createDocument(int width, int height, const QString &name, const QString &colorModel, const QString &colorDepth, const QString &profile, double resolution)
0330 {
0331     KisDocument *document = KisPart::instance()->createDocument();
0332     document->setObjectName(name);
0333 
0334     KisPart::instance()->addDocument(document, false);
0335     const KoColorSpace *cs = KoColorSpaceRegistry::instance()->colorSpace(colorModel, colorDepth, profile);
0336     Q_ASSERT(cs);
0337 
0338     QColor qc(Qt::white);
0339     KoColor bgColor(qc, cs);
0340 
0341     if (!document->newImage(name, width, height, cs, bgColor, KisConfig::RASTER_LAYER, 1, "", double(resolution / 72) )) {
0342         return 0;
0343     }
0344 
0345     Q_ASSERT(document->image());
0346     Document *doc = new Document(document, true);
0347 
0348     return doc;
0349 }
0350 
0351 Document* Krita::openDocument(const QString &filename)
0352 {
0353     KisDocument *document = KisPart::instance()->createDocument();
0354     document->setFileBatchMode(this->batchmode());
0355     if (!document->openPath(filename, KisDocument::DontAddToRecent)) {
0356         delete document;
0357         return 0;
0358     }
0359     KisPart::instance()->addDocument(document);
0360     document->setFileBatchMode(false);
0361     return new Document(document, true);
0362 }
0363 
0364 Window* Krita::openWindow()
0365 {
0366     KisMainWindow *mw = KisPart::instance()->createMainWindow();
0367     return new Window(mw);
0368 }
0369 
0370 void Krita::addExtension(Extension* extension)
0371 {
0372     d->extensions.append(extension);
0373 }
0374 
0375 QList< Extension* > Krita::extensions()
0376 {
0377     return d->extensions;
0378 }
0379 
0380 void Krita::writeSetting(const QString &group, const QString &name, const QString &value)
0381 {
0382     KConfigGroup grp = KSharedConfig::openConfig()->group(group);
0383     grp.writeEntry(name, value);
0384 }
0385 
0386 QString Krita::readSetting(const QString &group, const QString &name, const QString &defaultValue)
0387 {
0388     KConfigGroup grp = KSharedConfig::openConfig()->group(group);
0389     return grp.readEntry(name, defaultValue);
0390 }
0391 
0392 QIcon Krita::icon(QString &iconName) const
0393 {
0394     return KisIconUtils::loadIcon(iconName);
0395 }
0396 
0397 void Krita::addDockWidgetFactory(DockWidgetFactoryBase* factory)
0398 {
0399     KoDockRegistry::instance()->add(factory);
0400 }
0401 
0402 Krita* Krita::instance()
0403 {
0404     if (!s_instance)
0405     {
0406         s_instance = new Krita;
0407     }
0408     return s_instance;
0409 }
0410 
0411 /**
0412  * Scripter.fromVariant(variant)
0413  * variant is a QVariant
0414  * returns instance of QObject-subclass
0415  *
0416  * This is a helper method for PyQt because PyQt cannot cast a variant to a QObject or QWidget
0417  */
0418 QObject *Krita::fromVariant(const QVariant& v)
0419 {
0420 
0421     if (v.canConvert< QWidget* >())
0422     {
0423         QObject* obj = qvariant_cast< QWidget* >(v);
0424         return obj;
0425     }
0426     else if (v.canConvert< QObject* >())
0427     {
0428         QObject* obj = qvariant_cast< QObject* >(v);
0429         return obj;
0430     }
0431     else
0432         return 0;
0433 }
0434 
0435 QString Krita::krita_i18n(const QString &text)
0436 {
0437     return i18n(text.toUtf8().constData());
0438 }
0439 
0440 QString Krita::krita_i18nc(const QString &context, const QString &text)
0441 {
0442     return i18nc(context.toUtf8().constData(), text.toUtf8().constData());
0443 }
0444 
0445 QString Krita::getAppDataLocation()
0446 {
0447     return KoResourcePaths::getAppDataLocation();
0448 }
0449 
0450 void Krita::mainWindowIsBeingCreated(KisMainWindow *kisWindow)
0451 {
0452     Q_FOREACH(Extension *extension, d->extensions) {
0453         Window window(kisWindow);
0454         extension->createActions(&window);
0455     }
0456 }
0457 
0458 #include "moc_Krita.cpp"