Jak stworzyć wtyczkę Pythona dla Krity

Możesz posiadać swoje ciekawie napisane skrypty w środowisku uruchomieniowym Scripter Python, które możesz chcieć uruchamiać samoczynnie dla wystąpienie. Owijając swój skrypt we wtyczkę, możesz nadać mu więcej możliwości, niż te które ma, będąc wykonywanym z edytora Scripter.

Ok, więc nawet jeśli znasz bardzo dobrze Pythona, to istnieje kilka szczegółów odnośnie tego jak Krita rozpoznaje wtyczki Pythona. Ta strona daje pogląd na temat tego jak tworzyć różne rodzaje skryptów Pythona, które są wyjątkowe dla Krity.

Te mini-samouczki zostały napisane dla ludzi o podstawowej wiedzy nt Pythona i przez to mają zachęcać ludzi do próbowania zamiast zwykłego powielana kodu, więc czytaj ten tekst uważnie.

Umożliwienie Kricie rozpoznanie twojej wtyczki

Skrypt w Kricie ma dwa składniki – katalog skryptu (zawierający twoje pliki skryptów Python) oraz plik „.desktop”, których Krita używa do wczytywania i rejestrowania twoich skryptów. Aby Krita mogła wczytać twój skrypt, to oba te składniki muszą znaleźć się w podkatalogu pykrita twojego katalogu zasobów Krity (Aby poznać ścieżki dla danego systemu operacyjnego zajrzyj do ref:resource_management). Aby odnaleźć swój katalog zasobów, uruchom Kritę i wybierz z menu Ustawienia ‣ Zarządzaj zasobami…. Otworzy to okno dialogowe. Naciśnij na przycisk Otwórz katalog zasobów. Powinno to otworzyć przeglądarkę plików na twoim systemie w miejscu zasobów Krity. Zajrzyj do dokumentacji API w miejscu „Samoczynne uruchamianie skryptów”. Jeśli nie ma podkatalogu pykrita w katalogu zasobów Krity, to użyj swojej przeglądarki plików, aby taki stworzyć.

Skrypty są rozpoznawane po plikach, które są zakończone rozszerzeniem .``.desktop``, który zawiera dane o samym skrypcie.

Dlatego, dla każdej wtyczki będziesz musiał stworzyć katalog i dodać plik desktop.

Plik desktop powinien wyglądać następująco:

[Desktop Entry]
Type=Service
ServiceTypes=Krita/PythonPlugin
X-KDE-Library=mojawtyczka
X-Python-2-Compatible=false
X-Krita-Manual=podręcznikMojejWtyczki.html
Name=Moja własna wtyczka
Comment=Nasza własna wtyczka.
Rodzaj

To zawsze powinno usługą.

ServiceTypes

To zawsze powinno być Krita/PythonPlugin dla wtyczek Pythona.

X-KDE-Library

To powinno być nazwą katalogu wtyczki, którą właśnie stworzyłeś.

Zgodne-z-X-Python-2

Określa czy jest zgodne z Pythonem 2. Jeśli Krita została zbudowana na Pythonie 2 zamiast 3 (-DENABLE_PYTHON_2=ON w ustawieniach cmake), to wtyczka ta nie pojawi się na liście.

X-Krita-Manual

Opcjonalna wartość, która będzie wskazywać na element menu. Jest to pokazywane w zarządzaniu wtyczkami Pythona. Jeśli jest to plik HTML, to zostanie pokazany jako tekst formatowany <https://doc.qt.io/qt-5/richtext-html-subset.html>`_, a jeśli nie, to jako zwykły tekst.

Nazwa

Nazwa, która pojawi się w zarządzaniu wtyczkami Pythona.

Komentarz

Opis, który pojawi się w zarządzaniu wtyczkami Pythona.

Wtyczki Pythona dla Krity muszą być modułami Python, więc upewnij się, że zawierają one skrypt __init__.py, który zawiera coś takiego…

z .mojawtyczka import *

Gdzie .myplugin jest nazwą głównego pliku twojej wtyczki. Jeśli uruchomisz Kritę ponownie, to powinno się to pojawić w Zarządzaniu Wtyczkami Pythona w ustawieniach, lecz będzie wyszarzone, bo nie ma myplugin.py. Jeśli najedziesz na wyłączone wtyczki, to zobaczysz na nich błąd.

Informacja

Musisz jednoznacznie włączyć swoją wtyczkę. Przejdź do menu ustawień, otwórz okno dialogowe Ustawienia Krity i przejdź do strony zarządzania wtyczkami Pythona, gdzie musisz włączyć swoją wtyczkę.

