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