1 /***************************************************************************
2                  qgsdataitem.h  - Items representing data
3                              -------------------
4     begin                : 2011-04-01
5     copyright            : (C) 2011 Radim Blazek
6     email                : radim dot blazek at gmail dot com
7  ***************************************************************************/
8 
9 /***************************************************************************
10  *                                                                         *
11  *   This program is free software; you can redistribute it and/or modify  *
12  *   it under the terms of the GNU General Public License as published by  *
13  *   the Free Software Foundation; either version 2 of the License, or     *
14  *   (at your option) any later version.                                   *
15  *                                                                         *
16  ***************************************************************************/
17 #ifndef QGSDATAITEM_H
18 #define QGSDATAITEM_H
19 
20 #include "qgis_sip.h"
21 #include "qgis_core.h"
22 #include <QFileSystemWatcher>
23 #include <QFutureWatcher>
24 #include <QIcon>
25 #include <QObject>
26 #include <QPixmap>
27 #include <QString>
28 #include <QTreeWidget>
29 #include <QVector>
30 #include <QDateTime>
31 
32 #include "qgsmaplayer.h"
33 #include "qgscoordinatereferencesystem.h"
34 #include "qgsmimedatautils.h"
35 #include "qgswkbtypes.h"
36 #include "qgsabstractdatabaseproviderconnection.h"
37 
38 class QgsDataProvider;
39 class QgsDataItem;
40 class QgsAnimatedIcon;
41 class QgsBookmarkManager;
42 
43 typedef QgsDataItem *dataItem_t( QString, QgsDataItem * ) SIP_SKIP;
44 
45 /**
46  * \ingroup core
47  * \brief Base class for all items in the model.
48  *
49  * Parent/children hierarchy is not based on QObject.
50 */
51 class CORE_EXPORT QgsDataItem : public QObject
52 {
53 
54 #ifdef SIP_RUN
55     SIP_CONVERT_TO_SUBCLASS_CODE
56     if ( qobject_cast<QgsLayerItem *>( sipCpp ) )
57       sipType = sipType_QgsLayerItem;
58     else if ( qobject_cast<QgsErrorItem *>( sipCpp ) )
59       sipType = sipType_QgsErrorItem;
60     else if ( qobject_cast<QgsDirectoryItem *>( sipCpp ) )
61       sipType = sipType_QgsDirectoryItem;
62     else if ( qobject_cast<QgsFavoritesItem *>( sipCpp ) )
63       sipType = sipType_QgsFavoritesItem;
64     else if ( qobject_cast<QgsZipItem *>( sipCpp ) )
65       sipType = sipType_QgsZipItem;
66     else if ( qobject_cast<QgsDataCollectionItem *>( sipCpp ) )
67       sipType = sipType_QgsDataCollectionItem;
68     else if ( qobject_cast<QgsProjectItem *>( sipCpp ) )
69       sipType = sipType_QgsProjectItem;
70     else
71       sipType = 0;
72     SIP_END
73 #endif
74 
75     Q_OBJECT
76 
77   public:
78     enum Type
79     {
80       Collection,
81       Directory,
82       Layer,
83       Error,
84       Favorites, //!< Represents a favorite item
85       Project, //!< Represents a QGIS project
86       Custom, //!< Custom item type
87       Fields, //!< Collection of fields
88       Field, //!< Vector layer field
89     };
90 
91     Q_ENUM( Type )
92 
93     /**
94      * Constructor for QgsDataItem, with the specified \a parent item.
95      *
96      * The \a name argument specifies the text to show in the model for the item. A translated string should
97      * be used wherever appropriate.
98      *
99      * The \a path argument gives the item path in the browser tree. The \a path string can take any form,
100      * but QgsDataItem items pointing to different logical locations should always use a different item \a path.
101      *
102      * The optional \a providerKey string (added in QGIS 3.12) can be used to specify the key for the QgsDataItemProvider that created this item.
103      */
104     QgsDataItem( QgsDataItem::Type type, QgsDataItem *parent SIP_TRANSFERTHIS, const QString &name, const QString &path, const QString &providerKey = QString() );
105 
106     ~QgsDataItem() override;
107 
108     bool hasChildren();
109 
110     /**
111      * Returns TRUE if the data item is a collection of layers
112      * The default implementation returns FALSE, subclasses must implement this method if their children are layers.
113      * \since QGIS 3.14
114      */
115     virtual bool layerCollection() const;
116 
117     int rowCount();
118 
119     /**
120      * Create children. Children are not expected to have parent set.
121      * \warning This method MUST BE THREAD SAFE.
122     */
123     virtual QVector<QgsDataItem *> createChildren() SIP_TRANSFERBACK;
124 #ifdef SIP_RUN
125     SIP_VIRTUAL_CATCHER_CODE
126     PyObject *sipResObj = sipCallMethod( 0, sipMethod, "" );
127     // H = Convert a Python object to a mapped type instance.
128     // 5 = 1 (disallows the conversion of Py_None to NULL) + 4 (returns a copy of the C/C++ instance)
129     sipIsErr = !sipResObj || sipParseResult( 0, sipMethod, sipResObj, "H5", sipType_QVector_0101QgsDataItem, &sipRes ) < 0;
130     if ( !sipIsErr )
131     {
132       for ( QgsDataItem *item : sipRes )
133       {
134         PyObject *pyItem = sipGetPyObject( item, sipType_QgsDataItem );
135         if ( pyItem != NULL )
136         {
137           // pyItem is given an extra reference which is removed when the C++ instance’s destructor is called.
138           sipTransferTo( pyItem, Py_None );
139         }
140       }
141     }
142     if ( sipResObj != NULL )
143     {
144       Py_DECREF( sipResObj );
145     }
146     SIP_END
147 #endif
148 
149     enum State
150     {
151       NotPopulated, //!< Children not yet created
152       Populating,   //!< Creating children in separate thread (populating or refreshing)
153       Populated     //!< Children created
154     };
155     Q_ENUM( State )
156 
157     //! \since QGIS 2.8
158     State state() const;
159 
160     /**
161      * Set item state. It also take care about starting/stopping loading icon animation.
162      * \param state
163      * \since QGIS 2.8
164      */
165     virtual void setState( State state );
166 
167     /**
168      * Inserts a new child item. The child will be inserted at a position using an alphabetical order based on mName.
169      * \param child child item to insert. Ownership is transferred, and item parent will be set and relevant connections made.
170      * \param refresh - set to TRUE to refresh populated item, emitting relevant signals to the model
171      * \see deleteChildItem()
172      */
173     virtual void addChildItem( QgsDataItem *child SIP_TRANSFER, bool refresh = false );
174 
175     /**
176      * Removes and deletes a child item, emitting relevant signals to the model.
177      * \param child child to remove. Item must exist as a current child.
178      * \see addChildItem()
179      */
180     virtual void deleteChildItem( QgsDataItem *child );
181 
182     /**
183      * Removes a child item and returns it without deleting it. Emits relevant signals to model as required.
184      * \param child child to remove
185      * \returns pointer to the removed item or NULLPTR if no such item was found
186      */
187     virtual QgsDataItem *removeChildItem( QgsDataItem *child ) SIP_TRANSFERBACK;
188 
189     /**
190      * Returns TRUE if this item is equal to another item (by testing item type and path).
191      */
192     virtual bool equal( const QgsDataItem *other );
193 
194     /**
195      * Returns source widget from data item for QgsBrowserPropertiesWidget
196      *
197      * Use QgsDataItemGuiProvider::createParamWidget() instead
198      *
199      * \deprecated QGIS 3.10
200      */
paramWidget()201     Q_DECL_DEPRECATED virtual QWidget *paramWidget() SIP_FACTORY SIP_DEPRECATED { return nullptr; }
202 
203     /**
204      * Returns the list of actions available for this item. This is usually used for the popup menu on right-clicking
205      * the item. Subclasses should override this to provide actions.
206      *
207      * Subclasses should ensure that ownership of created actions is correctly handled by parenting them
208      * to the specified parent widget.
209      */
210     virtual QList<QAction *> actions( QWidget *parent );
211 
212     /**
213      * Returns the list of menus available for this item. This is usually used for the popup menu on right-clicking
214      * the item. Subclasses should override this to provide actions. Subclasses should ensure that ownership of
215      * created menus is correctly handled by parenting them to the specified parent widget.
216      * \param parent a parent widget of the menu
217      * \returns list of menus
218      * \since QGIS 3.0
219      */
220     virtual QList<QMenu *> menus( QWidget *parent );
221 
222     /**
223      * Returns whether the item accepts drag and dropped layers - e.g. for importing a dataset to a provider.
224      * Subclasses should override this and handleDrop() to accept dropped layers.
225      * \see handleDrop()
226      * \see QgsDataItemGuiProvider::handleDrop()
227      *
228      * \deprecated QGIS 3.10
229      */
acceptDrop()230     Q_DECL_DEPRECATED virtual bool acceptDrop() SIP_DEPRECATED { return false; }
231 
232     /**
233      * Attempts to process the mime data dropped on this item. Subclasses must override this and acceptDrop() if they
234      * accept dropped layers.
235      * \see acceptDrop()
236      * \see QgsDataItemGuiProvider::handleDrop()
237      *
238      * \deprecated QGIS 3.10
239      */
handleDrop(const QMimeData *,Qt::DropAction)240     Q_DECL_DEPRECATED virtual bool handleDrop( const QMimeData * /*data*/, Qt::DropAction /*action*/ ) SIP_DEPRECATED { return false; }
241 
242     /**
243      * Called when a user double clicks on the item. Subclasses should return TRUE
244      * if they have implemented a double-click handler and do not want the default
245      * double-click behavior for items.
246      * \since QGIS 3.0
247      */
248     virtual bool handleDoubleClick();
249 
250     /**
251      * Returns TRUE if the item may be dragged.
252      * Default implementation returns FALSE.
253      * A draggable item has to implement mimeUri() that will be used to pass data.
254      * \see mimeUri()
255      * \since QGIS 3.0
256      */
hasDragEnabled()257     virtual bool hasDragEnabled() const { return false; }
258 
259     /**
260      * Returns mime URI for the data item.
261      * Items that return valid URI will be returned in mime data when dragging a selection from browser model.
262      * \see hasDragEnabled()
263      * \since QGIS 3.0
264      */
mimeUri()265     virtual QgsMimeDataUtils::Uri mimeUri() const { return QgsMimeDataUtils::Uri(); }
266 
267     enum Capability
268     {
269       NoCapabilities    = 0,
270       SetCrs            = 1 << 0, //!< Can set CRS on layer or group of layers. \deprecated since QGIS 3.6 -- no longer used by QGIS and will be removed in QGIS 4.0
271       Fertile           = 1 << 1, //!< Can create children. Even items without this capability may have children, but cannot create them, it means that children are created by item ancestors.
272       Fast              = 1 << 2, //!< CreateChildren() is fast enough to be run in main thread when refreshing items, most root items (wms,wfs,wcs,postgres...) are considered fast because they are reading data only from QgsSettings
273       Collapse          = 1 << 3, //!< The collapse/expand status for this items children should be ignored in order to avoid undesired network connections (wms etc.)
274       Rename            = 1 << 4, //!< Item can be renamed
275       Delete            = 1 << 5, //!< Item can be deleted
276     };
Q_DECLARE_FLAGS(Capabilities,Capability)277     Q_DECLARE_FLAGS( Capabilities, Capability )
278 
279     /**
280      * Writes the selected crs into data source. The original data source will be modified when calling this
281      * method.
282      *
283      * \deprecated since QGIS 3.6. This method is no longer used by QGIS and will be removed in QGIS 4.0.
284      */
285     Q_DECL_DEPRECATED virtual bool setCrs( const QgsCoordinateReferenceSystem &crs ) SIP_DEPRECATED
286     {
287       Q_UNUSED( crs )
288       return false;
289     }
290 
291     /**
292      * Sets a new \a name for the item, and returns TRUE if the item was successfully renamed.
293      *
294      * Items which implement this method should return the QgsDataItem::Rename capability.
295      *
296      * The default implementation does nothing.
297      *
298      * Use QgsDataItemGuiProvider:
299      *
300      * \since QGIS 3.4
301      * \deprecated QGIS 3.10
302      */
303     Q_DECL_DEPRECATED virtual bool rename( const QString &name ) SIP_DEPRECATED;
304 
305     // ### QGIS 4 - rename to capabilities()
306 
307     /**
308      * Returns the capabilities for the data item.
309      *
310      * \see setCapabilities()
311      */
capabilities2()312     virtual Capabilities capabilities2() const { return mCapabilities; }
313 
314     /**
315      * Sets the capabilities for the data item.
316      *
317      * \see capabilities2()
318      */
setCapabilities(Capabilities capabilities)319     virtual void setCapabilities( Capabilities capabilities ) { mCapabilities = capabilities; }
320 
321     // static methods
322 
323     // Find child index in vector of items using '==' operator
324     static int findItem( QVector<QgsDataItem *> items, QgsDataItem *item );
325 
326     // members
327 
type()328     Type type() const { return mType; }
329 
330     /**
331      * Gets item parent. QgsDataItem maintains its own items hierarchy, it does not use
332      * QObject hierarchy.
333     */
parent()334     QgsDataItem *parent() const { return mParent; }
335 
336     /**
337      * Set item parent and connect / disconnect parent to / from item signals.
338      * It does not add itself to parents children (mChildren)
339     */
340     void setParent( QgsDataItem *parent );
children()341     QVector<QgsDataItem *> children() const { return mChildren; }
342     virtual QIcon icon();
343 
344     /**
345      * Returns the name of the item (the displayed text for the item).
346      *
347      * \see setName()
348      */
name()349     QString name() const { return mName; }
350 
351     /**
352      * Sets the \a name of the item (the displayed text for the item).
353      *
354      * \see name()
355      */
356     void setName( const QString &name );
357 
path()358     QString path() const { return mPath; }
setPath(const QString & path)359     void setPath( const QString &path ) { mPath = path; }
360 
361     /**
362      * Returns the provider key that created this item (e.g. "PostGIS")
363      *
364      * If key has a prefix "special:", it marks that the item was not created with a provider,
365      * but manually. For example "special:Favorites", "special:Home"
366      *
367      * \since QGIS 3.12
368      */
369     QString providerKey() const;
370 
371     /**
372      * Sets the provider key that created this item (e.g. "PostGIS")
373      *
374      * If key has a prefix "special:", it marks that the item was not created with a provider,
375      * but manually. For example "special:Favorites"
376      *
377      * \since QGIS 3.12
378      */
379     void setProviderKey( const QString &value );
380 
381     //! Create path component replacing path separators
382     static QString pathComponent( const QString &component );
383 
384     /**
385      * Returns the sorting key for the item. By default name() is returned,
386      * but setSortKey() can be used to set a custom sort key for the item.
387      *
388      * Alternatively subclasses can override this method to return a custom
389      * sort key.
390      *
391      * \see setSortKey()
392      * \since QGIS 3.0
393      */
394     virtual QVariant sortKey() const;
395 
396     /**
397      * Sets a custom sorting \a key for the item.
398      * \see sortKey()
399      * \since QGIS 3.0
400      */
401     void setSortKey( const QVariant &key );
402 
403 
404     // Because QIcon (QPixmap) must not be used in outside the GUI thread, it is
405     // not possible to set mIcon in constructor. Either use mIconName/setIconName()
406     // or implement icon().
setIcon(const QIcon & icon)407     void setIcon( const QIcon &icon ) { mIcon = icon; }
setIconName(const QString & iconName)408     void setIconName( const QString &iconName ) { mIconName = iconName; }
409 
setToolTip(const QString & msg)410     void setToolTip( const QString &msg ) { mToolTip = msg; }
toolTip()411     QString toolTip() const { return mToolTip; }
412 
413     // deleteLater() items and clear the vector
414     static void deleteLater( QVector<QgsDataItem *> &items );
415 
416     //! Move object and all its descendants to thread
417     void moveToThread( QThread *targetThread );
418 
419     /**
420      * For data items that represent a DB connection or one of its children,
421      * this method returns a connection.
422      * All other data items will return NULL.
423      *
424      * Ownership of the returned objects is transferred to the caller.
425      *
426      * \since QGIS 3.16
427      */
428     virtual QgsAbstractDatabaseProviderConnection *databaseConnection() const SIP_FACTORY;
429 
430   protected:
431     virtual void populate( const QVector<QgsDataItem *> &children );
432 
433     /**
434      * Refresh the items from a specified list of child items.
435      */
436     virtual void refresh( const QVector<QgsDataItem *> &children );
437 
438     /**
439      * The item is scheduled to be deleted. E.g. if deleteLater() is called when
440      * item is in Populating state (createChildren() running in another thread),
441      * the deferredDelete() returns TRUE and item will be deleted once Populating finished.
442      * Items with slow reateChildren() (for example network or database based) may
443      * check during createChildren() if deferredDelete() returns TRUE and return from
444      * createChildren() immediately because result will be useless.
445     */
deferredDelete()446     bool deferredDelete() { return mDeferredDelete; }
447 
448     Type mType;
449     Capabilities mCapabilities;
450     QgsDataItem *mParent = nullptr;
451     QVector<QgsDataItem *> mChildren; // easier to have it always
452     State mState;
453     QString mName;
454     QString mProviderKey;
455     // Path is slash ('/') separated chain of item identifiers which are usually item names, but may be different if it is
456     // necessary to distinguish paths of two providers to the same source (e.g GRASS location and standard directory have the same
457     // name but different paths). Identifiers in path must not contain '/' characters.
458     // The path is used to identify item in tree.
459     QString mPath;
460     QString mToolTip;
461     QString mIconName;
462     QIcon mIcon;
463     QMap<QString, QIcon> mIconMap;
464 
465     //! Custom sort key. If invalid, name() will be used for sorting instead.
466     QVariant mSortKey;
467 
468   public slots:
469 
470     /**
471      * Safely delete the item:
472      *
473      * - disconnects parent
474      * - unsets parent (but does not remove itself)
475      * - deletes all its descendants recursively
476      * - waits until Populating state (createChildren() in thread) finished without blocking main thread
477      * - calls QObject::deleteLater()
478      */
479     virtual void deleteLater();
480 
481     // Populate children using children vector created by createChildren()
482     // \param foreground run createChildren in foreground
483     virtual void populate( bool foreground = false );
484 
485     //! Remove children recursively and set as not populated. This is used when refreshing collapsed items.
486     virtual void depopulate();
487 
488     virtual void refresh();
489 
490     /**
491      * Causes a data item provider to refresh all registered connections.
492      *
493      * If \a providerKey is specified then only the matching provider will be refreshed. Otherwise,
494      * all providers will be refreshed (which is potentially very expensive!).
495      */
496     virtual void refreshConnections( const QString &providerKey = QString() );
497 
498     virtual void childrenCreated();
499 
500   signals:
501     void beginInsertItems( QgsDataItem *parent, int first, int last );
502     void endInsertItems();
503     void beginRemoveItems( QgsDataItem *parent, int first, int last );
504     void endRemoveItems();
505     void dataChanged( QgsDataItem *item );
506     void stateChanged( QgsDataItem *item, QgsDataItem::State oldState );
507 
508     /**
509      * Emitted when the connections of the provider with the specified \a providerKey have changed.
510      *
511      * This signal is normally forwarded to the app in order to refresh the connection
512      * item in the provider dialogs and to refresh the connection items in the other
513      * open browsers.
514      */
515     void connectionsChanged( const QString &providerKey = QString() );
516 
517   protected slots:
518 
519     /**
520      * Will request a repaint of this icon.
521      *
522      * \since QGIS 3.0
523      */
524     void updateIcon();
525 
526   private:
527     static QVector<QgsDataItem *> runCreateChildren( QgsDataItem *item );
528 
529     // Set to true if object has to be deleted when possible (nothing running in threads)
530     bool mDeferredDelete;
531     QFutureWatcher< QVector <QgsDataItem *> > *mFutureWatcher;
532     // number of items currently in loading (populating) state
533     static QgsAnimatedIcon *sPopulatingIcon;
534 };
535 
Q_DECLARE_OPERATORS_FOR_FLAGS(QgsDataItem::Capabilities)536 Q_DECLARE_OPERATORS_FOR_FLAGS( QgsDataItem::Capabilities )
537 
538 /**
539  * \ingroup core
540  * \brief Item that represents a layer that can be opened with one of the providers
541 */
542 class CORE_EXPORT QgsLayerItem : public QgsDataItem
543 {
544     Q_OBJECT
545 
546   public:
547     enum LayerType
548     {
549       NoType,
550       Vector,
551       Raster,
552       Point,
553       Line,
554       Polygon,
555       TableLayer,
556       Database,
557       Table,
558       Plugin,    //!< Added in 2.10
559       Mesh,      //!< Added in 3.2
560       VectorTile //!< Added in 3.14
561     };
562 
563     Q_ENUM( LayerType )
564 
565     QgsLayerItem( QgsDataItem *parent, const QString &name, const QString &path, const QString &uri, LayerType layerType, const QString &providerKey );
566 
567     // --- reimplemented from QgsDataItem ---
568 
569     bool equal( const QgsDataItem *other ) override;
570 
571     bool hasDragEnabled() const override { return true; }
572 
573     QgsMimeDataUtils::Uri mimeUri() const override;
574 
575     // --- New virtual methods for layer item derived classes ---
576 
577     //! Returns QgsMapLayerType
578     QgsMapLayerType mapLayerType() const;
579 
580     /**
581      * Returns the layer item type corresponding to a QgsMapLayer \a layer.
582      * \since QGIS 3.6
583      */
584     static LayerType typeFromMapLayer( QgsMapLayer *layer );
585 
586     //! Returns layer uri or empty string if layer cannot be created
587     QString uri() const { return mUri; }
588 
589     //! Returns provider key
590     QString providerKey() const { return mProviderKey; }
591 
592     /**
593      * Returns the supported CRS
594      *  \since QGIS 2.8
595      */
596     QStringList supportedCrs() const { return mSupportedCRS; }
597 
598     /**
599      * Returns the supported formats
600      *  \since QGIS 2.8
601      */
602     QStringList supportedFormats() const { return mSupportFormats; }
603 
604     /**
605      * Returns comments of the layer
606      * \since QGIS 2.12
607      */
608     virtual QString comments() const { return QString(); }
609 
610     /**
611      * Returns the string representation of the given \a layerType
612      * \since QGIS 3
613      */
614     static QString layerTypeAsString( LayerType layerType );
615 
616     /**
617      * Returns the icon name of the given \a layerType
618      * \since QGIS 3
619      */
620     static QString iconName( LayerType layerType );
621 
622     /**
623      * Delete this layer item
624      * Use QgsDataItemGuiProvider::deleteLayer instead
625      *
626      * \deprecated QGIS 3.10
627      */
628     Q_DECL_DEPRECATED virtual bool deleteLayer() SIP_DEPRECATED;
629 
630   protected:
631     //! The URI
632     QString mUri;
633     //! The layer type
634     LayerType mLayerType;
635     //! The list of supported CRS
636     QStringList mSupportedCRS;
637     //! The list of supported formats
638     QStringList mSupportFormats;
639 
640   public:
641     static QIcon iconPoint();
642     static QIcon iconLine();
643     static QIcon iconPolygon();
644     static QIcon iconTable();
645     static QIcon iconRaster();
646     static QIcon iconDefault();
647     //! Returns icon for mesh layer type
648     static QIcon iconMesh();
649     //! Returns icon for vector tile layer
650     static QIcon iconVectorTile();
651 
652     //! \returns the layer name
653     virtual QString layerName() const { return name(); }
654 
655 };
656 
657 
658 /**
659  * \ingroup core
660  * \brief A Collection: logical collection of layers or subcollections, e.g. GRASS location/mapset, database? wms source?
661 */
662 class CORE_EXPORT QgsDataCollectionItem : public QgsDataItem
663 {
664     Q_OBJECT
665   public:
666 
667     /**
668      * Constructor for QgsDataCollectionItem, with the specified \a parent item.
669      *
670      * The \a name argument specifies the text to show in the model for the item. A translated string should
671      * be used wherever appropriate.
672      *
673      * The \a path argument gives the item path in the browser tree. The \a path string can take any form,
674      * but QgsDataCollectionItem items pointing to different logical locations should always use a different item \a path.
675      *
676      * The optional \a providerKey string can be used to specify the key for the QgsDataItemProvider that created this item.
677      */
678     QgsDataCollectionItem( QgsDataItem *parent SIP_TRANSFERTHIS, const QString &name, const QString &path = QString(), const QString &providerKey = QString() );
679 
680     ~QgsDataCollectionItem() override;
681 
addChild(QgsDataItem * item SIP_TRANSFER)682     void addChild( QgsDataItem *item SIP_TRANSFER ) { mChildren.append( item ); }
683 
684     /**
685      * Returns the standard browser directory icon.
686      * \see iconDataCollection()
687      */
688     static QIcon iconDir();
689 
690     /**
691      * Returns the standard browser data collection icon.
692      * \see iconDir()
693      */
694     static QIcon iconDataCollection();
695 
696     QgsAbstractDatabaseProviderConnection *databaseConnection() const override;
697 
698   protected:
699 
700     /**
701      * Shared open directory icon.
702      * \since QGIS 3.4
703      */
704     static QIcon openDirIcon();
705 
706     /**
707      * Shared home directory icon.
708      * \since QGIS 3.4
709      */
710     static QIcon homeDirIcon();
711 
712 };
713 
714 
715 /**
716  * \ingroup core
717  * \brief A Collection that represents a database schema item
718  * \since QGIS 3.16
719 */
720 class CORE_EXPORT QgsDatabaseSchemaItem : public QgsDataCollectionItem
721 {
722     Q_OBJECT
723   public:
724 
725     /**
726      * Constructor for QgsDatabaseSchemaItem, with the specified \a parent item.
727      *
728      * The \a name argument specifies the text to show in the model for the item. A translated string should
729      * be used wherever appropriate.
730      *
731      * The \a path argument gives the item path in the browser tree. The \a path string can take any form,
732      * but QgsSchemaItem items pointing to different logical locations should always use a different item \a path.
733      *
734      * The optional \a providerKey string can be used to specify the key for the QgsDataItemProvider that created this item.
735      */
736     QgsDatabaseSchemaItem( QgsDataItem *parent SIP_TRANSFERTHIS, const QString &name, const QString &path = QString(), const QString &providerKey = QString() );
737 
738     ~QgsDatabaseSchemaItem() override;
739 
740     QgsAbstractDatabaseProviderConnection *databaseConnection() const override;
741 
742     /**
743      * Returns the standard browser data collection icon.
744      * \see iconDir()
745      */
746     static QIcon iconDataCollection();
747 
748 };
749 
750 
751 
752 /**
753  * \ingroup core
754  * \brief A Collection that represents a root group of connections from a single data provider
755  * \since QGIS 3.16
756 */
757 class CORE_EXPORT QgsConnectionsRootItem : public QgsDataCollectionItem
758 {
759     Q_OBJECT
760   public:
761 
762     /**
763      * Constructor for QgsConnectionsRootItem, with the specified \a parent item.
764      *
765      * The \a name argument specifies the text to show in the model for the item. A translated string should
766      * be used wherever appropriate.
767      *
768      * The \a path argument gives the item path in the browser tree. The \a path string can take any form,
769      * but QgsSchemaItem items pointing to different logical locations should always use a different item \a path.
770      *
771      * The optional \a providerKey string can be used to specify the key for the QgsDataItemProvider that created this item.
772      */
773     QgsConnectionsRootItem( QgsDataItem *parent SIP_TRANSFERTHIS, const QString &name, const QString &path = QString(), const QString &providerKey = QString() );
774 
775     ~QgsConnectionsRootItem() override = default;
776 };
777 
778 
779 /**
780  * \ingroup core
781  * \brief A directory: contains subdirectories and layers
782 */
783 class CORE_EXPORT QgsDirectoryItem : public QgsDataCollectionItem
784 {
785     Q_OBJECT
786   public:
787 
788     /**
789      * Constructor for QgsDirectoryItem, with the specified \a parent item.
790      *
791      * The \a name argument specifies the text to show in the model for the item. This is usually
792      * the directory name, but in certain cases may differ for special directories (e.g. "Home").
793      * If a non-directory-name text is used, it should be a translated string when appropriate.
794      *
795      * The \a path argument specifies the directory path in the file system (e.g. "/home/gsherman/stuff"). A valid
796      * directory path must be specified.
797      */
798     QgsDirectoryItem( QgsDataItem *parent SIP_TRANSFERTHIS, const QString &name, const QString &path );
799 
800 
801     // TODO QGIS 4.0 -- rename "name" to "title" or "text" or something more descriptive, and "path" to something
802     // else to clarify the role of dirPath vs path
803 
804     /**
805      * Constructor for QgsDirectoryItem, with the specified \a parent item.
806      *
807      * The \a name argument specifies the text to show in the model for the item. This is usually
808      * the directory name, but in certain cases may differ for special directories (e.g. "Home").
809      * If a non-directory-name text is used, it should be a translated string when appropriate.
810      *
811      * The \a dirPath argument specifies the directory path in the file system (e.g. "/home/gsherman/stuff"). A valid
812      * directory path must be specified.
813      *
814      * The \a path argument gives the item path in the browser tree. The \a path string can take any form, but is usually
815      * the same as \a dirPath or \a dirPath with a prefix, e.g. "favorites:/home/gsherman/Downloads"). QgsDirectoryItem
816      * items pointing to different \a dirPaths should always use a different item \a path.
817      *
818      * The optional \a providerKey string can be used to specify the key for the QgsDataItemProvider that created this item.
819      */
820     QgsDirectoryItem( QgsDataItem *parent SIP_TRANSFERTHIS, const QString &name, const QString &dirPath, const QString &path, const QString &providerKey = QString() );
821 
822     void setState( State state ) override;
823 
824     QVector<QgsDataItem *> createChildren() override;
825 
826     /**
827      * Returns the full path to the directory the item represents.
828      */
dirPath()829     QString dirPath() const { return mDirPath; }
830 
831     bool equal( const QgsDataItem *other ) override;
832     QIcon icon() override;
833     Q_DECL_DEPRECATED QWidget *paramWidget() override SIP_FACTORY SIP_DEPRECATED;
hasDragEnabled()834     bool hasDragEnabled() const override { return true; }
835     QgsMimeDataUtils::Uri mimeUri() const override;
836 
837     //! Check if the given path is hidden from the browser model
838     static bool hiddenPath( const QString &path );
839 
840   public slots:
841     void childrenCreated() override;
842     void directoryChanged();
843 
844   protected:
845     void init();
846     QString mDirPath;
847 
848   private:
849     QFileSystemWatcher *mFileSystemWatcher = nullptr;
850     bool mRefreshLater;
851     QDateTime mLastScan;
852 };
853 
854 /**
855  * \ingroup core
856  * \brief Data item that can be used to represent QGIS projects.
857  */
858 class CORE_EXPORT QgsProjectItem : public QgsDataItem
859 {
860     Q_OBJECT
861   public:
862 
863     /**
864      * \brief A data item holding a reference to a QGIS project file.
865      * \param parent The parent data item.
866      * \param name The name of the of the project. Displayed to the user.
867      * \param path The full path to the project.
868      * \param providerKey key of the provider that created this item
869      */
870     QgsProjectItem( QgsDataItem *parent, const QString &name, const QString &path, const QString &providerKey = QString() );
871 
hasDragEnabled()872     bool hasDragEnabled() const override { return true; }
873 
874     QgsMimeDataUtils::Uri mimeUri() const override;
875 
876 };
877 
878 /**
879  * \ingroup core
880  * \brief Data item that can be used to report problems (e.g. network error)
881  */
882 class CORE_EXPORT QgsErrorItem : public QgsDataItem
883 {
884     Q_OBJECT
885   public:
886 
887     QgsErrorItem( QgsDataItem *parent, const QString &error, const QString &path );
888 
889 };
890 
891 // ---------
892 
893 // TODO: move to qgis_gui for QGIS 4
894 
895 /**
896  * \ingroup core
897  * \class QgsDirectoryParamWidget
898  *
899  * \brief Browser parameter widget implementation for directory items.
900  */
901 class CORE_EXPORT QgsDirectoryParamWidget : public QTreeWidget
902 {
903     Q_OBJECT
904 
905   public:
906     QgsDirectoryParamWidget( const QString &path, QWidget *parent SIP_TRANSFERTHIS = nullptr );
907 
908   protected:
909     void mousePressEvent( QMouseEvent *event ) override;
910 
911   public slots:
912     void showHideColumn();
913 };
914 
915 /**
916  * \ingroup core
917  * \brief Contains various Favorites directories
918  * \since QGIS 3.0
919 */
920 class CORE_EXPORT QgsFavoritesItem : public QgsDataCollectionItem
921 {
922     Q_OBJECT
923   public:
924 
925     /**
926      * Constructor for QgsFavoritesItem. Accepts a path argument specifying the file path associated with
927      * the item.
928      */
929     QgsFavoritesItem( QgsDataItem *parent, const QString &name, const QString &path = QString() );
930 
931     QVector<QgsDataItem *> createChildren() override;
932 
933     /**
934      * Adds a new \a directory to the favorites group.
935      *
936      * If \a name is specified, it will be used as the favorite's name. Otherwise
937      * the name will be set to match \a directory.
938      *
939      * \see removeDirectory()
940      */
941     void addDirectory( const QString &directory, const QString &name = QString() );
942 
943     /**
944      * Removes an existing directory from the favorites group.
945      * \see addDirectory()
946      */
947     void removeDirectory( QgsDirectoryItem *item );
948 
949     /**
950      * Renames the stored favorite with corresponding \a path a new \a name.
951      */
952     void renameFavorite( const QString &path, const QString &name );
953 
954     //! Icon for favorites group
955     static QIcon iconFavorites();
956 
957     QVariant sortKey() const override;
958 
959   private:
960     QVector<QgsDataItem *> createChildren( const QString &favDir, const QString &name );
961 };
962 
963 /**
964  * \ingroup core
965  * \brief A zip file: contains layers, using GDAL/OGR VSIFILE mechanism
966 */
967 class CORE_EXPORT QgsZipItem : public QgsDataCollectionItem
968 {
969     Q_OBJECT
970 
971   protected:
972     QString mFilePath;
973     QString mVsiPrefix;
974     QStringList mZipFileList;
975 
976   public:
977     //! Constructor
978     QgsZipItem( QgsDataItem *parent, const QString &name, const QString &path );
979 
980     //! Constructor
981     QgsZipItem( QgsDataItem *parent, const QString &name, const QString &filePath, const QString &path, const QString &providerKey = QString() );
982 
983     QVector<QgsDataItem *> createChildren() override;
984     QStringList getZipFileList();
985 
986     //! \note not available via Python bindings
987     static QVector<dataItem_t *> sDataItemPtr SIP_SKIP;
988     static QStringList sProviderNames;
989 
vsiPrefix(const QString & uri)990     static QString vsiPrefix( const QString &uri ) { return qgsVsiPrefix( uri ); }
991 
992     /**
993      * Creates a new data item from the specified path.
994      */
995     static QgsDataItem *itemFromPath( QgsDataItem *parent, const QString &path, const QString &name ) SIP_FACTORY;
996 
997     /**
998     * Creates a new data item from the specified path.
999     * \note available in Python as itemFromFilePath
1000     */
1001     static QgsDataItem *itemFromPath( QgsDataItem *parent, const QString &filePath, const QString &name, const QString &path ) SIP_FACTORY SIP_PYNAME( itemFromFilePath );
1002 
1003     static QIcon iconZip();
1004 
1005   private:
1006     void init();
1007 };
1008 
1009 
1010 /**
1011  * \ingroup core
1012  * \brief A collection of field items with some internal logic to retrieve
1013  * the fields and a the vector layer instance from a connection URI,
1014  * the schema and the table name.
1015  * \since QGIS 3.16
1016 */
1017 class CORE_EXPORT QgsFieldsItem : public QgsDataItem
1018 {
1019     Q_OBJECT
1020 
1021   public:
1022 
1023     /**
1024      * Constructor for QgsFieldsItem, with the specified \a parent item.
1025      *
1026      * The \a path argument gives the item path in the browser tree. The \a path string can take any form,
1027      * but QgsDataItem items pointing to different logical locations should always use a different item \a path.
1028      * The \connectionUri argument is the connection part of the layer URI that it is used internally to create
1029      * a connection and retrieve fields information.
1030      * The \a providerKey string can be used to specify the key for the QgsDataItemProvider that created this item.
1031      * The \a schema and \a tableName are used to retrieve the layer and field information from the \a connectionUri.
1032      */
1033     QgsFieldsItem( QgsDataItem *parent SIP_TRANSFERTHIS,
1034                    const QString &path,
1035                    const QString &connectionUri,
1036                    const QString &providerKey,
1037                    const QString &schema,
1038                    const QString &tableName );
1039 
1040     ~QgsFieldsItem() override;
1041 
1042     QVector<QgsDataItem *> createChildren() override;
1043 
1044     QIcon icon() override;
1045 
1046     /**
1047      * Returns the schema name
1048      */
1049     QString schema() const;
1050 
1051     /**
1052      * Returns the table name
1053      */
1054     QString tableName() const;
1055 
1056     /**
1057      * Returns the connection URI
1058      */
1059     QString connectionUri() const;
1060 
1061     /**
1062      * Creates and returns a (possibly NULL) layer from the connection URI and schema/table information
1063      */
1064     QgsVectorLayer *layer() SIP_FACTORY;
1065 
1066     /**
1067      * Returns the (possibly NULL) properties of the table this fields belong to.
1068      * \since QGIS 3.16
1069      */
1070     QgsAbstractDatabaseProviderConnection::TableProperty *tableProperty() const;
1071 
1072   private:
1073 
1074     QString mSchema;
1075     QString mTableName;
1076     QString mConnectionUri;
1077     std::unique_ptr<QgsAbstractDatabaseProviderConnection::TableProperty> mTableProperty;
1078 
1079 };
1080 
1081 
1082 /**
1083  * \ingroup core
1084  * \brief A layer field item, information about the connection URI, the schema and the
1085  * table as well as the layer instance the field belongs to can be retrieved
1086  * from the parent QgsFieldsItem object.
1087  * \since QGIS 3.16
1088 */
1089 class CORE_EXPORT QgsFieldItem : public QgsDataItem
1090 {
1091     Q_OBJECT
1092   public:
1093 
1094     /**
1095      * Constructor for QgsFieldItem, with the specified \a parent item and \a field.
1096      * \note parent item must be a QgsFieldsItem
1097      */
1098     QgsFieldItem( QgsDataItem *parent SIP_TRANSFERTHIS,
1099                   const QgsField &field );
1100 
1101     ~QgsFieldItem() override;
1102 
1103     QIcon icon() override;
1104 
1105     //QgsField field() const;
1106 
1107 
1108   private:
1109 
1110     const QgsField mField;
1111 
1112 };
1113 
1114 
1115 
1116 ///@cond PRIVATE
1117 #ifndef SIP_RUN
1118 
1119 /**
1120  * \ingroup core
1121  * \brief A directory item showing the current project directory.
1122  * \since QGIS 3.0
1123 */
1124 class CORE_EXPORT QgsProjectHomeItem : public QgsDirectoryItem
1125 {
1126     Q_OBJECT
1127 
1128   public:
1129 
1130     QgsProjectHomeItem( QgsDataItem *parent, const QString &name, const QString &dirPath, const QString &path );
1131 
1132     QIcon icon() override;
1133     QVariant sortKey() const override;
1134 
1135 };
1136 
1137 /**
1138  * \ingroup core
1139  * \brief A directory item showing the a single favorite directory.
1140  * \since QGIS 3.0
1141 */
1142 Q_NOWARN_DEPRECATED_PUSH  // rename is deprecated
1143 class CORE_EXPORT QgsFavoriteItem : public QgsDirectoryItem
1144 {
1145     Q_OBJECT
1146 
1147   public:
1148 
1149     QgsFavoriteItem( QgsFavoritesItem *parent, const QString &name, const QString &dirPath, const QString &path );
1150 
1151     bool rename( const QString &name ) override;
1152 
1153   private:
1154 
1155     QgsFavoritesItem *mFavorites = nullptr;
1156 };
1157 Q_NOWARN_DEPRECATED_POP
1158 
1159 #endif
1160 ///@endcond
1161 
1162 #endif // QGSDATAITEM_H
1163 
1164 
1165