QGIS API Documentation  2.99.0-Master (314842d)
qgsdataitem.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgsdataitem.cpp - Data items
3  -------------------
4  begin : 2011-04-01
5  copyright : (C) 2011 Radim Blazek
6  email : radim dot blazek at gmail dot com
7  ***************************************************************************/
8 
9 /***************************************************************************
10  * *
11  * This program is free software; you can redistribute it and/or modify *
12  * it under the terms of the GNU General Public License as published by *
13  * the Free Software Foundation; either version 2 of the License, or *
14  * (at your option) any later version. *
15  * *
16  ***************************************************************************/
17 
18 #include <QApplication>
19 #include <QtConcurrentMap>
20 #include <QtConcurrentRun>
21 #include <QDateTime>
22 #include <QDir>
23 #include <QFileInfo>
24 #include <QMenu>
25 #include <QMouseEvent>
26 #include <QTreeWidget>
27 #include <QTreeWidgetItem>
28 #include <QVector>
29 #include <QStyle>
30 
31 #include "qgis.h"
32 #include "qgsdataitem.h"
33 #include "qgsapplication.h"
34 #include "qgsdataitemprovider.h"
36 #include "qgsdataprovider.h"
37 #include "qgslogger.h"
38 #include "qgsproviderregistry.h"
39 #include "qgsconfig.h"
40 #include "qgssettings.h"
41 #include "qgsanimatedicon.h"
42 
43 // use GDAL VSI mechanism
44 #include "cpl_vsi.h"
45 #include "cpl_string.h"
46 
47 // shared icons
49 {
50  return QgsApplication::getThemeIcon( QStringLiteral( "/mIconPointLayer.svg" ) );
51 }
52 
54 {
55  return QgsApplication::getThemeIcon( QStringLiteral( "/mIconLineLayer.svg" ) );
56 }
57 
59 {
60  return QgsApplication::getThemeIcon( QStringLiteral( "/mIconPolygonLayer.svg" ) );
61 }
62 
64 {
65  return QgsApplication::getThemeIcon( QStringLiteral( "/mIconTableLayer.svg" ) );
66 }
67 
69 {
70  return QgsApplication::getThemeIcon( QStringLiteral( "/mIconRaster.svg" ) );
71 }
72 
74 {
75  return QgsApplication::getThemeIcon( QStringLiteral( "/mIconLayer.png" ) );
76 }
77 
79 {
80  return QgsApplication::getThemeIcon( QStringLiteral( "/mIconDbSchema.png" ) );
81 }
82 
84 {
85  static QIcon sIcon;
86 
87  if ( sIcon.isNull() )
88  {
89  // initialize shared icons
90  QStyle *style = QApplication::style();
91  sIcon = QIcon( style->standardPixmap( QStyle::SP_DirClosedIcon ) );
92  sIcon.addPixmap( style->standardPixmap( QStyle::SP_DirOpenIcon ),
93  QIcon::Normal, QIcon::On );
94  }
95 
96  return sIcon;
97 }
98 
100 {
101  return QgsApplication::getThemeIcon( QStringLiteral( "/mIconFavourites.png" ) );
102 }
103 
105 {
106  return QgsApplication::getThemeIcon( QStringLiteral( "/mIconZip.png" ) );
107 // icon from http://www.softicons.com/free-icons/application-icons/mega-pack-icons-1-by-nikolay-verin/winzip-folder-icon
108 }
109 
110 QgsAnimatedIcon *QgsDataItem::sPopulatingIcon = nullptr;
111 
113 // Do not pass parent to QObject, Qt would delete this when parent is deleted
114  : QObject()
115  , mType( type )
117  , mParent( parent )
118  , mState( NotPopulated )
119  , mName( name )
120  , mPath( path )
121  , mDeferredDelete( false )
122  , mFutureWatcher( nullptr )
123 {
124 }
125 
127 {
128  QgsDebugMsgLevel( QString( "mName = %1 mPath = %2 mChildren.size() = %3" ).arg( mName, mPath ).arg( mChildren.size() ), 2 );
129  Q_FOREACH ( QgsDataItem *child, mChildren )
130  {
131  if ( !child ) // should not happen
132  continue;
133  child->deleteLater();
134  }
135  mChildren.clear();
136 
137  if ( mFutureWatcher && !mFutureWatcher->isFinished() )
138  {
139  // this should not usually happen (until the item was deleted directly when createChildren was running)
140  QgsDebugMsg( "mFutureWatcher not finished (should not happen) -> waitForFinished()" );
141  mDeferredDelete = true;
142  mFutureWatcher->waitForFinished();
143  }
144 
145  delete mFutureWatcher;
146 }
147 
148 QString QgsDataItem::pathComponent( const QString &string )
149 {
150  return QString( string ).replace( QRegExp( "[\\\\/]" ), QStringLiteral( "|" ) );
151 }
152 
154 {
155  QgsDebugMsgLevel( "path = " + path(), 3 );
156  setParent( nullptr ); // also disconnects parent
157  Q_FOREACH ( QgsDataItem *child, mChildren )
158  {
159  if ( !child ) // should not happen
160  continue;
161  child->deleteLater();
162  }
163  mChildren.clear();
164 
165  if ( mFutureWatcher && !mFutureWatcher->isFinished() )
166  {
167  QgsDebugMsg( "mFutureWatcher not finished -> schedule to delete later" );
168  mDeferredDelete = true;
169  }
170  else
171  {
172  QObject::deleteLater();
173  }
174 }
175 
176 void QgsDataItem::deleteLater( QVector<QgsDataItem *> &items )
177 {
178  Q_FOREACH ( QgsDataItem *item, items )
179  {
180  if ( !item ) // should not happen
181  continue;
182  item->deleteLater();
183  }
184  items.clear();
185 }
186 
187 void QgsDataItem::moveToThread( QThread *targetThread )
188 {
189  // QObject::moveToThread() cannot move objects with parent, but QgsDataItem is not using paren/children from QObject
190  Q_FOREACH ( QgsDataItem *child, mChildren )
191  {
192  if ( !child ) // should not happen
193  continue;
194  QgsDebugMsgLevel( "moveToThread child " + child->path(), 3 );
195  child->QObject::setParent( nullptr ); // to be sure
196  child->moveToThread( targetThread );
197  }
198  QObject::moveToThread( targetThread );
199 }
200 
202 {
203  if ( state() == Populating && sPopulatingIcon )
204  return sPopulatingIcon->icon();
205 
206  if ( !mIcon.isNull() )
207  return mIcon;
208 
209  if ( !mIconMap.contains( mIconName ) )
210  {
211  mIconMap.insert( mIconName, mIconName.startsWith( ':' ) ? QIcon( mIconName ) : QgsApplication::getThemeIcon( mIconName ) );
212  }
213 
214  return mIconMap.value( mIconName );
215 }
216 
217 QVector<QgsDataItem *> QgsDataItem::createChildren()
218 {
219  return QVector<QgsDataItem *>();
220 }
221 
222 void QgsDataItem::populate( bool foreground )
223 {
224  if ( state() == Populated || state() == Populating )
225  return;
226 
227  QgsDebugMsgLevel( "mPath = " + mPath, 2 );
228 
229  if ( capabilities2() & QgsDataItem::Fast || foreground )
230  {
232  }
233  else
234  {
235  setState( Populating );
236  // The watcher must not be created with item (in constructor) because the item may be created in thread and the watcher created in thread does not work correctly.
237  if ( !mFutureWatcher )
238  {
239  mFutureWatcher = new QFutureWatcher< QVector <QgsDataItem *> >( this );
240  }
241  connect( mFutureWatcher, &QFutureWatcherBase::finished, this, &QgsDataItem::childrenCreated );
242  mFutureWatcher->setFuture( QtConcurrent::run( runCreateChildren, this ) );
243  }
244 }
245 
246 // This is expected to be run in a separate thread
247 QVector<QgsDataItem *> QgsDataItem::runCreateChildren( QgsDataItem *item )
248 {
249  QgsDebugMsgLevel( "path = " + item->path(), 2 );
250  QTime time;
251  time.start();
252  QVector <QgsDataItem *> children = item->createChildren();
253  QgsDebugMsgLevel( QString( "%1 children created in %2 ms" ).arg( children.size() ).arg( time.elapsed() ), 3 );
254  // Children objects must be pushed to main thread.
255  Q_FOREACH ( QgsDataItem *child, children )
256  {
257  if ( !child ) // should not happen
258  continue;
259  QgsDebugMsgLevel( "moveToThread child " + child->path(), 2 );
260  if ( qApp )
261  child->moveToThread( qApp->thread() ); // moves also children
262  }
263  QgsDebugMsgLevel( QString( "finished path %1: %2 children" ).arg( item->path() ).arg( children.size() ), 3 );
264  return children;
265 }
266 
268 {
269  QgsDebugMsgLevel( QString( "path = %1 children.size() = %2" ).arg( path() ).arg( mFutureWatcher->result().size() ), 3 );
270 
271  if ( deferredDelete() )
272  {
273  QgsDebugMsg( "Item was scheduled to be deleted later" );
274  QObject::deleteLater();
275  return;
276  }
277 
278  if ( mChildren.isEmpty() ) // usually populating but may also be refresh if originally there were no children
279  {
280  populate( mFutureWatcher->result() );
281  }
282  else // refreshing
283  {
284  refresh( mFutureWatcher->result() );
285  }
286  disconnect( mFutureWatcher, &QFutureWatcherBase::finished, this, &QgsDataItem::childrenCreated );
287  emit dataChanged( this ); // to replace loading icon by normal icon
288 }
289 
291 {
292  emit dataChanged( this );
293 }
294 
295 void QgsDataItem::populate( const QVector<QgsDataItem *> &children )
296 {
297  QgsDebugMsgLevel( "mPath = " + mPath, 3 );
298 
299  Q_FOREACH ( QgsDataItem *child, children )
300  {
301  if ( !child ) // should not happen
302  continue;
303  // update after thread finished -> refresh
304  addChildItem( child, true );
305  }
306  setState( Populated );
307 }
308 
310 {
311  QgsDebugMsgLevel( "mPath = " + mPath, 3 );
312 
313  Q_FOREACH ( QgsDataItem *child, mChildren )
314  {
315  QgsDebugMsgLevel( "remove " + child->path(), 3 );
316  child->depopulate(); // recursive
317  deleteChildItem( child );
318  }
320 }
321 
323 {
324  if ( state() == Populating )
325  return;
326 
327  QgsDebugMsgLevel( "mPath = " + mPath, 3 );
328 
330  {
331  refresh( createChildren() );
332  }
333  else
334  {
335  setState( Populating );
336  if ( !mFutureWatcher )
337  {
338  mFutureWatcher = new QFutureWatcher< QVector <QgsDataItem *> >( this );
339  }
340  connect( mFutureWatcher, &QFutureWatcherBase::finished, this, &QgsDataItem::childrenCreated );
341  mFutureWatcher->setFuture( QtConcurrent::run( runCreateChildren, this ) );
342  }
343 }
344 
345 void QgsDataItem::refresh( const QVector<QgsDataItem *> &children )
346 {
347  QgsDebugMsgLevel( "mPath = " + mPath, 2 );
348 
349  // Remove no more present children
350  QVector<QgsDataItem *> remove;
351  Q_FOREACH ( QgsDataItem *child, mChildren )
352  {
353  if ( !child ) // should not happen
354  continue;
355  if ( findItem( children, child ) >= 0 )
356  continue;
357  remove.append( child );
358  }
359  Q_FOREACH ( QgsDataItem *child, remove )
360  {
361  QgsDebugMsgLevel( "remove " + child->path(), 3 );
362  deleteChildItem( child );
363  }
364 
365  // Add new children
366  Q_FOREACH ( QgsDataItem *child, children )
367  {
368  if ( !child ) // should not happen
369  continue;
370 
371  int index = findItem( mChildren, child );
372  if ( index >= 0 )
373  {
374  // Refresh recursively (some providers may create more generations of descendants)
375  if ( !( child->capabilities2() & QgsDataItem::Fertile ) )
376  {
377  // The child cannot createChildren() itself
378  mChildren.value( index )->refresh( child->children() );
379  }
380 
381  child->deleteLater();
382  continue;
383  }
384  addChildItem( child, true );
385  }
386  setState( Populated );
387 }
388 
390 {
391  return mChildren.size();
392 }
394 {
395  return ( state() == Populated ? !mChildren.isEmpty() : true );
396 }
397 
399 {
400  if ( mParent )
401  {
402  disconnect( this, nullptr, mParent, nullptr );
403  }
404  if ( parent )
405  {
407  connect( this, &QgsDataItem::endInsertItems, parent, &QgsDataItem::endInsertItems );
409  connect( this, &QgsDataItem::endRemoveItems, parent, &QgsDataItem::endRemoveItems );
410  connect( this, &QgsDataItem::dataChanged, parent, &QgsDataItem::dataChanged );
411  connect( this, &QgsDataItem::stateChanged, parent, &QgsDataItem::stateChanged );
412  }
413  mParent = parent;
414 }
415 
417 {
418  Q_ASSERT( child );
419  QgsDebugMsgLevel( QString( "path = %1 add child #%2 - %3 - %4" ).arg( mPath ).arg( mChildren.size() ).arg( child->mName ).arg( child->mType ), 3 );
420 
421  //calculate position to insert child
422  int i;
423  if ( type() == Directory )
424  {
425  for ( i = 0; i < mChildren.size(); i++ )
426  {
427  // sort items by type, so directories are before data items
428  if ( mChildren.at( i )->mType == child->mType &&
429  mChildren.at( i )->mName.localeAwareCompare( child->mName ) > 0 )
430  break;
431  }
432  }
433  else
434  {
435  for ( i = 0; i < mChildren.size(); i++ )
436  {
437  if ( mChildren.at( i )->mName.localeAwareCompare( child->mName ) >= 0 )
438  break;
439  }
440  }
441 
442  if ( refresh )
443  emit beginInsertItems( this, i, i );
444 
445  mChildren.insert( i, child );
446  child->setParent( this );
447 
448  if ( refresh )
449  emit endInsertItems();
450 }
451 
453 {
454  QgsDebugMsgLevel( "mName = " + child->mName, 2 );
455  int i = mChildren.indexOf( child );
456  Q_ASSERT( i >= 0 );
457  emit beginRemoveItems( this, i, i );
458  mChildren.remove( i );
459  child->deleteLater();
460  emit endRemoveItems();
461 }
462 
464 {
465  QgsDebugMsgLevel( "mName = " + child->mName, 2 );
466  int i = mChildren.indexOf( child );
467  Q_ASSERT( i >= 0 );
468  if ( i < 0 )
469  {
470  child->setParent( nullptr );
471  return nullptr;
472  }
473 
474  emit beginRemoveItems( this, i, i );
475  mChildren.remove( i );
476  emit endRemoveItems();
477  return child;
478 }
479 
480 int QgsDataItem::findItem( QVector<QgsDataItem *> items, QgsDataItem *item )
481 {
482  for ( int i = 0; i < items.size(); i++ )
483  {
484  Q_ASSERT_X( items[i], "findItem", QString( "item %1 is nullptr" ).arg( i ).toLatin1() );
485  QgsDebugMsgLevel( QString::number( i ) + " : " + items[i]->mPath + " x " + item->mPath, 2 );
486  if ( items[i]->equal( item ) )
487  return i;
488  }
489  return -1;
490 }
491 
492 bool QgsDataItem::equal( const QgsDataItem *other )
493 {
494  return ( metaObject()->className() == other->metaObject()->className() &&
495  mPath == other->path() );
496 }
497 
499 {
500  return mState;
501 }
502 
504 {
505  QgsDebugMsgLevel( QString( "item %1 set state %2 -> %3" ).arg( path() ).arg( this->state() ).arg( state ), 3 );
506  if ( state == mState )
507  return;
508 
509  State oldState = mState;
510 
511  if ( state == Populating ) // start loading
512  {
513  if ( !sPopulatingIcon )
514  {
515  // TODO: ensure that QgsAnimatedIcon is created on UI thread only
516  sPopulatingIcon = new QgsAnimatedIcon( QgsApplication::iconPath( QStringLiteral( "/mIconLoading.gif" ) ), QgsApplication::instance() );
517  }
518 
519  sPopulatingIcon->connectFrameChanged( this, &QgsDataItem::updateIcon );
520  }
521  else if ( mState == Populating && sPopulatingIcon ) // stop loading
522  {
523  sPopulatingIcon->disconnectFrameChanged( this, &QgsDataItem::updateIcon );
524  }
525 
526 
527  mState = state;
528 
529  emit stateChanged( this, oldState );
530  if ( state == Populated )
531  updateIcon();
532 }
533 
534 // ---------------------------------------------------------------------
535 
536 QgsLayerItem::QgsLayerItem( QgsDataItem *parent, const QString &name, const QString &path, const QString &uri, LayerType layerType, const QString &providerKey )
537  : QgsDataItem( Layer, parent, name, path )
538  , mProviderKey( providerKey )
539  , mUri( uri )
540  , mLayerType( layerType )
541 {
542  switch ( layerType )
543  {
544  case Point:
545  mIconName = QStringLiteral( "/mIconPointLayer.svg" );
546  break;
547  case Line:
548  mIconName = QStringLiteral( "/mIconLineLayer.svg" );
549  break;
550  case Polygon:
551  mIconName = QStringLiteral( "/mIconPolygonLayer.svg" );
552  break;
553  // TODO add a new icon for generic Vector layers
554  case Vector :
555  mIconName = QStringLiteral( "/mIconPolygonLayer.svg" );
556  break;
557  case TableLayer:
558  mIconName = QStringLiteral( "/mIconTableLayer.svg" );
559  break;
560  case Raster:
561  mIconName = QStringLiteral( "/mIconRaster.svg" );
562  break;
563  default:
564  mIconName = QStringLiteral( "/mIconLayer.png" );
565  break;
566  }
567 }
568 
570 {
576 }
577 
578 bool QgsLayerItem::equal( const QgsDataItem *other )
579 {
580  //QgsDebugMsg ( mPath + " x " + other->mPath );
581  if ( type() != other->type() )
582  {
583  return false;
584  }
585  //const QgsLayerItem *o = qobject_cast<const QgsLayerItem *> ( other );
586  const QgsLayerItem *o = dynamic_cast<const QgsLayerItem *>( other );
587  if ( !o )
588  return false;
589 
590  return ( mPath == o->mPath && mName == o->mName && mUri == o->mUri && mProviderKey == o->mProviderKey );
591 }
592 
594 {
596 
597  switch ( mapLayerType() )
598  {
600  u.layerType = QStringLiteral( "vector" );
601  break;
603  u.layerType = QStringLiteral( "raster" );
604  break;
606  u.layerType = QStringLiteral( "plugin" );
607  break;
608  default:
609  return u; // invalid URI
610  }
611 
612  u.providerKey = providerKey();
613  u.name = layerName();
614  u.uri = uri();
617  return u;
618 }
619 
620 // ---------------------------------------------------------------------
622  : QgsDataItem( Collection, parent, name, path )
623 {
625  mIconName = QStringLiteral( "/mIconDbSchema.png" );
626 }
627 
629 {
630  QgsDebugMsgLevel( "mName = " + mName + " mPath = " + mPath, 2 );
631 
632 // Do not delete children, children are deleted by QObject parent
633 #if 0
634  Q_FOREACH ( QgsDataItem *i, mChildren )
635  {
636  QgsDebugMsgLevel( QString( "delete child = 0x%0" ).arg( ( qlonglong )i, 8, 16, QLatin1Char( '0' ) ), 2 );
637  delete i;
638  }
639 #endif
640 }
641 
642 //-----------------------------------------------------------------------
643 
644 QgsDirectoryItem::QgsDirectoryItem( QgsDataItem *parent, const QString &name, const QString &path )
645  : QgsDataCollectionItem( parent, name, path )
646  , mDirPath( path )
647  , mFileSystemWatcher( nullptr )
648  , mRefreshLater( false )
649 {
650  mType = Directory;
651  init();
652 }
653 
654 QgsDirectoryItem::QgsDirectoryItem( QgsDataItem *parent, const QString &name, const QString &dirPath, const QString &path )
655  : QgsDataCollectionItem( parent, name, path )
656  , mDirPath( dirPath )
657  , mFileSystemWatcher( nullptr )
658  , mRefreshLater( false )
659 {
660  mType = Directory;
661  init();
662 }
663 
665 {
666 }
667 
669 {
670  if ( state() == Populating )
671  return QgsDataItem::icon();
672  return iconDir();
673 }
674 
675 
676 QVector<QgsDataItem *> QgsDirectoryItem::createChildren()
677 {
678  QVector<QgsDataItem *> children;
679  QDir dir( mDirPath );
680 
681  QStringList entries = dir.entryList( QDir::AllDirs | QDir::NoDotAndDotDot, QDir::Name | QDir::IgnoreCase );
682  Q_FOREACH ( const QString &subdir, entries )
683  {
684  if ( mRefreshLater )
685  {
686  deleteLater( children );
687  return children;
688  }
689 
690  QString subdirPath = dir.absoluteFilePath( subdir );
691 
692  QgsDebugMsgLevel( QString( "creating subdir: %1" ).arg( subdirPath ), 2 );
693 
694  QString path = mPath + '/' + subdir; // may differ from subdirPath
695  if ( QgsDirectoryItem::hiddenPath( path ) )
696  continue;
697  QgsDirectoryItem *item = new QgsDirectoryItem( this, subdir, subdirPath, path );
698  // propagate signals up to top
699 
700  children.append( item );
701  }
702 
703  QStringList fileEntries = dir.entryList( QDir::Dirs | QDir::NoDotAndDotDot | QDir::Files, QDir::Name );
704  Q_FOREACH ( const QString &name, fileEntries )
705  {
706  if ( mRefreshLater )
707  {
708  deleteLater( children );
709  return children;
710  }
711 
712  QString path = dir.absoluteFilePath( name );
713  QFileInfo fileInfo( path );
714 
715  if ( fileInfo.suffix() == QLatin1String( "qgs" ) )
716  {
717  QgsDataItem *item = new QgsProjectItem( this, name, path );
718  children.append( item );
719  continue;
720  }
721 
722  // vsizip support was added to GDAL/OGR 1.6 but GDAL_VERSION_NUM not available here
723  // so we assume it's available anyway
724  {
725  QgsDataItem *item = QgsZipItem::itemFromPath( this, path, name, mPath + '/' + name );
726  if ( item )
727  {
728  children.append( item );
729  continue;
730  }
731  }
732 
733  Q_FOREACH ( QgsDataItemProvider *provider, QgsApplication::dataItemProviderRegistry()->providers() )
734  {
735  int capabilities = provider->capabilities();
736 
737  if ( !( ( fileInfo.isFile() && ( capabilities & QgsDataProvider::File ) ) ||
738  ( fileInfo.isDir() && ( capabilities & QgsDataProvider::Dir ) ) ) )
739  {
740  continue;
741  }
742 
743  QgsDataItem *item = provider->createDataItem( path, this );
744  if ( item )
745  {
746  children.append( item );
747  }
748  }
749 
750  }
751 
752  return children;
753 }
754 
756 {
758 
759  if ( state == Populated )
760  {
761  if ( !mFileSystemWatcher )
762  {
763  mFileSystemWatcher = new QFileSystemWatcher( this );
764  mFileSystemWatcher->addPath( mDirPath );
765  connect( mFileSystemWatcher, &QFileSystemWatcher::directoryChanged, this, &QgsDirectoryItem::directoryChanged );
766  }
767  }
768  else if ( state == NotPopulated )
769  {
770  if ( mFileSystemWatcher )
771  {
772  delete mFileSystemWatcher;
773  mFileSystemWatcher = nullptr;
774  }
775  }
776 }
777 
779 {
780  if ( state() == Populating )
781  {
782  // schedule to refresh later, because refres() simply returns if Populating
783  mRefreshLater = true;
784  }
785  else
786  {
787  refresh();
788  }
789 }
790 
791 bool QgsDirectoryItem::hiddenPath( const QString &path )
792 {
793  QgsSettings settings;
794  QStringList hiddenItems = settings.value( QStringLiteral( "browser/hiddenPaths" ),
795  QStringList() ).toStringList();
796  int idx = hiddenItems.indexOf( path );
797  return ( idx > -1 );
798 }
799 
801 {
802  QgsDebugMsgLevel( QString( "mRefreshLater = %1" ).arg( mRefreshLater ), 3 );
803 
804  if ( mRefreshLater )
805  {
806  QgsDebugMsgLevel( "directory changed during createChidren() -> refresh() again", 3 );
807  mRefreshLater = false;
808  setState( Populated );
809  refresh();
810  }
811  else
812  {
814  }
815 }
816 
818 {
819  //QgsDebugMsg ( mPath + " x " + other->mPath );
820  if ( type() != other->type() )
821  {
822  return false;
823  }
824  return ( path() == other->path() );
825 }
826 
828 {
829  return new QgsDirectoryParamWidget( mPath );
830 }
831 
833  : QTreeWidget( parent )
834 {
835  setRootIsDecorated( false );
836 
837  // name, size, date, permissions, owner, group, type
838  setColumnCount( 7 );
839  QStringList labels;
840  labels << tr( "Name" ) << tr( "Size" ) << tr( "Date" ) << tr( "Permissions" ) << tr( "Owner" ) << tr( "Group" ) << tr( "Type" );
841  setHeaderLabels( labels );
842 
843  QStyle *style = QApplication::style();
844  QIcon iconDirectory = QIcon( style->standardPixmap( QStyle::SP_DirClosedIcon ) );
845  QIcon iconFile = QIcon( style->standardPixmap( QStyle::SP_FileIcon ) );
846  QIcon iconDirLink = QIcon( style->standardPixmap( QStyle::SP_DirLinkIcon ) );
847  QIcon iconFileLink = QIcon( style->standardPixmap( QStyle::SP_FileLinkIcon ) );
848 
849  QList<QTreeWidgetItem *> items;
850 
851  QDir dir( path );
852  QStringList entries = dir.entryList( QDir::AllEntries | QDir::NoDotAndDotDot, QDir::Name | QDir::IgnoreCase );
853  Q_FOREACH ( const QString &name, entries )
854  {
855  QFileInfo fi( dir.absoluteFilePath( name ) );
856  QStringList texts;
857  texts << name;
858  QString size;
859  if ( fi.size() > 1024 )
860  {
861  size = size.sprintf( "%.1f KiB", fi.size() / 1024.0 );
862  }
863  else if ( fi.size() > 1.048576e6 )
864  {
865  size = size.sprintf( "%.1f MiB", fi.size() / 1.048576e6 );
866  }
867  else
868  {
869  size = QStringLiteral( "%1 B" ).arg( fi.size() );
870  }
871  texts << size;
872  texts << fi.lastModified().toString( Qt::SystemLocaleShortDate );
873  QString perm;
874  perm += fi.permission( QFile::ReadOwner ) ? 'r' : '-';
875  perm += fi.permission( QFile::WriteOwner ) ? 'w' : '-';
876  perm += fi.permission( QFile::ExeOwner ) ? 'x' : '-';
877  // QFile::ReadUser, QFile::WriteUser, QFile::ExeUser
878  perm += fi.permission( QFile::ReadGroup ) ? 'r' : '-';
879  perm += fi.permission( QFile::WriteGroup ) ? 'w' : '-';
880  perm += fi.permission( QFile::ExeGroup ) ? 'x' : '-';
881  perm += fi.permission( QFile::ReadOther ) ? 'r' : '-';
882  perm += fi.permission( QFile::WriteOther ) ? 'w' : '-';
883  perm += fi.permission( QFile::ExeOther ) ? 'x' : '-';
884  texts << perm;
885 
886  texts << fi.owner();
887  texts << fi.group();
888 
889  QString type;
890  QIcon icon;
891  if ( fi.isDir() && fi.isSymLink() )
892  {
893  type = tr( "folder" );
894  icon = iconDirLink;
895  }
896  else if ( fi.isDir() )
897  {
898  type = tr( "folder" );
899  icon = iconDirectory;
900  }
901  else if ( fi.isFile() && fi.isSymLink() )
902  {
903  type = tr( "file" );
904  icon = iconFileLink;
905  }
906  else if ( fi.isFile() )
907  {
908  type = tr( "file" );
909  icon = iconFile;
910  }
911 
912  texts << type;
913 
914  QTreeWidgetItem *item = new QTreeWidgetItem( texts );
915  item->setIcon( 0, icon );
916  items << item;
917  }
918 
919  addTopLevelItems( items );
920 
921  // hide columns that are not requested
922  QgsSettings settings;
923  QList<QVariant> lst = settings.value( QStringLiteral( "dataitem/directoryHiddenColumns" ) ).toList();
924  Q_FOREACH ( const QVariant &colVariant, lst )
925  {
926  setColumnHidden( colVariant.toInt(), true );
927  }
928 }
929 
931 {
932  if ( event->button() == Qt::RightButton )
933  {
934  // show the popup menu
935  QMenu popupMenu;
936 
937  QStringList labels;
938  labels << tr( "Name" ) << tr( "Size" ) << tr( "Date" ) << tr( "Permissions" ) << tr( "Owner" ) << tr( "Group" ) << tr( "Type" );
939  for ( int i = 0; i < labels.count(); i++ )
940  {
941  QAction *action = popupMenu.addAction( labels[i], this, SLOT( showHideColumn() ) );
942  action->setObjectName( QString::number( i ) );
943  action->setCheckable( true );
944  action->setChecked( !isColumnHidden( i ) );
945  }
946 
947  popupMenu.exec( event->globalPos() );
948  }
949 }
950 
952 {
953  QAction *action = qobject_cast<QAction *>( sender() );
954  if ( !action )
955  return; // something is wrong
956 
957  int columnIndex = action->objectName().toInt();
958  setColumnHidden( columnIndex, !isColumnHidden( columnIndex ) );
959 
960  // save in settings
961  QgsSettings settings;
962  QList<QVariant> lst;
963  for ( int i = 0; i < columnCount(); i++ )
964  {
965  if ( isColumnHidden( i ) )
966  lst.append( QVariant( i ) );
967  }
968  settings.setValue( QStringLiteral( "dataitem/directoryHiddenColumns" ), lst );
969 }
970 
971 QgsProjectItem::QgsProjectItem( QgsDataItem *parent, const QString &name, const QString &path )
972  : QgsDataItem( QgsDataItem::Project, parent, name, path )
973 {
974  mIconName = QStringLiteral( ":/images/icons/qgis-icon-16x16.png" );
975 
976  setState( Populated ); // no more children
977 }
978 
979 QgsErrorItem::QgsErrorItem( QgsDataItem *parent, const QString &error, const QString &path )
980  : QgsDataItem( QgsDataItem::Error, parent, error, path )
981 {
982  mIconName = QStringLiteral( "/mIconDelete.png" );
983 
984  setState( Populated ); // no more children
985 }
986 
987 QgsFavoritesItem::QgsFavoritesItem( QgsDataItem *parent, const QString &name, const QString &path )
988  : QgsDataCollectionItem( parent, name, QStringLiteral( "favorites:" ) )
989 {
990  Q_UNUSED( path );
991  mCapabilities |= Fast;
992  mType = Favorites;
993  mIconName = QStringLiteral( "/mIconFavourites.png" );
994  populate();
995 }
996 
997 QVector<QgsDataItem *> QgsFavoritesItem::createChildren()
998 {
999  QVector<QgsDataItem *> children;
1000 
1001  QgsSettings settings;
1002  QStringList favDirs = settings.value( QStringLiteral( "browser/favourites" ), QVariant() ).toStringList();
1003 
1004  Q_FOREACH ( const QString &favDir, favDirs )
1005  {
1006  children << createChildren( favDir );
1007  }
1008 
1009  return children;
1010 }
1011 
1012 void QgsFavoritesItem::addDirectory( const QString &favDir )
1013 {
1014  QgsSettings settings;
1015  QStringList favDirs = settings.value( QStringLiteral( "browser/favourites" ) ).toStringList();
1016  favDirs.append( favDir );
1017  settings.setValue( QStringLiteral( "browser/favourites" ), favDirs );
1018 
1019  if ( state() == Populated )
1020  {
1021  QVector<QgsDataItem *> items = createChildren( favDir );
1022  Q_FOREACH ( QgsDataItem *item, items )
1023  {
1024  addChildItem( item, true );
1025  }
1026  }
1027 }
1028 
1030 {
1031  if ( !item )
1032  return;
1033 
1034  QgsSettings settings;
1035  QStringList favDirs = settings.value( QStringLiteral( "browser/favourites" ) ).toStringList();
1036  favDirs.removeAll( item->dirPath() );
1037  settings.setValue( QStringLiteral( "browser/favourites" ), favDirs );
1038 
1039  int idx = findItem( mChildren, item );
1040  if ( idx < 0 )
1041  {
1042  QgsDebugMsg( QString( "favorites item %1 not found" ).arg( item->path() ) );
1043  return;
1044  }
1045 
1046  if ( state() == Populated )
1047  deleteChildItem( mChildren.at( idx ) );
1048 }
1049 
1050 QVector<QgsDataItem *> QgsFavoritesItem::createChildren( const QString &favDir )
1051 {
1052  QVector<QgsDataItem *> children;
1053  QString pathName = pathComponent( favDir );
1054  Q_FOREACH ( QgsDataItemProvider *provider, QgsApplication::dataItemProviderRegistry()->providers() )
1055  {
1056  int capabilities = provider->capabilities();
1057 
1058  if ( capabilities & QgsDataProvider::Dir )
1059  {
1060  QgsDataItem *item = provider->createDataItem( favDir, this );
1061  if ( item )
1062  {
1063  item->setName( favDir );
1064  children.append( item );
1065  }
1066  }
1067  }
1068  if ( children.isEmpty() )
1069  {
1070  QgsDataItem *item = new QgsDirectoryItem( this, favDir, favDir, mPath + '/' + pathName );
1071  if ( item )
1072  {
1073  children.append( item );
1074  }
1075  }
1076  return children;
1077 }
1078 
1079 //-----------------------------------------------------------------------
1080 QStringList QgsZipItem::sProviderNames = QStringList();
1081 QVector<dataItem_t *> QgsZipItem::sDataItemPtr = QVector<dataItem_t *>();
1082 
1083 
1084 QgsZipItem::QgsZipItem( QgsDataItem *parent, const QString &name, const QString &path )
1085  : QgsDataCollectionItem( parent, name, path )
1086 {
1087  mFilePath = path;
1088  init();
1089 }
1090 
1091 QgsZipItem::QgsZipItem( QgsDataItem *parent, const QString &name, const QString &filePath, const QString &path )
1092  : QgsDataCollectionItem( parent, name, path )
1093  , mFilePath( filePath )
1094 {
1095  init();
1096 }
1097 
1098 void QgsZipItem::init()
1099 {
1100  mType = Collection; //Zip??
1101  mIconName = QStringLiteral( "/mIconZip.png" );
1103 
1104  if ( sProviderNames.isEmpty() )
1105  {
1106  // QStringList keys = QgsProviderRegistry::instance()->providerList();
1107  // only use GDAL and OGR providers as we use the VSIFILE mechanism
1108  QStringList keys;
1109  // keys << "ogr" << "gdal";
1110  keys << QStringLiteral( "gdal" ) << QStringLiteral( "ogr" );
1111 
1112  QStringList::const_iterator i;
1113  for ( i = keys.begin(); i != keys.end(); ++i )
1114  {
1115  QString k( *i );
1116  QgsDebugMsgLevel( "provider " + k, 3 );
1117  // some providers hangs with empty uri (Postgis) etc...
1118  // -> using libraries directly
1119  std::unique_ptr< QLibrary > library( QgsProviderRegistry::instance()->providerLibrary( k ) );
1120  if ( library )
1121  {
1122  dataCapabilities_t *dataCapabilities = reinterpret_cast< dataCapabilities_t * >( cast_to_fptr( library->resolve( "dataCapabilities" ) ) );
1123  if ( !dataCapabilities )
1124  {
1125  QgsDebugMsg( library->fileName() + " does not have dataCapabilities" );
1126  continue;
1127  }
1128  if ( dataCapabilities() == QgsDataProvider::NoDataCapabilities )
1129  {
1130  QgsDebugMsg( library->fileName() + " has NoDataCapabilities" );
1131  continue;
1132  }
1133  QgsDebugMsg( QString( "%1 dataCapabilities : %2" ).arg( library->fileName() ).arg( dataCapabilities() ) );
1134 
1135  dataItem_t *dataItem = reinterpret_cast< dataItem_t * >( cast_to_fptr( library->resolve( "dataItem" ) ) );
1136  if ( ! dataItem )
1137  {
1138  QgsDebugMsg( library->fileName() + " does not have dataItem" );
1139  continue;
1140  }
1141 
1142  // mLibraries.append( library );
1143  sDataItemPtr.append( dataItem );
1144  sProviderNames.append( k );
1145  }
1146  else
1147  {
1148  //QgsDebugMsg ( "Cannot get provider " + k );
1149  }
1150  }
1151  }
1152 
1153 }
1154 
1155 // internal function to scan a vsidir (zip or tar file) recursively
1156 // GDAL trunk has this since r24423 (05/16/12) - VSIReadDirRecursive()
1157 // use a copy of the function internally for now,
1158 // but use char ** and CSLAddString, because CPLStringList was added in gdal-1.9
1159 char **VSIReadDirRecursive1( const char *pszPath )
1160 {
1161  // CPLStringList oFiles = nullptr;
1162  char **papszOFiles = nullptr;
1163  char **papszFiles1 = nullptr;
1164  char **papszFiles2 = nullptr;
1165  VSIStatBufL psStatBuf;
1166  CPLString osTemp1, osTemp2;
1167  int i, j;
1168  int nCount1, nCount2;
1169 
1170  // get listing
1171  papszFiles1 = VSIReadDir( pszPath );
1172  if ( ! papszFiles1 )
1173  return nullptr;
1174 
1175  // get files and directories inside listing
1176  nCount1 = CSLCount( papszFiles1 );
1177  for ( i = 0; i < nCount1; i++ )
1178  {
1179  // build complete file name for stat
1180  osTemp1.clear();
1181  osTemp1.append( pszPath );
1182  osTemp1.append( "/" );
1183  osTemp1.append( papszFiles1[i] );
1184 
1185  // if is file, add it
1186  if ( VSIStatL( osTemp1.c_str(), &psStatBuf ) == 0 &&
1187  VSI_ISREG( psStatBuf.st_mode ) )
1188  {
1189  // oFiles.AddString( papszFiles1[i] );
1190  papszOFiles = CSLAddString( papszOFiles, papszFiles1[i] );
1191  }
1192  else if ( VSIStatL( osTemp1.c_str(), &psStatBuf ) == 0 &&
1193  VSI_ISDIR( psStatBuf.st_mode ) )
1194  {
1195  // add directory entry
1196  osTemp2.clear();
1197  osTemp2.append( papszFiles1[i] );
1198  osTemp2.append( "/" );
1199  // oFiles.AddString( osTemp2.c_str() );
1200  papszOFiles = CSLAddString( papszOFiles, osTemp2.c_str() );
1201 
1202  // recursively add files inside directory
1203  papszFiles2 = VSIReadDirRecursive1( osTemp1.c_str() );
1204  if ( papszFiles2 )
1205  {
1206  nCount2 = CSLCount( papszFiles2 );
1207  for ( j = 0; j < nCount2; j++ )
1208  {
1209  osTemp2.clear();
1210  osTemp2.append( papszFiles1[i] );
1211  osTemp2.append( "/" );
1212  osTemp2.append( papszFiles2[j] );
1213  // oFiles.AddString( osTemp2.c_str() );
1214  papszOFiles = CSLAddString( papszOFiles, osTemp2.c_str() );
1215  }
1216  CSLDestroy( papszFiles2 );
1217  }
1218  }
1219  }
1220  CSLDestroy( papszFiles1 );
1221 
1222  // return oFiles.StealList();
1223  return papszOFiles;
1224 }
1225 
1226 QVector<QgsDataItem *> QgsZipItem::createChildren()
1227 {
1228  QVector<QgsDataItem *> children;
1229  QString tmpPath;
1230  QgsSettings settings;
1231  QString scanZipSetting = settings.value( QStringLiteral( "qgis/scanZipInBrowser2" ), "basic" ).toString();
1232 
1233  mZipFileList.clear();
1234 
1235  QgsDebugMsgLevel( QString( "mFilePath = %1 path = %2 name= %3 scanZipSetting= %4 vsiPrefix= %5" ).arg( mFilePath, path(), name(), scanZipSetting, mVsiPrefix ), 2 );
1236 
1237  // if scanZipBrowser == no: skip to the next file
1238  if ( scanZipSetting == QLatin1String( "no" ) )
1239  {
1240  return children;
1241  }
1242 
1243  // first get list of files
1244  getZipFileList();
1245 
1246  // loop over files inside zip
1247  Q_FOREACH ( const QString &fileName, mZipFileList )
1248  {
1249  QFileInfo info( fileName );
1250  tmpPath = mVsiPrefix + mFilePath + '/' + fileName;
1251  QgsDebugMsgLevel( "tmpPath = " + tmpPath, 3 );
1252 
1253  // Q_FOREACH( dataItem_t *dataItem, mDataItemPtr )
1254  for ( int i = 0; i < sProviderNames.size(); i++ )
1255  {
1256  // ugly hack to remove .dbf file if there is a .shp file
1257  if ( sProviderNames[i] == QLatin1String( "ogr" ) )
1258  {
1259  if ( info.suffix().toLower() == QLatin1String( "dbf" ) )
1260  {
1261  if ( mZipFileList.indexOf( fileName.left( fileName.count() - 4 ) + ".shp" ) != -1 )
1262  continue;
1263  }
1264  if ( info.completeSuffix().toLower() == QLatin1String( "shp.xml" ) )
1265  {
1266  continue;
1267  }
1268  }
1269 
1270  // try to get data item from provider
1271  dataItem_t *dataItem = sDataItemPtr.at( i );
1272  if ( dataItem )
1273  {
1274  QgsDebugMsgLevel( QString( "trying to load item %1 with %2" ).arg( tmpPath, sProviderNames.at( i ) ), 3 );
1275  QgsDataItem *item = dataItem( tmpPath, this );
1276  if ( item )
1277  {
1278  QgsDebugMsgLevel( "loaded item", 3 );
1279  // the item comes with zipped file name, set the name to relative path within zip file
1280  item->setName( fileName );
1281  children.append( item );
1282  break;
1283  }
1284  else
1285  {
1286  QgsDebugMsgLevel( "not loaded item", 3 );
1287  }
1288  }
1289  }
1290 
1291  }
1292 
1293  return children;
1294 }
1295 
1296 QgsDataItem *QgsZipItem::itemFromPath( QgsDataItem *parent, const QString &path, const QString &name )
1297 {
1298  return itemFromPath( parent, path, name, path );
1299 }
1300 
1301 QgsDataItem *QgsZipItem::itemFromPath( QgsDataItem *parent, const QString &filePath, const QString &name, const QString &path )
1302 {
1303  QgsSettings settings;
1304  QString scanZipSetting = settings.value( QStringLiteral( "qgis/scanZipInBrowser2" ), "basic" ).toString();
1305  int zipFileCount = 0;
1306  QStringList zipFileList;
1307  QString vsiPrefix = QgsZipItem::vsiPrefix( filePath );
1308  QgsZipItem *zipItem = nullptr;
1309  bool populated = false;
1310 
1311  QgsDebugMsgLevel( QString( "path = %1 name= %2 scanZipSetting= %3 vsiPrefix= %4" ).arg( path, name, scanZipSetting, vsiPrefix ), 3 );
1312 
1313  // don't scan if scanZipBrowser == no
1314  if ( scanZipSetting == QLatin1String( "no" ) )
1315  return nullptr;
1316 
1317  // don't scan if this file is not a /vsizip/ or /vsitar/ item
1318  if ( ( vsiPrefix != QLatin1String( "/vsizip/" ) && vsiPrefix != QLatin1String( "/vsitar/" ) ) )
1319  return nullptr;
1320 
1321  zipItem = new QgsZipItem( parent, name, filePath, path );
1322 
1323  if ( zipItem )
1324  {
1325  // force populate zipItem if it has less than 10 items and is not a .tgz or .tar.gz file (slow loading)
1326  // for other items populating will be delayed until item is opened
1327  // this might be polluting the tree with empty items but is necessary for performance reasons
1328  // could also accept all files smaller than a certain size and add options for file count and/or size
1329 
1330  // first get list of files inside .zip or .tar files
1331  if ( path.endsWith( QLatin1String( ".zip" ), Qt::CaseInsensitive ) ||
1332  path.endsWith( QLatin1String( ".tar" ), Qt::CaseInsensitive ) )
1333  {
1334  zipFileList = zipItem->getZipFileList();
1335  }
1336  // force populate if less than 10 items
1337  if ( !zipFileList.isEmpty() && zipFileList.count() <= 10 )
1338  {
1339  zipItem->populate( zipItem->createChildren() );
1340  populated = true; // there is no QgsDataItem::isPopulated() function
1341  QgsDebugMsgLevel( QString( "Got zipItem with %1 children, path=%2, name=%3" ).arg( zipItem->rowCount() ).arg( zipItem->path(), zipItem->name() ), 3 );
1342  }
1343  else
1344  {
1345  QgsDebugMsgLevel( QString( "Delaying populating zipItem with path=%1, name=%2" ).arg( zipItem->path(), zipItem->name() ), 3 );
1346  }
1347  }
1348 
1349  // only display if has children or if is not populated
1350  if ( zipItem && ( !populated || zipItem->rowCount() > 1 ) )
1351  {
1352  QgsDebugMsgLevel( "returning zipItem", 3 );
1353  return zipItem;
1354  }
1355  // if 1 or 0 child found, create a single data item using the normal path or the full path given by QgsZipItem
1356  else
1357  {
1358  QString vsiPath = vsiPrefix + filePath;
1359  if ( zipItem )
1360  {
1361  QVector<QgsDataItem *> children = zipItem->children();
1362  if ( children.size() == 1 )
1363  {
1364  // take the name of the only child so we can get a normal data item from it
1365  QgsLayerItem *layerItem = qobject_cast<QgsLayerItem *>( children.first() );
1366  if ( layerItem )
1367  vsiPath = layerItem->uri();
1368  }
1369  zipFileCount = zipFileList.count();
1370  delete zipItem;
1371  }
1372 
1373  QgsDebugMsgLevel( QString( "will try to create a normal dataItem from filePath= %2 or vsiPath = %3" ).arg( filePath, vsiPath ), 3 );
1374 
1375  // try to open using registered providers (gdal and ogr)
1376  for ( int i = 0; i < sProviderNames.size(); i++ )
1377  {
1378  dataItem_t *dataItem = sDataItemPtr.at( i );
1379  if ( dataItem )
1380  {
1381  QgsDataItem *item = nullptr;
1382  // try first with normal path (Passthru)
1383  // this is to simplify .qml handling, and without this some tests will fail
1384  // (e.g. testZipItemVectorTransparency(), second test)
1385  if ( ( sProviderNames.at( i ) == QLatin1String( "ogr" ) ) ||
1386  ( sProviderNames.at( i ) == QLatin1String( "gdal" ) && zipFileCount == 1 ) )
1387  item = dataItem( filePath, parent );
1388  // try with /vsizip/
1389  if ( ! item )
1390  item = dataItem( vsiPath, parent );
1391  if ( item )
1392  return item;
1393  }
1394  }
1395  }
1396 
1397  return nullptr;
1398 }
1399 
1401 {
1402  if ( ! mZipFileList.isEmpty() )
1403  return mZipFileList;
1404 
1405  QString tmpPath;
1406  QgsSettings settings;
1407  QString scanZipSetting = settings.value( QStringLiteral( "qgis/scanZipInBrowser2" ), "basic" ).toString();
1408 
1409  QgsDebugMsgLevel( QString( "mFilePath = %1 name= %2 scanZipSetting= %3 vsiPrefix= %4" ).arg( mFilePath, name(), scanZipSetting, mVsiPrefix ), 3 );
1410 
1411  // if scanZipBrowser == no: skip to the next file
1412  if ( scanZipSetting == QLatin1String( "no" ) )
1413  {
1414  return mZipFileList;
1415  }
1416 
1417  // get list of files inside zip file
1418  QgsDebugMsgLevel( QString( "Open file %1 with gdal vsi" ).arg( mVsiPrefix + mFilePath ), 3 );
1419  char **papszSiblingFiles = VSIReadDirRecursive1( QString( mVsiPrefix + mFilePath ).toLocal8Bit().constData() );
1420  if ( papszSiblingFiles )
1421  {
1422  for ( int i = 0; i < CSLCount( papszSiblingFiles ); i++ )
1423  {
1424  tmpPath = papszSiblingFiles[i];
1425  QgsDebugMsgLevel( QString( "Read file %1" ).arg( tmpPath ), 3 );
1426  // skip directories (files ending with /)
1427  if ( tmpPath.right( 1 ) != QLatin1String( "/" ) )
1428  mZipFileList << tmpPath;
1429  }
1430  CSLDestroy( papszSiblingFiles );
1431  }
1432  else
1433  {
1434  QgsDebugMsg( QString( "Error reading %1" ).arg( mFilePath ) );
1435  }
1436 
1437  return mZipFileList;
1438 }
A Collection: logical collection of layers or subcollections, e.g.
Definition: qgsdataitem.h:379
QString layerType
Type of URI. Recognized types: "vector" / "raster" / "plugin" / "custom".
static QIcon iconRaster()
Definition: qgsdataitem.cpp:68
void beginInsertItems(QgsDataItem *parent, int first, int last)
QString path() const
Definition: qgsdataitem.h:190
static unsigned index
static QgsProviderRegistry * instance(const QString &pluginPath=QString::null)
Means of accessing canonical single instance.
bool disconnectFrameChanged(const typename QtPrivate::FunctionPointer< Func1 >::Object *receiver, Func1 slot)
Convenience function to disconnect the same style that the frame change connection was established...
QgsFavoritesItem(QgsDataItem *parent, const QString &name, const QString &path=QString())
Constructor for QgsFavoritesItem.
virtual void childrenCreated()
virtual QString layerName() const
Definition: qgsdataitem.h:372
virtual void childrenCreated() override
virtual void refresh()
QString providerKey() const
Returns provider key.
Definition: qgsdataitem.h:333
QgsErrorItem(QgsDataItem *parent, const QString &error, const QString &path)
QString name() const
Definition: qgsdataitem.h:188
void dataChanged(QgsDataItem *item)
static QgsApplication * instance()
Returns the singleton instance of the QgsApplication.
This class is a composition of two QSettings instances:
Definition: qgssettings.h:51
virtual QgsDataItem * createDataItem(const QString &path, QgsDataItem *parentItem)=0
Create a new instance of QgsDataItem (or null) for given path and parent item.
void addDirectory(const QString &directory)
Adds a new directory to the favorites group.
QgsMapLayer::LayerType mapLayerType() const
Returns QgsMapLayer::LayerType.
#define QgsDebugMsg(str)
Definition: qgslogger.h:36
QString mProviderKey
The provider key.
Definition: qgsdataitem.h:353
QString name
Human readable name to be used e.g. in layer tree.
static QString pathComponent(const QString &component)
Create path component replacing path separators.
static QString iconPath(const QString &iconFile)
Returns path to the desired icon file.
virtual QIcon icon()
virtual void setState(State state) override
Set item state.
QString mIconName
Definition: qgsdataitem.h:238
State mState
Definition: qgsdataitem.h:230
static QIcon getThemeIcon(const QString &name)
Helper to get a theme icon.
static QIcon iconLine()
Definition: qgsdataitem.cpp:53
Type type() const
Definition: qgsdataitem.h:177
QStringList supportedFormats
static QIcon iconPoint()
Definition: qgsdataitem.cpp:48
virtual void depopulate()
Remove children recursively and set as not populated. This is used when refreshing collapsed items...
static QIcon iconDefault()
Definition: qgsdataitem.cpp:73
QgsDirectoryItem(QgsDataItem *parent, const QString &name, const QString &path)
char ** VSIReadDirRecursive1(const char *pszPath)
void endRemoveItems()
State state() const
A zip file: contains layers, using GDAL/OGR VSIFILE mechanism.
Definition: qgsdataitem.h:535
virtual bool equal(const QgsDataItem *other)
Returns true if this item is equal to another item (by testing item type and path).
static void deleteLater(QVector< QgsDataItem *> &items)
QString mFilePath
Definition: qgsdataitem.h:540
QgsDataItem * parent() const
Get item parent.
Definition: qgsdataitem.h:181
virtual ~QgsDataItem()
static QIcon iconPolygon()
Definition: qgsdataitem.cpp:58
void beginRemoveItems(QgsDataItem *parent, int first, int last)
#define QgsDebugMsgLevel(str, level)
Definition: qgslogger.h:37
QString mName
Definition: qgsdataitem.h:231
LayerType
Types of layers that can be added to a map.
Definition: qgsmaplayer.h:62
static QIcon iconDir()
Definition: qgsdataitem.cpp:83
QStringList mZipFileList
Definition: qgsdataitem.h:542
QgsDirectoryParamWidget(const QString &path, QWidget *parent=nullptr)
QgsZipItem(QgsDataItem *parent, const QString &name, const QString &path)
static QgsDataItem * itemFromPath(QgsDataItem *parent, const QString &path, const QString &name)
Creates a new data item from the specified path.
Children not yet created.
Definition: qgsdataitem.h:76
Creating children in separate thread (populating or refreshing)
Definition: qgsdataitem.h:77
void updateIcon()
Will request a repaint of this icon.
virtual int capabilities()=0
Return combination of flags from QgsDataProvider::DataCapabilities.
QgsDataCollectionItem(QgsDataItem *parent, const QString &name, const QString &path=QString::null)
bool hasChildren()
static bool hiddenPath(const QString &path)
Check if the given path is hidden from the browser model.
#define cast_to_fptr(f)
Definition: qgis.h:128
virtual bool equal(const QgsDataItem *other) override
Returns true if this item is equal to another item (by testing item type and path).
QgsDataItem(QgsDataItem::Type type, QgsDataItem *parent, const QString &name, const QString &path)
Create new data item.
virtual QIcon icon() override
A directory: contains subdirectories and layers.
Definition: qgsdataitem.h:395
static QStringList sProviderNames
Definition: qgsdataitem.h:553
Base class for all items in the model.
Definition: qgsdataitem.h:46
void mousePressEvent(QMouseEvent *event) override
Capabilities mCapabilities
Definition: qgsdataitem.h:227
virtual void setState(State state)
Set item state.
virtual void addChildItem(QgsDataItem *child, bool refresh=false)
Inserts a new child item.
void setName(const QString &name)
Definition: qgsdataitem.h:189
Can create children. Even items without this capability may have children, but cannot create them...
Definition: qgsdataitem.h:151
QVector< QgsDataItem * > children() const
Definition: qgsdataitem.h:186
QString mPath
Definition: qgsdataitem.h:236
QVector< QgsDataItem * > createChildren() override
Create children.
QString mUri
The URI.
Definition: qgsdataitem.h:355
static QIcon iconZip()
void moveToThread(QThread *targetThread)
Move object and all its descendants to thread.
static QVector< dataItem_t * > sDataItemPtr
Definition: qgsdataitem.h:552
QVector< QgsDataItem * > createChildren() override
Create children.
void removeDirectory(QgsDirectoryItem *item)
Removes an existing directory from the favorites group.
QString mVsiPrefix
Definition: qgsdataitem.h:541
virtual QgsMimeDataUtils::Uri mimeUri() const override
Return mime URI for the data item.
QStringList supportedFormats() const
Returns the supported formats.
Definition: qgsdataitem.h:343
void setParent(QgsDataItem *parent)
Set item parent and connect / disconnect parent to / from item signals.
Animated icon is keeping an animation running if there are listeners connected to frameChanged...
QString uri() const
Returns layer uri or empty string if layer cannot be created.
Definition: qgsdataitem.h:330
QgsDataItem * mParent
Definition: qgsdataitem.h:228
bool deferredDelete()
The item is scheduled to be deleted.
Definition: qgsdataitem.h:224
QString dirPath() const
Definition: qgsdataitem.h:423
QIcon icon() const
Get the icons representation in the current frame.
QVariant value(const QString &key, const QVariant &defaultValue=QVariant(), const Section section=Section::NoSection) const
Returns the value for setting key.
static QIcon iconFavorites()
Icon for favorites group.
Definition: qgsdataitem.cpp:99
QString providerKey
For "vector" / "raster" type: provider id.
void endInsertItems()
QString uri
Identifier of the data source recognized by its providerKey.
virtual QVector< QgsDataItem * > createChildren()
Create children.
static QIcon iconDataCollection()
Definition: qgsdataitem.cpp:78
QVector< QgsDataItem * > createChildren() override
Create children.
Item that represents a layer that can be opened with one of the providers.
Definition: qgsdataitem.h:296
static QIcon iconTable()
Definition: qgsdataitem.cpp:63
QgsProjectItem(QgsDataItem *parent, const QString &name, const QString &path)
A data item holding a reference to a QGIS project file.
static int findItem(QVector< QgsDataItem *> items, QgsDataItem *item)
QgsDataItem * dataItem_t(QString, QgsDataItem *)
Definition: qgsdataitem.h:40
virtual QgsDataItem * removeChildItem(QgsDataItem *child)
Removes a child item and returns it without deleting it.
virtual void deleteChildItem(QgsDataItem *child)
Removes and deletes a child item, emitting relevant signals to the model.
virtual void populate(const QVector< QgsDataItem *> &children)
QgsLayerItem(QgsDataItem *parent, const QString &name, const QString &path, const QString &uri, LayerType layerType, const QString &providerKey)
Data item that can be used to represent QGIS projects.
Definition: qgsdataitem.h:447
Children created.
Definition: qgsdataitem.h:78
LayerType mLayerType
The layer type.
Definition: qgsdataitem.h:357
virtual bool equal(const QgsDataItem *other) override
Returns true if this item is equal to another item (by testing item type and path).
int dataCapabilities_t()
void setValue(const QString &key, const QVariant &value, const Section section=Section::NoSection)
Sets the value of setting key to value.
QVector< QgsDataItem * > mChildren
Definition: qgsdataitem.h:229
QStringList getZipFileList()
virtual void deleteLater()
Safely delete the item:
static QgsDataItemProviderRegistry * dataItemProviderRegistry()
Returns the application&#39;s data item provider registry, which keeps a list of data item providers that...
virtual QWidget * paramWidget() override
CreateChildren() is fast enough to be run in main thread when refreshing items, most root items (wms...
Definition: qgsdataitem.h:152
bool connectFrameChanged(const typename QtPrivate::FunctionPointer< Func1 >::Object *receiver, Func1 slot)
Connect a slot that will be notified repeatedly whenever a frame changes and which should request the...
Represents a favorite item.
Definition: qgsdataitem.h:58
This is the interface for those who want to add custom data items to the browser tree.
QStringList supportedCrs() const
Returns the supported CRS.
Definition: qgsdataitem.h:338
void stateChanged(QgsDataItem *item, QgsDataItem::State oldState)
static QString vsiPrefix(const QString &uri)
Definition: qgsdataitem.h:555
QMap< QString, QIcon > mIconMap
Definition: qgsdataitem.h:240
Added in 2.10.
Definition: qgsdataitem.h:311
virtual Capabilities capabilities2() const
Definition: qgsdataitem.h:163