Podsumowanie

Podsumowując, jeśli chcesz stworzyć skrypt o nazwie mojawtyczka:

  • w swoim katalogu Krita resources/pykrita stwórz
    • katalog o nazwie mojawtyczka

    • plik o nazwie mojawtyczka.desktop

  • w katalogu mojawtyczka utwórz
    • plik o nazwie __init__.py

    • plik o nazwie mojawtyczka.py

  • w pliku __init__.py umieść ten kod:

z .mojawtyczka import *
  • w pliku desktop umieść ten kod:

    [Desktop Entry]
    Type=Service
    ServiceTypes=Krita/PythonPlugin
    X-KDE-Library=mojawtyczka
    X-Python-2-Compatible=false
    Name=Moja własna wtyczka
    Comment=Nasza własna wtyczka.
    
  • napisz swój skrypt w pliku 'mojawtyczka/mojawtyczka.py'.

Tworzenie rozszerzenia

Rozszrzenia są stosunkowo prostymi skryptami Pythona, które są uruchamiane wraz z uruchomieniem Krity. Są stworzone jako rozszerzenia klas, a najbardziej podstawowe rozszerzenie wygląda tak:

from krita import *

class MyExtension(Extension):

    def __init__(self, parent):
        #To rozpoczyna element nadrzędny,  zawsze ważne przy tworzeniu klas pochodnych.
        super().__init__(parent)

    def setup(self):
        pass

    def createActions(self, window):
        pass

# Oraz dodaj rozszerzenie do listy rozszerzeń Krity:
Krita.instance().addExtension(MyExtension(Krita.instance()))

Ten kod oczywiście nie robi nic. w createActions zazwyczaj dodajemy działania Krity, tak abyśmy mogli uzyskać dostęp do naszego skryptu z menu Narzędzia.

Najpierw utwórzmy działanie. Możemy to łatwo zrobić poprzez Window.createAction(). Krita wywoła createActions dla każdego Okna, które zostanie stworzone i przekaże właściwy obiekt okna, którego musimy użyć.

Więc…

def createActions(self, window):
    action = window.createAction("mojeDziałanie", "Mój skrypt", "tools/scripts")
„mojeDziałanie”

To powinno być zastąpione niepowtarzalnym ID, którego Krita użyje do znalezienia działania.

„Mój skrypt”

To co jest widoczne w Menu narzędzi.

Teraz jeśli ponownie uruchomisz Kritę, to będziesz miał działanie o nazwie „Mój skrypt”. Nadal nie robi on nic, bo nie podłączyliśmy go do skryptu.

Tak więc, przygotujmy prosty skrypt do eksportu dokumentów. Dodaj następujące wiersze do rozszerzonej klasy, upewnij się, że jest powyżej względem tego, gdzie dodajesz rozszerzenie do Krity:

def exportDocument(self):
    # Pobierz dokument:
    doc =  Krita.instance().activeDocument()
    # Zapisanie nieistniejącego dokumentu powoduje usterkę, więc sprawdź to najpierw.
    if doc is not None:
        # To wywołuje okno dialogowe zapisu. Okno to zwraca daną rodzaju tuple.
        fileName = QFileDialog.getSaveFileName()[0]
        # Oraz wyeksportuj dokument do miejsca określonego zmienną fileName.
        # InfoObject jest słownikiem z danymi ustawieniami eksportu, lecz gdy będzie pusty, to Krita użyje domyślnych ustawień.
        doc.exportImage(fileName, InfoObject())

Oraz dodaj import dla QFileDialog powyżej przy użyciu następujących wierszy:

from krita import *
from PyQt5.QtWidgets import QFileDialog

Następnie, aby podłączyć działanie do nowo wyeksportowanego dokumentu:

def createActions(self, window):
    action = window.createAction("mojeDziałanie", "Mój skrypt")
    action.triggered.connect(self.exportDocument)

Jest to przykład połączenia sygnał/slot, którego aplikacje Qt, takie jak Krita, często używają. Przejdziemy przez to jak tworzyć własne sygnały i sloty trochę później.

Uruchom Kritę ponownie, a twoje nowe działanie powinno teraz móc eksportować dokumenty.

Tworzenie skrótów klawiszowych do ustawienia

Teraz, twoje nowe działanie nie pokazuje się w Ustawienia ‣ Ustawienia Krity… ‣ Skróty klawiszowe.

Krita, z różnych powodów, dodaje działania tylko do Ustawienia skrótów, gdy są dostępne w pliku .action. Plik .action powinien wyglądać następująco, aby można było z niego dodać skróty:

