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