File indexing completed on 2024-12-22 04:16:28

0001 # SPDX-FileCopyrightText: 2019 Rebecca Breu <rebecca@rbreu.de>
0002 
0003 # This file is part of Krita.
0004 
0005 # SPDX-License-Identifier: GPL-3.0-or-later
0006 
0007 import html
0008 import os
0009 import tempfile
0010 
0011 import krita
0012 
0013 from PyQt5.QtCore import QStandardPaths
0014 from PyQt5.QtWidgets import QFileDialog, QMessageBox, QInputDialog
0015 
0016 from .plugin_importer import PluginImporter, PluginImportError
0017 from .plugin_downloader import download_plugin, PluginDownloadError
0018 
0019 
0020 class PluginImporterExtension(krita.Extension):
0021 
0022     def __init__(self, parent):
0023         super().__init__(parent)
0024         self.parent = parent
0025 
0026     def setup(self):
0027         pass
0028 
0029     def createActions(self, window):
0030         action = window.createAction(
0031             'plugin_importer_file',
0032             i18n('Import Python Plugin from File...'),
0033             'tools/scripts')
0034         action.triggered.connect(self.import_plugin_from_file)
0035         action = window.createAction(
0036             'plugin_importer_web',
0037             i18n('Import Python Plugin from Web...'),
0038             'tools/scripts')
0039         action.triggered.connect(self.import_plugin_from_web)
0040 
0041     def confirm_overwrite(self, plugin):
0042         reply = QMessageBox.question(
0043             self.parent.activeWindow().qwindow(),
0044             i18n('Overwrite Plugin'),
0045             i18n('The plugin "%s" already exists. Overwrite it?') % (
0046                 plugin['ui_name']),
0047             QMessageBox.Yes | QMessageBox.No)
0048         return reply == QMessageBox.Yes
0049 
0050     def confirm_activate(self, plugins):
0051         txt = [
0052             '<p>',
0053             i18n('The following plugins were imported:'),
0054             '</p>',
0055             '<ul>'
0056         ]
0057         for plugin in plugins:
0058             txt.append('<li>%s</li>' % plugin['ui_name'])
0059 
0060         txt.append('</ul>')
0061         txt.append('<p><strong>')
0062         txt.append(i18n(
0063             'Enable plugins now? (Requires restart)'))
0064         txt.append('</strong></p>')
0065 
0066         reply = QMessageBox.question(
0067             self.parent.activeWindow().qwindow(),
0068             i18n('Activate Plugins?'),
0069             ('\n').join(txt),
0070             QMessageBox.Yes | QMessageBox.No)
0071         return reply == QMessageBox.Yes
0072 
0073     def display_errors(self, error):
0074         msg = '<p>%s</p><pre>%s</pre>' % (
0075             i18n('Error during import:'),
0076             html.escape(str(error)))
0077         QMessageBox.warning(
0078             self.parent.activeWindow().qwindow(),
0079             i18n('Error'),
0080             msg)
0081 
0082     def activate_plugins(self, plugins):
0083         for plugin in plugins:
0084             Application.writeSetting(
0085                 'python',
0086                 'enable_%s' % plugin['name'],
0087                 'true')
0088 
0089     def get_resources_dir(self):
0090         return Krita.instance().getAppDataLocation()
0091 
0092     def import_plugin_from_web(self):
0093         infotext = i18n(
0094             '<p><strong>Enter download URL</strong></p>'
0095             '<p>For example:'
0096             '<ul>'
0097             '<li>Zip download link (http://example.com/plugin.zip)</li>'
0098             '<li>Github repository (https://github.com/test/plugin)</li>'
0099         )
0100         url = QInputDialog.getText(
0101             self.parent.activeWindow().qwindow(),
0102             i18n('Import Plugin'),
0103             infotext)[0]
0104         if url:
0105             with tempfile.TemporaryDirectory() as tmpdir:
0106                 try:
0107                     zipfile = download_plugin(url=url, dest_dir=tmpdir)
0108                 except PluginDownloadError as e:
0109                     self.display_errors(e)
0110                     return
0111                 self.do_import(zipfile)
0112 
0113     def import_plugin_from_file(self):
0114         zipfile = QFileDialog.getOpenFileName(
0115             self.parent.activeWindow().qwindow(),
0116             i18n('Import Plugin'),
0117             os.path.expanduser('~'),
0118             '%s (*.zip)' % i18n('Zip Archives'),
0119         )[0]
0120 
0121         if not zipfile:
0122             return
0123 
0124         self.do_import(zipfile)
0125 
0126     def do_import(self, zipfile):
0127         try:
0128             imported = PluginImporter(
0129                 zipfile,
0130                 self.get_resources_dir(),
0131                 self.confirm_overwrite
0132             ).import_all()
0133         except PluginImportError as e:
0134             self.display_errors(e)
0135             return
0136 
0137         if imported:
0138             activate = self.confirm_activate(imported)
0139             if activate:
0140                 self.activate_plugins(imported)