QGIS API Documentation 4.1.0-Master (60fea48833c)
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 QgsDataItem *item() const { return mItem; }
58
59 signals:
60 void finished( QgsDataItem *item, const QVector<QgsDataItem *> &items );
61
62 private:
63 QgsDataItem *mItem = nullptr;
64};
66
67// sort function for QList<QgsDataItem*>, e.g. sorted/grouped provider listings
68static bool cmpByDataItemName_( QgsDataItem *a, QgsDataItem *b )
69{
70 return QString::localeAwareCompare( a->name(), b->name() ) < 0;
71}
72
74 : QAbstractItemModel( parent )
75
76{
77 connect( QgsApplication::dataItemProviderRegistry(), &QgsDataItemProviderRegistry::providerAdded, this, &QgsBrowserModel::dataItemProviderAdded );
78 connect( QgsApplication::dataItemProviderRegistry(), &QgsDataItemProviderRegistry::providerWillBeRemoved, this, &QgsBrowserModel::dataItemProviderWillBeRemoved );
79}
80
85
87{
88 QString home = QgsProject::instance()->homePath(); // skip-keyword-check
89 if ( mProjectHome && mProjectHome->path().mid( QStringLiteral( PROJECT_HOME_PREFIX ).length() ) == home )
90 return;
91
92 int idx = mRootItems.indexOf( mProjectHome );
93
94 // using layoutAboutToBeChanged() was messing expanded items
95 if ( idx >= 0 )
96 {
97 beginRemoveRows( QModelIndex(), idx, idx );
98 mRootItems.remove( idx );
99 endRemoveRows();
100 }
101 delete mProjectHome;
102 mProjectHome = home.isNull() ? nullptr : new QgsProjectHomeItem( nullptr, tr( "Project Home" ), home, QStringLiteral( PROJECT_HOME_PREFIX ) + home );
103 if ( mProjectHome )
104 {
105 setupItemConnections( mProjectHome );
106
107 beginInsertRows( QModelIndex(), 0, 0 );
108 mRootItems.insert( 0, mProjectHome );
109 endInsertRows();
110 }
111}
112
114{
116
117 // give the home directory a prominent third place
118 QgsDirectoryItem *item = new QgsDirectoryItem( nullptr, tr( "Home" ), QDir::homePath(), QStringLiteral( HOME_PREFIX ) + QDir::homePath(), u"special:Home"_s );
119 item->setSortKey( u" 2"_s );
120 setupItemConnections( item );
121 mRootItems << item;
122
123 // add favorite directories
124 mFavorites = new QgsFavoritesItem( nullptr, tr( "Favorites" ) );
125 if ( mFavorites )
126 {
127 setupItemConnections( mFavorites );
129 }
130
131 // add drives
132 const auto drives { QDir::drives() };
133 for ( const QFileInfo &drive : drives )
134 {
135 const QString path = drive.absolutePath();
136
137 if ( QgsDirectoryItem::hiddenPath( path ) )
138 continue;
139
140 const QString driveName = QStorageInfo( path ).displayName();
141 const QString name = driveName.isEmpty() || driveName == path ? path : u"%1 (%2)"_s.arg( path, driveName );
142
143 QgsDirectoryItem *item = new QgsDirectoryItem( nullptr, name, path, path, u"special:Drives"_s );
144 item->setSortKey( u" 3 %1"_s.arg( path ) );
145 mDriveItems.insert( path, item );
146
147 setupItemConnections( item );
148 mRootItems << item;
149 }
150
151#ifdef Q_OS_MAC
152 QString path = QString( "/Volumes" );
153 QgsDirectoryItem *vols = new QgsDirectoryItem( nullptr, path, path, path, u"special:Volumes"_s );
154 setupItemConnections( vols );
155 mRootItems << vols;
156#endif
157
158 // container for displaying providers as sorted groups (by QgsDataProvider::DataCapability enum)
159 QMultiMap<int, QgsDataItem *> providerMap;
160
161 const auto constProviders = QgsApplication::dataItemProviderRegistry()->providers();
162 for ( QgsDataItemProvider *pr : constProviders )
163 {
164 if ( QgsDataItem *item = addProviderRootItem( pr ) )
165 {
166 providerMap.insert( pr->capabilities(), item );
167 }
168 }
169
170 // add as sorted groups by QgsDataProvider::DataCapability enum
171 const auto constUniqueKeys = providerMap.uniqueKeys();
172 for ( int key : constUniqueKeys )
173 {
174 QList<QgsDataItem *> providerGroup = providerMap.values( key );
175 if ( providerGroup.size() > 1 )
176 {
177 std::sort( providerGroup.begin(), providerGroup.end(), cmpByDataItemName_ );
178 }
179
180 const auto constProviderGroup = providerGroup;
181 for ( QgsDataItem *ditem : constProviderGroup )
182 {
183 mRootItems << ditem;
184 }
185 }
186}
187
189{
190 const auto constMRootItems = mRootItems;
191 for ( QgsDataItem *item : constMRootItems )
192 {
193 delete item;
194 }
195
196 mRootItems.clear();
197 mDriveItems.clear();
198}
199
200void QgsBrowserModel::dataItemProviderAdded( QgsDataItemProvider *provider )
201{
202 if ( !mInitialized )
203 return;
204
205 if ( QgsDataItem *item = addProviderRootItem( provider ) )
206 {
207 beginInsertRows( QModelIndex(), rowCount(), rowCount() );
208 mRootItems << item;
209 endInsertRows();
210 }
211}
212
213void QgsBrowserModel::dataItemProviderWillBeRemoved( QgsDataItemProvider *provider )
214{
215 const auto constMRootItems = mRootItems;
216 for ( QgsDataItem *item : constMRootItems )
217 {
218 if ( item->providerKey() == provider->name() )
219 {
220 removeRootItem( item );
221 break; // assuming there is max. 1 root item per provider
222 }
223 }
224}
225
226void QgsBrowserModel::onConnectionsChanged( const QString &providerKey )
227{
228 // refresh the matching provider
229 for ( QgsDataItem *item : std::as_const( mRootItems ) )
230 {
231 if ( item->providerKey() == providerKey )
232 {
233 item->refresh();
234 break; // assuming there is max. 1 root item per provider
235 }
236 }
237
238 emit connectionsChanged( providerKey );
239}
240
241QMap<QString, QgsDirectoryItem *> QgsBrowserModel::driveItems() const
242{
243 return mDriveItems;
244}
245
246
248{
249 if ( !mInitialized )
250 {
252 addRootItems();
253 mInitialized = true;
254 }
255}
256
257Qt::ItemFlags QgsBrowserModel::flags( const QModelIndex &index ) const
258{
259 if ( !index.isValid() )
260 return Qt::ItemFlags();
261
262 Qt::ItemFlags flags = Qt::ItemIsEnabled | Qt::ItemIsSelectable;
263
264 QgsDataItem *ptr = dataItem( index );
265
266 if ( !ptr )
267 {
268 QgsDebugMsgLevel( u"FLAGS PROBLEM!"_s, 4 );
269 return Qt::ItemFlags();
270 }
271
272 if ( ptr->hasDragEnabled() )
273 flags |= Qt::ItemIsDragEnabled;
274
276 if ( ptr->acceptDrop() )
277 flags |= Qt::ItemIsDropEnabled;
279
281 flags |= Qt::ItemIsEditable;
282
283 return flags;
284}
285
286QVariant QgsBrowserModel::data( const QModelIndex &index, int role ) const
287{
288 if ( !index.isValid() )
289 return QVariant();
290
291 QgsDataItem *item = dataItem( index );
292 if ( !item )
293 {
294 return QVariant();
295 }
296 else if ( role == Qt::DisplayRole || role == Qt::EditRole )
297 {
298 return item->name();
299 }
300 else if ( role == static_cast< int >( QgsBrowserModel::CustomRole::Sort ) )
301 {
302 return item->sortKey();
303 }
304 else if ( role == Qt::ToolTipRole )
305 {
306 return item->toolTip();
307 }
308 else if ( role == Qt::DecorationRole && index.column() == 0 )
309 {
310 return item->icon();
311 }
312 else if ( role == static_cast< int >( QgsBrowserModel::CustomRole::Path ) )
313 {
314 return item->path();
315 }
316 else if ( role == static_cast< int >( QgsBrowserModel::CustomRole::Comment ) )
317 {
318 if ( item->type() == Qgis::BrowserItemType::Layer )
319 {
320 QgsLayerItem *lyrItem = qobject_cast<QgsLayerItem *>( item );
321 return lyrItem->comments();
322 }
323 return QVariant();
324 }
325 else if ( role == static_cast< int >( QgsBrowserModel::CustomRole::LayerMetadata ) )
326 {
327 if ( item->type() == Qgis::BrowserItemType::Layer )
328 {
329 QgsLayerItem *lyrItem = qobject_cast<QgsLayerItem *>( item );
330 return QVariant::fromValue( lyrItem->layerMetadata() );
331 }
332 return QVariant();
333 }
334 else if ( role == static_cast< int >( QgsBrowserModel::CustomRole::ProviderKey ) )
335 {
336 return item->providerKey();
337 }
338 else
339 {
340 // unsupported role
341 return QVariant();
342 }
343}
344
345bool QgsBrowserModel::setData( const QModelIndex &index, const QVariant &value, int role )
346{
347 if ( !index.isValid() )
348 return false;
349
350
351 QgsDataItem *item = dataItem( index );
352 if ( !item )
353 {
354 return false;
355 }
356
358 return false;
359
360 switch ( role )
361 {
362 case Qt::EditRole:
363 {
365 return item->rename( value.toString() );
367 }
368 }
369 return false;
370}
371
372QVariant QgsBrowserModel::headerData( int section, Qt::Orientation orientation, int role ) const
373{
374 Q_UNUSED( section )
375 if ( orientation == Qt::Horizontal && role == Qt::DisplayRole )
376 {
377 return QVariant( "header" );
378 }
379
380 return QVariant();
381}
382
383int QgsBrowserModel::rowCount( const QModelIndex &parent ) const
384{
385 //QgsDebugMsgLevel(QString("isValid = %1 row = %2 column = %3").arg(parent.isValid()).arg(parent.row()).arg(parent.column()), 2);
386
387 if ( !parent.isValid() )
388 {
389 // root item: its children are top level items
390 return mRootItems.count(); // mRoot
391 }
392 else
393 {
394 // ordinary item: number of its children
395 QgsDataItem *item = dataItem( parent );
396 //if ( item ) QgsDebugMsgLevel(QString("path = %1 rowCount = %2").arg(item->path()).arg(item->rowCount()), 2);
397 return item ? item->rowCount() : 0;
398 }
399}
400
401bool QgsBrowserModel::hasChildren( const QModelIndex &parent ) const
402{
403 if ( !parent.isValid() )
404 return !mRootItems.isEmpty(); // root item: its children are top level items
405
406 QgsDataItem *item = dataItem( parent );
407 return item && item->hasChildren();
408}
409
410int QgsBrowserModel::columnCount( const QModelIndex &parent ) const
411{
412 Q_UNUSED( parent )
413 return 1;
414}
415
416QModelIndex QgsBrowserModel::findPath( const QString &path, Qt::MatchFlag matchFlag )
417{
418 return findPath( this, path, matchFlag );
419}
420
421QModelIndex QgsBrowserModel::findPath( QAbstractItemModel *model, const QString &path, Qt::MatchFlag matchFlag )
422{
423 if ( !model )
424 return QModelIndex();
425
426 QModelIndex index; // starting from root
427 bool foundChild = true;
428
429 while ( foundChild )
430 {
431 foundChild = false; // assume that the next child item will not be found
432
433 for ( int i = 0; i < model->rowCount( index ); i++ )
434 {
435 QModelIndex idx = model->index( i, 0, index );
436
437 QString itemPath = model->data( idx, static_cast< int >( QgsBrowserModel::CustomRole::Path ) ).toString();
438 if ( itemPath == path )
439 {
440 QgsDebugMsgLevel( "Arrived " + itemPath, 4 );
441 return idx; // we have found the item we have been looking for
442 }
443
444 // paths are slash separated identifier
445 if ( path.startsWith( itemPath + '/' ) )
446 {
447 foundChild = true;
448 index = idx;
449 break;
450 }
451 }
452 }
453
454 if ( matchFlag == Qt::MatchStartsWith )
455 return index;
456
457 QgsDebugMsgLevel( u"path not found"_s, 4 );
458 return QModelIndex(); // not found
459}
460
461QModelIndex QgsBrowserModel::findUri( const QString &uri, QModelIndex index )
462{
463 for ( int i = 0; i < this->rowCount( index ); i++ )
464 {
465 QModelIndex idx = this->index( i, 0, index );
466
467 if ( qobject_cast<QgsLayerItem *>( dataItem( idx ) ) )
468 {
469 QString itemUri = qobject_cast<QgsLayerItem *>( dataItem( idx ) )->uri();
470
471 if ( itemUri == uri )
472 {
473 QgsDebugMsgLevel( "Arrived " + itemUri, 4 );
474 return idx; // we have found the item we have been looking for
475 }
476 }
477
478 QModelIndex childIdx = findUri( uri, idx );
479 if ( childIdx.isValid() )
480 return childIdx;
481 }
482 return QModelIndex();
483}
484
486{
487 // deprecated, no use
488}
489
491{
492 // TODO: put items creating currently children in threads to deleteLater (does not seem urget because reload() is not used in QGIS)
493 beginResetModel();
495 addRootItems();
496 endResetModel();
497}
498
500{
501 const QList< QFileInfo > drives = QDir::drives();
502 // remove any removed drives
503 const QStringList existingDrives = mDriveItems.keys();
504 for ( const QString &drivePath : existingDrives )
505 {
506 bool stillExists = false;
507 for ( const QFileInfo &drive : drives )
508 {
509 if ( drivePath == drive.absolutePath() )
510 {
511 stillExists = true;
512 break;
513 }
514 }
515
516 if ( stillExists )
517 continue;
518
519 // drive has been removed, remove corresponding item
520 if ( QgsDirectoryItem *driveItem = mDriveItems.value( drivePath ) )
521 removeRootItem( driveItem );
522 }
523
524 for ( const QFileInfo &drive : drives )
525 {
526 const QString path = drive.absolutePath();
527
528 if ( QgsDirectoryItem::hiddenPath( path ) )
529 continue;
530
531 // does an item for this drive already exist?
532 if ( !mDriveItems.contains( path ) )
533 {
534 const QString driveName = QStorageInfo( path ).displayName();
535 const QString name = driveName.isEmpty() || driveName == path ? path : u"%1 (%2)"_s.arg( path, driveName );
536
537 QgsDirectoryItem *item = new QgsDirectoryItem( nullptr, name, path, path, u"special:Drives"_s );
538 item->setSortKey( u" 3 %1"_s.arg( path ) );
539
540 mDriveItems.insert( path, item );
541 setupItemConnections( item );
542
543 beginInsertRows( QModelIndex(), mRootItems.count(), mRootItems.count() );
544 mRootItems << item;
545 endInsertRows();
546 }
547 }
548}
549
550QModelIndex QgsBrowserModel::index( int row, int column, const QModelIndex &parent ) const
551{
552 if ( column < 0 || column >= columnCount() || row < 0 )
553 return QModelIndex();
554
556 const QVector<QgsDataItem *> &items = p ? p->children() : mRootItems;
557 QgsDataItem *item = items.value( row, nullptr );
558 return item ? createIndex( row, column, item ) : QModelIndex();
559}
560
561QModelIndex QgsBrowserModel::parent( const QModelIndex &index ) const
562{
563 QgsDataItem *item = dataItem( index );
564 if ( !item )
565 return QModelIndex();
566
567 return findItem( item->parent(), item->parent() ? item->parent()->parent() : nullptr );
568}
569
571{
572 const QVector<QgsDataItem *> &items = parent ? parent->children() : mRootItems;
573
574 for ( int i = 0; i < items.size(); i++ )
575 {
576 if ( items[i] == item )
577 return createIndex( i, 0, item );
578
579 QModelIndex childIndex = findItem( item, items[i] );
580 if ( childIndex.isValid() )
581 return childIndex;
582 }
583 return QModelIndex();
584}
585
587{
588 QgsDebugMsgLevel( "parent mPath = " + parent->path(), 3 );
589 QModelIndex idx = findItem( parent );
590 if ( !idx.isValid() )
591 return;
592 QgsDebugMsgLevel( u"valid"_s, 3 );
593 beginInsertRows( idx, first, last );
594 QgsDebugMsgLevel( u"end"_s, 3 );
595}
597{
598 QgsDebugMsgLevel( u"Entered"_s, 3 );
599 endInsertRows();
600}
602{
603 QgsDebugMsgLevel( "parent mPath = " + parent->path(), 3 );
604 QModelIndex idx = findItem( parent );
605 if ( !idx.isValid() )
606 return;
607 beginRemoveRows( idx, first, last );
608}
610{
611 QgsDebugMsgLevel( u"Entered"_s, 3 );
612 endRemoveRows();
613}
615{
616 QgsDebugMsgLevel( u"Entered"_s, 3 );
617 QModelIndex idx = findItem( item );
618 if ( !idx.isValid() )
619 return;
620 emit dataChanged( idx, idx );
621}
623{
624 if ( !item )
625 return;
626 QModelIndex idx = findItem( item );
627 if ( !idx.isValid() )
628 return;
629 QgsDebugMsgLevel( u"item %1 state changed %2 -> %3"_s.arg( item->path() ).arg( qgsEnumValueToKey< Qgis::BrowserItemState >( oldState ) ).arg( qgsEnumValueToKey< Qgis::BrowserItemState >( item->state() ) ), 4 );
630 emit stateChanged( idx, oldState );
631}
632
633void QgsBrowserModel::setupItemConnections( QgsDataItem *item )
634{
641
642 // if it's a collection item, also forwards connectionsChanged
643 QgsDataCollectionItem *collectionItem = qobject_cast<QgsDataCollectionItem *>( item );
644 if ( collectionItem )
645 connect( collectionItem, &QgsDataCollectionItem::connectionsChanged, this, &QgsBrowserModel::onConnectionsChanged );
646}
647
648QStringList QgsBrowserModel::mimeTypes() const
649{
650 QStringList types;
651 // In theory the mime type convention is: application/x-vnd.<vendor>.<application>.<type>
652 // but it seems a bit over formalized. Would be an application/x-qgis-uri better?
653 types << u"application/x-vnd.qgis.qgis.uri"_s;
654 return types;
655}
656
657QMimeData *QgsBrowserModel::mimeData( const QModelIndexList &indexes ) const
658{
660 const auto constIndexes = indexes;
661 for ( const QModelIndex &index : constIndexes )
662 {
663 if ( index.isValid() )
664 {
665 QgsDataItem *ptr = reinterpret_cast< QgsDataItem * >( index.internalPointer() );
667 if ( uris.isEmpty() )
668 {
670 QgsMimeDataUtils::Uri uri = ptr->mimeUri();
672 if ( uri.isValid() )
673 {
674 uris << uri;
675 }
676 }
677 for ( QgsMimeDataUtils::Uri uri : std::as_const( uris ) )
678 {
680 {
681 uri.filePath = ptr->path();
682 }
683 lst.append( uri );
684 }
685 }
686 }
688}
689
690bool QgsBrowserModel::dropMimeData( const QMimeData *data, Qt::DropAction action, int, int, const QModelIndex &parent )
691{
692 QgsDataItem *destItem = dataItem( parent );
693 if ( !destItem )
694 {
695 QgsDebugMsgLevel( u"DROP PROBLEM!"_s, 4 );
696 return false;
697 }
698
700 return destItem->handleDrop( data, action );
702}
703
704QgsDataItem *QgsBrowserModel::dataItem( const QModelIndex &idx ) const
705{
706 void *v = idx.internalPointer();
707 QgsDataItem *d = reinterpret_cast<QgsDataItem *>( v );
708 Q_ASSERT( !v || d );
709 return d;
710}
711
712bool QgsBrowserModel::canFetchMore( const QModelIndex &parent ) const
713{
714 QgsDataItem *item = dataItem( parent );
715 // if ( item )
716 // QgsDebugMsgLevel( u"path = %1 canFetchMore = %2"_s.arg( item->path() ).arg( item && ! item->isPopulated() ), 2 );
717 return ( item && item->state() == Qgis::BrowserItemState::NotPopulated );
718}
719
720void QgsBrowserModel::fetchMore( const QModelIndex &parent )
721{
722 QgsDataItem *item = dataItem( parent );
723
725 return;
726
727 QgsDebugMsgLevel( "path = " + item->path(), 4 );
728
729 item->populate();
730}
731
732/* Refresh dir path */
733void QgsBrowserModel::refresh( const QString &path )
734{
735 QModelIndex index = findPath( path );
736 refresh( index );
737}
738
739/* Refresh item */
740void QgsBrowserModel::refresh( const QModelIndex &index )
741{
742 QgsDataItem *item = dataItem( index );
743 if ( !item || item->state() == Qgis::BrowserItemState::Populating )
744 return;
745
746 QgsDebugMsgLevel( "Refresh " + item->path(), 4 );
747
748 item->refresh();
749}
750
751void QgsBrowserModel::addFavoriteDirectory( const QString &directory, const QString &name )
752{
753 Q_ASSERT( mFavorites );
754 mFavorites->addDirectory( directory, name );
755}
756
757void QgsBrowserModel::removeFavorite( const QModelIndex &index )
758{
759 QgsDirectoryItem *item = qobject_cast<QgsDirectoryItem *>( dataItem( index ) );
760 if ( !item )
761 return;
762
763 mFavorites->removeDirectory( item );
764}
765
767{
768 if ( !favorite )
769 return;
770
771 mFavorites->removeDirectory( favorite );
772}
773
775{
776 QgsSettings settings;
777 QStringList hiddenItems = settings.value( u"browser/hiddenPaths"_s, QStringList() ).toStringList();
778 int idx = hiddenItems.indexOf( item->path() );
779 if ( idx != -1 )
780 {
781 hiddenItems.removeAt( idx );
782 }
783 else
784 {
785 hiddenItems << item->path();
786 }
787 settings.setValue( u"browser/hiddenPaths"_s, hiddenItems );
788 if ( item->parent() )
789 {
790 item->parent()->deleteChildItem( item );
791 }
792 else
793 {
794 removeRootItem( item );
795 }
796}
797
798
799void QgsBrowserModel::removeRootItem( QgsDataItem *item )
800{
801 int i = mRootItems.indexOf( item );
802 beginRemoveRows( QModelIndex(), i, i );
803 mRootItems.remove( i );
804 QgsDirectoryItem *dirItem = qobject_cast< QgsDirectoryItem * >( item );
805 if ( !mDriveItems.key( dirItem ).isEmpty() )
806 {
807 mDriveItems.remove( mDriveItems.key( dirItem ) );
808 }
809 item->deleteLater();
810 endRemoveRows();
811}
812
813QgsDataItem *QgsBrowserModel::addProviderRootItem( QgsDataItemProvider *pr )
814{
815 const Qgis::DataItemProviderCapabilities capabilities = pr->capabilities();
817 {
818 QgsDebugMsgLevel( pr->name() + " does not have any dataCapabilities", 4 );
819 return nullptr;
820 }
821
822 QgsDataItem *item = pr->createDataItem( QString(), nullptr ); // empty path -> top level
823 if ( item )
824 {
825 // make sure the top level key is always set
826 item->setProviderKey( pr->name() );
827 // Forward the signal from the root items to the model (and then to the app)
828 connect( item, &QgsDataItem::connectionsChanged, this, &QgsBrowserModel::onConnectionsChanged );
829 QgsDebugMsgLevel( "Add new top level item : " + item->name(), 4 );
830 setupItemConnections( item );
831 }
832 return item;
833}
834
835// For QgsBrowserWatcher
836#include "qgsbrowsermodel.moc"
@ NoCapabilities
No capabilities.
Definition qgis.h:1003
BrowserItemState
Browser item states.
Definition qgis.h:964
@ NotPopulated
Children not yet created.
Definition qgis.h:965
@ Populating
Creating children in separate thread (populating or refreshing).
Definition qgis.h:966
@ Populated
Children created.
Definition qgis.h:967
@ Rename
Item can be renamed.
Definition qgis.h:983
@ ItemRepresentsFile
Item's path() directly represents a file on disk.
Definition qgis.h:985
QFlags< DataItemProviderCapability > DataItemProviderCapabilities
Capabilities for data item providers.
Definition qgis.h:1018
@ Layer
Represents a map layer.
Definition qgis.h:948
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:7504
QString qgsEnumValueToKey(const T &value, bool *returnOk=nullptr)
Returns the value for the given key of an enum.
Definition qgis.h:7157
#define Q_NOWARN_DEPRECATED_PUSH
Definition qgis.h:7503
#define PROJECT_HOME_PREFIX
#define HOME_PREFIX
#define QgsDebugMsgLevel(str, level)
Definition qgslogger.h:63