File indexing completed on 2024-12-22 04:15:08

0001 /*
0002  * SPDX-FileCopyrightText: 2014 Boudewijn Rempt (boud@valdyas.org)
0003  *
0004  *  SPDX-License-Identifier: LGPL-2.0-only
0005  */
0006 
0007 #include "plugin.h"
0008 
0009 #include <klocalizedstring.h>
0010 #include <kis_debug.h>
0011 #include <kpluginfactory.h>
0012 
0013 #include <kis_preference_set_registry.h>
0014 #include "pyqtpluginsettings.h"
0015 
0016 #include <QCoreApplication>
0017 
0018 #include <Krita.h>
0019 
0020 K_PLUGIN_FACTORY_WITH_JSON(KritaPyQtPluginFactory, "kritapykrita.json", registerPlugin<KritaPyQtPlugin>();)
0021 
0022 KritaPyQtPlugin::KritaPyQtPlugin(QObject *parent, const QVariantList &)
0023     : QObject(parent)
0024     , m_autoReload(false)
0025 {
0026     dbgScript << "Loading Python plugin";
0027 
0028     PyKrita::InitResult initResult = PyKrita::initialize();
0029     switch (initResult) {
0030         case PyKrita::INIT_OK:
0031             break;
0032         case PyKrita::INIT_CANNOT_LOAD_PYTHON_LIBRARY:
0033             qWarning() << i18n("Cannot load Python library");
0034             return;
0035         case PyKrita::INIT_CANNOT_SET_PYTHON_PATHS:
0036             qWarning() << i18n("Cannot set Python paths");
0037             return;
0038         case PyKrita::INIT_CANNOT_LOAD_PYKRITA_MODULE:
0039             qWarning() << i18n("Cannot load built-in pykrita module");
0040             return;
0041         default:
0042             qWarning() << i18n("Unexpected error initializing python plugin.");
0043             return;
0044     }
0045 
0046     pluginManager = PyKrita::pluginManager();
0047 
0048     KisPreferenceSetRegistry *preferenceSetRegistry = KisPreferenceSetRegistry::instance();
0049     PyQtPluginSettingsFactory* settingsFactory = new PyQtPluginSettingsFactory(pluginManager);
0050 
0051     //load and save preferences
0052     //if something in kritarc is missing, then the default from this load function will be used and saved back to kconfig.
0053     //this way, cfg.readEntry() in any part won't be able to set its own default
0054     KisPreferenceSet* settings = settingsFactory->createPreferenceSet();
0055     KIS_SAFE_ASSERT_RECOVER_RETURN(settings);
0056     settings->loadPreferences();
0057     settings->savePreferences();
0058     delete settings;
0059 
0060     preferenceSetRegistry->add("PyQtPluginSettingsFactory", settingsFactory);
0061 
0062     // Try to import the `pykrita` module
0063     PyKrita::Python py = PyKrita::Python();
0064     PyObject* pykritaPackage = py.moduleImport("pykrita");
0065     pykritaPackage = py.moduleImport("krita");
0066 
0067     if (pykritaPackage) {
0068         dbgScript << "Loaded pykrita, now load plugins";
0069         pluginManager->scanPlugins();
0070         pluginManager->tryLoadEnabledPlugins();
0071         //py.functionCall("_pykritaLoaded", PyKrita::Python::PYKRITA_ENGINE);
0072     } else  {
0073         dbgScript << "Cannot load pykrita module";
0074     }
0075 
0076     Q_FOREACH (Extension *extension, Krita::instance()->extensions()) {
0077         extension->setup();
0078     }
0079 
0080     // This ensures that QObject's owned by Python are destructed before
0081     // the destructor of QCoreApplication is called, in order to prevent
0082     // a crash on exit.
0083     // See https://bugs.kde.org/show_bug.cgi?id=417465
0084     // XXX: Commented out because this still can cause crashes:
0085     // https://invent.kde.org/graphics/krita/-/commit/a0c29913114164ff3f2ba4e255ccee1c52cb3e86#note_260688
0086     // connect(QCoreApplication::instance(), &QCoreApplication::aboutToQuit, this, []() { PyKrita::finalize(); });
0087 }
0088 
0089 KritaPyQtPlugin::~KritaPyQtPlugin()
0090 {
0091     // Don't call PyKrita::finalize here, because that can result in a crash
0092     // deep inside Qt.
0093 }
0094 
0095 #include "plugin.moc"