QGIS lumpuh saat melakukan kemunduran setelah memodifikasi nilai fitur yang ditambahkan pengguna dengan pyQGIS

8

Saya sedang mengembangkan addon untuk QGIS yang perlu menetapkan UUID untuk fitur apa pun segera setelah ditambahkan ke layer. Saya menggunakan sinyal fiturAdded untuk menulis UUID di bidang fitur yang sesuai.

Ini adalah kode yang saya gunakan (sesederhana mungkin):

def run(self):
    self.iface.mapCanvas().currentLayer().featureAdded.connect(self.onFeatureAdded)

def onFeatureAdded(self, fid):
    layer = self.iface.mapCanvas().currentLayer()
    layer.beginEditCommand("Set UUID")
    print layer.changeAttributeValue(fid, layer.fieldNameIndex('guid_pol'), 'some_random_uuid') # prints True
    layer.endEditCommand()

(Saya membuat plugin baru dengan add-on 'Plugin Builder' dan di atas adalah satu-satunya kode yang telah saya tambahkan padanya .)

Kecuali jika saya melewatkan sesuatu, ini mengikuti pedoman dari dokumentasi dalam buku masak pengembang QGIS : http://docs.qgis.org/testing/en/docs/pyqgis_developer_cookbook/vector.html#modifying-vector-layers-with- an-editing-buffer

Ketika saya mengedit layer, jika saya menambahkan fitur, bidang 'guid_pol' diatur ke 'some_random_uuid' seperti yang diharapkan. Saya dapat melakukan perubahan tanpa masalah, namun, alih-alih melakukan perubahan, saya mencoba membatalkannya QGIS lumpuh dengan kesalahan 0xC0000005 (Pelanggaran Akses) .

Menariknya, perintah 'Set UUID' tidak ditambahkan ke undo / redo stack (setidaknya, bukan ke Undo / redo Panel ) dan jika saya mencoba untuk membatalkannya crash juga .

Saya menggunakan QGIS 2.14 tetapi saya mengamati perilaku yang sama dengan QGIS 2.12.

Saya mengalami kesulitan mendapatkan ini berfungsi. Apakah ada yang salah yang saya lakukan?

mhm
sumber

Jawaban:

5

Saya menjawab sendiri :-) Saya telah menemukan penjelasan di sini http://qgis-developer.osgeo.narkive.com/5wnziigA/wrapping-changeattributevalue-between-begin-and-end-editcommand#post2

Saat ini tidak aman untuk melakukan panggilan yang memodifikasi data layer vektor dalam slot yang terhubung ke sinyal yang memberitahukan tentang perubahan data (seperti featureAdded). Masalahnya adalah bahwa pada saat sinyal-sinyal itu dipancarkan, perintah undo yang mendasarinya belum didorong ke stack, sehingga melakukan panggilan pengeditan lebih lanjut menyebabkan korupsi dari undo stack (perintah undo untuk operasi tindak lanjut ditempatkan sebelum operasi pertama).

Solusi saya adalah menunda penanganan penambahan fitur menggunakan slot editCommandEnded. Ini adalah kode yang relevan:

def onFeatureAdded(self, fid):
    if fid < 0:
        self._addedFeatures.append(fid)

def onEditCommandEnded(self):
    while self._addedFeatures:
        fid = self._addedFeatures.pop()
        self._handleAdded(fid)

def _handleAdded(self, fid):
    guid_pol = str(uuid4()) # RFC 4122 UUID v4
    try:
        self.layer.beginEditCommand(u"Assign UUID")
        self.layer.changeAttributeValue(fid, self.layer.fieldNameIndex('guid_pol'), guid_pol)
        self.layer.endEditCommand()
    except:
        self.layer.destroyEditCommand()
        raise

Saya harap ini membantu orang lain.

mhm
sumber
3

mhm,

Jawaban Anda sangat bagus dan menyelesaikan masalah kami di sini. Tetapi untuk sepenuhnya memahami mengapa ini terjadi saya bagaimana menyelesaikannya, saya mempelajari kode sumber QGIS dan rekan kerja saya dan saya membuat artikel yang menjelaskan masalah secara rinci. Tolong, jangan ragu untuk memeriksanya!

https://gis4programmers.wordpress.com/2017/02/26/working-properly-with-pyqgqis-edit-buffer-to-enable-undo-commands/

pendamping
sumber
1
Bahkan hari ini dengan QGIS v3.4 Saya menghadapi masalah dan posting Anda memberi saya cara untuk menyelesaikannya, terima kasih telah memposting ini! BTW, saya sudah mengangkat jawaban Anda, seperti setahun lalu atau lebih: D
Germán Carrillo