1 /***************************************************************************
2                       qgsidentifyresults.h  -  description
3                                ------------------
4         begin                : Fri Oct 25 2002
5         copyright            : (C) 2002 by Gary E.Sherman
6         email                : sherman at mrcc dot com
7         Romans 3:23=>Romans 6:23=>Romans 5:8=>Romans 10:9,10=>Romans 12
8  ***************************************************************************/
9 
10 /***************************************************************************
11  *                                                                         *
12  *   This program is free software; you can redistribute it and/or modify  *
13  *   it under the terms of the GNU General Public License as published by  *
14  *   the Free Software Foundation; either version 2 of the License, or     *
15  *   (at your option) any later version.                                   *
16  *                                                                         *
17  ***************************************************************************/
18 #ifndef QGSIDENTIFYRESULTSDIALOG_H
19 #define QGSIDENTIFYRESULTSDIALOG_H
20 
21 #include "ui_qgsidentifyresultsbase.h"
22 #include "qgshelp.h"
23 #include "qgsfeature.h"
24 #include "qgsfields.h"
25 #include "qgscoordinatereferencesystem.h"
26 #include "qgsmaptoolidentify.h"
27 #include "qgswebview.h"
28 #include "qgsexpressioncontext.h"
29 #include "qgsmaptoolselectionhandler.h"
30 
31 #include <QWidget>
32 #include <QList>
33 #include <QNetworkRequest>
34 #include <QNetworkReply>
35 #include <QUrl>
36 #include "qgis_app.h"
37 
38 class QCloseEvent;
39 class QTreeWidgetItem;
40 class QAction;
41 class QMenu;
42 
43 class QgsFeatureStore;
44 class QgsVectorLayer;
45 class QgsRasterLayer;
46 class QgsHighlight;
47 class QgsMapCanvas;
48 class QgsMeshLayer;
49 class QgsDockWidget;
50 class QgsMapLayerAction;
51 class QgsEditorWidgetSetup;
52 
53 class QwtPlotCurve;
54 
55 class APP_EXPORT QgsIdentifyResultsWebView : public QgsWebView
56 {
57     Q_OBJECT
58   public:
59     QgsIdentifyResultsWebView( QWidget *parent = nullptr );
60     QSize sizeHint() const override;
61   public slots:
62     void print();
63     void downloadRequested( const QNetworkRequest &request );
64     void unsupportedContent( QNetworkReply *reply );
65   protected:
66     void contextMenuEvent( QContextMenuEvent * ) override;
67     QgsWebView *createWindow( QWebPage::WebWindowType type ) override;
68   private:
69     void handleDownload( QUrl url );
70 };
71 
72 class APP_EXPORT QgsIdentifyResultsFeatureItem: public QTreeWidgetItem
73 {
74   public:
75     QgsIdentifyResultsFeatureItem( const QgsFields &fields, const QgsFeature &feature, const QgsCoordinateReferenceSystem &crs, const QStringList &strings = QStringList() );
fields()76     const QgsFields &fields() const { return mFields; }
feature()77     const QgsFeature &feature() const { return mFeature; }
crs()78     QgsCoordinateReferenceSystem crs() const { return mCrs; }
79 
80   private:
81     QgsFields mFields;
82     QgsFeature mFeature;
83     QgsCoordinateReferenceSystem mCrs;
84 };
85 
86 class APP_EXPORT QgsIdentifyResultsWebViewItem: public QObject, public QTreeWidgetItem
87 {
88     Q_OBJECT
89 
90   public:
91     QgsIdentifyResultsWebViewItem( QTreeWidget *treeWidget = nullptr );
webView()92     QgsIdentifyResultsWebView *webView() { return mWebView; }
93     void setHtml( const QString &html );
94     //! \since QGIS 2.1
95     void setContent( const QByteArray &data, const QString &mimeType = QString(), const QUrl &baseUrl = QUrl() );
96 
97   public slots:
98     void loadFinished( bool ok );
99 
100   private:
101     QgsIdentifyResultsWebView *mWebView = nullptr;
102 };
103 
104 class APP_EXPORT QgsIdentifyPlotCurve
105 {
106   public:
107 
QgsIdentifyPlotCurve()108     QgsIdentifyPlotCurve() { mPlotCurve = nullptr; }
109     QgsIdentifyPlotCurve( const QMap<QString, QString> &attributes,
110                           QwtPlot *plot, const QString &title = QString(), QColor color = QColor() );
111     ~QgsIdentifyPlotCurve();
112 
113     QgsIdentifyPlotCurve( const QgsIdentifyPlotCurve &rh ) = delete;
114     QgsIdentifyPlotCurve &operator=( const QgsIdentifyPlotCurve &rh ) = delete;
115 
116   private:
117     QwtPlotCurve *mPlotCurve = nullptr;
118 
119 };
120 
121 class APP_EXPORT QgsIdentifyResultsDialog: public QDialog, private Ui::QgsIdentifyResultsBase
122 {
123     Q_OBJECT
124 
125   public:
126 
127     /**
128      * Constructor -
129      * takes its own copy of the QgsAttributeAction so
130      * that it is independent of whoever created it.
131      */
132     QgsIdentifyResultsDialog( QgsMapCanvas *canvas, QWidget *parent = nullptr, Qt::WindowFlags f = Qt::WindowFlags() );
133 
134     ~QgsIdentifyResultsDialog() override;
135 
136     //! Adds feature from vector layer
137     void addFeature( QgsVectorLayer *layer,
138                      const QgsFeature &f,
139                      const QMap< QString, QString > &derivedAttributes );
140 
141     //! Adds feature from raster layer
142     void addFeature( QgsRasterLayer *layer,
143                      const QString &label,
144                      const QMap< QString, QString > &attributes,
145                      const QMap< QString, QString > &derivedAttributes,
146                      const QgsFields &fields = QgsFields(),
147                      const QgsFeature &feature = QgsFeature(),
148                      const QMap<QString, QVariant> &params = ( QMap<QString, QVariant>() ) );
149 
150     /**
151      * Adds results from mesh layer
152      * \since QGIS 3.6
153      */
154     void addFeature( QgsMeshLayer *layer,
155                      const QString &label,
156                      const QMap< QString, QString > &attributes,
157                      const QMap< QString, QString > &derivedAttributes );
158 
159     /**
160      * Adds results from vector tile layer
161      * \since QGIS 3.14
162      */
163     void addFeature( QgsVectorTileLayer *layer,
164                      const QString &label,
165                      const QgsFields &fields,
166                      const QgsFeature &feature,
167                      const QMap< QString, QString > &derivedAttributes );
168 
169     /**
170      * Adds results from point cloud layer
171      * \since QGIS 3.18
172      */
173     void addFeature( QgsPointCloudLayer *layer,
174                      const QString &label,
175                      const QMap< QString, QString > &attributes );
176 
177     //! Adds feature from identify results
178     void addFeature( const QgsMapToolIdentify::IdentifyResult &result );
179 
180     //! Map tool was deactivated
181     void deactivate();
182 
183     //! Map tool was activated
184     void activate();
185 
186     /**
187      * Sets an expression context scope to consider for resolving underlying
188      * actions.
189      *
190      * \since QGIS 3.0
191      */
192     void setExpressionContextScope( const QgsExpressionContextScope &scope );
193 
194     /**
195      * Returns an expression context scope used for resolving underlying
196      * actions.
197      *
198      * \since QGIS 3.0
199      */
200     QgsExpressionContextScope expressionContextScope() const;
201 
202     QgsMapToolSelectionHandler::SelectionMode selectionMode() const;
203 
204   signals:
205     void selectedFeatureChanged( QgsVectorLayer *, QgsFeatureId featureId );
206 
207     // Emitted when raster identify format of a layer changed
208     void formatChanged( QgsRasterLayer *layer );
209 
210     void copyToClipboard( QgsFeatureStore &featureStore );
211 
212     void activateLayer( QgsMapLayer * );
213 
214     void selectionModeChanged();
215 
216   public slots:
217     //! Remove results
218     void clear();
219 
220     void updateViewModes();
221 
222     void show();
223 
224     void contextMenuEvent( QContextMenuEvent * ) override;
225 
226     void layerDestroyed();
227     void editingToggled();
228     void featureDeleted( QgsFeatureId fid );
229     void attributeValueChanged( QgsFeatureId fid, int idx, const QVariant & );
230 
231     void featureForm();
232     void zoomToFeature();
233     void copyAttributeValue();
234     void copyFeature();
235     void toggleFeatureSelection();
236     void copyFeatureAttributes();
237     void copyGetFeatureInfoUrl();
238     void highlightAll();
239     void highlightLayer();
240     void activateLayer();
241     void layerProperties();
242     void clearHighlights();
243     void expandAll();
244     void collapseAll();
245 
246     /**
247      * Called when an item is expanded so that we can ensure that the
248      * column width if expanded to show it.
249      */
250     void itemExpanded( QTreeWidgetItem * );
251 
252     //! sends signal if current feature id has changed
253     void handleCurrentItemChanged( QTreeWidgetItem *current, QTreeWidgetItem *previous );
254     /* Item in tree was clicked */
255     void itemClicked( QTreeWidgetItem *lvi, int column );
256 
257     QTreeWidgetItem *retrieveAttributes( QTreeWidgetItem *item, QgsAttributeMap &attributes, int &currentIdx );
258 
259     void cmbIdentifyMode_currentIndexChanged( int index );
260 
261     void cmbViewMode_currentIndexChanged( int index );
262 
263     void mExpandNewAction_triggered( bool checked );
264 
265     void mActionAutoFeatureForm_toggled( bool checked );
266 
267     void mActionHideDerivedAttributes_toggled( bool checked );
268 
mExpandAction_triggered(bool checked)269     void mExpandAction_triggered( bool checked ) { Q_UNUSED( checked ) expandAll(); }
mCollapseAction_triggered(bool checked)270     void mCollapseAction_triggered( bool checked ) { Q_UNUSED( checked ) collapseAll(); }
271 
272     void mActionCopy_triggered( bool checked );
273 
274     void formatChanged( int index );
275 
276     void printCurrentItem();
277 
278     void mapLayerActionDestroyed();
279 
280     void showHelp();
281 
282   private:
283     QString representValue( QgsVectorLayer *vlayer, const QgsEditorWidgetSetup &setup, const QString &fieldName, const QVariant &value );
284 
285     enum ItemDataRole
286     {
287       GetFeatureInfoUrlRole = Qt::UserRole + 10,
288       FeatureRole,
289     };
290 
291     QMenu *mActionPopup = nullptr;
292     QHash<QTreeWidgetItem *, QgsHighlight * > mHighlights;
293     QgsMapCanvas *mCanvas = nullptr;
294     QList<QgsFeature> mFeatures;
295     QMap< QString, QMap< QString, QVariant > > mWidgetCaches;
296     QgsExpressionContextScope mExpressionContextScope;
297     QToolButton *mSelectModeButton = nullptr;
298 
299     QgsMapLayer *layer( QTreeWidgetItem *item );
300     QgsVectorLayer *vectorLayer( QTreeWidgetItem *item );
301     QgsRasterLayer *rasterLayer( QTreeWidgetItem *item );
302     QgsMeshLayer *meshLayer( QTreeWidgetItem *item );
303     QgsVectorTileLayer *vectorTileLayer( QTreeWidgetItem *item );
304     QgsPointCloudLayer *pointCloudLayer( QTreeWidgetItem *item );
305     QTreeWidgetItem *featureItem( QTreeWidgetItem *item );
306     QTreeWidgetItem *layerItem( QTreeWidgetItem *item );
307     QTreeWidgetItem *layerItem( QObject *layer );
308 
309 
310     void highlightLayer( QTreeWidgetItem *object );
311     void layerProperties( QTreeWidgetItem *object );
312     void disconnectLayer( QObject *object );
313 
314     void saveWindowLocation();
315 
316     void setColumnText( int column, const QString &label );
317     void expandColumnsToFit();
318 
319     void highlightFeature( QTreeWidgetItem *item );
320 
321     void doAction( QTreeWidgetItem *item, const QString &action );
322 
323     void doMapLayerAction( QTreeWidgetItem *item, QgsMapLayerAction *action );
324 
325     QgsDockWidget *mDock = nullptr;
326 
327     QVector<QgsIdentifyPlotCurve *> mPlotCurves;
328 
329     QgsMapToolSelectionHandler::SelectionMode mSelectionMode = QgsMapToolSelectionHandler::SelectSimple;
330 
331     void setSelectionMode();
332 
333     void initSelectionModes();
334     QgsIdentifyResultsFeatureItem *createFeatureItem( QgsVectorLayer *vlayer, const QgsFeature &f, const QMap<QString, QString> &derivedAttributes, bool includeRelations, QTreeWidgetItem *parentItem );
335 };
336 
337 class QgsIdentifyResultsDialogMapLayerAction : public QAction
338 {
339     Q_OBJECT
340 
341   public:
QgsIdentifyResultsDialogMapLayerAction(const QString & name,QObject * parent,QgsMapLayerAction * action,QgsMapLayer * layer,QgsFeature * f)342     QgsIdentifyResultsDialogMapLayerAction( const QString &name, QObject *parent, QgsMapLayerAction *action, QgsMapLayer *layer, QgsFeature *f )
343       : QAction( name, parent )
344       , mAction( action )
345       , mFeature( f )
346       , mLayer( layer )
347     {}
348 
349   public slots:
350     void execute();
351 
352   private:
353     QgsMapLayerAction *mAction = nullptr;
354     QgsFeature *mFeature = nullptr;
355     QgsMapLayer *mLayer = nullptr;
356 };
357 
358 #endif
359