QGIS API Documentation  2.14.0-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 }
674 
675 // ---------------------------------------------------------------------
676 
677 QgsLayerItem::QgsLayerItem( QgsDataItem* parent, const QString& name, const QString& path, const QString& uri, LayerType layerType, const QString& providerKey )
678  : QgsDataItem( Layer, parent, name, path )
679  , mProviderKey( providerKey )
680  , mUri( uri )
681  , mLayerType( layerType )
682 {
683  switch ( layerType )
684  {
685  case Point:
686  mIconName = "/mIconPointLayer.svg";
687  break;
688  case Line:
689  mIconName = "/mIconLineLayer.svg";
690  break;
691  case Polygon:
692  mIconName = "/mIconPolygonLayer.svg";
693  break;
694  // TODO add a new icon for generic Vector layers
695  case Vector :
696  mIconName = "/mIconPolygonLayer.svg";
697  break;
698  case TableLayer:
699  mIconName = "/mIconTableLayer.png";
700  break;
701  case Raster:
702  mIconName = "/mIconRaster.svg";
703  break;
704  default:
705  mIconName = "/mIconLayer.png";
706  break;
707  }
708 }
709 
711 {
717 }
718 
719 bool QgsLayerItem::equal( const QgsDataItem *other )
720 {
721  //QgsDebugMsg ( mPath + " x " + other->mPath );
722  if ( type() != other->type() )
723  {
724  return false;
725  }
726  //const QgsLayerItem *o = qobject_cast<const QgsLayerItem *> ( other );
727  const QgsLayerItem *o = dynamic_cast<const QgsLayerItem *>( other );
728  if ( !o )
729  return false;
730 
731  return ( mPath == o->mPath && mName == o->mName && mUri == o->mUri && mProviderKey == o->mProviderKey );
732 }
733 
734 // ---------------------------------------------------------------------
736  : QgsDataItem( Collection, parent, name, path )
737 {
739  mIconName = "/mIconDbSchema.png";
740 }
741 
743 {
744  QgsDebugMsgLevel( "mName = " + mName + " mPath = " + mPath, 2 );
745 
746 // Do not delete children, children are deleted by QObject parent
747 #if 0
748  Q_FOREACH ( QgsDataItem* i, mChildren )
749  {
750  QgsDebugMsgLevel( QString( "delete child = 0x%0" ).arg(( qlonglong )i, 8, 16, QLatin1Char( '0' ) ), 2 );
751  delete i;
752  }
753 #endif
754 }
755 
756 //-----------------------------------------------------------------------
757 // QVector<QgsDataProvider*> QgsDirectoryItem::mProviders = QVector<QgsDataProvider*>();
761 
763  : QgsDataCollectionItem( parent, name, path )
764  , mDirPath( path )
765  , mFileSystemWatcher( nullptr )
766  , mRefreshLater( false )
767 {
768  mType = Directory;
769  init();
770 }
771 
773  : QgsDataCollectionItem( parent, name, path )
774  , mDirPath( dirPath )
775  , mFileSystemWatcher( nullptr )
776  , mRefreshLater( false )
777 {
778  mType = Directory;
779  init();
780 }
781 
783 {
784 }
785 
787 {
788 }
789 
791 {
792  if ( state() == Populating )
793  return QgsDataItem::icon();
794  return iconDir();
795 }
796 
797 
799 {
801  QDir dir( mDirPath );
802 
803  QStringList entries = dir.entryList( QDir::AllDirs | QDir::NoDotAndDotDot, QDir::Name | QDir::IgnoreCase );
804  Q_FOREACH ( const QString& subdir, entries )
805  {
806  if ( mRefreshLater )
807  {
808  deleteLater( children );
809  return children;
810  }
811 
812  QString subdirPath = dir.absoluteFilePath( subdir );
813 
814  QgsDebugMsgLevel( QString( "creating subdir: %1" ).arg( subdirPath ), 2 );
815 
816  QString path = mPath + '/' + subdir; // may differ from subdirPath
817  if ( QgsDirectoryItem::hiddenPath( path ) )
818  continue;
819  QgsDirectoryItem *item = new QgsDirectoryItem( this, subdir, subdirPath, path );
820  // propagate signals up to top
821 
822  children.append( item );
823  }
824 
825  QStringList fileEntries = dir.entryList( QDir::Dirs | QDir::NoDotAndDotDot | QDir::Files, QDir::Name );
826  Q_FOREACH ( const QString& name, fileEntries )
827  {
828  if ( mRefreshLater )
829  {
830  deleteLater( children );
831  return children;
832  }
833 
834  QString path = dir.absoluteFilePath( name );
835  QFileInfo fileInfo( path );
836 
837  if ( fileInfo.suffix() == "qgs" )
838  {
839  QgsDataItem * item = new QgsProjectItem( this, name, path );
840  children.append( item );
841  continue;
842  }
843 
844  // vsizip support was added to GDAL/OGR 1.6 but GDAL_VERSION_NUM not available here
845  // so we assume it's available anyway
846  {
847  QgsDataItem * item = QgsZipItem::itemFromPath( this, path, name, mPath + '/' + name );
848  if ( item )
849  {
850  children.append( item );
851  continue;
852  }
853  }
854 
855  Q_FOREACH ( QgsDataItemProvider* provider, QgsDataItemProviderRegistry::instance()->providers() )
856  {
857  int capabilities = provider->capabilities();
858 
859  if ( !(( fileInfo.isFile() && ( capabilities & QgsDataProvider::File ) ) ||
860  ( fileInfo.isDir() && ( capabilities & QgsDataProvider::Dir ) ) ) )
861  {
862  continue;
863  }
864 
865  QgsDataItem * item = provider->createDataItem( path, this );
866  if ( item )
867  {
868  children.append( item );
869  }
870  }
871 
872  }
873 
874  return children;
875 }
876 
878 {
879  QgsDebugMsg( "Entered" );
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  QgsDebugMsg( "Entered" );
904  if ( state() == Populating )
905  {
906  // schedule to refresh later, because refres() simply returns if Populating
907  mRefreshLater = true;
908  }
909  else
910  {
911  refresh();
912  }
913 }
914 
916 {
917  QSettings settings;
918  QStringList hiddenItems = settings.value( "/browser/hiddenPaths",
920  int idx = hiddenItems.indexOf( path );
921  return ( idx > -1 );
922 }
923 
925 {
926  QgsDebugMsg( QString( "mRefreshLater = %1" ).arg( mRefreshLater ) );
927 
928  if ( mRefreshLater )
929  {
930  QgsDebugMsg( "directory changed during createChidren() -> refresh() again" );
931  mRefreshLater = false;
932  setState( Populated );
933  refresh();
934  }
935  else
936  {
938  }
939 }
940 
942 {
943  //QgsDebugMsg ( mPath + " x " + other->mPath );
944  if ( type() != other->type() )
945  {
946  return false;
947  }
948  return ( path() == other->path() );
949 }
950 
952 {
953  return new QgsDirectoryParamWidget( mPath );
954 }
955 
957  : QTreeWidget( parent )
958 {
959  setRootIsDecorated( false );
960 
961  // name, size, date, permissions, owner, group, type
962  setColumnCount( 7 );
963  QStringList labels;
964  labels << tr( "Name" ) << tr( "Size" ) << tr( "Date" ) << tr( "Permissions" ) << tr( "Owner" ) << tr( "Group" ) << tr( "Type" );
965  setHeaderLabels( labels );
966 
968  QIcon iconDirectory = QIcon( style->standardPixmap( QStyle::SP_DirClosedIcon ) );
969  QIcon iconFile = QIcon( style->standardPixmap( QStyle::SP_FileIcon ) );
970  QIcon iconDirLink = QIcon( style->standardPixmap( QStyle::SP_DirLinkIcon ) );
971  QIcon iconFileLink = QIcon( style->standardPixmap( QStyle::SP_FileLinkIcon ) );
972 
974 
975  QDir dir( path );
976  QStringList entries = dir.entryList( QDir::AllEntries | QDir::NoDotAndDotDot, QDir::Name | QDir::IgnoreCase );
977  Q_FOREACH ( const QString& name, entries )
978  {
979  QFileInfo fi( dir.absoluteFilePath( name ) );
980  QStringList texts;
981  texts << name;
982  QString size;
983  if ( fi.size() > 1024 )
984  {
985  size = size.sprintf( "%.1f KiB", fi.size() / 1024.0 );
986  }
987  else if ( fi.size() > 1.048576e6 )
988  {
989  size = size.sprintf( "%.1f MiB", fi.size() / 1.048576e6 );
990  }
991  else
992  {
993  size = QString( "%1 B" ).arg( fi.size() );
994  }
995  texts << size;
996  texts << fi.lastModified().toString( Qt::SystemLocaleShortDate );
997  QString perm;
998  perm += fi.permission( QFile::ReadOwner ) ? 'r' : '-';
999  perm += fi.permission( QFile::WriteOwner ) ? 'w' : '-';
1000  perm += fi.permission( QFile::ExeOwner ) ? 'x' : '-';
1001  // QFile::ReadUser, QFile::WriteUser, QFile::ExeUser
1002  perm += fi.permission( QFile::ReadGroup ) ? 'r' : '-';
1003  perm += fi.permission( QFile::WriteGroup ) ? 'w' : '-';
1004  perm += fi.permission( QFile::ExeGroup ) ? 'x' : '-';
1005  perm += fi.permission( QFile::ReadOther ) ? 'r' : '-';
1006  perm += fi.permission( QFile::WriteOther ) ? 'w' : '-';
1007  perm += fi.permission( QFile::ExeOther ) ? 'x' : '-';
1008  texts << perm;
1009 
1010  texts << fi.owner();
1011  texts << fi.group();
1012 
1013  QString type;
1014  QIcon icon;
1015  if ( fi.isDir() && fi.isSymLink() )
1016  {
1017  type = tr( "folder" );
1018  icon = iconDirLink;
1019  }
1020  else if ( fi.isDir() )
1021  {
1022  type = tr( "folder" );
1023  icon = iconDirectory;
1024  }
1025  else if ( fi.isFile() && fi.isSymLink() )
1026  {
1027  type = tr( "file" );
1028  icon = iconFileLink;
1029  }
1030  else if ( fi.isFile() )
1031  {
1032  type = tr( "file" );
1033  icon = iconFile;
1034  }
1035 
1036  texts << type;
1037 
1038  QTreeWidgetItem *item = new QTreeWidgetItem( texts );
1039  item->setIcon( 0, icon );
1040  items << item;
1041  }
1042 
1043  addTopLevelItems( items );
1044 
1045  // hide columns that are not requested
1046  QSettings settings;
1047  QList<QVariant> lst = settings.value( "/dataitem/directoryHiddenColumns" ).toList();
1048  Q_FOREACH ( const QVariant& colVariant, lst )
1049  {
1050  setColumnHidden( colVariant.toInt(), true );
1051  }
1052 }
1053 
1055 {
1056  if ( event->button() == Qt::RightButton )
1057  {
1058  // show the popup menu
1059  QMenu popupMenu;
1060 
1061  QStringList labels;
1062  labels << tr( "Name" ) << tr( "Size" ) << tr( "Date" ) << tr( "Permissions" ) << tr( "Owner" ) << tr( "Group" ) << tr( "Type" );
1063  for ( int i = 0; i < labels.count(); i++ )
1064  {
1065  QAction* action = popupMenu.addAction( labels[i], this, SLOT( showHideColumn() ) );
1066  action->setObjectName( QString::number( i ) );
1067  action->setCheckable( true );
1068  action->setChecked( !isColumnHidden( i ) );
1069  }
1070 
1071  popupMenu.exec( event->globalPos() );
1072  }
1073 }
1074 
1076 {
1077  QAction* action = qobject_cast<QAction*>( sender() );
1078  if ( !action )
1079  return; // something is wrong
1080 
1081  int columnIndex = action->objectName().toInt();
1082  setColumnHidden( columnIndex, !isColumnHidden( columnIndex ) );
1083 
1084  // save in settings
1085  QSettings settings;
1086  QList<QVariant> lst;
1087  for ( int i = 0; i < columnCount(); i++ )
1088  {
1089  if ( isColumnHidden( i ) )
1090  lst.append( QVariant( i ) );
1091  }
1092  settings.setValue( "/dataitem/directoryHiddenColumns", lst );
1093 }
1094 
1096  : QgsDataItem( QgsDataItem::Project, parent, name, path )
1097 {
1098  mIconName = ":/images/icons/qgis-icon-16x16.png";
1099 
1100  setState( Populated ); // no more children
1101 }
1102 
1104 {
1105 }
1106 
1108  : QgsDataItem( QgsDataItem::Error, parent, error, path )
1109 {
1110  mIconName = "/mIconDelete.png";
1111 
1112  setState( Populated ); // no more children
1113 }
1114 
1116 {
1117 }
1118 
1120  : QgsDataCollectionItem( parent, name, "favourites:" )
1121 {
1122  Q_UNUSED( path );
1123  mCapabilities |= Fast;
1124  mType = Favourites;
1125  mIconName = "/mIconFavourites.png";
1126  populate();
1127 }
1128 
1130 {
1131 }
1132 
1134 {
1136 
1137  QSettings settings;
1138  QStringList favDirs = settings.value( "/browser/favourites", QVariant() ).toStringList();
1139 
1140  Q_FOREACH ( const QString& favDir, favDirs )
1141  {
1142  children << createChildren( favDir );
1143  }
1144 
1145  return children;
1146 }
1147 
1149 {
1150  QSettings settings;
1151  QStringList favDirs = settings.value( "/browser/favourites" ).toStringList();
1152  favDirs.append( favDir );
1153  settings.setValue( "/browser/favourites", favDirs );
1154 
1155  if ( state() == Populated )
1156  {
1157  QVector<QgsDataItem*> items = createChildren( favDir );
1158  Q_FOREACH ( QgsDataItem* item, items )
1159  {
1160  addChildItem( item, true );
1161  }
1162  }
1163 }
1164 
1166 {
1167  if ( !item )
1168  return;
1169 
1170  QSettings settings;
1171  QStringList favDirs = settings.value( "/browser/favourites" ).toStringList();
1172  favDirs.removeAll( item->dirPath() );
1173  settings.setValue( "/browser/favourites", favDirs );
1174 
1175  int idx = findItem( mChildren, item );
1176  if ( idx < 0 )
1177  {
1178  QgsDebugMsg( QString( "favourites item %1 not found" ).arg( item->path() ) );
1179  return;
1180  }
1181 
1182  if ( state() == Populated )
1183  deleteChildItem( mChildren.at( idx ) );
1184 }
1185 
1187 {
1189  QString pathName = pathComponent( favDir );
1190  Q_FOREACH ( QgsDataItemProvider* provider, QgsDataItemProviderRegistry::instance()->providers() )
1191  {
1192  int capabilities = provider->capabilities();
1193 
1194  if ( capabilities & QgsDataProvider::Dir )
1195  {
1196  QgsDataItem * item = provider->createDataItem( favDir, this );
1197  if ( item )
1198  {
1199  item->setName( favDir );
1200  children.append( item );
1201  }
1202  }
1203  }
1204  if ( children.isEmpty() )
1205  {
1206  QgsDataItem *item = new QgsDirectoryItem( this, favDir, favDir, mPath + '/' + pathName );
1207  if ( item )
1208  {
1209  children.append( item );
1210  }
1211  }
1212  return children;
1213 }
1214 
1215 //-----------------------------------------------------------------------
1218 
1219 
1221  : QgsDataCollectionItem( parent, name, path )
1222 {
1223  mFilePath = path;
1224  init();
1225 }
1226 
1228  : QgsDataCollectionItem( parent, name, path )
1229  , mFilePath( filePath )
1230 {
1231  init();
1232 }
1233 
1234 void QgsZipItem::init()
1235 {
1236  mType = Collection; //Zip??
1237  mIconName = "/mIconZip.png";
1239 
1240  if ( mProviderNames.isEmpty() )
1241  {
1242  // QStringList keys = QgsProviderRegistry::instance()->providerList();
1243  // only use GDAL and OGR providers as we use the VSIFILE mechanism
1244  QStringList keys;
1245  // keys << "ogr" << "gdal";
1246  keys << "gdal" << "ogr";
1247 
1249  for ( i = keys.begin(); i != keys.end(); ++i )
1250  {
1251  QString k( *i );
1252  QgsDebugMsg( "provider " + k );
1253  // some providers hangs with empty uri (Postgis) etc...
1254  // -> using libraries directly
1256  if ( library )
1257  {
1258  dataCapabilities_t * dataCapabilities = reinterpret_cast< dataCapabilities_t * >( cast_to_fptr( library->resolve( "dataCapabilities" ) ) );
1259  if ( !dataCapabilities )
1260  {
1261  QgsDebugMsg( library->fileName() + " does not have dataCapabilities" );
1262  continue;
1263  }
1264  if ( dataCapabilities() == QgsDataProvider::NoDataCapabilities )
1265  {
1266  QgsDebugMsg( library->fileName() + " has NoDataCapabilities" );
1267  continue;
1268  }
1269  QgsDebugMsg( QString( "%1 dataCapabilities : %2" ).arg( library->fileName() ).arg( dataCapabilities() ) );
1270 
1271  dataItem_t * dataItem = reinterpret_cast< dataItem_t * >( cast_to_fptr( library->resolve( "dataItem" ) ) );
1272  if ( ! dataItem )
1273  {
1274  QgsDebugMsg( library->fileName() + " does not have dataItem" );
1275  continue;
1276  }
1277 
1278  // mLibraries.append( library );
1279  mDataItemPtr.append( dataItem );
1280  mProviderNames.append( k );
1281  }
1282  else
1283  {
1284  //QgsDebugMsg ( "Cannot get provider " + k );
1285  }
1286  }
1287  }
1288 
1289 }
1290 
1292 {
1293 }
1294 
1295 // internal function to scan a vsidir (zip or tar file) recursively
1296 // GDAL trunk has this since r24423 (05/16/12) - VSIReadDirRecursive()
1297 // use a copy of the function internally for now,
1298 // but use char ** and CSLAddString, because CPLStringList was added in gdal-1.9
1299 char **VSIReadDirRecursive1( const char *pszPath )
1300 {
1301  // CPLStringList oFiles = nullptr;
1302  char **papszOFiles = nullptr;
1303  char **papszFiles1 = nullptr;
1304  char **papszFiles2 = nullptr;
1305  VSIStatBufL psStatBuf;
1306  CPLString osTemp1, osTemp2;
1307  int i, j;
1308  int nCount1, nCount2;
1309 
1310  // get listing
1311  papszFiles1 = VSIReadDir( pszPath );
1312  if ( ! papszFiles1 )
1313  return nullptr;
1314 
1315  // get files and directories inside listing
1316  nCount1 = CSLCount( papszFiles1 );
1317  for ( i = 0; i < nCount1; i++ )
1318  {
1319  // build complete file name for stat
1320  osTemp1.clear();
1321  osTemp1.append( pszPath );
1322  osTemp1.append( "/" );
1323  osTemp1.append( papszFiles1[i] );
1324 
1325  // if is file, add it
1326  if ( VSIStatL( osTemp1.c_str(), &psStatBuf ) == 0 &&
1327  VSI_ISREG( psStatBuf.st_mode ) )
1328  {
1329  // oFiles.AddString( papszFiles1[i] );
1330  papszOFiles = CSLAddString( papszOFiles, papszFiles1[i] );
1331  }
1332  else if ( VSIStatL( osTemp1.c_str(), &psStatBuf ) == 0 &&
1333  VSI_ISDIR( psStatBuf.st_mode ) )
1334  {
1335  // add directory entry
1336  osTemp2.clear();
1337  osTemp2.append( papszFiles1[i] );
1338  osTemp2.append( "/" );
1339  // oFiles.AddString( osTemp2.c_str() );
1340  papszOFiles = CSLAddString( papszOFiles, osTemp2.c_str() );
1341 
1342  // recursively add files inside directory
1343  papszFiles2 = VSIReadDirRecursive1( osTemp1.c_str() );
1344  if ( papszFiles2 )
1345  {
1346  nCount2 = CSLCount( papszFiles2 );
1347  for ( j = 0; j < nCount2; j++ )
1348  {
1349  osTemp2.clear();
1350  osTemp2.append( papszFiles1[i] );
1351  osTemp2.append( "/" );
1352  osTemp2.append( papszFiles2[j] );
1353  // oFiles.AddString( osTemp2.c_str() );
1354  papszOFiles = CSLAddString( papszOFiles, osTemp2.c_str() );
1355  }
1356  CSLDestroy( papszFiles2 );
1357  }
1358  }
1359  }
1360  CSLDestroy( papszFiles1 );
1361 
1362  // return oFiles.StealList();
1363  return papszOFiles;
1364 }
1365 
1367 {
1369  QString tmpPath;
1370  QSettings settings;
1371  QString scanZipSetting = settings.value( "/qgis/scanZipInBrowser2", "basic" ).toString();
1372 
1373  mZipFileList.clear();
1374 
1375  QgsDebugMsgLevel( QString( "mFilePath = %1 path = %2 name= %3 scanZipSetting= %4 vsiPrefix= %5" ).arg( mFilePath, path(), name(), scanZipSetting, mVsiPrefix ), 2 );
1376 
1377  // if scanZipBrowser == no: skip to the next file
1378  if ( scanZipSetting == "no" )
1379  {
1380  return children;
1381  }
1382 
1383  // first get list of files
1384  getZipFileList();
1385 
1386  // loop over files inside zip
1387  Q_FOREACH ( const QString& fileName, mZipFileList )
1388  {
1389  QFileInfo info( fileName );
1390  tmpPath = mVsiPrefix + mFilePath + '/' + fileName;
1391  QgsDebugMsgLevel( "tmpPath = " + tmpPath, 3 );
1392 
1393  // Q_FOREACH( dataItem_t *dataItem, mDataItemPtr )
1394  for ( int i = 0; i < mProviderNames.size(); i++ )
1395  {
1396  // ugly hack to remove .dbf file if there is a .shp file
1397  if ( mProviderNames[i] == "ogr" )
1398  {
1399  if ( info.suffix().toLower() == "dbf" )
1400  {
1401  if ( mZipFileList.indexOf( fileName.left( fileName.count() - 4 ) + ".shp" ) != -1 )
1402  continue;
1403  }
1404  if ( info.completeSuffix().toLower() == "shp.xml" )
1405  {
1406  continue;
1407  }
1408  }
1409 
1410  // try to get data item from provider
1411  dataItem_t *dataItem = mDataItemPtr.at( i );
1412  if ( dataItem )
1413  {
1414  QgsDebugMsgLevel( QString( "trying to load item %1 with %2" ).arg( tmpPath, mProviderNames.at( i ) ), 3 );
1415  QgsDataItem * item = dataItem( tmpPath, this );
1416  if ( item )
1417  {
1418  QgsDebugMsgLevel( "loaded item", 3 );
1419  // the item comes with zipped file name, set the name to relative path within zip file
1420  item->setName( fileName );
1421  children.append( item );
1422  break;
1423  }
1424  else
1425  {
1426  QgsDebugMsgLevel( "not loaded item", 3 );
1427  }
1428  }
1429  }
1430 
1431  }
1432 
1433  return children;
1434 }
1435 
1437 {
1438  return itemFromPath( parent, path, name, path );
1439 }
1440 
1442 {
1443  QSettings settings;
1444  QString scanZipSetting = settings.value( "/qgis/scanZipInBrowser2", "basic" ).toString();
1445  int zipFileCount = 0;
1446  QStringList zipFileList;
1447  QFileInfo fileInfo( filePath );
1448  QString vsiPrefix = QgsZipItem::vsiPrefix( filePath );
1449  QgsZipItem * zipItem = nullptr;
1450  bool populated = false;
1451 
1452  QgsDebugMsgLevel( QString( "path = %1 name= %2 scanZipSetting= %3 vsiPrefix= %4" ).arg( path, name, scanZipSetting, vsiPrefix ), 3 );
1453 
1454  // don't scan if scanZipBrowser == no
1455  if ( scanZipSetting == "no" )
1456  return nullptr;
1457 
1458  // don't scan if this file is not a /vsizip/ or /vsitar/ item
1459  if (( vsiPrefix != "/vsizip/" && vsiPrefix != "/vsitar/" ) )
1460  return nullptr;
1461 
1462  zipItem = new QgsZipItem( parent, name, filePath, path );
1463 
1464  if ( zipItem )
1465  {
1466  // force populate zipItem if it has less than 10 items and is not a .tgz or .tar.gz file (slow loading)
1467  // for other items populating will be delayed until item is opened
1468  // this might be polluting the tree with empty items but is necessary for performance reasons
1469  // could also accept all files smaller than a certain size and add options for file count and/or size
1470 
1471  // first get list of files inside .zip or .tar files
1472  if ( path.endsWith( ".zip", Qt::CaseInsensitive ) ||
1473  path.endsWith( ".tar", Qt::CaseInsensitive ) )
1474  {
1475  zipFileList = zipItem->getZipFileList();
1476  }
1477  // force populate if less than 10 items
1478  if ( !zipFileList.isEmpty() && zipFileList.count() <= 10 )
1479  {
1480  zipItem->populate( zipItem->createChildren() );
1481  populated = true; // there is no QgsDataItem::isPopulated() function
1482  QgsDebugMsgLevel( QString( "Got zipItem with %1 children, path=%2, name=%3" ).arg( zipItem->rowCount() ).arg( zipItem->path(), zipItem->name() ), 3 );
1483  }
1484  else
1485  {
1486  QgsDebugMsgLevel( QString( "Delaying populating zipItem with path=%1, name=%2" ).arg( zipItem->path(), zipItem->name() ), 3 );
1487  }
1488  }
1489 
1490  // only display if has children or if is not populated
1491  if ( zipItem && ( !populated || zipItem->rowCount() > 1 ) )
1492  {
1493  QgsDebugMsgLevel( "returning zipItem", 3 );
1494  return zipItem;
1495  }
1496  // if 1 or 0 child found, create a single data item using the normal path or the full path given by QgsZipItem
1497  else
1498  {
1499  QString vsiPath = vsiPrefix + filePath;
1500  if ( zipItem )
1501  {
1503  if ( children.size() == 1 )
1504  {
1505  // take the name of the only child so we can get a normal data item from it
1506  QgsLayerItem *layerItem = qobject_cast<QgsLayerItem*>( children.first() );
1507  if ( layerItem )
1508  vsiPath = layerItem->uri();
1509  }
1510  zipFileCount = zipFileList.count();
1511  delete zipItem;
1512  }
1513 
1514  QgsDebugMsgLevel( QString( "will try to create a normal dataItem from filePath= %2 or vsiPath = %3" ).arg( filePath, vsiPath ), 3 );
1515 
1516  // try to open using registered providers (gdal and ogr)
1517  for ( int i = 0; i < mProviderNames.size(); i++ )
1518  {
1519  dataItem_t *dataItem = mDataItemPtr.at( i );
1520  if ( dataItem )
1521  {
1522  QgsDataItem *item = nullptr;
1523  // try first with normal path (Passthru)
1524  // this is to simplify .qml handling, and without this some tests will fail
1525  // (e.g. testZipItemVectorTransparency(), second test)
1526  if (( mProviderNames.at( i ) == "ogr" ) ||
1527  ( mProviderNames.at( i ) == "gdal" && zipFileCount == 1 ) )
1528  item = dataItem( filePath, parent );
1529  // try with /vsizip/
1530  if ( ! item )
1531  item = dataItem( vsiPath, parent );
1532  if ( item )
1533  return item;
1534  }
1535  }
1536  }
1537 
1538  return nullptr;
1539 }
1540 
1542 {
1543  if ( ! mZipFileList.isEmpty() )
1544  return mZipFileList;
1545 
1546  QString tmpPath;
1547  QSettings settings;
1548  QString scanZipSetting = settings.value( "/qgis/scanZipInBrowser2", "basic" ).toString();
1549 
1550  QgsDebugMsgLevel( QString( "mFilePath = %1 name= %2 scanZipSetting= %3 vsiPrefix= %4" ).arg( mFilePath, name(), scanZipSetting, mVsiPrefix ), 3 );
1551 
1552  // if scanZipBrowser == no: skip to the next file
1553  if ( scanZipSetting == "no" )
1554  {
1555  return mZipFileList;
1556  }
1557 
1558  // get list of files inside zip file
1559  QgsDebugMsgLevel( QString( "Open file %1 with gdal vsi" ).arg( mVsiPrefix + mFilePath ), 3 );
1560  char **papszSiblingFiles = VSIReadDirRecursive1( QString( mVsiPrefix + mFilePath ).toLocal8Bit().constData() );
1561  if ( papszSiblingFiles )
1562  {
1563  for ( int i = 0; i < CSLCount( papszSiblingFiles ); i++ )
1564  {
1565  tmpPath = papszSiblingFiles[i];
1566  QgsDebugMsgLevel( QString( "Read file %1" ).arg( tmpPath ), 3 );
1567  // skip directories (files ending with /)
1568  if ( tmpPath.right( 1 ) != "/" )
1569  mZipFileList << tmpPath;
1570  }
1571  CSLDestroy( papszSiblingFiles );
1572  }
1573  else
1574  {
1575  QgsDebugMsg( QString( "Error reading %1" ).arg( mFilePath ) );
1576  }
1577 
1578  return mZipFileList;
1579 }
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)
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)
void dataChanged(QgsDataItem *item)
static void deleteLater(QVector< QgsDataItem * > &items)
bool contains(const Key &key) const
static QMap< QString, QIcon > mIconMap
Definition: qgsdataitem.h:250
QVector< QgsDataItem * > children() const
Definition: qgsdataitem.h:199
QString name() const
Definition: qgsdataitem.h:201
QPixmap currentPixmap() const
void append(const T &value)
virtual Capabilities capabilities2() const
Definition: qgsdataitem.h:180
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.
QgsDataItem * parent() const
Get item parent.
Definition: qgsdataitem.h:195
static const QIcon & iconPoint()
Definition: qgsdataitem.cpp:98
static QgsDataItem * itemFromPath(QgsDataItem *parent, QString path, QString name)
QIcon icon() const
Definition: qgsdataitem.h:52
#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.
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:407
void setIcon(int column, const QIcon &icon)
void insert(int i, const T &value)
State state() const
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
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()
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
void append(const T &value)
const QPoint & globalPos() const
QString mFilePath
Definition: qgsdataitem.h:521
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
QString iconPath() const
Definition: qgsdataitem.cpp:61
QString dirPath() const
Definition: qgsdataitem.h:421
#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
QString path() const
Definition: qgsdataitem.h:203
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()
Type type() const
Definition: qgsdataitem.h:191
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
QLibrary * providerLibrary(const QString &providerKey) const
#define Q_NOWARN_DEPRECATED_POP
Definition: qgis.h:408
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)
static int findItem(QVector< QgsDataItem * > items, QgsDataItem *item)
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
virtual void populate(const QVector< QgsDataItem * > &children)
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 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
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()
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
const T value(const Key &key) const
void frameChanged()
Emitted when icon changed.