Auto edycja warstwy - Wersja do druku +- Forum QGIS (http://forum.quantum-gis.pl) +-- Dział: Desktop GIS (http://forum.quantum-gis.pl/forum-4.html) +--- Dział: QGIS (http://forum.quantum-gis.pl/forum-5.html) +--- Wątek: Auto edycja warstwy (/thread-918.html) |
Auto edycja warstwy - jakosek - 03-04-2013 Od jakiegoś czasu zgłębiam tajniki QGIS i większość odpowiedzi znalazłem już tu na forum lub w dokumentacji Quantuma. Otóż: Mam bardzo duży projekt - ponad 40 warstw do których zrobiłem personalizowane formularze edycji. W większości starałem się unikać Pythona. Przy takiej ilości danych mam ustawione otwieranie bezpośrednio formularza obiektu oraz wyszukiwanie wyników identyfikacji od góry do dołu. Przy odpowiednim układzie warstw fajnie to działa - kliknięcie na mapie otwiera formularz pierwszego znalezionego obiektu. I tutaj problem - warstw jest tyle że ciężko teraz odnaleźć w legendzie warstwę do której należy obiekt, do tego trzeba włączyć edycję - wybrać obiekt jeszcze raz... Pomysł mi zaświtał żeby w funkcji inicjującej formularz umieścić fragment włączający edycję danej warstwy i po zakończeniu "OK" - zapis, "Cancel" - powrót. Znalazłem odpowiednie klasy i z konsoli Pythona potrafię coś takiego zrobić. Czy funkcja inicjująca może wogóle takie rzeczy obsługiwać? Tutaj mi się nie udało dotychczas znaleźć odpowiedzi a dokumentacja w tym kierunku jest raczej skąpa. Trochę mnie przeraża szukanie odpowiedzi w kodzie źródłowym qgisa Będę wdzięczny za podpowiedzi. Może jest inna droga? RE: Auto edycja warstwy - borys - 03-04-2013 Nie mam pod ręką stabilnego Quantuma, tylko rozgrzebaną alfę 2.0, ale nie powinno być z tym problemu. W funkcji inicjującej włączasz tryb edycji oraz podłączasz sygnały z klawiszy OK i Cancel do dwóch kolejnych funkcji, w których implementujesz koniec trybu edycji. Z grubsza powinno to wyglądać jak w tym przykładzie: http://nathanw.net/2011/09/05/qgis-tips-custom-feature-forms-with-python-logic/ tylko zamiast funkcji validate() tworzysz np. zaakceptowano() i odrzucono(), w których wywołujesz warstwa.commitChanges() i warstwa.rollBack(). A skąd wziąć w nich warstwę? Zwróć uwagę na zmienne globalne (tutaj nameField i myDialog) - do zmiennej globalnej np. warstwa w funkcji inicjącej zapiszesz warstwę, żeby móc ją wywołać w tych dwóch pozostałych funkcjach. Ważna uwaga: niestety po każdej zmianie w pliku zawierającym funkcję inicjującą MUSISZ przeładować QGISa, żeby zobaczył zmianę. Dlatego próby wygodniej jest robić w konsoli. Ważna uwaga 2: API QGIS-a 1.x i nadchodzącego wielkimi krokami 2.x się różnią, więc przeglądając dokumentację online zwracaj na to uwagę. Np. w adresie: http://www.qgis.org/api/1.8/classQgsVectorLayer.html jest człon 1.8 - bez niego wyświetli się API gałęzi master, czyli alphy 2.0. Zasadnicza różnica przy formularzach jest taka, że w QGIS-ie 1.x do funkcji inicjującej przekazywane są id warstwy i obiektu, czyli musisz znaleźć warstwę po id. Nie pamiętam teraz, jak to najłatwiej zrobić, pewnie trzeba szukać w klasie QgsMapLayerRegistry albo QgsMapCanvas. Natomiast w QGIS-ie rozwojowym/nocnym, czyli przyszłym 2.0, do funkcji inicjującej przekazywane są już nie id warstwy i obiektu, tylko warstwa i obiekt we własnych osobach, czyli obiekty klasy QgsVectorLayer i QgsFeature. Dzięki temu można od razu wywołać warstwa.startEditing() RE: Auto edycja warstwy - jakosek - 03-04-2013 Działa! Dziękuję bardzo za rzeczową odpowiedź! Wszystko to gdzieś czytałem i jakoś mi to nie chciało działać. Twój post pomógł mi to usystematyzować. To że zmiany nie łapią już wyczytałem i przy takim projekcie to upierdliwe, fakt. Obiekt typu QgsVectorLayer udało mi się wydłubać z mapCanvas().layers() według znanej nazwy - działa też z legendInterface().layers() O zmianach w funkcji inicjującej w wersji 2.0 znalazłem i uprościło by to mój kod (swoją drogą to jedna z niewielu informacji które można znaleźć na temat inicjacji formularzy poza linkiem do blogu Nathana który podałeś...) ALE Teraz jeszcze jedna zagadka: Qgis otwiera formularze w 2 sposoby - zależnie czy edycja jest włączona czy nie. No i mimo że wszystko fajnie, edycja włącza się tak jak zakładałem - to formularz ma wyłączone pola i przycisk "OK". Da się w tym stanie wybrać drugi formularz na tej samej warstwie i ten już jest aktywny, "OK" i "Cancel" działa prawidłowo. Tylko potem "Cancel" w pierwszym formularzu wywala QGIS Jeżeli tego nie da się przeskoczyć to marny pożytek z tej możliwości. RE: Auto edycja warstwy - borys - 03-04-2013 Hmmm, no tak, skoro funkcja inicjująca dostaje jako pierwszy parametr okno formularza, to ono już musi być wcześniej otwarte. Takie gorące pomysły rozwiązania, pewnie wyjdą przy nich kolejne problemy: 1. Pierwszy jest partyzancki. Można spróbować na wszystkich widgetach w oknie wywołać metodę setEnabled(True), a potem uczynić okno modalnym, żeby uniemożliwić otwarcie drugiego: Kod: for widzet in dialog.findChildren(QLineEdit): widzet.setEnabled(True) 2. Można spróbować w metodzie inicjującej zamknąć ten dialog, włączyć tryb edycji i spróbować go jakoś wywołać ponownie. Nie jestem pewien, czy gdziekolwiek w API jest wystawiona taka możliwość. Jeśli jest, to powinno to być rozwiązanie prostsze i czystsze od poprzedniego. Jeśli nie ma, to w zasadzie niemożliwe. 3. Najelegantsze ale i najbardziej pracochłonne: dać sobie spokój ze standardowym narzędziem do odpytywania i napisać wtyczkę, która tworzy własne narzędzie (potomka QgsMapTool), a wtedy można już robić co dusza zapragnie. RE: Auto edycja warstwy - jakosek - 04-04-2013 Niestety, powalczyłem i odpuściłem. 1. sposób działa o tyle że QGIS chowa przycisk "OK" a zdefiniowanie swojego przycisku do slotu accepted() nie zapisuje wyników edycji. 2. openFeatureForm zastosowany w funkcji inicjującej zawiesza całego Qgisa. 3. Może w przyszłym projekcie, już planuję naukę pisania własnych wtyczek. Podstawy Pythona już opanowałem. Jeszcze raz dziekuję za pomoc. Fajnie że ktoś z Polski jest w ekipie rozwojowej QGIS - to wielkie wsparcie, bo dokumentacja w wielu przypadkach jest bardzo skąpa. RE: Auto edycja warstwy - borys - 04-04-2013 Dzięki :-) Co do pkt 1) to może ten klawisz jest tylko schowany. Nie pamiętam, czy to jest QPushButton, czy QToolButton: Kod: for widzet in dialog.findChildren(QPushButton): widzet.show() RE: Auto edycja warstwy - jakosek - 04-04-2013 Poszukałem dziś jeszcze trochę i znalazłem trochę informacji, tak jak by ktoś potrzebował. Za rysowanie okna formularza odpowiada klasa QgsAttributeDialog i w niej zawarte są całe sztuczki. Kod: buttonBox->setStandardButtons( QDialogButtonBox::Cancel ); W ten sposób są chowane przyciski buttonBox'a. Załatwiłem to szybko i wszystko widać: Kod: buttonbox.setStandardButtons(QDialogButtonBox.Ok|QDialogButtonBox.Cancel) Ale zapis zmienionych atrybutów nadal nie działa - chyba nie jest odpowiednio przekazywany spowrotem sygnał accept()... Próbowałem nawet przenieść do Pythona poniższy fragment: Kod: const QgsFields& fields = mLayer->pendingFields(); Ale sobie odpuściłem, nie do końca wiem jak obsłużyć to w Pythonie (o ile wogóle się da). Problemem tu jest przekazanie konkretnego QWidget do QgsAttributeEditor.retrieveValue() bo resztę mniej - więcej kojarzę. Dlatego temat odpuszczam, szkoda życia. Prędzej by było skompilować QGIS z drobnymi zmianami RE: Auto edycja warstwy - borys - 05-04-2013 Ja się właśnie zbieram do Valmiery [1] (straszyli łotewskimi drogami, to ruszamy pięć dni wcześniej l-) ) więc już też nie spojrzę, w którym momencie to utyka. Jeśli dotarłeś do granic możliwości tego dostosowywania formularzy, to pozostaje wtyka albo właśnie przeróbka w kodzie. Można by ją wprowadzić na stałe, tylko chyba ten przypadek nie jest zbyt typowy... [1] http://hub.qgis.org/wiki/quantum-gis/9_QGIS_Developer_Meeting_in_Valmiera_2013 RE: Auto edycja warstwy - jakosek - 05-04-2013 Cytat:Można by ją wprowadzić na stałe, tylko chyba ten przypadek nie jest zbyt typowy... Właściwie to w starszych wersjach QGIS było tylko okno edycji, potem to rozdzielono. Generalnie ma to sens, tylko mi w tym jednym przypadku nie pasuje. [1] Niezła zakładka 5 dni UPDATE: Udało mi się osiągnąć efekt zupełnie inną drogą. Efekty są nawet lepsze od oczekiwanych. Dodałem do wszystkich warstw akcję otwierającą formularz edycyjny _PO_ włączeniu edycji. Jak komuś brakowało możliwości otwierania formularza z akcji to może sobie coś wyłowić z tego kodu (chyba nawet ktoś postulował o dodanie tego do domyślnych akcji). Reszta bajeru która powoduje że korzysta się z tego przyjemnie to wtyczka "Hotlink" - klikając na mapie wyświetla listę dostępnych akcji na wszystkich widocznych warstwach. Akcja w Pythonie: Kod: layers = qgis.utils.iface.mapCanvas().layers() |