Krita’da Python eklentisi yapımı

Betikleyici Python penceresinde gayet güzel betikler yazmış olabilirsiniz; ancak belki daha fazlasını yapmak isterseniz; örneğin kendiliğinden çalıştırmak gibi, onları bir eklenti içine koyarak Betikleyici düzenleyicisinden çok daha fazla güç ve esneklik kazanabilirsiniz.

Tamam, Python’u gerçekten iyi biliyor olsanız bile, Krita’nın bir Python eklentisini tanımasını sağlamak için bazı küçük ayrıntılar vardır. Bu yüzden bu sayfa, Krita’ya özgü çeşitli Python betik türlerinin nasıl oluşturulacağına dair genel bir bakış sunacaktır.

Bu mini öğreticiler, temel python bilgisine sahip kişiler için ve kodu kopyalayıp yapıştırmak yerine denemeyi teşvik edecek şekilde yazılmıştır, bu nedenle metni dikkatlice okuyun.

Krita’nın eklentinizi tanımasını sağlamak

Krita’daki bir betiğin iki bileşeni vardır – betik dizini (betiğinizin Python dosyalarını içeren dosyalar) ve Krita’nın betiğinizi kaydetmek ve yüklemek için kullandığı bir “.desktop” dosyası. Krita’nın betiğinizi yükleyebilmesi içim bu iki dosya, Krita özkaynaklarınızın pykrita alt dizinine koyulmalıdır (işletim sistemlerinin kullandığı yollar için Özkaynak Yönetimi bölümüne bakın. Özkaynaklar klasörünüzü bulmak için Krita’yı başlatın ve Ayarlar ‣ Özkaynakları Yönet… menü ögesine tıklayın. Bu, bir iletişim kutusu açar. Özkaynaklar Klasörünü Aç düğmesine tıklayın. Bu bir dosya yöneticisinde Krita’nın özkaynaklar klasörünü gösterir. “Auto starting scripts” hakkındaki API belgelerine bakın. Krita özkaynaklar dizininde bir pykrita klasörü yoksa bir tane yaratmak için dosya yöneticinizi kullanın.

Betikler, betiğin kendisi üzerine bilgi veren bir .desktop dosyasıyla tanımlanırlar.

Bundan dolayı, her bir doğru betik için bir klasör ve bir Desktop dosyası yaratmanız gerekir.

Desktop dosyası aşağıdaki gibi görünmelidir:

[Desktop Entry]
Type=Service
ServiceTypes=Krita/PythonPlugin
X-KDE-Library=eklentim
X-Python-2-Compatible=false
X-Krita-Manual=myPluginManual.html
Name=Benim Eklentim
Comment=Benim yaptığım eklentim.
Type

Bu, her zaman bir hizmet olmalıdır.

ServiceTypes

Python eklentileri için bu her zaman Krita/PythonPlugin olmalıdır.

X-KDE-Library

Bu, şimdi yarattığınız eklenti klasörünün adı olmalıdır.

X-Python-2-Compatible

Python 2 ile uyumlu olup olmadığı. Krita Python 3 yerine 2 ile yapılmışsa (cmake yapılandırmasında -DENABLE_PYTHON_2=ON) bu eklenti listede görünmez.

X-Krita-Manual

Elle belirtilen ögeye işaret eden isteğe bağlı bir değer. Bu, Python Eklentisi Yöneticisi’nde gösterilir. Bir HTML dosyasıysa zengin metin olarak gösterilir, değilse düz metin olarak kullanılır.

Ad

Python Eklentisi Yöneticisi’nde gösterilecek ad.

Comment

Python Eklentisi Yöneticisi’nde gösterilecek açıklama.

Krita’nın Python eklentilerinin Python modülleri olması gerekir, bu nedenle şöyle bir şeyler içeren bir __init__.py betiğinin olduğundan emin olun…

from .eklentim import *

.eklentim, eklentinizin ana dosyasının adıdır. Krita’yı yeniden başlatırsanız Ayarlar’da Python Eklentisi Yöneticisi bölümünde bu adla görünmelidir. Henüz gridir; çünkü bir eklentim.py dosyası yoktur. Devre dışı bırakılan eklentilerin üzerine fareyle gelirseniz hatanın kendisini görebilirsiniz.

Not

Eklentinizi açıkça etkinleştirmeniz gerekir. Ayarlar menüsünden Krita’yı Yapılandır iletişim kutusunu açıp Python Eklentisi Yöneticisi sekmesine gidin ve eklentinizi etkinleştirin.

Özet

Özet olarak, eklentim adında bir betik oluşturmak istiyorsanız:

  • resources/pykrita Krita dizininde şunları oluşturun:
    • eklentim adında bir klasör

    • eklentim.desktop adında bir dosya

  • eklentim klasöründe şunları oluşturun:
    • __init__.py adında bir dosya

    • eklentim.py adında bir dosya

  • __init__.py dosyasına şu kodu koyun:

from .eklentim import *
  • desktop dosyasına şu kodu koyun:

    [Desktop Entry]
    Type=Service
    ServiceTypes=Krita/PythonPlugin
    X-KDE-Library=eklentim
    X-Python-2-Compatible=false
    Name=Kendi Eklentim
    Comment=Kendi yazdığım eklenti.
    
  • betiğinizi eklentim/eklentim.py dosyasında yazın.

Bir uzantı oluşturmak

Uzantılar, Krita’nın başlangıcında çalışan görece yalın Python betikleridir. Extension sınıfını genişleterek yapılırlar ve en temel uzantılar şöyle görünürler:

from krita import *

class Uzantım(Extension):

    def __init__(self, parent):
        # Bu, üst ögeyi ilklendirir, alt sınıflara ayırırken önemlidir.
        super().__init__(parent)

    def setup(self):
        pass

    def createActions(self, window):
        pass

# Uzantıyı, Krita'nın uzantılar listesine ekleyin:
Krita.instance().addExtension(Uzantım(Krita.instance()))

Bu kod doğal olarak bir şey yapmaz. Tipik olarak, createActions içinde Krita’ya eylemler ekler ve Araçlar menüsünden betiğimize erişiriz.

İlk olarak, bir eylem oluşturalım. Bunu, Window.createAction() ile kolaylıkla yapabiliriz. Krita, oluşturulan her bir pencere için createActions’ı çağırır ve kullanmak durumunda olduğumuz doğru pencere nesnesini geçirir.

Demeli…

def createActions(self, window):
    action = window.createAction("eylemim", "Betiğim", "tools/scripts")
“eylemim”

Bu, Krita’nın eylemi bulmak için kullanacağı benzersiz bir kimlikle değiştirilmelidir.

“Betiğim”

Bu, Araçlar Menüsü içinde görünür olacak şeydir.

Krita’yı şimdi yeniden başlatırsanız “Betiğim” adında bir eyleminiz olacaktır. Henüz bir şey yapmaz; çünkü onu bir betiğe bağlamadık.

Şimdi basit bir belge dışa aktarma betiği yapalım. Aşağıdakini Extension sınıfına ekleyin; onun Krita’ya uzantıları eklediğiniz yerin üzerinde olduğundan emin olun.

def exportDocument(self):
    # Belgeyi alın:
    doc =  Krita.instance().activeDocument()
    # Var olmayan bir belgeyi kaydetmek çökmeye neden olur, buna bakalım.
    if doc is not None:
        # Bu, bir ikili döndüren kaydet iletişim kutusunu çağırır.
        fileName = QFileDialog.getSaveFileName()[0]
        # Belgeyi fileName konumuna dışa aktarın.
        # InfoObject, belirli dışa aktarma seçenekleri içeren bir sözlüktür; ancak boş bir tane yaparsak Krita öntanımlı dışa aktarma ayarlarını kullanır.
        doc.exportImage(fileName, InfoObject())

İçe aktarmayı yukarıda QFileDialog ile ekleyin:

from krita import *
from PyQt5.QtWidgets import QFileDialog

Sonrasında, eylemi yeni dışa aktarılan belgeye bağlayın:

def createActions(self, window):
    action = window.createAction("eylemim", "Betiğim")
    action.triggered.connect(self.exportDocument)

Bu, Krita gibi Qt uygulamalarının çok kullandığı bir sinyal/yuva bağlantısı örneğidir. Kendi sinyallerimizi ve yuvalarımızı yapmayı daha sonra göreceğiz.

Krita’yı yeniden başlatın ve yeni eyleminiz artık belgeyi dışa aktarmalıdır.

Yapılandırılabilir klavye kısayolları oluşturmak

Şimdi, yeni eyleminiz Ayarlar ‣ Krita’yı Yapılandır ‣ Klavye Kısayolları bölümünde görünmez.

Krita, çeşitli nedenlerden dolayı eylemleri yalnızca bir .action dosyasında varken Kısayol Ayarları bölümüne ekler. Eylemimizi kısayollara eklemek için gereken eylem dosyası şuna benzemelidir:

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

        <Action name="myAction">
        <icon></icon>
        <text>My Script</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>Betiklerim</text>

Bu, kısayollarınızı eklemeniz için “Betiklerim” adında bir alt kategori oluşturur

name

Bu, uzantının kurulumunda eyleminizi oluştururken oluşturduğunuz benzersiz kimlik olmalıdır.

icon

Olası bir simgenin adı. GNOME ve Windows kullanıcıları çirkin göründüklerinden şikayet ettikleri için bunlar yalnızca KDE Plasma’da görünecek.

text

Kısayol düzenleyicide görünecek metin.

whatsThis

Bir Qt uygulaması, bir yardım eylemi olan ‘Bu Nedir?’i çağırdığında görünecek metin.

toolTip

Fareyle üzerine gelindiğinde görünecek olan araç ipucu.

iconText

Bir araç çubuğunda gösterilecek metin. Örneğin, “Görseli Yeni Bir Boyuta Yeniden Boyutlandır” adlı bir kısayol “Görseli Boyutlandır” olarak kısaltılabilir.

activationFlags

Bu, bir eylemin ne zaman devre dışı olup olmadığını belirler.

activationConditions

Bu, etkinleştirme koşullarını belirler (örneğin, yalnızca seçim düzenlenebilirken etkinleştir). Örnekler için koda bakın.

shortcut

Öntanımlı kısayol.

isCheckable

Bunun bir onay kutusu olup olmadığı.

statusTip

Bir durum çubuğunda görüntülenen durum ipucu.

Bu dosyayı, eklentim.action olarak kaydedin; burada eklentim, eklentinizin adıdır. Eylem dosyası pykrita özkaynaklar klasöründe değil de “actions” adındaki bir klasörde kaydedilmelidir (Demeli, share/pykrita Python eklentilerinin ve Desktop dosyalarının koyulduğu klasörken share/actions ise eylem dosyalarının klasörüdür). Krita’yı yeniden başlatın. Kısayol artık kısayol eylem listenizde görünmelidir.

Bir panel oluşturmak

Özel bir panel oluşturmak, aynı bir uzantı oluşturmak gibidir. Paneller biraz daha kolaydır; ancak daha fazla araç takımı kullanımı gerektirirler. Temel panel kodu şöyledir:

from PyQt5.QtWidgets import *
from krita import *

class MyDocker(DockWidget):

    def __init__(self):
        super().__init__()
        self.setWindowTitle("Panelim")

    def canvasChanged(self, canvas):
        pass

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

Pencere başlığı, Krita’nın paneller listesinde nasıl görüneceğini belirler. canvasChanged’in her zaman olması gerekir; ancak onunla bir şey yapmanız gerekmeyebilir; dolayısıyla ‘pass’ yapabilirsiniz.

addDockWidgetFactory için…

“panelim”

Bunu, Krita’nın panelinizi takip etmek için kullanacağı benzersiz bir kimlikle değiştirin.

DockWidgetFactoryBase.DockRight

Konumu. Bunlar; DockTornOff, DockTop, DockBottom, DockRight, DockLeft veya DockMinimized olabilir.

MyDocker

Bunu, eklemek istediğiniz panelin sınıfının adıyla değiştirin.

Böyleyken, uzantı bölümündeki belge dışa aktarma işlevimizin kodunu bu panel koduna eklemek istersek, kullanıcının onu nasıl etkinleştirmesini sağlayabiliriz? Biraz Qt Grafik Arabirim kodlaması yapmamız gerekecek: Haydi bir düğme ekleyelim!

Öntanımlı olarak Krita PyQt kullanır; ancak belgelendirmesi pek kötüdür; aslında bunun nedeni özünde Qt belgelendirmesinin çok iyi olduğundan bunu kötüymüş gibi göstermesidir. Örneğin, QWidget sınıfının PyQt belgelendirmesi, o sınıf için olan olağan Qt “belgelendirmesinin garip bir kopyası gibidir.

Her neyse, ilk yapmamız gereken bir QWidget eklemek; setWindowTitle altında şunu ekleyin:

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

Sonrasında bir düğme ekliyoruz:

buttonExportDocument = QPushButton("Belgeyi Dışa Aktar", mainWidget)

Şimdi, düğmemizi işlevimize bağlamak için belgelendirmedeki sinyallere bakacağız. QPushButton ögesinin kendine özel benzersiz sinyalleri yoktur; ancak QAbstractButton ögesinden 4 sinyal devraldığını yazar. Bu da onları da kullanabileceğimiz anlamına gelir. Bizim istediğimiz ‘clicked’.

buttonExportDocument.clicked.connect(self.exportDocument)

Krita’yı şimdi yeniden başlatırsak yeni bir panelimiz ve o panelde yeni bir düğmemiz olacak. Düğmeye tıklamak, dışa aktarma işlevini çağırır.

Hmm, düğme düzgünce hizalanmamış gibi duruyor. Bunun nedeni, mainWidget ögemizin herhangi bir yerleşime sahip olmaması. Tez yapalım:

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

Qt’nin birkaç yerleşimi vardır; ancak QHBoxLayout ve QVBoxLayout <https://doc.qt.io/qt-5/qboxlayout.html>, kullanımı en kolay olanlardır; bunlar araç takımlarını yatay veya dikey olarak düzenlerler.

Krita’yı yeniden başlatın ve düğmenin güzelce yerleştirilmiş olduğunu göreceksiniz.

PyQt Sinyalleri ve Yuvaları

PyQt sinyallerini ve yuvalarını halihazırda kullandık; ancak PyQt’nin belgelendirmesini anlamak pek güç olduğundan ve sinyal ve yuva oluşturmanın Qt C++’den pek farklı olduğundan kendi sinyallerinizi ve yuvalarınızı oluşturmak isteyeceksiniz. Bunu, burada anlattık:

PyQt’de yaptığınız tüm Python işlevlerine yuva denebilir; yani, bunlar Action.triggered veya QPushButton.clicked gibi sinyallere bağlanabilirler. Ancak, QCheckBox ögesinin açma/kapatma işlevi için bir Boole değeri sinyali vardır. İşlevimizin bu Boole değerini anlamasını nasıl sağlarız?

Öncelikle, özel yuvalar yapmak için doğru kitaplığı içe aktardığımızdan emin olalım:

from PyQt5.QtCore import pyqtSlot

(İçe aktarmalar içinde halihazırda bir from PyQt5.QtCore import * varsa bunu yapmanıza gerek yoktur.)

Sonrasında, işlevinizden önce bir PyQt yuva tanımı eklemeniz gerekir:

@pyqtSlot(bool)
def myFunction(self, enabled):
    enabledString = "devre dışı"
    if (enabled == True):
        enabledString = "etkin"
    print("Onay kutusu "+enabledString)

Onay kutunuzu etkinleştirdikten sonra myCheckbox.toggled.connect(self.myFunction) gibi bir şey yapabilirsiniz.

Benzer olarak, kendi PyQt sinyalleriniz için şunu yaparsınız:

# sinyal adı, sınıfın üye değişkenlerine eklenir
signal_name = pyqtSignal(bool, name='signalName')

def emitMySignal(self):
    # Bu da yayılacak sinyalin nasıl tetikleneceğidir.
    self.signal_name.emit(True)

Doğru içe aktarmayı kullanmayı unutmayın:

from PyQt5.QtCore import pyqtSignal

Standart Python nesnesi olmayan nesneler için yuvalar yaymak veya oluşturmak için onların adlarını tırnak içine almanız yeterlidir.

Birim sınamaları üzerine bir not

Eklentiniz için birim sınamaları yazmak istiyorsanız mock Krita modülüne bakın.

Sonuç

Bu belge, Python eklentileri oluşturmak için Krita’ya özgü tüm ayrıntıları kapsıyor. Piksel verisinin nasıl ayrıştırılacağını veya belgelerle ilgili en iyi uygulamaları ele almaz; ancak Python ile biraz deneyiminiz varsa kendi eklentilerinizi oluşturmaya başlayabilmeniz gerekir.

Her zaman dediğimiz gibi; Krita, Python ve Qt API belgelerini okuyun. Kısa zamanda çok mesafe katedersiniz.