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