その5:プロバイダプラグインの実装ではとりあえず要素の描画はできましたが、
選択条件を無視していたので、キャンバスのどこをクリックしても全て選択されるなど不具合がありました。
ここでは、要素選択に対応する部分を実装していきます。
select()関数
この関数はnextFeature()関数が呼び出される直前にQGIS側から呼び出されます。
引数に選択条件が渡されるので、プラグイン側はその条件をクラスのメンバ変数に保存しておきます。
ざっと以下のようなコードでしょうか。
1: void QgsCompassSurveyDataProvider::select( QgsAttributeList fetchAttributes, 2: QgsRectangle rect, 3: bool fetchGeometry, 4: bool useIntersect ) 5: { 6: mSelectionRectangle = rect; 7: mAttributesToFetch = fetchAttributes; 8: mFetchGeom = fetchGeometry; 9: if ( rect.isEmpty() ) 10: { 11: mSelectionRectangle = mExtent; 12: } 13: else 14: { 15: mSelectionRectangle = rect; 16: } 17: 18: m_nCurFeature = 0; 19: }
引数fetchAttributesはQGISが要求するフィールド番号のリストで、
nextFeature()関数ではこのリストのフィールドを要素に詰め込んで返す必要があります。
属性テーブルを表示したりするときに使用されます。
属性テーブルをフィールドでソートするときとかは、そのフィールドだけが要求されるようです。
rectは範囲矩形で、引数fetchGeometryがtrueならば、
nextFeature()関数ではこの範囲内の要素を返却する必要があります。
useIntersectがtrueならば、範囲矩形に交差する要素も選択対象とする必要があります。
引数fetchGeometryがtrueならば、nextFeature()関数は図形情報もつめて返す必要がありますが、
falseならば属性情報だけつめて返すこともできます。
nextFeature()関数
nextFeature()関数はselect()関数で設定された条件をフィルタとして要素を返すように書き換えます。
上記のとおり、select()関数の引数fetchGeometryがfalseならば、引数featureに図形情報はつめる必要がなく、
またfetchAttributeがフィールドの一部であればそのフィールドの値だけをつめて返せばいいです。
ただ、要求されていない情報をつめて返してもエラーになるわけではなく、QGISに使われないだけです。
今回の例ではコンストラクタでQgsFeature型を作ってしまっているので、
手抜きをして選択矩形だけを考慮するようにしてみます。
1: bool QgsCompassSurveyDataProvider::nextFeature( QgsFeature& feature ) 2: { 3: feature.setValid( false ); 4: 5: while ( m_nCurFeature < mFeatures.size() ) 6: { 7: feature = mFeatures[m_nCurFeature]; 8: 9: if ( mUseIntersect && !feature.geometry()->intersects( mSelectionRectangle ) ) 10: { 11: m_nCurFeature++; 12: continue; 13: } 14: 15: m_nCurFeature++; 16: feature.setValid( true ); 17: 18: return true; 19: } 20: 21: return false; 22: }
前回と同じように画面上で要素を選択してみます。
以下の図のように個別に選択されれば成功です。

一応これで完成(たぶん)です。
あとは、属性数や属性の型が未知の場合の対応とか、属性の追加・削除・編集を許可するとか、
図形が編集されたときの対応などもプロバイダプラグインの役割になるので、必要に応じて追加することになるでしょう。