<?xml version="1.0" encoding="UTF-8"?>
<ActionCollection version="2" name="Scripts">
    <Actions category="Scripts">
        <text>Moje skrypty</text>

        <Action name="myAction">
        <icon></icon>
        <text>Mój skrypt</text>
        <whatsThis></whatsThis>
        <toolTip></toolTip>
        <iconText></iconText>
        <activationFlags>10000</activationFlags>
        <activationConditions>0</activationConditions>
        <shortcut>ctrl+alt+shift+p</shortcut>
        <isCheckable>false</isCheckable>
        <statusTip></statusTip>
        </Action>
    </Actions>
</ActionCollection>
<text>Moje skrypty</text>

Stworzy to podkategorię w skryptach o nazwie „Moje skrypt”, aby dodać do nich skróty.

nazwa

To powinno być niepowtarzalnym ID, który nadałeś swojemu działaniu przy tworzeniu go w ustawieniach rozszerzenia.

ikona

Nazwa możliwej ikony. Pokaże się to tylko w Plazmie KDE, bo użytkownicy Gnome oraz Windowsa narzekali, że wygląda to brzydko.

tekst

Tekst, który pojawi się w edytorze skrótów.

coTo

Tekst, który wyświetli się po wywołaniu «co to jest», co jest działaniem skierowanym na pomoc użytkownikowi.

Podpowiedź

Wskazówka narzędzia, która pojawi się po najechaniu na nie.

tekstIkony

Tekst pojawi się teraz, gdy będzie wyświetlany na pasku narzędzi. Na przykład „Zmień rozmiar obrazu do nowego” można skrócić do „Zmień rozmiar obrazu”, aby zaoszczędzić przestrzeń, tak więc umieścilibyśmy to tutaj.

flagiUruchomienia

Określa to kiedy działanie jest wyłączone, a kiedy nie.

warunkiUruchomienia

Określa to warunki uruchomienia (np. uruchom tylko gdy zaznaczenie jest możliwe do zmiany). Po przykłady obejrzyj kod.

skrót

Domyślny skrót.

isCheckable

Określa czy to jest pole zaznaczane, czy nie.

wskazówkaStanu

Wskazówka stanu wyświetlana na pasku stanu.

Zapisz ten plik jako myplugin.action, gdzie myplugin jest nazwą twojej wtyczki. Plik działania powinien zostać zapisany, nie w katalogu zasobów pykrita, lecz raczej w katalogu zasobów o nazwie „actions”. (Tak więc, share/pykrita jest miejscem, do którego trafiają wtyczki pythona i pliki desktop, a share/actions gdzie trafiają pliki działań) Uruchom Kritę ponownie. Skrót powinien teraz pojawić się na liście skrótów.

Tworzenie doku

Tworzenie własnego doku jest podobne do tworzenia rozszerzenia. Doki są w pewnym sensie łatwiejsze, lecz wymagają także większego używania elementów interfejsu. Jest to szkielet kod doku:

from PyQt5.QtWidgets import *
from krita import *

class MyDocker(DockWidget):

    def __init__(self):
        super().__init__()
        self.setWindowTitle("My Docker")

    def canvasChanged(self, canvas):
        pass

Krita.instance().addDockWidgetFactory(DockWidgetFactory("myDocker", DockWidgetFactoryBase.DockRight, MyDocker))

Tytuł okna pojawi się na liście doku w Kricie. canvasChanged musi być zawsze obecny, lecz nie musisz z nim nic robić, więc wystarczy, że dodasz «pass».

Dla addDockWidgetFactory…

„mójDok”

Zastąp to niepowtarzalnym ID dla twojego doku, którego Krita używa, aby to działanie śledzić.

DockWidgetFactoryBase.DockRight

Położenia. Może to być DockTornOff, DockTop, DockBottom, DockRight, DockLeft``lub ``DockMinimized

MójDok

Zastąp to nazwą klasy doku, który chcesz dodać.

Tak więc, jeśli dodamy naszą funkcję eksportu dokumentu, którą utworzyliśmy w tym dziale rozszerzenia do kodu doku, to jak mamy umożliwić użytkownikowi jego używanie? Najpierw, potrzebujemy trochę kodu interfejsu Qt: Dodajmy przycisk!

Domyślnie Kirta używa PyQt, lecz jego dokumentacja jest bardzo słaba, zazwyczaj ponieważ dokumentacja Qt jest na prawdę dobra i często zauważysz, że dokumentacja PyQt klasy, mówi , QWidget tak jakby była to dziwna kopia zwykłej dokumentacji Qt dla tej klasy.

