QGIS API Documentation  2.18.21-Las Palmas (9fba24a)
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 #include <QSettings>
31 
32 #include "qgis.h"
33 #include "qgsdataitem.h"
34 
35 #include "qgsdataitemprovider.h"
37 #include "qgsdataprovider.h"
38 #include "qgslogger.h"
39 #include "qgsproviderregistry.h"
40 #include "qgsconfig.h"
41 
42 // use GDAL VSI mechanism
43 #define CPL_SUPRESS_CPLUSPLUS
44 #include "cpl_vsi.h"
45 #include "cpl_string.h"
46 
48  : QObject()
49  , mCount( 0 )
50  , mMovie( nullptr )
51 {
52  // QApplication as parent to ensure that it is deleted before QApplication
53  mMovie = new QMovie( QApplication::instance() );
54  if ( !iconPath.isEmpty() )
55  {
56  mMovie->setFileName( iconPath );
57  }
58  mMovie->setCacheMode( QMovie::CacheAll );
59  connect( mMovie, SIGNAL( frameChanged( int ) ), SLOT( onFrameChanged() ) );
60 }
61 
63 {
64  return mMovie->fileName();
65 }
66 
68 {
69  mMovie->setFileName( iconPath );
70 }
71 
73 {
74  mIcon = QIcon( mMovie->currentPixmap() );
75  emit frameChanged();
76 }
77 
78 void QgsAnimatedIcon::connectFrameChanged( const QObject * receiver, const char * method )
79 {
80  if ( connect( this, SIGNAL( frameChanged() ), receiver, method ) )
81  {
82  mCount++;
83  }
84  mMovie->setPaused( mCount == 0 );
85  QgsDebugMsgLevel( QString( "mCount = %1" ).arg( mCount ), 3 );
86 }
87 
88 void QgsAnimatedIcon::disconnectFrameChanged( const QObject * receiver, const char * method )
89 {
90  if ( disconnect( this, SIGNAL( frameChanged() ), receiver, method ) )
91  {
92  mCount--;
93  }
94  mMovie->setPaused( mCount == 0 );
95  QgsDebugMsgLevel( QString( "mCount = %1" ).arg( mCount ), 3 );
96 }
97 
98 // shared icons
100 {
101  static QIcon icon;
102 
103  if ( icon.isNull() )
104  icon = QgsApplication::getThemeIcon( "/mIconPointLayer.svg" );
105 
106  return icon;
107 }
108 
110 {
111  static QIcon icon;
112 
113  if ( icon.isNull() )
114  icon = QgsApplication::getThemeIcon( "/mIconLineLayer.svg" );
115 
116  return icon;
117 }
118 
120 {
121  static QIcon icon;
122 
123  if ( icon.isNull() )
124  icon = QgsApplication::getThemeIcon( "/mIconPolygonLayer.svg" );
125 
126  return icon;
127 }
128 
130 {
131  static QIcon icon;
132 
133  if ( icon.isNull() )
134  icon = QgsApplication::getThemeIcon( "/mIconTableLayer.svg" );
135 
136  return icon;
137 }
138 
140 {
141  static QIcon icon;
142 
143  if ( icon.isNull() )
144  icon = QgsApplication::getThemeIcon( "/mIconRaster.svg" );
145 
146  return icon;
147 }
148 
150 {
151  static QIcon icon;
152 
153  if ( icon.isNull() )
154  icon = QgsApplication::getThemeIcon( "/mIconLayer.png" );
155 
156  return icon;
157 }
158 
160 {
161  static QIcon icon;
162 
163  if ( icon.isNull() )
164  icon = QgsApplication::getThemeIcon( "/mIconDbSchema.png" );
165 
166  return icon;
167 }
168 
170 {
171  static QIcon icon;
172 
173  if ( icon.isNull() )
174  {
175  // initialize shared icons
176  QStyle *style = QApplication::style();
177  icon = QIcon( style->standardPixmap( QStyle::SP_DirClosedIcon ) );
178  icon.addPixmap( style->standardPixmap( QStyle::SP_DirOpenIcon ),
179  QIcon::Normal, QIcon::On );
180  }
181 
182  return icon;
183 }
184 
186 {
187  static QIcon icon;
188 
189  if ( icon.isNull() )
190  icon = QgsApplication::getThemeIcon( "/mIconFavourites.png" );
191 
192  return icon;
193 }
194 
196 {
197  static QIcon icon;
198 
199  if ( icon.isNull() )
200  icon = QgsApplication::getThemeIcon( "/mIconZip.png" );
201 // icon from http://www.softicons.com/free-icons/application-icons/mega-pack-icons-1-by-nikolay-verin/winzip-folder-icon
202 
203  return icon;
204 }
205 
206 QgsAnimatedIcon * QgsDataItem::mPopulatingIcon = nullptr;
207 
209 // Do not pass parent to QObject, Qt would delete this when parent is deleted
210  : QObject()
211  , mType( type )
212  , mCapabilities( NoCapabilities )
213  , mParent( parent )
214  , mState( NotPopulated )
215  , mPopulated( false )
216  , mName( name )
217  , mPath( path )
218  , mDeferredDelete( false )
219  , mFutureWatcher( nullptr )
220 {
221 }
222 
224 {
225  QgsDebugMsgLevel( QString( "mName = %1 mPath = %2 mChildren.size() = %3" ).arg( mName, mPath ).arg( mChildren.size() ), 2 );
226  Q_FOREACH ( QgsDataItem *child, mChildren )
227  {
228  if ( !child ) // should not happen
229  continue;
230  child->deleteLater();
231  }
232  mChildren.clear();
233 
234  if ( mFutureWatcher && !mFutureWatcher->isFinished() )
235  {
236  // this should not usually happen (until the item was deleted directly when createChildren was running)
237  QgsDebugMsg( "mFutureWatcher not finished (should not happen) -> waitForFinished()" );
238  mDeferredDelete = true;
239  mFutureWatcher->waitForFinished();
240  }
241 
242  delete mFutureWatcher;
243 }
244 
246 {
247  return QString( string ).replace( QRegExp( "[\\\\/]" ), "|" );
248 }
249 
251 {
252  QgsDebugMsgLevel( "path = " + path(), 3 );
253  setParent( nullptr ); // also disconnects parent
254  Q_FOREACH ( QgsDataItem *child, mChildren )
255  {
256  if ( !child ) // should not happen
257  continue;
258  child->deleteLater();
259  }
260  mChildren.clear();
261 
262  if ( mFutureWatcher && !mFutureWatcher->isFinished() )
263  {
264  QgsDebugMsg( "mFutureWatcher not finished -> schedule to delete later" );
265  mDeferredDelete = true;
266  }
267  else
268  {
270  }
271 }
272 
274 {
275  Q_FOREACH ( QgsDataItem *item, items )
276  {
277  if ( !item ) // should not happen
278  continue;
279  item->deleteLater();
280  }
281  items.clear();
282 }
283 
284 void QgsDataItem::moveToThread( QThread * targetThread )
285 {
286  // QObject::moveToThread() cannot move objects with parent, but QgsDataItem is not using paren/children from QObject
287  Q_FOREACH ( QgsDataItem* child, mChildren )
288  {
289  if ( !child ) // should not happen
290  continue;
291  QgsDebugMsgLevel( "moveToThread child " + child->path(), 3 );
292  child->QObject::setParent( nullptr ); // to be sure
293  child->moveToThread( targetThread );
294  }
295  QObject::moveToThread( targetThread );
296 }
297 
299 {
300  if ( state() == Populating && mPopulatingIcon )
301  return mPopulatingIcon->icon();
302 
303  if ( !mIcon.isNull() )
304  return mIcon;
305 
306  if ( !mIconMap.contains( mIconName ) )
307  {
309  }
310 
311  return mIconMap.value( mIconName );
312 }
313 
315 {
316  emit beginInsertItems( parent, first, last );
317 }
319 {
320  emit endInsertItems();
321 }
323 {
324  emit beginRemoveItems( parent, first, last );
325 }
327 {
328  emit endRemoveItems();
329 }
330 
332 {
333  emit dataChanged( item );
334 }
335 
337 {
338  emit dataChanged( this );
339 }
340 
342 {
343  if ( !item )
344  return;
345  QgsDebugMsgLevel( QString( "item %1 state changed %2 -> %3" ).arg( item->path() ).arg( oldState ).arg( item->state() ), 2 );
346  emit stateChanged( item, oldState );
347 }
348 
350 {
351  return QVector<QgsDataItem*>();
352 }
353 
354 void QgsDataItem::populate( bool foreground )
355 {
356  if ( state() == Populated || state() == Populating )
357  return;
358 
359  QgsDebugMsgLevel( "mPath = " + mPath, 2 );
360 
361  if ( capabilities2() & QgsDataItem::Fast || foreground )
362  {
364  }
365  else
366  {
367  setState( Populating );
368  // 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.
369  if ( !mFutureWatcher )
370  {
371  mFutureWatcher = new QFutureWatcher< QVector <QgsDataItem*> >( this );
372  }
373  connect( mFutureWatcher, SIGNAL( finished() ), SLOT( childrenCreated() ) );
374  mFutureWatcher->setFuture( QtConcurrent::run( runCreateChildren, this ) );
375  }
376 }
377 
378 // This is expected to be run in a separate thread
379 QVector<QgsDataItem*> QgsDataItem::runCreateChildren( QgsDataItem* item )
380 {
381  QgsDebugMsgLevel( "path = " + item->path(), 2 );
382  QTime time;
383  time.start();
385  QgsDebugMsgLevel( QString( "%1 children created in %2 ms" ).arg( children.size() ).arg( time.elapsed() ), 3 );
386  // Children objects must be pushed to main thread.
387  Q_FOREACH ( QgsDataItem* child, children )
388  {
389  if ( !child ) // should not happen
390  continue;
391  QgsDebugMsgLevel( "moveToThread child " + child->path(), 2 );
392  if ( qApp )
393  child->moveToThread( qApp->thread() ); // moves also children
394  }
395  QgsDebugMsgLevel( QString( "finished path %1: %2 children" ).arg( item->path() ).arg( children.size() ), 3 );
396  return children;
397 }
398 
400 {
401  QgsDebugMsgLevel( QString( "path = %1 children.size() = %2" ).arg( path() ).arg( mFutureWatcher->result().size() ), 3 );
402 
403  if ( deferredDelete() )
404  {
405  QgsDebugMsg( "Item was scheduled to be deleted later" );
407  return;
408  }
409 
410  if ( mChildren.isEmpty() ) // usually populating but may also be refresh if originaly there were no children
411  {
412  populate( mFutureWatcher->result() );
413  }
414  else // refreshing
415  {
416  refresh( mFutureWatcher->result() );
417  }
418  disconnect( mFutureWatcher, SIGNAL( finished() ), this, SLOT( childrenCreated() ) );
419  emit dataChanged( this ); // to replace loading icon by normal icon
420 }
421 
423 {
424  QgsDebugMsgLevel( "mPath = " + mPath, 3 );
425 
426  Q_FOREACH ( QgsDataItem *child, children )
427  {
428  if ( !child ) // should not happen
429  continue;
430  // update after thread finished -> refresh
431  addChildItem( child, true );
432  }
433  setState( Populated );
434 }
435 
437 {
438  QgsDebugMsgLevel( "mPath = " + mPath, 3 );
439 
440  Q_FOREACH ( QgsDataItem *child, mChildren )
441  {
442  QgsDebugMsgLevel( "remove " + child->path(), 3 );
443  child->depopulate(); // recursive
444  deleteChildItem( child );
445  }
447 }
448 
450 {
451  if ( state() == Populating )
452  return;
453 
454  QgsDebugMsgLevel( "mPath = " + mPath, 3 );
455 
457  {
458  refresh( createChildren() );
459  }
460  else
461  {
462  setState( Populating );
463  if ( !mFutureWatcher )
464  {
465  mFutureWatcher = new QFutureWatcher< QVector <QgsDataItem*> >( this );
466  }
467  connect( mFutureWatcher, SIGNAL( finished() ), SLOT( childrenCreated() ) );
468  mFutureWatcher->setFuture( QtConcurrent::run( runCreateChildren, this ) );
469  }
470 }
471 
473 {
474  QgsDebugMsgLevel( "mPath = " + mPath, 2 );
475 
476  // Remove no more present children
477  QVector<QgsDataItem*> remove;
478  Q_FOREACH ( QgsDataItem *child, mChildren )
479  {
480  if ( !child ) // should not happen
481  continue;
482  if ( findItem( children, child ) >= 0 )
483  continue;
484  remove.append( child );
485  }
486  Q_FOREACH ( QgsDataItem *child, remove )
487  {
488  QgsDebugMsgLevel( "remove " + child->path(), 3 );
489  deleteChildItem( child );
490  }
491 
492  // Add new children
493  Q_FOREACH ( QgsDataItem *child, children )
494  {
495  if ( !child ) // should not happen
496  continue;
497 
498  int index = findItem( mChildren, child );
499  if ( index >= 0 )
500  {
501  // Refresh recursively (some providers may create more generations of descendants)
502  if ( !( child->capabilities2() & QgsDataItem::Fertile ) )
503  {
504  // The child cannot createChildren() itself
505  mChildren.value( index )->refresh( child->children() );
506  }
507 
508  child->deleteLater();
509  continue;
510  }
511  addChildItem( child, true );
512  }
513  setState( Populated );
514 }
515 
517 {
518  return mChildren.size();
519 }
521 {
522  return ( state() == Populated ? !mChildren.isEmpty() : true );
523 }
524 
526 {
527  if ( mParent )
528  {
529  disconnect( this, nullptr, mParent, nullptr );
530  }
531  if ( parent )
532  {
533  connect( this, SIGNAL( beginInsertItems( QgsDataItem*, int, int ) ),
534  parent, SLOT( emitBeginInsertItems( QgsDataItem*, int, int ) ) );
535  connect( this, SIGNAL( endInsertItems() ),
536  parent, SLOT( emitEndInsertItems() ) );
537  connect( this, SIGNAL( beginRemoveItems( QgsDataItem*, int, int ) ),
538  parent, SLOT( emitBeginRemoveItems( QgsDataItem*, int, int ) ) );
539  connect( this, SIGNAL( endRemoveItems() ),
540  parent, SLOT( emitEndRemoveItems() ) );
541  connect( this, SIGNAL( dataChanged( QgsDataItem* ) ),
542  parent, SLOT( emitDataChanged( QgsDataItem* ) ) );
543  connect( this, SIGNAL( stateChanged( QgsDataItem*, QgsDataItem::State ) ),
544  parent, SLOT( emitStateChanged( QgsDataItem*, QgsDataItem::State ) ) );
545  }
546  mParent = parent;
547 }
548 
550 {
551  Q_ASSERT( child );
552  QgsDebugMsgLevel( QString( "path = %1 add child #%2 - %3 - %4" ).arg( mPath ).arg( mChildren.size() ).arg( child->mName ).arg( child->mType ), 3 );
553 
554  //calculate position to insert child
555  int i;
556  if ( type() == Directory )
557  {
558  for ( i = 0; i < mChildren.size(); i++ )
559  {
560  // sort items by type, so directories are before data items
561  if ( mChildren.at( i )->mType == child->mType &&
562  mChildren.at( i )->mName.localeAwareCompare( child->mName ) > 0 )
563  break;
564  }
565  }
566  else
567  {
568  for ( i = 0; i < mChildren.size(); i++ )
569  {
570  if ( mChildren.at( i )->mName.localeAwareCompare( child->mName ) >= 0 )
571  break;
572  }
573  }
574 
575  if ( refresh )
576  emit beginInsertItems( this, i, i );
577 
578  mChildren.insert( i, child );
579  child->setParent( this );
580 
581  if ( refresh )
582  emit endInsertItems();
583 }
584 
586 {
587  QgsDebugMsgLevel( "mName = " + child->mName, 2 );
588  int i = mChildren.indexOf( child );
589  Q_ASSERT( i >= 0 );
590  emit beginRemoveItems( this, i, i );
591  mChildren.remove( i );
592  child->deleteLater();
593  emit endRemoveItems();
594 }
595 
597 {
598  QgsDebugMsgLevel( "mName = " + child->mName, 2 );
599  int i = mChildren.indexOf( child );
600  Q_ASSERT( i >= 0 );
601  if ( i < 0 )
602  {
603  child->setParent( nullptr );
604  return nullptr;
605  }
606 
607  emit beginRemoveItems( this, i, i );
608  mChildren.remove( i );
609  emit endRemoveItems();
610  return child;
611 }
612 
614 {
615  for ( int i = 0; i < items.size(); i++ )
616  {
617  Q_ASSERT_X( items[i], "findItem", QString( "item %1 is nullptr" ).arg( i ).toAscii() );
618  QgsDebugMsgLevel( QString::number( i ) + " : " + items[i]->mPath + " x " + item->mPath, 2 );
619  if ( items[i]->equal( item ) )
620  return i;
621  }
622  return -1;
623 }
624 
625 bool QgsDataItem::equal( const QgsDataItem *other )
626 {
627  if ( metaObject()->className() == other->metaObject()->className() &&
628  mPath == other->path() )
629  {
630  return true;
631  }
632  return false;
633 }
634 
636 {
637  // for backward compatibility (if subclass set mPopulated directly)
638  // TODO: remove in 3.0
639  if ( mPopulated )
640  return Populated;
641  return mState;
642 }
643 
645 {
646  QgsDebugMsgLevel( QString( "item %1 set state %2 -> %3" ).arg( path() ).arg( this->state() ).arg( state ), 3 );
647  if ( state == mState )
648  return;
649 
650  State oldState = mState;
651 
652  if ( state == Populating ) // start loading
653  {
654  if ( !mPopulatingIcon )
655  {
656  // TODO: ensure that QgsAnimatedIcon is created on UI thread only
657  mPopulatingIcon = new QgsAnimatedIcon( QgsApplication::iconPath( "/mIconLoading.gif" ) );
658  }
659  mPopulatingIcon->connectFrameChanged( this, SLOT( emitDataChanged() ) );
660  }
661  else if ( mState == Populating && mPopulatingIcon ) // stop loading
662  {
663  mPopulatingIcon->disconnectFrameChanged( this, SLOT( emitDataChanged() ) );
664  }
665 
666  mState = state;
667  // for backward compatibility (if subclass access mPopulated directly)
668  // TODO: remove in 3.0
669  mPopulated = state == Populated;
670 
671  emit stateChanged( this, oldState );
672  if ( state == Populated )
673  emitDataChanged();
674 }
675 
676 // ---------------------------------------------------------------------
677 
678 QgsLayerItem::QgsLayerItem( QgsDataItem* parent, const QString& name, const QString& path, const QString& uri, LayerType layerType, const QString& providerKey )
679  : QgsDataItem( Layer, parent, name, path )
680  , mProviderKey( providerKey )
681  , mUri( uri )
682  , mLayerType( layerType )
683 {
684  switch ( layerType )
685  {
686  case Point:
687  mIconName = "/mIconPointLayer.svg";
688  break;
689  case Line:
690  mIconName = "/mIconLineLayer.svg";
691  break;
692  case Polygon:
693  mIconName = "/mIconPolygonLayer.svg";
694  break;
695  // TODO add a new icon for generic Vector layers
696  case Vector :
697  mIconName = "/mIconPolygonLayer.svg";
698  break;
699  case TableLayer:
700  mIconName = "/mIconTableLayer.svg";
701  break;
702  case Raster:
703  mIconName = "/mIconRaster.svg";
704  break;
705  default:
706  mIconName = "/mIconLayer.png";
707  break;
708  }
709 }
710 
712 {
718 }
719 
720 bool QgsLayerItem::equal( const QgsDataItem *other )
721 {
722  //QgsDebugMsg ( mPath + " x " + other->mPath );
723  if ( type() != other->type() )
724  {
725  return false;
726  }
727  //const QgsLayerItem *o = qobject_cast<const QgsLayerItem *> ( other );
728  const QgsLayerItem *o = dynamic_cast<const QgsLayerItem *>( other );
729  if ( !o )
730  return false;
731 
732  return ( mPath == o->mPath && mName == o->mName && mUri == o->mUri && mProviderKey == o->mProviderKey );
733 }
734 
735 // ---------------------------------------------------------------------
737  : QgsDataItem( Collection, parent, name, path )
738 {
740  mIconName = "/mIconDbSchema.png";
741 }
742 
744 {
745  QgsDebugMsgLevel( "mName = " + mName + " mPath = " + mPath, 2 );
746 
747 // Do not delete children, children are deleted by QObject parent
748 #if 0
749  Q_FOREACH ( QgsDataItem* i, mChildren )
750  {
751  QgsDebugMsgLevel( QString( "delete child = 0x%0" ).arg(( qlonglong )i, 8, 16, QLatin1Char( '0' ) ), 2 );
752  delete i;
753  }
754 #endif
755 }
756 
757 //-----------------------------------------------------------------------
758 // QVector<QgsDataProvider*> QgsDirectoryItem::mProviders = QVector<QgsDataProvider*>();
762 
764  : QgsDataCollectionItem( parent, name, path )
765  , mDirPath( path )
766  , mFileSystemWatcher( nullptr )
767  , mRefreshLater( false )
768 {
769  mType = Directory;
770  init();
771 }
772 
774  : QgsDataCollectionItem( parent, name, path )
775  , mDirPath( dirPath )
776  , mFileSystemWatcher( nullptr )
777  , mRefreshLater( false )
778 {
779  mType = Directory;
780  init();
781 }
782 
784 {
785 }
786 
788 {
789 }
790 
792 {
793  if ( state() == Populating )
794  return QgsDataItem::icon();
795  return iconDir();
796 }
797 
798 
800 {
802  QDir dir( mDirPath );
803 
804  QStringList entries = dir.entryList( QDir::AllDirs | QDir::NoDotAndDotDot, QDir::Name | QDir::IgnoreCase );
805  Q_FOREACH ( const QString& subdir, entries )
806  {
807  if ( mRefreshLater )
808  {
809  deleteLater( children );
810  return children;
811  }
812 
813  QString subdirPath = dir.absoluteFilePath( subdir );
814 
815  QgsDebugMsgLevel( QString( "creating subdir: %1" ).arg( subdirPath ), 2 );
816 
817  QString path = mPath + '/' + subdir; // may differ from subdirPath
818  if ( QgsDirectoryItem::hiddenPath( path ) )
819  continue;
820  QgsDirectoryItem *item = new QgsDirectoryItem( this, subdir, subdirPath, path );
821  // propagate signals up to top
822 
823  children.append( item );
824  }
825 
826  QStringList fileEntries = dir.entryList( QDir::Dirs | QDir::NoDotAndDotDot | QDir::Files, QDir::Name );
827  Q_FOREACH ( const QString& name, fileEntries )
828  {
829  if ( mRefreshLater )
830  {
831  deleteLater( children );
832  return children;
833  }
834 
835  QString path = dir.absoluteFilePath( name );
836  QFileInfo fileInfo( path );
837 
838  if ( fileInfo.suffix() == "qgs" )
839  {
840  QgsDataItem * item = new QgsProjectItem( this, name, path );
841  children.append( item );
842  continue;
843  }
844 
845  // vsizip support was added to GDAL/OGR 1.6 but GDAL_VERSION_NUM not available here
846  // so we assume it's available anyway
847  {
848  QgsDataItem * item = QgsZipItem::itemFromPath( this, path, name, mPath + '/' + name );
849  if ( item )
850  {
851  children.append( item );
852  continue;
853  }
854  }
855 
856  Q_FOREACH ( QgsDataItemProvider* provider, QgsDataItemProviderRegistry::instance()->providers() )
857  {
858  int capabilities = provider->capabilities();
859 
860  if ( !(( fileInfo.isFile() && ( capabilities & QgsDataProvider::File ) ) ||
861  ( fileInfo.isDir() && ( capabilities & QgsDataProvider::Dir ) ) ) )
862  {
863  continue;
864  }
865 
866  QgsDataItem * item = provider->createDataItem( path, this );
867  if ( item )
868  {
869  children.append( item );
870  }
871  }
872 
873  }
874 
875  return children;
876 }
877 
879 {
881 
882  if ( state == Populated )
883  {
884  if ( !mFileSystemWatcher )
885  {
886  mFileSystemWatcher = new QFileSystemWatcher( this );
887  mFileSystemWatcher->addPath( mDirPath );
888  connect( mFileSystemWatcher, SIGNAL( directoryChanged( const QString & ) ), SLOT( directoryChanged() ) );
889  }
890  }
891  else if ( state == NotPopulated )
892  {
893  if ( mFileSystemWatcher )
894  {
895  delete mFileSystemWatcher;
896  mFileSystemWatcher = nullptr;
897  }
898  }
899 }
900 
902 {
903  if ( state() == Populating )
904  {
905  // schedule to refresh later, because refres() simply returns if Populating
906  mRefreshLater = true;
907  }
908  else
909  {
910  refresh();
911  }
912 }
913 
915 {
916  QSettings settings;
917  QStringList hiddenItems = settings.value( "/browser/hiddenPaths",
919  int idx = hiddenItems.indexOf( path );
920  return ( idx > -1 );
921 }
922 
924 {
925  QgsDebugMsgLevel( QString( "mRefreshLater = %1" ).arg( mRefreshLater ), 3 );
926 
927  if ( mRefreshLater )
928  {
929  QgsDebugMsgLevel( "directory changed during createChidren() -> refresh() again", 3 );
930  mRefreshLater = false;
931  setState( Populated );
932  refresh();
933  }
934  else
935  {
937  }
938 }
939 
941 {
942  //QgsDebugMsg ( mPath + " x " + other->mPath );
943  if ( type() != other->type() )
944  {
945  return false;
946  }
947  return ( path() == other->path() );
948 }
949 
951 {
952  return new QgsDirectoryParamWidget( mPath );
953 }
954 
956  : QTreeWidget( parent )
957 {
958  setRootIsDecorated( false );
959 
960  // name, size, date, permissions, owner, group, type
961  setColumnCount( 7 );
962  QStringList labels;
963  labels << tr( "Name" ) << tr( "Size" ) << tr( "Date" ) << tr( "Permissions" ) << tr( "Owner" ) << tr( "Group" ) << tr( "Type" );
964  setHeaderLabels( labels );
965 
967  QIcon iconDirectory = QIcon( style->standardPixmap( QStyle::SP_DirClosedIcon ) );
968  QIcon iconFile = QIcon( style->standardPixmap( QStyle::SP_FileIcon ) );
969  QIcon iconDirLink = QIcon( style->standardPixmap( QStyle::SP_DirLinkIcon ) );
970  QIcon iconFileLink = QIcon( style->standardPixmap( QStyle::SP_FileLinkIcon ) );
971 
973 
974  QDir dir( path );
975  QStringList entries = dir.entryList( QDir::AllEntries | QDir::NoDotAndDotDot, QDir::Name | QDir::IgnoreCase );
976  Q_FOREACH ( const QString& name, entries )
977  {
978  QFileInfo fi( dir.absoluteFilePath( name ) );
979  QStringList texts;
980  texts << name;
981  QString size;
982  if ( fi.size() > 1024 )
983  {
984  size = size.sprintf( "%.1f KiB", fi.size() / 1024.0 );
985  }
986  else if ( fi.size() > 1.048576e6 )
987  {
988  size = size.sprintf( "%.1f MiB", fi.size() / 1.048576e6 );
989  }
990  else
991  {
992  size = QString( "%1 B" ).arg( fi.size() );
993  }
994  texts << size;
995  texts << fi.lastModified().toString( Qt::SystemLocaleShortDate );
996  QString perm;
997  perm += fi.permission( QFile::ReadOwner ) ? 'r' : '-';
998  perm += fi.permission( QFile::WriteOwner ) ? 'w' : '-';
999  perm += fi.permission( QFile::ExeOwner ) ? 'x' : '-';
1000  // QFile::ReadUser, QFile::WriteUser, QFile::ExeUser
1001  perm += fi.permission( QFile::ReadGroup ) ? 'r' : '-';
1002  perm += fi.permission( QFile::WriteGroup ) ? 'w' : '-';
1003  perm += fi.permission( QFile::ExeGroup ) ? 'x' : '-';
1004  perm += fi.permission( QFile::ReadOther ) ? 'r' : '-';
1005  perm += fi.permission( QFile::WriteOther ) ? 'w' : '-';
1006  perm += fi.permission( QFile::ExeOther ) ? 'x' : '-';
1007  texts << perm;
1008 
1009  texts << fi.owner();
1010  texts << fi.group();
1011 
1012  QString type;
1013  QIcon icon;
1014  if ( fi.isDir() && fi.isSymLink() )
1015  {
1016  type = tr( "folder" );
1017  icon = iconDirLink;
1018  }
1019  else if ( fi.isDir() )
1020  {
1021  type = tr( "folder" );
1022  icon = iconDirectory;
1023  }
1024  else if ( fi.isFile() && fi.isSymLink() )
1025  {
1026  type = tr( "file" );
1027  icon = iconFileLink;
1028  }
1029  else if ( fi.isFile() )
1030  {
1031  type = tr( "file" );
1032  icon = iconFile;
1033  }
1034 
1035  texts << type;
1036 
1037  QTreeWidgetItem *item = new QTreeWidgetItem( texts );
1038  item->setIcon( 0, icon );
1039  items << item;
1040  }
1041 
1042  addTopLevelItems( items );
1043 
1044  // hide columns that are not requested
1045  QSettings settings;
1046  QList<QVariant> lst = settings.value( "/dataitem/directoryHiddenColumns" ).toList();
1047  Q_FOREACH ( const QVariant& colVariant, lst )
1048  {
1049  setColumnHidden( colVariant.toInt(), true );
1050  }
1051 }
1052 
1054 {
1055  if ( event->button() == Qt::RightButton )
1056  {
1057  // show the popup menu
1058  QMenu popupMenu;
1059 
1060  QStringList labels;
1061  labels << tr( "Name" ) << tr( "Size" ) << tr( "Date" ) << tr( "Permissions" ) << tr( "Owner" ) << tr( "Group" ) << tr( "Type" );
1062  for ( int i = 0; i < labels.count(); i++ )
1063  {
1064  QAction* action = popupMenu.addAction( labels[i], this, SLOT( showHideColumn() ) );
1065  action->setObjectName( QString::number( i ) );
1066  action->setCheckable( true );
1067  action->setChecked( !isColumnHidden( i ) );
1068  }
1069 
1070  popupMenu.exec( event->globalPos() );
1071  }
1072 }
1073 
1075 {
1076  QAction* action = qobject_cast<QAction*>( sender() );
1077  if ( !action )
1078  return; // something is wrong
1079 
1080  int columnIndex = action->objectName().toInt();
1081  setColumnHidden( columnIndex, !isColumnHidden( columnIndex ) );
1082 
1083  // save in settings
1084  QSettings settings;
1085  QList<QVariant> lst;
1086  for ( int i = 0; i < columnCount(); i++ )
1087  {
1088  if ( isColumnHidden( i ) )
1089  lst.append( QVariant( i ) );
1090  }
1091  settings.setValue( "/dataitem/directoryHiddenColumns", lst );
1092 }
1093 
1095  : QgsDataItem( QgsDataItem::Project, parent, name, path )
1096 {
1097  mIconName = ":/images/icons/qgis-icon-16x16.png";
1098 
1099  setState( Populated ); // no more children
1100 }
1101 
1103 {
1104 }
1105 
1107  : QgsDataItem( QgsDataItem::Error, parent, error, path )
1108 {
1109  mIconName = "/mIconDelete.png";
1110 
1111  setState( Populated ); // no more children
1112 }
1113 
1115 {
1116 }
1117 
1119  : QgsDataCollectionItem( parent, name, "favourites:" )
1120 {
1121  Q_UNUSED( path );
1122  mCapabilities |= Fast;
1123  mType = Favourites;
1124  mIconName = "/mIconFavourites.png";
1125  populate();
1126 }
1127 
1129 {
1130 }
1131 
1133 {
1135 
1136  QSettings settings;
1137  QStringList favDirs = settings.value( "/browser/favourites", QVariant() ).toStringList();
1138 
1139  Q_FOREACH ( const QString& favDir, favDirs )
1140  {
1141  children << createChildren( favDir );
1142  }
1143 
1144  return children;
1145 }
1146 
1148 {
1149  QSettings settings;
1150  QStringList favDirs = settings.value( "/browser/favourites" ).toStringList();
1151  favDirs.append( favDir );
1152  settings.setValue( "/browser/favourites", favDirs );
1153 
1154  if ( state() == Populated )
1155  {
1156  QVector<QgsDataItem*> items = createChildren( favDir );
1157  Q_FOREACH ( QgsDataItem* item, items )
1158  {
1159  addChildItem( item, true );
1160  }
1161  }
1162 }
1163 
1165 {
1166  if ( !item )
1167  return;
1168 
1169  QSettings settings;
1170  QStringList favDirs = settings.value( "/browser/favourites" ).toStringList();
1171  favDirs.removeAll( item->dirPath() );
1172  settings.setValue( "/browser/favourites", favDirs );
1173 
1174  int idx = findItem( mChildren, item );
1175  if ( idx < 0 )
1176  {
1177  QgsDebugMsg( QString( "favourites item %1 not found" ).arg( item->path() ) );
1178  return;
1179  }
1180 
1181  if ( state() == Populated )
1182  deleteChildItem( mChildren.at( idx ) );
1183 }
1184 
1186 {
1188  QString pathName = pathComponent( favDir );
1189  Q_FOREACH ( QgsDataItemProvider* provider, QgsDataItemProviderRegistry::instance()->providers() )
1190  {
1191  int capabilities = provider->capabilities();
1192 
1193  if ( capabilities & QgsDataProvider::Dir )
1194  {
1195  QgsDataItem * item = provider->createDataItem( favDir, this );
1196  if ( item )
1197  {
1198  item->setName( favDir );
1199  children.append( item );
1200  }
1201  }
1202  }
1203  if ( children.isEmpty() )
1204  {
1205  QgsDataItem *item = new QgsDirectoryItem( this, favDir, favDir, mPath + '/' + pathName );
1206  if ( item )
1207  {
1208  children.append( item );
1209  }
1210  }
1211  return children;
1212 }
1213 
1214 //-----------------------------------------------------------------------
1217 
1218 
1220  : QgsDataCollectionItem( parent, name, path )
1221 {
1222  mFilePath = path;
1223  init();
1224 }
1225 
1227  : QgsDataCollectionItem( parent, name, path )
1228  , mFilePath( filePath )
1229 {
1230  init();
1231 }
1232 
1233 void QgsZipItem::init()
1234 {
1235  mType = Collection; //Zip??
1236  mIconName = "/mIconZip.png";
1238 
1239  if ( mProviderNames.isEmpty() )
1240  {
1241  // QStringList keys = QgsProviderRegistry::instance()->providerList();
1242  // only use GDAL and OGR providers as we use the VSIFILE mechanism
1243  QStringList keys;
1244  // keys << "ogr" << "gdal";
1245  keys << "gdal" << "ogr";
1246 
1248  for ( i = keys.begin(); i != keys.end(); ++i )
1249  {
1250  QString k( *i );
1251  QgsDebugMsgLevel( "provider " + k, 3 );
1252  // some providers hangs with empty uri (Postgis) etc...
1253  // -> using libraries directly
1255  if ( library )
1256  {
1257  dataCapabilities_t * dataCapabilities = reinterpret_cast< dataCapabilities_t * >( cast_to_fptr( library->resolve( "dataCapabilities" ) ) );
1258  if ( !dataCapabilities )
1259  {
1260  QgsDebugMsg( library->fileName() + " does not have dataCapabilities" );
1261  continue;
1262  }
1263  if ( dataCapabilities() == QgsDataProvider::NoDataCapabilities )
1264  {
1265  QgsDebugMsg( library->fileName() + " has NoDataCapabilities" );
1266  continue;
1267  }
1268  QgsDebugMsg( QString( "%1 dataCapabilities : %2" ).arg( library->fileName() ).arg( dataCapabilities() ) );
1269 
1270  dataItem_t * dataItem = reinterpret_cast< dataItem_t * >( cast_to_fptr( library->resolve( "dataItem" ) ) );
1271  if ( ! dataItem )
1272  {
1273  QgsDebugMsg( library->fileName() + " does not have dataItem" );
1274  continue;
1275  }
1276 
1277  // mLibraries.append( library );
1278  mDataItemPtr.append( dataItem );
1279  mProviderNames.append( k );
1280  }
1281  else
1282  {
1283  //QgsDebugMsg ( "Cannot get provider " + k );
1284  }
1285  }
1286  }
1287 
1288 }
1289 
1291 {
1292 }
1293 
1294 // internal function to scan a vsidir (zip or tar file) recursively
1295 // GDAL trunk has this since r24423 (05/16/12) - VSIReadDirRecursive()
1296 // use a copy of the function internally for now,
1297 // but use char ** and CSLAddString, because CPLStringList was added in gdal-1.9
1298 char **VSIReadDirRecursive1( const char *pszPath )
1299 {
1300  // CPLStringList oFiles = nullptr;
1301  char **papszOFiles = nullptr;
1302  char **papszFiles1 = nullptr;
1303  char **papszFiles2 = nullptr;
1304  VSIStatBufL psStatBuf;
1305  QString temp1, temp2;
1306  int i, j;
1307  int nCount1, nCount2;
1308 
1309  // get listing
1310  papszFiles1 = VSIReadDir( pszPath );
1311  if ( ! papszFiles1 )
1312  return nullptr;
1313 
1314  // get files and directories inside listing
1315  nCount1 = CSLCount( papszFiles1 );
1316  for ( i = 0; i < nCount1; i++ )
1317  {
1318  // build complete file name for stat
1319  temp1 = QString( "%1/%2" ).arg( pszPath, papszFiles1[i] );
1320 
1321  // if is file, add it
1322  if ( VSIStatL( temp1.toUtf8(), &psStatBuf ) == 0 &&
1323  VSI_ISREG( psStatBuf.st_mode ) )
1324  {
1325  // oFiles.AddString( papszFiles1[i] );
1326  papszOFiles = CSLAddString( papszOFiles, papszFiles1[i] );
1327  }
1328  else if ( VSIStatL( temp1.toUtf8(), &psStatBuf ) == 0 &&
1329  VSI_ISDIR( psStatBuf.st_mode ) )
1330  {
1331  // add directory entry
1332  temp2 = QString( "%1/" ).arg( papszFiles1[i] );
1333 
1334  // oFiles.AddString( temp2.toUtf8() );
1335  papszOFiles = CSLAddString( papszOFiles, temp2.toUtf8() );
1336 
1337  // recursively add files inside directory
1338  papszFiles2 = VSIReadDirRecursive1( temp1.toUtf8() );
1339  if ( papszFiles2 )
1340  {
1341  nCount2 = CSLCount( papszFiles2 );
1342  for ( j = 0; j < nCount2; j++ )
1343  {
1344  temp2 = QString( "%1/%2" ).arg( papszFiles1[i], papszFiles2[j] );
1345 
1346  // oFiles.AddString( temp2.toUtf8() );
1347  papszOFiles = CSLAddString( papszOFiles, temp2.toUtf8() );
1348  }
1349  CSLDestroy( papszFiles2 );
1350  }
1351  }
1352  }
1353  CSLDestroy( papszFiles1 );
1354 
1355  // return oFiles.StealList();
1356  return papszOFiles;
1357 }
1358 
1360 {
1362  QString tmpPath;
1363  QSettings settings;
1364  QString scanZipSetting = settings.value( "/qgis/scanZipInBrowser2", "basic" ).toString();
1365 
1366  mZipFileList.clear();
1367 
1368  QgsDebugMsgLevel( QString( "mFilePath = %1 path = %2 name= %3 scanZipSetting= %4 vsiPrefix= %5" ).arg( mFilePath, path(), name(), scanZipSetting, mVsiPrefix ), 2 );
1369 
1370  // if scanZipBrowser == no: skip to the next file
1371  if ( scanZipSetting == "no" )
1372  {
1373  return children;
1374  }
1375 
1376  // first get list of files
1377  getZipFileList();
1378 
1379  // loop over files inside zip
1380  Q_FOREACH ( const QString& fileName, mZipFileList )
1381  {
1382  QFileInfo info( fileName );
1383  tmpPath = mVsiPrefix + mFilePath + '/' + fileName;
1384  QgsDebugMsgLevel( "tmpPath = " + tmpPath, 3 );
1385 
1386  // Q_FOREACH( dataItem_t *dataItem, mDataItemPtr )
1387  for ( int i = 0; i < mProviderNames.size(); i++ )
1388  {
1389  // ugly hack to remove .dbf file if there is a .shp file
1390  if ( mProviderNames[i] == "ogr" )
1391  {
1392  if ( info.suffix().toLower() == "dbf" )
1393  {
1394  if ( mZipFileList.indexOf( fileName.left( fileName.count() - 4 ) + ".shp" ) != -1 )
1395  continue;
1396  }
1397  if ( info.completeSuffix().toLower() == "shp.xml" )
1398  {
1399  continue;
1400  }
1401  }
1402 
1403  // try to get data item from provider
1404  dataItem_t *dataItem = mDataItemPtr.at( i );
1405  if ( dataItem )
1406  {
1407  QgsDebugMsgLevel( QString( "trying to load item %1 with %2" ).arg( tmpPath, mProviderNames.at( i ) ), 3 );
1408  QgsDataItem * item = dataItem( tmpPath, this );
1409  if ( item )
1410  {
1411  QgsDebugMsgLevel( "loaded item", 3 );
1412  // the item comes with zipped file name, set the name to relative path within zip file
1413  item->setName( fileName );
1414  children.append( item );
1415  break;
1416  }
1417  else
1418  {
1419  QgsDebugMsgLevel( "not loaded item", 3 );
1420  }
1421  }
1422  }
1423 
1424  }
1425 
1426  return children;
1427 }
1428 
1430 {
1431  return itemFromPath( parent, path, name, path );
1432 }
1433 
1435 {
1436  QSettings settings;
1437  QString scanZipSetting = settings.value( "/qgis/scanZipInBrowser2", "basic" ).toString();
1438  int zipFileCount = 0;
1439  QStringList zipFileList;
1440  QString vsiPrefix = QgsZipItem::vsiPrefix( filePath );
1441  QgsZipItem * zipItem = nullptr;
1442  bool populated = false;
1443 
1444  QgsDebugMsgLevel( QString( "path = %1 name= %2 scanZipSetting= %3 vsiPrefix= %4" ).arg( path, name, scanZipSetting, vsiPrefix ), 3 );
1445 
1446  // don't scan if scanZipBrowser == no
1447  if ( scanZipSetting == "no" )
1448  return nullptr;
1449 
1450  // don't scan if this file is not a /vsizip/ or /vsitar/ item
1451  if (( vsiPrefix != "/vsizip/" && vsiPrefix != "/vsitar/" ) )
1452  return nullptr;
1453 
1454  zipItem = new QgsZipItem( parent, name, filePath, path );
1455 
1456  if ( zipItem )
1457  {
1458  // force populate zipItem if it has less than 10 items and is not a .tgz or .tar.gz file (slow loading)
1459  // for other items populating will be delayed until item is opened
1460  // this might be polluting the tree with empty items but is necessary for performance reasons
1461  // could also accept all files smaller than a certain size and add options for file count and/or size
1462 
1463  // first get list of files inside .zip or .tar files
1464  if ( path.endsWith( ".zip", Qt::CaseInsensitive ) ||
1465  path.endsWith( ".tar", Qt::CaseInsensitive ) )
1466  {
1467  zipFileList = zipItem->getZipFileList();
1468  }
1469  // force populate if less than 10 items
1470  if ( !zipFileList.isEmpty() && zipFileList.count() <= 10 )
1471  {
1472  zipItem->populate( zipItem->createChildren() );
1473  populated = true; // there is no QgsDataItem::isPopulated() function
1474  QgsDebugMsgLevel( QString( "Got zipItem with %1 children, path=%2, name=%3" ).arg( zipItem->rowCount() ).arg( zipItem->path(), zipItem->name() ), 3 );
1475  }
1476  else
1477  {
1478  QgsDebugMsgLevel( QString( "Delaying populating zipItem with path=%1, name=%2" ).arg( zipItem->path(), zipItem->name() ), 3 );
1479  }
1480  }
1481 
1482  // only display if has children or if is not populated
1483  if ( zipItem && ( !populated || zipItem->rowCount() > 1 ) )
1484  {
1485  QgsDebugMsgLevel( "returning zipItem", 3 );
1486  return zipItem;
1487  }
1488  // if 1 or 0 child found, create a single data item using the normal path or the full path given by QgsZipItem
1489  else
1490  {
1491  QString vsiPath = vsiPrefix + filePath;
1492  if ( zipItem )
1493  {
1495  if ( children.size() == 1 )
1496  {
1497  // take the name of the only child so we can get a normal data item from it
1498  QgsLayerItem *layerItem = qobject_cast<QgsLayerItem*>( children.first() );
1499  if ( layerItem )
1500  vsiPath = layerItem->uri();
1501  }
1502  zipFileCount = zipFileList.count();
1503  delete zipItem;
1504  }
1505 
1506  QgsDebugMsgLevel( QString( "will try to create a normal dataItem from filePath= %2 or vsiPath = %3" ).arg( filePath, vsiPath ), 3 );
1507 
1508  // try to open using registered providers (gdal and ogr)
1509  for ( int i = 0; i < mProviderNames.size(); i++ )
1510  {
1511  dataItem_t *dataItem = mDataItemPtr.at( i );
1512  if ( dataItem )
1513  {
1514  QgsDataItem *item = nullptr;
1515  // try first with normal path (Passthru)
1516  // this is to simplify .qml handling, and without this some tests will fail
1517  // (e.g. testZipItemVectorTransparency(), second test)
1518  if (( mProviderNames.at( i ) == "ogr" ) ||
1519  ( mProviderNames.at( i ) == "gdal" && zipFileCount == 1 ) )
1520  item = dataItem( filePath, parent );
1521  // try with /vsizip/
1522  if ( ! item )
1523  item = dataItem( vsiPath, parent );
1524  if ( item )
1525  return item;
1526  }
1527  }
1528  }
1529 
1530  return nullptr;
1531 }
1532 
1534 {
1535  if ( ! mZipFileList.isEmpty() )
1536  return mZipFileList;
1537 
1538  QString tmpPath;
1539  QSettings settings;
1540  QString scanZipSetting = settings.value( "/qgis/scanZipInBrowser2", "basic" ).toString();
1541 
1542  QgsDebugMsgLevel( QString( "mFilePath = %1 name= %2 scanZipSetting= %3 vsiPrefix= %4" ).arg( mFilePath, name(), scanZipSetting, mVsiPrefix ), 3 );
1543 
1544  // if scanZipBrowser == no: skip to the next file
1545  if ( scanZipSetting == "no" )
1546  {
1547  return mZipFileList;
1548  }
1549 
1550  // get list of files inside zip file
1551  QgsDebugMsgLevel( QString( "Open file %1 with gdal vsi" ).arg( mVsiPrefix + mFilePath ), 3 );
1552  char **papszSiblingFiles = VSIReadDirRecursive1( QString( mVsiPrefix + mFilePath ).toLocal8Bit().constData() );
1553  if ( papszSiblingFiles )
1554  {
1555  for ( int i = 0; i < CSLCount( papszSiblingFiles ); i++ )
1556  {
1557  tmpPath = papszSiblingFiles[i];
1558  QgsDebugMsgLevel( QString( "Read file %1" ).arg( tmpPath ), 3 );
1559  // skip directories (files ending with /)
1560  if ( tmpPath.right( 1 ) != "/" )
1561  mZipFileList << tmpPath;
1562  }
1563  CSLDestroy( papszSiblingFiles );
1564  }
1565  else
1566  {
1567  QgsDebugMsg( QString( "Error reading %1" ).arg( mFilePath ) );
1568  }
1569 
1570  return mZipFileList;
1571 }
QString iconPath() const
Definition: qgsdataitem.cpp:62
QString completeSuffix() const
const char * className() const
QObject * child(const char *objName, const char *inheritsClass, bool recursiveSearch) const
A Collection: logical collection of layers or subcollections, e.g.
Definition: qgsdataitem.h:387
void clear()
void beginInsertItems(QgsDataItem *parent, int first, int last)
QString path() const
Definition: qgsdataitem.h:208
static unsigned index
static QgsProviderRegistry * instance(const QString &pluginPath=QString::null)
Means of accessing canonical single instance.
void removeDirectory(QgsDirectoryItem *item)
virtual void childrenCreated()
static QgsDataItemProviderRegistry * instance()
virtual void childrenCreated() override
virtual void refresh()
QgsErrorItem(QgsDataItem *parent, const QString &error, const QString &path)
QString name() const
Definition: qgsdataitem.h:206
void dataChanged(QgsDataItem *item)
bool contains(const Key &key) const
QPixmap currentPixmap() const
void append(const T &value)
static const QIcon & iconDefault()
void disconnectFrameChanged(const QObject *receiver, const char *method)
Disconnect listener from frameChanged() signal.
Definition: qgsdataitem.cpp:88
virtual QgsDataItem * createDataItem(const QString &path, QgsDataItem *parentItem)=0
Create a new instance of QgsDataItem (or null) for given path and parent item.
static const QIcon & iconPoint()
Definition: qgsdataitem.cpp:99
static QgsDataItem * itemFromPath(QgsDataItem *parent, QString path, QString name)
QVector< QgsDataItem * > children() const
Definition: qgsdataitem.h:204
#define QgsDebugMsg(str)
Definition: qgslogger.h:33
QString mProviderKey
The provider key.
Definition: qgsdataitem.h:361
void addPath(const QString &path)
int indexOf(const T &value, int from) const
QList< QVariant > toList() const
QObject * sender() const
void setChecked(bool)
void moveToThread(QThread *targetThread)
QStyle * style() const
static QIcon getThemeIcon(const QString &theName)
Helper to get a theme icon.
QLibrary * providerLibrary(const QString &providerKey) const
static QString pathComponent(const QString &component)
Create path component replacing path separators.
static const QIcon & iconFavourites()
const T & at(int i) const
static QString iconPath(const QString &iconFile)
Returns path to the desired icon file.
virtual QIcon icon()
void addAction(QAction *action)
#define Q_NOWARN_DEPRECATED_PUSH
Definition: qgis.h:515
void setIcon(int column, const QIcon &icon)
void insert(int i, const T &value)
virtual void setState(State state) override
Set item state.
QString mIconName
Definition: qgsdataitem.h:253
virtual const QMetaObject * metaObject() const
State mState
Definition: qgsdataitem.h:243
QList< QTreeWidgetItem * > items(const QMimeData *data) const
Type type() const
Definition: qgsdataitem.h:196
virtual void depopulate()
Remove children recursively and set as not populated.
const QPixmap * icon() const
static const QIcon & iconPolygon()
T & first()
QString iconPath(const QString &iconFile)
bool disconnect(const QObject *sender, const char *signal, const QObject *receiver, const char *method)
QString tr(const char *sourceText, const char *disambiguation, int n)
QString uri()
Returns layer uri or empty string if layer cannot be created.
Definition: qgsdataitem.h:338
bool isColumnHidden(int column) const
int size() const
char ** VSIReadDirRecursive1(const char *pszPath)
void endRemoveItems()
State state() const
T value(int i) const
A zip file: contains layers, using GDAL/OGR VSIFILE mechanism.
Definition: qgsdataitem.h:533
virtual bool equal(const QgsDataItem *other)
Returns true if this item is equal to another item (by testing item type and path).
bool isFile() const
void setValue(const QString &key, const QVariant &value)
static const QIcon & iconDataCollection()
QSize size() const
const char * name() const
void setPaused(bool paused)
void clear()
void setFileName(const QString &fileName)
bool isFinished() const
QString number(int n, int base)
int count(const T &value) const
static void deleteLater(QVector< QgsDataItem *> &items)
void append(const T &value)
const QPoint & globalPos() const
QString mFilePath
Definition: qgsdataitem.h:538
QgsDataItem * parent() const
Get item parent.
Definition: qgsdataitem.h:200
virtual ~QgsDataItem()
int toInt(bool *ok) const
void addTopLevelItems(const QList< QTreeWidgetItem * > &items)
void beginRemoveItems(QgsDataItem *parent, int first, int last)
static const QIcon & iconRaster()
void connectFrameChanged(const QObject *receiver, const char *method)
Connect listener to frameChanged() signal.
Definition: qgsdataitem.cpp:78
#define QgsDebugMsgLevel(str, level)
Definition: qgslogger.h:34
bool isDir() const
QString mName
Definition: qgsdataitem.h:246
LayerType
Layers enum defining the types of layers that can be added to a map.
Definition: qgsmaplayer.h:57
QStringList mZipFileList
Definition: qgsdataitem.h:540
QgsDirectoryParamWidget(const QString &path, QWidget *parent=nullptr)
QgsZipItem(QgsDataItem *parent, const QString &name, const QString &path)
Qt::MouseButton button() const
bool isEmpty() const
static const QIcon & iconDir()
void setObjectName(const QString &name)
bool isEmpty() const
int removeAll(const T &value)
QString fileName() const
void remove(int i)
bool startsWith(const QString &s, Qt::CaseSensitivity cs) const
Children not yet created.
Definition: qgsdataitem.h:109
void onFrameChanged()
Definition: qgsdataitem.cpp:72
Creating children in separate thread (populating or refreshing)
Definition: qgsdataitem.h:110
bool endsWith(const QString &s, Qt::CaseSensitivity cs) const
void addPixmap(const QPixmap &pixmap, Mode mode, State state)
QFuture< T > run(Function function,...)
QCoreApplication * instance()
virtual int capabilities()=0
Return combination of flags from QgsDataProvider::DataCapabilities.
QgsDataCollectionItem(QgsDataItem *parent, const QString &name, const QString &path=QString::null)
void deleteLater()
bool hasChildren()
static QStringList mProviderNames
Definition: qgsdataitem.h:552
QAction * exec()
void setFuture(const QFuture< T > &future)
virtual bool equal(const QgsDataItem *other) override
Returns true if this item is equal to another item (by testing item type and path).
void setColumnCount(int columns)
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:403
QString right(int n) const
Base class for all items in the model.
Definition: qgsdataitem.h:79
iterator end()
QString toLower() const
void setColumnHidden(int column, bool hide)
void mousePressEvent(QMouseEvent *event) override
void setCacheMode(CacheMode mode)
void addDirectory(const QString &favIcon)
const char * className() const
Capabilities mCapabilities
Definition: qgsdataitem.h:240
void emitDataChanged()
virtual void setState(State state)
Set item state.
void setCheckable(bool)
virtual void addChildItem(QgsDataItem *child, bool refresh=false)
Inserts a new child item.
void setName(const QString &name)
Definition: qgsdataitem.h:207
static QVector< dataItem_t * > mDataItemPtr
Definition: qgsdataitem.h:551
Can create children. Even items without this capability may have children, but cannot create them...
Definition: qgsdataitem.h:172
QgsFavouritesItem(QgsDataItem *parent, const QString &name, const QString &path=QString())
void emitBeginInsertItems(QgsDataItem *parent, int first, int last)
static const QIcon & iconTable()
QString mPath
Definition: qgsdataitem.h:251
#define Q_NOWARN_DEPRECATED_POP
Definition: qgis.h:516
QString mUri
The URI.
Definition: qgsdataitem.h:363
void waitForFinished()
void setHeaderLabels(const QStringList &labels)
QString & replace(int position, int n, QChar after)
virtual bool event(QEvent *e)
void moveToThread(QThread *targetThread)
Move object and all its descendants to thread.
const T & at(int i) const
QVariant value(const QString &key, const QVariant &defaultValue) const
static bool hiddenPath(QString path)
Check if the given path is hidden from the browser model.
QgsAnimatedIcon(const QString &iconPath=QString::null)
Constructor.
Definition: qgsdataitem.cpp:47
T result() const
virtual Q_DECL_DEPRECATED Capability capabilities()
Definition: qgsdataitem.h:183
QString suffix() const
QStringList toStringList() const
void * resolve(const char *symbol)
QStyle * style()
QVector< QgsDataItem * > createChildren() override
Create children.
QString mVsiPrefix
Definition: qgsdataitem.h:539
bool isEmpty() const
bool isNull() const
QStringList entryList(QFlags< QDir::Filter > filters, QFlags< QDir::SortFlag > sort) const
QgsDirectoryItem(QgsDataItem *parent, const QString &name, const QString &path)
QString & sprintf(const char *cformat,...)
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...
Definition: qgsdataitem.h:43
QgsMapLayer::LayerType mapLayerType()
Returns QgsMapLayer::LayerType.
QgsDataItem * mParent
Definition: qgsdataitem.h:241
bool deferredDelete()
The item is scheduled to be deleted.
Definition: qgsdataitem.h:237
QString dirPath() const
Definition: qgsdataitem.h:432
QIcon icon() const
Definition: qgsdataitem.h:54
QString absoluteFilePath(const QString &fileName) const
static const QIcon & iconLine()
void endInsertItems()
void emitEndInsertItems()
virtual QVector< QgsDataItem * > createChildren()
Create children.
bool mPopulated
Definition: qgsdataitem.h:245
QVector< QgsDataItem * > createChildren() override
Create children.
Item that represents a layer that can be opened with one of the providers.
Definition: qgsdataitem.h:308
void start()
QgsProjectItem(QgsDataItem *parent, const QString &name, const QString &path)
A data item holding a reference to a QGIS project file.
int indexOf(const QRegExp &rx, int from) const
static int findItem(QVector< QgsDataItem *> items, QgsDataItem *item)
iterator insert(const Key &key, const T &value)
QgsDataItem * dataItem_t(QString, QgsDataItem *)
Definition: qgsdataitem.h:38
void(*)() cast_to_fptr(void *p)
Definition: qgis.h:272
virtual QgsDataItem * removeChildItem(QgsDataItem *child)
Removes a child item and returns it without deleting it.
static Q_DECL_DEPRECATED QVector< QLibrary * > mLibraries
Definition: qgsdataitem.h:440
virtual void deleteChildItem(QgsDataItem *child)
Removes and deletes a child item, emitting relevant signals to the model.
QVector< QgsDataItem * > mChildren
Definition: qgsdataitem.h:242
void emitEndRemoveItems()
virtual void populate(const QVector< QgsDataItem *> &children)
QgsLayerItem(QgsDataItem *parent, const QString &name, const QString &path, const QString &uri, LayerType layerType, const QString &providerKey)
void emitBeginRemoveItems(QgsDataItem *parent, int first, int last)
Data item that can be used to represent QGIS projects.
Definition: qgsdataitem.h:461
void setRootIsDecorated(bool show)
children created
Definition: qgsdataitem.h:111
LayerType mLayerType
The layer type.
Definition: qgsdataitem.h:365
virtual bool equal(const QgsDataItem *other) override
Returns true if this item is equal to another item (by testing item type and path).
bool connect(const QObject *sender, const char *signal, const QObject *receiver, const char *method, Qt::ConnectionType type)
QObject * parent() const
int size() const
int dataCapabilities_t()
virtual QPixmap standardPixmap(StandardPixmap standardPixmap, const QStyleOption *option, const QWidget *widget) const=0
static const QIcon & iconZip()
QString arg(qlonglong a, int fieldWidth, int base, const QChar &fillChar) const
QString toString() const
void emitStateChanged(QgsDataItem *item, QgsDataItem::State oldState)
virtual void deleteLater()
Safely delete the item:
virtual QWidget * paramWidget() override
iterator begin()
createChildren() is fast enough to be run in main thread when refreshing items, most root items (wms...
Definition: qgsdataitem.h:173
void setIconPath(const QString &iconPath)
Definition: qgsdataitem.cpp:67
QVector< QgsDataItem * > createChildren() override
Create children.
This is the interface for those who want to add custom data items to the browser tree.
void stateChanged(QgsDataItem *item, QgsDataItem::State oldState)
static QString vsiPrefix(const QString &uri)
Definition: qgsdataitem.h:554
const QStringList & getZipFileList()
QMap< QString, QIcon > mIconMap
Definition: qgsdataitem.h:255
added in 2.10
Definition: qgsdataitem.h:323
virtual Capabilities capabilities2() const
Definition: qgsdataitem.h:185
const T value(const Key &key) const
void frameChanged()
Emitted when icon changed.
QByteArray toUtf8() const