File indexing completed on 2024-05-12 15:59:06

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     return mainWindow->dockWidgets();
0312 }
0313 
0314 
0315 QStringList Krita::recentDocuments() const
0316 {
0317     KConfigGroup grp = KSharedConfig::openConfig()->group(QString("RecentFiles"));
0318     QStringList keys = grp.keyList();
0319     QStringList recentDocuments;
0320 
0321     for(int i = 0; i <= keys.filter("File").count(); i++)
0322         recentDocuments << grp.readEntry(QString("File%1").arg(i), QString(""));
0323 
0324     return recentDocuments;
0325 }
0326 
0327 Document* Krita::createDocument(int width, int height, const QString &name, const QString &colorModel, const QString &colorDepth, const QString &profile, double resolution)
0328 {
0329     KisDocument *document = KisPart::instance()->createDocument();
0330     document->setObjectName(name);
0331 
0332     KisPart::instance()->addDocument(document, false);
0333     const KoColorSpace *cs = KoColorSpaceRegistry::instance()->colorSpace(colorModel, colorDepth, profile);
0334     Q_ASSERT(cs);
0335 
0336     QColor qc(Qt::white);
0337     KoColor bgColor(qc, cs);
0338 
0339     if (!document->newImage(name, width, height, cs, bgColor, KisConfig::RASTER_LAYER, 1, "", double(resolution / 72) )) {
0340         return 0;
0341     }
0342 
0343     Q_ASSERT(document->image());
0344     Document *doc = new Document(document, true);
0345 
0346     return doc;
0347 }
0348 
0349 Document* Krita::openDocument(const QString &filename)
0350 {
0351     KisDocument *document = KisPart::instance()->createDocument();
0352     document->setFileBatchMode(this->batchmode());
0353     if (!document->openPath(filename, KisDocument::DontAddToRecent)) {
0354         delete document;
0355         return 0;
0356     }
0357     KisPart::instance()->addDocument(document);
0358     document->setFileBatchMode(false);
0359     return new Document(document, true);
0360 }
0361 
0362 Window* Krita::openWindow()
0363 {
0364     KisMainWindow *mw = KisPart::instance()->createMainWindow();
0365     return new Window(mw);
0366 }
0367 
0368 void Krita::addExtension(Extension* extension)
0369 {
0370     d->extensions.append(extension);
0371 }
0372 
0373 QList< Extension* > Krita::extensions()
0374 {
0375     return d->extensions;
0376 }
0377 
0378 void Krita::writeSetting(const QString &group, const QString &name, const QString &value)
0379 {
0380     KConfigGroup grp = KSharedConfig::openConfig()->group(group);
0381     grp.writeEntry(name, value);
0382 }
0383 
0384 QString Krita::readSetting(const QString &group, const QString &name, const QString &defaultValue)
0385 {
0386     KConfigGroup grp = KSharedConfig::openConfig()->group(group);
0387     return grp.readEntry(name, defaultValue);
0388 }
0389 
0390 QIcon Krita::icon(QString &iconName) const
0391 {
0392     return KisIconUtils::loadIcon(iconName);
0393 }
0394 
0395 void Krita::addDockWidgetFactory(DockWidgetFactoryBase* factory)
0396 {
0397     KoDockRegistry::instance()->add(factory);
0398 }
0399 
0400 Krita* Krita::instance()
0401 {
0402     if (!s_instance)
0403     {
0404         s_instance = new Krita;
0405     }
0406     return s_instance;
0407 }
0408 
0409 /**
0410  * Scripter.fromVariant(variant)
0411  * variant is a QVariant
0412  * returns instance of QObject-subclass
0413  *
0414  * This is a helper method for PyQt because PyQt cannot cast a variant to a QObject or QWidget
0415  */
0416 QObject *Krita::fromVariant(const QVariant& v)
0417 {
0418 
0419     if (v.canConvert< QWidget* >())
0420     {
0421         QObject* obj = qvariant_cast< QWidget* >(v);
0422         return obj;
0423     }
0424     else if (v.canConvert< QObject* >())
0425     {
0426         QObject* obj = qvariant_cast< QObject* >(v);
0427         return obj;
0428     }
0429     else
0430         return 0;
0431 }
0432 
0433 QString Krita::krita_i18n(const QString &text)
0434 {
0435     return i18n(text.toUtf8().constData());
0436 }
0437 
0438 QString Krita::krita_i18nc(const QString &context, const QString &text)
0439 {
0440     return i18nc(context.toUtf8().constData(), text.toUtf8().constData());
0441 }
0442 
0443 QString Krita::getAppDataLocation()
0444 {
0445     return KoResourcePaths::getAppDataLocation();
0446 }
0447 
0448 void Krita::mainWindowIsBeingCreated(KisMainWindow *kisWindow)
0449 {
0450     Q_FOREACH(Extension *extension, d->extensions) {
0451         Window window(kisWindow);
0452         extension->createActions(&window);
0453     }
0454 }
0455 
0456 #include "moc_Krita.cpp"