Mimo wszystko, to co musimy najpierw zrobić, to utworzyć QWidget, co nie jest trudne. Wystarczy dodać pod setWindowTitle:

mainWidget = QWidget(self)
self.setWidget(mainWidget)

Następnie tworzymy przycisk:

buttonExportDocument = QPushButton("Eksportuj dokument", mainWidget)

Teraz, aby podłączyć nasz przycisk do funkcji, będziemy musieli spojrzeć na sygnały w dokumentacji. QPushButton ma swoje niepowtarzalne sygnały, lecz mówi także, że dziedziczy 4 sygnały z QAbstractButton, co oznacza, że możemy ich także użyć. W tym przypadku, chcemy sygnału „clicked”.

buttonExportDocument.clicked.connect(self.exportDocument)

Teraz jeśli ponownie uruchomimy Kritę, to będziemy mieli nowy dok, a w nim przycisk. Naciśnięcie na nim wywoła funkcję eksportu.

Jednakże, przycisk jest trochę dziwnie wyrównany. Powodem jest to, że nasz mainWidget nie ma układu. Nadajmy mu szybko taki układ:

mainWidget.setLayout(QVBoxLayout())
mainWidget.layout().addWidget(buttonExportDocument)

Qt ma kilka układów, lecz QHBoxLayout oraz QVBoxLayout są najłatwiejszymi w użyciu, bo układają elementy interfejsu w poziomie i pionie.

Uruchom Kritę ponownie, a przycisk powinien być teraz ładnie rozmieszczony.

Sygnały i sloty PyQt

Już używaliśmy sygnałów i slotów PyQt, lecz czasami potrzebujesz utworzyć swój własny sygnał i slot. Jako iż dokumentacja PyQt jest całkiem trudna w zrozumieniu, oraz z tego powodu, że tworzenie sygnałów i slotów różni się bardzo od tego w C++ Qt, to wyjaśniliśmy to tutaj:

Wszystkie funkcje, które tworzysz w PyQt, są także rozumiane jako sloty, co oznacza, że można je podłączyć do sygnałów takich jak Action.triggered` lub ``QPushButton.clicked. Jednakże QCheckBox ma sygnał dla toggled, który wysyła zmienną zerojedynkową. Jak sprawić, aby nasza funkcja przyjmowała zmienną zerojedynkową?

Najpierw upewnij się, czy masz właściwe wiersze importujące do tworzenia własnych slotów:

from PyQt5.QtCore import pyqtSlot

(Jeśli istnieje from PyQt5.QtCore import * na liście importów, to oczywiście nie musisz tego robić.)

Następnie, musisz dodać definicję slotu PyQt przed swoją funkcją:

@pyqtSlot(bool)
def myFunction(self, enabled):
    enabledString = "disabled"
    if (enabled == True):
        enabledString = "enabled"
    print("Pole zaznaczane jest "+enabledString)

Gdy już utworzysz swoje pole zaznaczane, to możesz zrobić coś takiego myCheckbox.toggled.connect(self.myFunction).

Podobnie, aby tworzyć swoje własne sygnały PyQt, robisz następującą rzecz:

# nazwa sygnału jest dodana do zmiennych członkowskich klasy
signal_name = pyqtSignal(bool, name='signalName')

def emitMySignal(self):
    # A oto sposób w jaki wywołujesz wysyłanie sygnału.
    self.signal_name.emit(True)

I użyj właściwych wierszy importu:

from PyQt5.QtCore import pyqtSignal

Aby wywołać lub stworzyć sloty dla obiektów, które nie są standardowymi obiektami Pythona, musisz tylko zawrzeć ich nazwy w cudzysłowach.

Uwaga dotycząca testów jednostkowych

Jeśli chcesz napisać testy jednostkowe dla twojej wtyczki, to spójrz na makieta modułu Krity.

Wnioski

Ok, więc to pokrywa wszystkie szczegóły dotyczące tworzenia wtyczek Pythona. Nie zajmuje się jednak tym jak przetwarzać dane pikselowe, czy najlepszych praktyk związanych z dokumentami, lecz jeśli masz już trochę doświadczenia z Pythonem, to powinieneś móc rozpocząć tworzyć swoje własne wtyczki.

Jak zawsze, przeczytaj kod uważnie, a także dokumentację API dla Pythona, Krity oraz Qt, aby zobaczyć, co jest możliwe, a tym sposobem zajdziesz daleko.