QGIS API Documentation 3.99.0-Master (8e76e220402)
Loading...
Searching...
No Matches
qgsbrowsermodel.cpp
Go to the documentation of this file.
1/***************************************************************************
2 qgsbrowsermodel.cpp
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#include "qgsbrowsermodel.h"
16
17#include "qgis.h"
18#include "qgsapplication.h"
19#include "qgsdataitemprovider.h"
21#include "qgsdirectoryitem.h"
22#include "qgsfavoritesitem.h"
23#include "qgslayeritem.h"
24#include "qgslayermetadata.h"
25#include "qgslogger.h"
26#include "qgsmimedatautils.h"
27#include "qgsproject.h"
28#include "qgssettings.h"
29
30#include <QApplication>
31#include <QDir>
32#include <QFuture>
33#include <QFutureWatcher>
34#include <QStorageInfo>
35#include <QString>
36#include <QStyle>
37#include <QUrl>
38
39#include "moc_qgsbrowsermodel.cpp"
40
41using namespace Qt::StringLiterals;
42
43#define PROJECT_HOME_PREFIX "project:"
44#define HOME_PREFIX "home:"
45
47class QgsBrowserWatcher : public QFutureWatcher<QVector <QgsDataItem *> >
48{
49 Q_OBJECT
50
51 public:
52 QgsBrowserWatcher( QgsDataItem *item )
53 : QFutureWatcher( nullptr )
54 , mItem( item )
55 {
56 }
57
58 QgsDataItem *item() const { return mItem; }
59
60 signals:
61 void finished( QgsDataItem *item, const QVector <QgsDataItem *> &items );
62
63 private:
64 QgsDataItem *mItem = nullptr;
65};
67
68// sort function for QList<QgsDataItem*>, e.g. sorted/grouped provider listings
69static bool cmpByDataItemName_( QgsDataItem *a, QgsDataItem *b )
70{
71 return QString::localeAwareCompare( a->name(), b->name() ) < 0;
72}
73
75 : QAbstractItemModel( parent )
76
77{
79 this, &QgsBrowserModel::dataItemProviderAdded );
81 this, &QgsBrowserModel::dataItemProviderWillBeRemoved );
82}
83
88
90{
91 QString home = QgsProject::instance()->homePath(); // skip-keyword-check
92 if ( mProjectHome && mProjectHome->path().mid( QStringLiteral( PROJECT_HOME_PREFIX ).length() ) == home )
93 return;
94
95 int idx = mRootItems.indexOf( mProjectHome );
96
97 // using layoutAboutToBeChanged() was messing expanded items
98 if ( idx >= 0 )
99 {
100 beginRemoveRows( QModelIndex(), idx, idx );
101 mRootItems.remove( idx );
102 endRemoveRows();
103 }
104 delete mProjectHome;
105 mProjectHome = home.isNull() ? nullptr : new QgsProjectHomeItem( nullptr, tr( "Project Home" ), home, QStringLiteral( PROJECT_HOME_PREFIX ) + home );
106 if ( mProjectHome )
107 {
108 setupItemConnections( mProjectHome );
109
110 beginInsertRows( QModelIndex(), 0, 0 );
111 mRootItems.insert( 0, mProjectHome );
112 endInsertRows();
113 }
114}
115
117{
119
120 // give the home directory a prominent third place
121 QgsDirectoryItem *item = new QgsDirectoryItem( nullptr, tr( "Home" ), QDir::homePath(),
122 QStringLiteral( HOME_PREFIX ) + QDir::homePath(),
123 u"special:Home"_s );
124 item->setSortKey( u" 2"_s );
125 setupItemConnections( item );
126 mRootItems << item;
127
128 // add favorite directories
129 mFavorites = new QgsFavoritesItem( nullptr, tr( "Favorites" ) );
130 if ( mFavorites )
131 {
132 setupItemConnections( mFavorites );
134 }
135
136 // add drives
137 const auto drives { QDir::drives() };
138 for ( const QFileInfo &drive : drives )
139 {
140 const QString path = drive.absolutePath();
141
142 if ( QgsDirectoryItem::hiddenPath( path ) )
143 continue;
144
145 const QString driveName = QStorageInfo( path ).displayName();
146 const QString name = driveName.isEmpty() || driveName == path ? path : u"%1 (%2)"_s.arg( path, driveName );
147
148 QgsDirectoryItem *item = new QgsDirectoryItem( nullptr, name, path, path, u"special:Drives"_s );
149 item->setSortKey( u" 3 %1"_s.arg( path ) );
150 mDriveItems.insert( path, item );
151
152 setupItemConnections( item );
153 mRootItems << item;
154 }
155
156#ifdef Q_OS_MAC
157 QString path = QString( "/Volumes" );
158 QgsDirectoryItem *vols = new QgsDirectoryItem( nullptr, path, path, path, u"special:Volumes"_s );
159 setupItemConnections( vols );
160 mRootItems << vols;
161#endif
162
163 // container for displaying providers as sorted groups (by QgsDataProvider::DataCapability enum)
164 QMultiMap<int, QgsDataItem *> providerMap;
165
166 const auto constProviders = QgsApplication::dataItemProviderRegistry()->providers();
167 for ( QgsDataItemProvider *pr : constProviders )
168 {
169 if ( QgsDataItem *item = addProviderRootItem( pr ) )
170 {
171 providerMap.insert( pr->capabilities(), item );
172 }
173 }
174
175 // add as sorted groups by QgsDataProvider::DataCapability enum
176 const auto constUniqueKeys = providerMap.uniqueKeys();
177 for ( int key : constUniqueKeys )
178 {
179 QList<QgsDataItem *> providerGroup = providerMap.values( key );
180 if ( providerGroup.size() > 1 )
181 {
182 std::sort( providerGroup.begin(), providerGroup.end(), cmpByDataItemName_ );
183 }
184
185 const auto constProviderGroup = providerGroup;
186 for ( QgsDataItem *ditem : constProviderGroup )
187 {
188 mRootItems << ditem;
189 }
190 }
191}
192
194{
195 const auto constMRootItems = mRootItems;
196 for ( QgsDataItem *item : constMRootItems )
197 {
198 delete item;
199 }
200
201 mRootItems.clear();
202 mDriveItems.clear();
203}
204
205void QgsBrowserModel::dataItemProviderAdded( QgsDataItemProvider *provider )
206{
207 if ( !mInitialized )
208 return;
209
210 if ( QgsDataItem *item = addProviderRootItem( provider ) )
211 {
212 beginInsertRows( QModelIndex(), rowCount(), rowCount() );
213 mRootItems << item;
214 endInsertRows();
215 }
216}
217
218void QgsBrowserModel::dataItemProviderWillBeRemoved( QgsDataItemProvider *provider )
219{
220 const auto constMRootItems = mRootItems;
221 for ( QgsDataItem *item : constMRootItems )
222 {
223 if ( item->providerKey() == provider->name() )
224 {
225 removeRootItem( item );
226 break; // assuming there is max. 1 root item per provider
227 }
228 }
229}
230
231void QgsBrowserModel::onConnectionsChanged( const QString &providerKey )
232{
233 // refresh the matching provider
234 for ( QgsDataItem *item : std::as_const( mRootItems ) )
235 {
236 if ( item->providerKey() == providerKey )
237 {
238 item->refresh();
239 break; // assuming there is max. 1 root item per provider
240 }
241 }
242
243 emit connectionsChanged( providerKey );
244}
245
246QMap<QString, QgsDirectoryItem *> QgsBrowserModel::driveItems() const
247{
248 return mDriveItems;
249}
250
251
253{
254 if ( ! mInitialized )
255 {
257 addRootItems();
258 mInitialized = true;
259 }
260}
261
262Qt::ItemFlags QgsBrowserModel::flags( const QModelIndex &index ) const
263{
264 if ( !index.isValid() )
265 return Qt::ItemFlags();
266
267 Qt::ItemFlags flags = Qt::ItemIsEnabled | Qt::ItemIsSelectable;
268
269 QgsDataItem *ptr = dataItem( index );
270
271 if ( !ptr )
272 {
273 QgsDebugMsgLevel( u"FLAGS PROBLEM!"_s, 4 );
274 return Qt::ItemFlags();
275 }
276
277 if ( ptr->hasDragEnabled() )
278 flags |= Qt::ItemIsDragEnabled;
279
281 if ( ptr->acceptDrop() )
282 flags |= Qt::ItemIsDropEnabled;
284
287 flags |= Qt::ItemIsEditable;
288
289 return flags;
290}
291
292QVariant QgsBrowserModel::data( const QModelIndex &index, int role ) const
293{
294 if ( !index.isValid() )
295 return QVariant();
296
297 QgsDataItem *item = dataItem( index );
298 if ( !item )
299 {
300 return QVariant();
301 }
302 else if ( role == Qt::DisplayRole || role == Qt::EditRole )
303 {
304 return item->name();
305 }
306 else if ( role == static_cast< int >( QgsBrowserModel::CustomRole::Sort ) )
307 {
308 return item->sortKey();
309 }
310 else if ( role == Qt::ToolTipRole )
311 {
312 return item->toolTip();
313 }
314 else if ( role == Qt::DecorationRole && index.column() == 0 )
315 {
316 return item->icon();
317 }
318 else if ( role == static_cast< int >( QgsBrowserModel::CustomRole::Path ) )
319 {
320 return item->path();
321 }
322 else if ( role == static_cast< int >( QgsBrowserModel::CustomRole::Comment ) )
323 {
324 if ( item->type() == Qgis::BrowserItemType::Layer )
325 {
326 QgsLayerItem *lyrItem = qobject_cast<QgsLayerItem *>( item );
327 return lyrItem->comments();
328 }
329 return QVariant();
330 }
331 else if ( role == static_cast< int >( QgsBrowserModel::CustomRole::LayerMetadata ) )
332 {
333 if ( item->type() == Qgis::BrowserItemType::Layer )
334 {
335 QgsLayerItem *lyrItem = qobject_cast<QgsLayerItem *>( item );
336 return QVariant::fromValue( lyrItem->layerMetadata() );
337 }
338 return QVariant();
339 }
340 else if ( role == static_cast< int >( QgsBrowserModel::CustomRole::ProviderKey ) )
341 {
342 return item->providerKey();
343 }
344 else
345 {
346 // unsupported role
347 return QVariant();
348 }
349}
350
351bool QgsBrowserModel::setData( const QModelIndex &index, const QVariant &value, int role )
352{
353 if ( !index.isValid() )
354 return false;
355
356
357 QgsDataItem *item = dataItem( index );
358 if ( !item )
359 {
360 return false;
361 }
362
365 return false;
366
367 switch ( role )
368 {
369 case Qt::EditRole:
370 {
372 return item->rename( value.toString() );
374 }
375 }
376 return false;
377}
378
379QVariant QgsBrowserModel::headerData( int section, Qt::Orientation orientation, int role ) const
380{
381 Q_UNUSED( section )
382 if ( orientation == Qt::Horizontal && role == Qt::DisplayRole )
383 {
384 return QVariant( "header" );
385 }
386
387 return QVariant();
388}
389
390int QgsBrowserModel::rowCount( const QModelIndex &parent ) const
391{
392 //QgsDebugMsgLevel(QString("isValid = %1 row = %2 column = %3").arg(parent.isValid()).arg(parent.row()).arg(parent.column()), 2);
393
394 if ( !parent.isValid() )
395 {
396 // root item: its children are top level items
397 return mRootItems.count(); // mRoot
398 }
399 else
400 {
401 // ordinary item: number of its children
402 QgsDataItem *item = dataItem( parent );
403 //if ( item ) QgsDebugMsgLevel(QString("path = %1 rowCount = %2").arg(item->path()).arg(item->rowCount()), 2);
404 return item ? item->rowCount() : 0;
405 }
406}
407
408bool QgsBrowserModel::hasChildren( const QModelIndex &parent ) const
409{
410 if ( !parent.isValid() )
411 return !mRootItems.isEmpty(); // root item: its children are top level items
412
413 QgsDataItem *item = dataItem( parent );
414 return item && item->hasChildren();
415}
416
417int QgsBrowserModel::columnCount( const QModelIndex &parent ) const
418{
419 Q_UNUSED( parent )
420 return 1;
421}
422
423QModelIndex QgsBrowserModel::findPath( const QString &path, Qt::MatchFlag matchFlag )
424{
425 return findPath( this, path, matchFlag );
426}
427
428QModelIndex QgsBrowserModel::findPath( QAbstractItemModel *model, const QString &path, Qt::MatchFlag matchFlag )
429{
430 if ( !model )
431 return QModelIndex();
432
433 QModelIndex index; // starting from root
434 bool foundChild = true;
435
436 while ( foundChild )
437 {
438 foundChild = false; // assume that the next child item will not be found
439
440 for ( int i = 0; i < model->rowCount( index ); i++ )
441 {
442 QModelIndex idx = model->index( i, 0, index );
443
444 QString itemPath = model->data( idx, static_cast< int >( QgsBrowserModel::CustomRole::Path ) ).toString();
445 if ( itemPath == path )
446 {
447 QgsDebugMsgLevel( "Arrived " + itemPath, 4 );
448 return idx; // we have found the item we have been looking for
449 }
450
451 // paths are slash separated identifier
452 if ( path.startsWith( itemPath + '/' ) )
453 {
454 foundChild = true;
455 index = idx;
456 break;
457 }
458 }
459 }
460
461 if ( matchFlag == Qt::MatchStartsWith )
462 return index;
463
464 QgsDebugMsgLevel( u"path not found"_s, 4 );
465 return QModelIndex(); // not found
466}
467
468QModelIndex QgsBrowserModel::findUri( const QString &uri, QModelIndex index )
469{
470 for ( int i = 0; i < this->rowCount( index ); i++ )
471 {
472 QModelIndex idx = this->index( i, 0, index );
473
474 if ( qobject_cast<QgsLayerItem *>( dataItem( idx ) ) )
475 {
476 QString itemUri = qobject_cast<QgsLayerItem *>( dataItem( idx ) )->uri();
477
478 if ( itemUri == uri )
479 {
480 QgsDebugMsgLevel( "Arrived " + itemUri, 4 );
481 return idx; // we have found the item we have been looking for
482 }
483 }
484
485 QModelIndex childIdx = findUri( uri, idx );
486 if ( childIdx.isValid() )
487 return childIdx;
488 }
489 return QModelIndex();
490}
491
493{
494 // deprecated, no use
495}
496
498{
499 // TODO: put items creating currently children in threads to deleteLater (does not seem urget because reload() is not used in QGIS)
500 beginResetModel();
502 addRootItems();
503 endResetModel();
504}
505
507{
508 const QList< QFileInfo > drives = QDir::drives();
509 // remove any removed drives
510 const QStringList existingDrives = mDriveItems.keys();
511 for ( const QString &drivePath : existingDrives )
512 {
513 bool stillExists = false;
514 for ( const QFileInfo &drive : drives )
515 {
516 if ( drivePath == drive.absolutePath() )
517 {
518 stillExists = true;
519 break;
520 }
521 }
522
523 if ( stillExists )
524 continue;
525
526 // drive has been removed, remove corresponding item
527 if ( QgsDirectoryItem *driveItem = mDriveItems.value( drivePath ) )
528 removeRootItem( driveItem );
529 }
530
531 for ( const QFileInfo &drive : drives )
532 {
533 const QString path = drive.absolutePath();
534
535 if ( QgsDirectoryItem::hiddenPath( path ) )
536 continue;
537
538 // does an item for this drive already exist?
539 if ( !mDriveItems.contains( path ) )
540 {
541 const QString driveName = QStorageInfo( path ).displayName();
542 const QString name = driveName.isEmpty() || driveName == path ? path : u"%1 (%2)"_s.arg( path, driveName );
543
544 QgsDirectoryItem *item = new QgsDirectoryItem( nullptr, name, path, path, u"special:Drives"_s );
545 item->setSortKey( u" 3 %1"_s.arg( path ) );
546
547 mDriveItems.insert( path, item );
548 setupItemConnections( item );
549
550 beginInsertRows( QModelIndex(), mRootItems.count(), mRootItems.count() );
551 mRootItems << item;
552 endInsertRows();
553 }
554 }
555}
556
557QModelIndex QgsBrowserModel::index( int row, int column, const QModelIndex &parent ) const
558{
559 if ( column < 0 || column >= columnCount() || row < 0 )
560 return QModelIndex();
561
563 const QVector<QgsDataItem *> &items = p ? p->children() : mRootItems;
564 QgsDataItem *item = items.value( row, nullptr );
565 return item ? createIndex( row, column, item ) : QModelIndex();
566}
567
568QModelIndex QgsBrowserModel::parent( const QModelIndex &index ) const
569{
570 QgsDataItem *item = dataItem( index );
571 if ( !item )
572 return QModelIndex();
573
574 return findItem( item->parent(), item->parent() ? item->parent()->parent() : nullptr );
575}
576
578{
579 const QVector<QgsDataItem *> &items = parent ? parent->children() : mRootItems;
580
581 for ( int i = 0; i < items.size(); i++ )
582 {
583 if ( items[i] == item )
584 return createIndex( i, 0, item );
585
586 QModelIndex childIndex = findItem( item, items[i] );
587 if ( childIndex.isValid() )
588 return childIndex;
589 }
590 return QModelIndex();
591}
592
594{
595 QgsDebugMsgLevel( "parent mPath = " + parent->path(), 3 );
596 QModelIndex idx = findItem( parent );
597 if ( !idx.isValid() )
598 return;
599 QgsDebugMsgLevel( u"valid"_s, 3 );
600 beginInsertRows( idx, first, last );
601 QgsDebugMsgLevel( u"end"_s, 3 );
602}
604{
605 QgsDebugMsgLevel( u"Entered"_s, 3 );
606 endInsertRows();
607}
609{
610 QgsDebugMsgLevel( "parent mPath = " + parent->path(), 3 );
611 QModelIndex idx = findItem( parent );
612 if ( !idx.isValid() )
613 return;
614 beginRemoveRows( idx, first, last );
615}
617{
618 QgsDebugMsgLevel( u"Entered"_s, 3 );
619 endRemoveRows();
620}
622{
623 QgsDebugMsgLevel( u"Entered"_s, 3 );
624 QModelIndex idx = findItem( item );
625 if ( !idx.isValid() )
626 return;
627 emit dataChanged( idx, idx );
628}
630{
631 if ( !item )
632 return;
633 QModelIndex idx = findItem( item );
634 if ( !idx.isValid() )
635 return;
636 QgsDebugMsgLevel( u"item %1 state changed %2 -> %3"_s.arg( item->path() ).arg( qgsEnumValueToKey< Qgis::BrowserItemState >( oldState ) ).arg( qgsEnumValueToKey< Qgis::BrowserItemState >( item->state() ) ), 4 );
637 emit stateChanged( idx, oldState );
638}
639
640void QgsBrowserModel::setupItemConnections( QgsDataItem *item )
641{
642 connect( item, &QgsDataItem::beginInsertItems,
644 connect( item, &QgsDataItem::endInsertItems,
646 connect( item, &QgsDataItem::beginRemoveItems,
648 connect( item, &QgsDataItem::endRemoveItems,
650 connect( item, &QgsDataItem::dataChanged,
652 connect( item, &QgsDataItem::stateChanged,
654
655 // if it's a collection item, also forwards connectionsChanged
656 QgsDataCollectionItem *collectionItem = qobject_cast<QgsDataCollectionItem *>( item );
657 if ( collectionItem )
658 connect( collectionItem, &QgsDataCollectionItem::connectionsChanged, this, &QgsBrowserModel::onConnectionsChanged );
659}
660
661QStringList QgsBrowserModel::mimeTypes() const
662{
663 QStringList types;
664 // In theory the mime type convention is: application/x-vnd.<vendor>.<application>.<type>
665 // but it seems a bit over formalized. Would be an application/x-qgis-uri better?
666 types << u"application/x-vnd.qgis.qgis.uri"_s;
667 return types;
668}
669
670QMimeData *QgsBrowserModel::mimeData( const QModelIndexList &indexes ) const
671{
673 const auto constIndexes = indexes;
674 for ( const QModelIndex &index : constIndexes )
675 {
676 if ( index.isValid() )
677 {
678 QgsDataItem *ptr = reinterpret_cast< QgsDataItem * >( index.internalPointer() );
680 if ( uris.isEmpty() )
681 {
683 QgsMimeDataUtils::Uri uri = ptr->mimeUri();
685 if ( uri.isValid() )
686 {
687 uris << uri;
688 }
689 }
690 for ( QgsMimeDataUtils::Uri uri : std::as_const( uris ) )
691 {
693 {
694 uri.filePath = ptr->path();
695 }
696 lst.append( uri );
697 }
698 }
699 }
701}
702
703bool QgsBrowserModel::dropMimeData( const QMimeData *data, Qt::DropAction action, int, int, const QModelIndex &parent )
704{
705 QgsDataItem *destItem = dataItem( parent );
706 if ( !destItem )
707 {
708 QgsDebugMsgLevel( u"DROP PROBLEM!"_s, 4 );
709 return false;
710 }
711
713 return destItem->handleDrop( data, action );
715}
716
717QgsDataItem *QgsBrowserModel::dataItem( const QModelIndex &idx ) const
718{
719 void *v = idx.internalPointer();
720 QgsDataItem *d = reinterpret_cast<QgsDataItem *>( v );
721 Q_ASSERT( !v || d );
722 return d;
723}
724
725bool QgsBrowserModel::canFetchMore( const QModelIndex &parent ) const
726{
727 QgsDataItem *item = dataItem( parent );
728 // if ( item )
729 // QgsDebugMsgLevel( u"path = %1 canFetchMore = %2"_s.arg( item->path() ).arg( item && ! item->isPopulated() ), 2 );
730 return ( item && item->state() == Qgis::BrowserItemState::NotPopulated );
731}
732
733void QgsBrowserModel::fetchMore( const QModelIndex &parent )
734{
735 QgsDataItem *item = dataItem( parent );
736
738 return;
739
740 QgsDebugMsgLevel( "path = " + item->path(), 4 );
741
742 item->populate();
743}
744
745/* Refresh dir path */
746void QgsBrowserModel::refresh( const QString &path )
747{
748 QModelIndex index = findPath( path );
749 refresh( index );
750}
751
752/* Refresh item */
753void QgsBrowserModel::refresh( const QModelIndex &index )
754{
755 QgsDataItem *item = dataItem( index );
756 if ( !item || item->state() == Qgis::BrowserItemState::Populating )
757 return;
758
759 QgsDebugMsgLevel( "Refresh " + item->path(), 4 );
760
761 item->refresh();
762}
763
764void QgsBrowserModel::addFavoriteDirectory( const QString &directory, const QString &name )
765{
766 Q_ASSERT( mFavorites );
767 mFavorites->addDirectory( directory, name );
768}
769
770void QgsBrowserModel::removeFavorite( const QModelIndex &index )
771{
772 QgsDirectoryItem *item = qobject_cast<QgsDirectoryItem *>( dataItem( index ) );
773 if ( !item )
774 return;
775
776 mFavorites->removeDirectory( item );
777}
778
780{
781 if ( !favorite )
782 return;
783
784 mFavorites->removeDirectory( favorite );
785}
786
788{
789 QgsSettings settings;
790 QStringList hiddenItems = settings.value( u"browser/hiddenPaths"_s,
791 QStringList() ).toStringList();
792 int idx = hiddenItems.indexOf( item->path() );
793 if ( idx != -1 )
794 {
795 hiddenItems.removeAt( idx );
796 }
797 else
798 {
799 hiddenItems << item->path();
800 }
801 settings.setValue( u"browser/hiddenPaths"_s, hiddenItems );
802 if ( item->parent() )
803 {
804 item->parent()->deleteChildItem( item );
805 }
806 else
807 {
808 removeRootItem( item );
809 }
810}
811
812
813void QgsBrowserModel::removeRootItem( QgsDataItem *item )
814{
815 int i = mRootItems.indexOf( item );
816 beginRemoveRows( QModelIndex(), i, i );
817 mRootItems.remove( i );
818 QgsDirectoryItem *dirItem = qobject_cast< QgsDirectoryItem * >( item );
819 if ( !mDriveItems.key( dirItem ).isEmpty() )
820 {
821 mDriveItems.remove( mDriveItems.key( dirItem ) );
822 }
823 item->deleteLater();
824 endRemoveRows();
825}
826
827QgsDataItem *QgsBrowserModel::addProviderRootItem( QgsDataItemProvider *pr )
828{
829 const Qgis::DataItemProviderCapabilities capabilities = pr->capabilities();
831 {
832 QgsDebugMsgLevel( pr->name() + " does not have any dataCapabilities", 4 );
833 return nullptr;
834 }
835
836 QgsDataItem *item = pr->createDataItem( QString(), nullptr ); // empty path -> top level
837 if ( item )
838 {
839 // make sure the top level key is always set
840 item->setProviderKey( pr->name() );
841 // Forward the signal from the root items to the model (and then to the app)
842 connect( item, &QgsDataItem::connectionsChanged, this, &QgsBrowserModel::onConnectionsChanged );
843 QgsDebugMsgLevel( "Add new top level item : " + item->name(), 4 );
844 setupItemConnections( item );
845 }
846 return item;
847}
848
849// For QgsBrowserWatcher
850#include "qgsbrowsermodel.moc"
@ NoCapabilities
No capabilities.
Definition qgis.h:996
BrowserItemState
Browser item states.
Definition qgis.h:957
@ NotPopulated
Children not yet created.
Definition qgis.h:958
@ Populating
Creating children in separate thread (populating or refreshing).
Definition qgis.h:959
@ Populated
Children created.
Definition qgis.h:960
@ Rename
Item can be renamed.
Definition qgis.h:976
@ ItemRepresentsFile
Item's path() directly represents a file on disk.
Definition qgis.h:978
QFlags< DataItemProviderCapability > DataItemProviderCapabilities
Capabilities for data item providers.
Definition qgis.h:1011
@ Layer
Represents a map layer.
Definition qgis.h:941
static QgsDataItemProviderRegistry * dataItemProviderRegistry()
Returns the application's data item provider registry, which keeps a list of data item providers that...
Q_DECL_DEPRECATED void connectItem(QgsDataItem *item)
void connectionsChanged(const QString &providerKey)
Emitted when connections for the specified providerKey have changed in the browser.
bool hasChildren(const QModelIndex &parent=QModelIndex()) const override
QgsFavoritesItem * mFavorites
QgsDataItem * dataItem(const QModelIndex &idx) const
Returns the data item at the specified index, or nullptr if no item exists at the index.
bool canFetchMore(const QModelIndex &parent) const override
void hidePath(QgsDataItem *item)
Hide the given path in the browser model.
void refreshDrives()
Refreshes the list of drive items, removing any corresponding to removed drives and adding newly adde...
void reload()
Reload the whole model.
Qt::ItemFlags flags(const QModelIndex &index) const override
void itemStateChanged(QgsDataItem *item, Qgis::BrowserItemState oldState)
Emitted when an item's state is changed.
void beginInsertItems(QgsDataItem *parent, int first, int last)
QModelIndex findPath(const QString &path, Qt::MatchFlag matchFlag=Qt::MatchExactly)
Returns index of item with given path.
QVariant headerData(int section, Qt::Orientation orientation, int role=Qt::DisplayRole) const override
void refresh(const QString &path)
Refresh item specified by path.
bool setData(const QModelIndex &index, const QVariant &value, int role=Qt::EditRole) override
int columnCount(const QModelIndex &parent=QModelIndex()) const override
QVariant data(const QModelIndex &index, int role=Qt::DisplayRole) const override
QVector< QgsDataItem * > mRootItems
QMap< QString, QgsDirectoryItem * > driveItems() const
Returns a map of the root drive items shown in the browser.
~QgsBrowserModel() override
int rowCount(const QModelIndex &parent=QModelIndex()) const override
void beginRemoveItems(QgsDataItem *parent, int first, int last)
QStringList mimeTypes() const override
QModelIndex parent(const QModelIndex &index) const override
QModelIndex findItem(QgsDataItem *item, QgsDataItem *parent=nullptr) const
Returns the model index corresponding to the specified data item.
void initialize()
Delayed initialization, needed because the provider registry must be already populated.
QMimeData * mimeData(const QModelIndexList &indexes) const override
void addFavoriteDirectory(const QString &directory, const QString &name=QString())
Adds a directory to the favorites group.
QgsBrowserModel(QObject *parent=nullptr)
Constructor for QgsBrowserModel, with the specified parent object.
QgsDirectoryItem * mProjectHome
QModelIndex index(int row, int column, const QModelIndex &parent=QModelIndex()) const override
void stateChanged(const QModelIndex &index, Qgis::BrowserItemState oldState)
Emitted when item children fetch was finished.
void itemDataChanged(QgsDataItem *item)
void addRootItems()
Populates the model.
QModelIndex findUri(const QString &uri, QModelIndex index=QModelIndex())
Returns index of layer item with given uri.
@ Sort
Custom sort role, see QgsDataItem::sortKey().
@ Path
Item path used to access path in the tree, see QgsDataItem::mPath.
@ ProviderKey
Data item provider key that created the item, see QgsDataItem::providerKey().
bool dropMimeData(const QMimeData *data, Qt::DropAction action, int row, int column, const QModelIndex &parent) override
void removeFavorite(const QModelIndex &index)
Removes a favorite directory from its corresponding model index.
void fetchMore(const QModelIndex &parent) override
A browser item for collections of data.
QList< QgsDataItemProvider * > providers() const
Returns the list of available providers.
void providerWillBeRemoved(QgsDataItemProvider *provider)
Emitted when a data item provider is about to be removed.
void providerAdded(QgsDataItemProvider *provider)
Emitted when a new data item provider has been added.
Interface for providers that add custom data items to the browser tree.
virtual QString name()=0
Human-readable name of the provider name.
virtual QgsDataItem * createDataItem(const QString &path, QgsDataItem *parentItem)=0
Create a new instance of QgsDataItem (or nullptr) for given path and parent item.
virtual Qgis::DataItemProviderCapabilities capabilities() const =0
Returns combination of flags from QgsDataProvider::DataCapabilities.
Base class for all items in the model.
Definition qgsdataitem.h:50
void stateChanged(QgsDataItem *item, Qgis::BrowserItemState oldState)
Emitted when an item's state is changed.
void setSortKey(const QVariant &key)
Sets a custom sorting key for the item.
bool hasChildren() const
Returns whether this item has children.
int rowCount() const
Returns the number of rows of this item.
virtual void deleteChildItem(QgsDataItem *child)
Removes and deletes a child item, emitting relevant signals to the model.
virtual QVariant sortKey() const
Returns the sorting key for the item.
virtual Q_DECL_DEPRECATED bool handleDrop(const QMimeData *, Qt::DropAction)
Attempts to process the mime data dropped on this item.
virtual void refresh(const QVector< QgsDataItem * > &children)
Refresh the items from a specified list of child items.
void dataChanged(QgsDataItem *item)
Emitted when data changes for an item.
static void deleteLater(QVector< QgsDataItem * > &items)
void endRemoveItems()
Emitted after child items have been removed from this data item.
QVector< QgsDataItem * > children() const
void beginRemoveItems(QgsDataItem *parent, int first, int last)
Emitted before child items are removed from this data item.
virtual Q_DECL_DEPRECATED bool acceptDrop()
Returns whether the item accepts drag and dropped layers - e.g.
Qgis::BrowserItemType type() const
Qgis::BrowserItemState state() const
virtual bool hasDragEnabled() const
Returns true if the item may be dragged.
virtual Q_DECL_DEPRECATED bool rename(const QString &name)
Sets a new name for the item, and returns true if the item was successfully renamed.
void connectionsChanged(const QString &providerKey=QString())
Emitted when the connections of the provider with the specified providerKey have changed.
virtual Q_DECL_DEPRECATED QgsMimeDataUtils::Uri mimeUri() const
Returns mime URI for the data item.
QString name() const
Returns the name of the item (the displayed text for the item).
QString path() const
virtual QIcon icon()
void beginInsertItems(QgsDataItem *parent, int first, int last)
Emitted before child items are added to this data item.
QString toolTip() const
QgsDataItem * parent() const
Gets item parent.
virtual QgsMimeDataUtils::UriList mimeUris() const
Returns mime URIs for the data item, most data providers will only return a single URI but some data ...
QString providerKey() const
Returns the provider key that created this item (e.g.
void endInsertItems()
Emitted after child items have been added to this data item.
virtual Qgis::BrowserItemCapabilities capabilities2() const
Returns the capabilities for the data item.
void setProviderKey(const QString &value)
Sets the provider key that created this item (e.g.
virtual void populate(const QVector< QgsDataItem * > &children)
A browser item for directories: contains subdirectories and layers.
static bool hiddenPath(const QString &path)
Check if the given path is hidden from the browser model.
A directory item showing a single favorite directory.
A browser item which contains various Favorites directories.
A browser item that represents a layer that can be opened with one of the providers.
virtual QString comments() const
Returns comments of the layer.
const QgsLayerMetadata & layerMetadata() const
Returns layer's metadata, it may be a default constructed metadata if metadata is not explicitly set.
QList< QgsMimeDataUtils::Uri > UriList
static QMimeData * encodeUriList(const UriList &layers)
Encodes a URI list to a new QMimeData object.
A directory item showing the current project directory.
static QgsProject * instance()
Returns the QgsProject singleton instance.
void homePathChanged()
Emitted when the home path of the project changes.
QString homePath
Definition qgsproject.h:118
Stores settings for use within QGIS.
Definition qgssettings.h:68
QVariant value(const QString &key, const QVariant &defaultValue=QVariant(), Section section=NoSection) const
Returns the value for setting key.
void setValue(const QString &key, const QVariant &value, QgsSettings::Section section=QgsSettings::NoSection)
Sets the value of setting key to value.
#define Q_NOWARN_DEPRECATED_POP
Definition qgis.h:7486
QString qgsEnumValueToKey(const T &value, bool *returnOk=nullptr)
Returns the value for the given key of an enum.
Definition qgis.h:7126
#define Q_NOWARN_DEPRECATED_PUSH
Definition qgis.h:7485
#define PROJECT_HOME_PREFIX
#define HOME_PREFIX
#define QgsDebugMsgLevel(str, level)
Definition qgslogger.h:63