Branch data Line data Source code
1 : : /***************************************************************************
2 : : qgsbrowsermodel.h
3 : : ---------------------
4 : : begin : July 2011
5 : : copyright : (C) 2011 by Martin Dobias
6 : : email : wonder dot sk at gmail dot com
7 : : ***************************************************************************
8 : : * *
9 : : * This program is free software; you can redistribute it and/or modify *
10 : : * it under the terms of the GNU General Public License as published by *
11 : : * the Free Software Foundation; either version 2 of the License, or *
12 : : * (at your option) any later version. *
13 : : * *
14 : : ***************************************************************************/
15 : : #ifndef QGSBROWSERMODEL_H
16 : : #define QGSBROWSERMODEL_H
17 : :
18 : : #include "qgis_core.h"
19 : : #include <QAbstractItemModel>
20 : : #include <QIcon>
21 : : #include <QMimeData>
22 : : #include <QMovie>
23 : : #include <QFuture>
24 : : #include <QFutureWatcher>
25 : :
26 : : #include "qgsdataitem.h"
27 : :
28 : : class QgsDataItemProvider;
29 : :
30 : : /**
31 : : * \ingroup core
32 : : * \class QgsBrowserWatcher
33 : : * \note not available in Python bindings
34 : : */
35 : : #ifndef SIP_RUN
36 : : class CORE_EXPORT QgsBrowserWatcher : public QFutureWatcher<QVector <QgsDataItem *> >
37 : : {
38 : : Q_OBJECT
39 : :
40 : : public:
41 : : QgsBrowserWatcher( QgsDataItem *item );
42 : :
43 : : QgsDataItem *item() const { return mItem; }
44 : :
45 : : signals:
46 : : void finished( QgsDataItem *item, const QVector <QgsDataItem *> &items );
47 : :
48 : : private:
49 : : QgsDataItem *mItem = nullptr;
50 : : };
51 : : #endif
52 : :
53 : : /**
54 : : * \ingroup core
55 : : * \class QgsBrowserModel
56 : : *
57 : : * \brief A model for showing available data sources and other items in a structured
58 : : * tree.
59 : : *
60 : : * QgsBrowserModel is the foundation for the QGIS browser panel, and includes
61 : : * items for the different data providers and folders accessible to users.
62 : : *
63 : : * QgsBrowserModel models are not initially populated and use a deferred initialization
64 : : * approach. After constructing a QgsBrowserModel, a call must be made
65 : : * to initialize() in order to populate the model.
66 : : *
67 : : * \note Since QGIS 3.10 it is recommended to use QgsBrowserGuiModel from GUI library.
68 : : * Implementation of data items used from QgsBrowserModel should not trigger any GUI
69 : : * operations such as opening of widgets/dialogs or showing message boxes. Such actions
70 : : * should be implemented in a new QgsDataItemGuiProvider subclass which is used
71 : : * by QgsBrowserGuiModel (but not by QgsBrowserModel).
72 : : */
73 : : class CORE_EXPORT QgsBrowserModel : public QAbstractItemModel
74 : : {
75 : 0 : Q_OBJECT
76 : :
77 : : public:
78 : :
79 : : /**
80 : : * Constructor for QgsBrowserModel, with the specified \a parent object.
81 : : *
82 : : * \note QgsBrowserModel models are not initially populated and use a deferred initialization
83 : : * approach. After constructing a QgsBrowserModel, a call must be made
84 : : * to initialize() in order to populate the model.
85 : : */
86 : : explicit QgsBrowserModel( QObject *parent = nullptr );
87 : :
88 : : ~QgsBrowserModel() override;
89 : :
90 : : enum ItemDataRole
91 : : {
92 : : PathRole = Qt::UserRole, //!< Item path used to access path in the tree, see QgsDataItem::mPath
93 : : CommentRole = Qt::UserRole + 1, //!< Item comment
94 : : SortRole, //!< Custom sort role, see QgsDataItem::sortKey()
95 : : ProviderKeyRole, //!< Data item provider key that created the item, see QgsDataItem::providerKey() \since QGIS 3.12
96 : : };
97 : : // implemented methods from QAbstractItemModel for read-only access
98 : :
99 : : Qt::ItemFlags flags( const QModelIndex &index ) const override;
100 : : QVariant data( const QModelIndex &index, int role = Qt::DisplayRole ) const override;
101 : : bool setData( const QModelIndex &index, const QVariant &value, int role = Qt::EditRole ) override;
102 : : QVariant headerData( int section, Qt::Orientation orientation, int role = Qt::DisplayRole ) const override;
103 : : int rowCount( const QModelIndex &parent = QModelIndex() ) const override;
104 : : int columnCount( const QModelIndex &parent = QModelIndex() ) const override;
105 : : QModelIndex index( int row, int column, const QModelIndex &parent = QModelIndex() ) const override;
106 : : QModelIndex parent( const QModelIndex &index ) const override;
107 : : QStringList mimeTypes() const override;
108 : : QMimeData *mimeData( const QModelIndexList &indexes ) const override;
109 : : bool dropMimeData( const QMimeData *data, Qt::DropAction action, int row, int column, const QModelIndex &parent ) override;
110 : : bool hasChildren( const QModelIndex &parent = QModelIndex() ) const override;
111 : : bool canFetchMore( const QModelIndex &parent ) const override;
112 : : void fetchMore( const QModelIndex &parent ) override;
113 : :
114 : : /**
115 : : * Returns the model index corresponding to the specified data \a item.
116 : : * If the item was not found, an invalid QModelIndex is returned.
117 : : *
118 : : * If the \a parent item is argument is specified, then only items which are children
119 : : * of \a parent are searched. If no \a parent is specified, then all items within
120 : : * the model are searched.
121 : : */
122 : : QModelIndex findItem( QgsDataItem *item, QgsDataItem *parent = nullptr ) const;
123 : :
124 : : /**
125 : : * Returns the data item at the specified index, or NULLPTR if no item
126 : : * exists at the index.
127 : : */
128 : : QgsDataItem *dataItem( const QModelIndex &idx ) const;
129 : :
130 : : //! Refresh item specified by path
131 : : void refresh( const QString &path );
132 : :
133 : : //! Refresh item children
134 : : void refresh( const QModelIndex &index = QModelIndex() );
135 : :
136 : : /**
137 : : * Returns index of item with given path. It only searches in currently fetched
138 : : * items, i.e. it does not fetch children.
139 : : * \param path item path
140 : : * \param matchFlag supported is Qt::MatchExactly and Qt::MatchStartsWith which has reverse meaning, i.e. find
141 : : * item with the longest match from start with path (to get as close/deep as possible to deleted item).
142 : : * \returns model index, invalid if item not found
143 : : */
144 : : QModelIndex findPath( const QString &path, Qt::MatchFlag matchFlag = Qt::MatchExactly );
145 : :
146 : : //! \note not available in Python bindings
147 : : static QModelIndex findPath( QAbstractItemModel *model, const QString &path, Qt::MatchFlag matchFlag = Qt::MatchExactly ) SIP_SKIP;
148 : :
149 : : /**
150 : : * Returns index of layer item with given uri. It only searches in currently fetched
151 : : * items, i.e. it does not fetch children.
152 : : * \param uri item uri
153 : : * \param index the current index of the parent (to search for children)
154 : : * \returns model index, invalid if item not found
155 : : *
156 : : * \since QGIS 3.6
157 : : */
158 : : QModelIndex findUri( const QString &uri, QModelIndex index = QModelIndex() );
159 : :
160 : : /**
161 : : * \deprecated Deprecated since QGIS 3.4 -- this method has no effect, and is dangerous to call in earlier QGIS versions. Any usage should be removed (and will have no harmful side-effects!).
162 : : */
163 : : Q_DECL_DEPRECATED void connectItem( QgsDataItem *item ) SIP_DEPRECATED;
164 : :
165 : : /**
166 : : * Returns TRUE if the model has been initialized.
167 : : *
168 : : * \see initialize()
169 : : */
170 : : bool initialized() const { return mInitialized; }
171 : :
172 : : /**
173 : : * Returns a map of the root drive items shown in the browser.
174 : : *
175 : : * These correspond to the top-level directory items shown, e.g. on Windows the C:\, D:\, etc,
176 : : * and on Linux the "/" root directory.
177 : : *
178 : : * \since QGIS 3.6
179 : : */
180 : : QMap<QString, QgsDirectoryItem *> driveItems() const;
181 : : signals:
182 : :
183 : : //! Emitted when item children fetch was finished
184 : : void stateChanged( const QModelIndex &index, QgsDataItem::State oldState );
185 : :
186 : : /**
187 : : * Emitted when connections for the specified \a providerKey have changed in the browser.
188 : : *
189 : : * Forwarded to the widget and used to notify the provider dialogs of a changed connection.
190 : : */
191 : : void connectionsChanged( const QString &providerKey );
192 : :
193 : : public slots:
194 : : //! Reload the whole model
195 : : void reload();
196 : :
197 : : /**
198 : : * Refreshes the list of drive items, removing any corresponding to removed
199 : : * drives and adding newly added drives.
200 : : *
201 : : * \since QGIS 3.4
202 : : */
203 : : void refreshDrives();
204 : :
205 : : void beginInsertItems( QgsDataItem *parent, int first, int last );
206 : : void endInsertItems();
207 : : void beginRemoveItems( QgsDataItem *parent, int first, int last );
208 : : void endRemoveItems();
209 : : void itemDataChanged( QgsDataItem *item );
210 : : void itemStateChanged( QgsDataItem *item, QgsDataItem::State oldState );
211 : :
212 : : /**
213 : : * Adds a \a directory to the favorites group.
214 : : *
215 : : * If \a name is specified, it will be used as the favorite's name. Otherwise
216 : : * the name will be set to match \a directory.
217 : : *
218 : : * \see removeFavorite()
219 : : * \since QGIS 3.0
220 : : */
221 : : void addFavoriteDirectory( const QString &directory, const QString &name = QString() );
222 : :
223 : : /**
224 : : * Removes a favorite directory from its corresponding model index.
225 : : * \see addFavoriteDirectory()
226 : : * \since QGIS 3.0
227 : : */
228 : : void removeFavorite( const QModelIndex &index );
229 : :
230 : : /**
231 : : * Removes a \a favorite item.
232 : : * \see addFavoriteDirectory()
233 : : * \note Not available in Python bindings
234 : : * \since QGIS 3.6
235 : : */
236 : : void removeFavorite( QgsFavoriteItem *favorite ) SIP_SKIP;
237 : :
238 : : void updateProjectHome();
239 : :
240 : : //! Hide the given path in the browser model
241 : : void hidePath( QgsDataItem *item );
242 : :
243 : : /**
244 : : * Delayed initialization, needed because the provider registry must be already populated.
245 : : * \see initialized()
246 : : */
247 : : void initialize();
248 : :
249 : : protected:
250 : : //! Populates the model
251 : : void addRootItems();
252 : : void removeRootItems();
253 : :
254 : : QVector<QgsDataItem *> mRootItems;
255 : : QgsFavoritesItem *mFavorites = nullptr;
256 : : QgsDirectoryItem *mProjectHome = nullptr;
257 : :
258 : : private slots:
259 : : void dataItemProviderAdded( QgsDataItemProvider *provider );
260 : : void dataItemProviderWillBeRemoved( QgsDataItemProvider *provider );
261 : : void onConnectionsChanged( const QString &providerKey );
262 : :
263 : : private:
264 : : bool mInitialized = false;
265 : : QMap< QString, QgsDirectoryItem * > mDriveItems;
266 : :
267 : : void setupItemConnections( QgsDataItem *item );
268 : :
269 : : void removeRootItem( QgsDataItem *item );
270 : :
271 : : QgsDataItem *addProviderRootItem( QgsDataItemProvider *provider );
272 : :
273 : : friend class TestQgsBrowserModel;
274 : : friend class TestQgsBrowserProxyModel;
275 : : };
276 : :
277 : : #endif // QGSBROWSERMODEL_H
|