QGIS API Documentation  2.12.0-Lyon
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( 0 )
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 = 0;
208 
209 QgsDataItem::QgsDataItem( QgsDataItem::Type type, QgsDataItem* parent, const QString& name, const QString& path )
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( 0 )
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( 0 ); // 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( 0 ); // 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 
315 void QgsDataItem::emitBeginInsertItems( QgsDataItem* parent, int first, int last )
316 {
317  emit beginInsertItems( parent, first, last );
318 }
320 {
321  emit endInsertItems();
322 }
323 void QgsDataItem::emitBeginRemoveItems( QgsDataItem* parent, int first, int last )
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.size() == 0 ) // 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.count() > 0 : true );
524 }
525 
527 {
528  if ( mParent )
529  {
530  disconnect( this, 0, mParent, 0 );
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 
550 void QgsDataItem::addChildItem( QgsDataItem * child, bool refresh )
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  int i;
556  if ( type() == Directory )
557  {
558  for ( i = 0; i < mChildren.size(); i++ )
559  {
560  // sort items by type, so directories are before data items
561  if ( mChildren[i]->mType == child->mType &&
562  mChildren[i]->mName.localeAwareCompare( child->mName ) > 0 )
563  break;
564  }
565  }
566  else
567  {
568  for ( i = 0; i < mChildren.size(); i++ )
569  {
570  if ( mChildren[i]->mName.localeAwareCompare( child->mName ) >= 0 )
571  break;
572  }
573  }
574 
575  if ( refresh )
576  emit beginInsertItems( this, i, i );
577 
578  mChildren.insert( i, child );
579  child->setParent( this );
580 
581  if ( refresh )
582  emit endInsertItems();
583 }
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  emit beginRemoveItems( this, i, i );
601  mChildren.remove( i );
602  emit endRemoveItems();
603  child->setParent( 0 );
604  return child;
605 }
606 
608 {
609  for ( int i = 0; i < items.size(); i++ )
610  {
611  Q_ASSERT_X( items[i], "findItem", QString( "item %1 is NULL" ).arg( i ).toAscii() );
612  QgsDebugMsgLevel( QString::number( i ) + " : " + items[i]->mPath + " x " + item->mPath, 2 );
613  if ( items[i]->equal( item ) )
614  return i;
615  }
616  return -1;
617 }
618 
619 bool QgsDataItem::equal( const QgsDataItem *other )
620 {
621  if ( metaObject()->className() == other->metaObject()->className() &&
622  mPath == other->path() )
623  {
624  return true;
625  }
626  return false;
627 }
628 
630 {
631  // for backward compatibility (if subclass set mPopulated directly)
632  // TODO: remove in 3.0
633  if ( mPopulated )
634  return Populated;
635  return mState;
636 }
637 
639 {
640  QgsDebugMsg( QString( "item %1 set state %2 -> %3" ).arg( path() ).arg( this->state() ).arg( state ) );
641  if ( state == mState )
642  return;
643 
644  State oldState = mState;
645 
646  if ( state == Populating ) // start loading
647  {
648  if ( !mPopulatingIcon )
649  {
650  // TODO: ensure that QgsAnimatedIcon is created on UI thread only
651  mPopulatingIcon = new QgsAnimatedIcon( QgsApplication::iconPath( "/mIconLoading.gif" ) );
652  }
653  mPopulatingIcon->connectFrameChanged( this, SLOT( emitDataChanged() ) );
654  }
655  else if ( mState == Populating && mPopulatingIcon ) // stop loading
656  {
657  mPopulatingIcon->disconnectFrameChanged( this, SLOT( emitDataChanged() ) );
658  }
659 
660  mState = state;
661  // for backward compatibility (if subclass access mPopulated directly)
662  // TODO: remove in 3.0
663  mPopulated = state == Populated;
664 
665  emit stateChanged( this, oldState );
666 }
667 
668 // ---------------------------------------------------------------------
669 
670 QgsLayerItem::QgsLayerItem( QgsDataItem* parent, const QString& name, const QString& path, const QString& uri, LayerType layerType, const QString& providerKey )
671  : QgsDataItem( Layer, parent, name, path )
672  , mProviderKey( providerKey )
673  , mUri( uri )
674  , mLayerType( layerType )
675 {
676  switch ( layerType )
677  {
678  case Point: mIconName = "/mIconPointLayer.svg"; break;
679  case Line: mIconName = "/mIconLineLayer.svg"; break;
680  case Polygon: mIconName = "/mIconPolygonLayer.svg"; break;
681  // TODO add a new icon for generic Vector layers
682  case Vector : mIconName = "/mIconPolygonLayer.svg"; break;
683  case TableLayer: mIconName = "/mIconTableLayer.png"; break;
684  case Raster: mIconName = "/mIconRaster.svg"; break;
685  default: mIconName = "/mIconLayer.png"; break;
686  }
687 }
688 
690 {
696 }
697 
698 bool QgsLayerItem::equal( const QgsDataItem *other )
699 {
700  //QgsDebugMsg ( mPath + " x " + other->mPath );
701  if ( type() != other->type() )
702  {
703  return false;
704  }
705  //const QgsLayerItem *o = qobject_cast<const QgsLayerItem *> ( other );
706  const QgsLayerItem *o = dynamic_cast<const QgsLayerItem *>( other );
707  if ( !o )
708  return false;
709 
710  return ( mPath == o->mPath && mName == o->mName && mUri == o->mUri && mProviderKey == o->mProviderKey );
711 }
712 
713 // ---------------------------------------------------------------------
715  : QgsDataItem( Collection, parent, name, path )
716 {
718  mIconName = "/mIconDbSchema.png";
719 }
720 
722 {
723  QgsDebugMsgLevel( "mName = " + mName + " mPath = " + mPath, 2 );
724 
725 // Do not delete children, children are deleted by QObject parent
726 #if 0
727  Q_FOREACH ( QgsDataItem* i, mChildren )
728  {
729  QgsDebugMsgLevel( QString( "delete child = 0x%0" ).arg(( qlonglong )i, 8, 16, QLatin1Char( '0' ) ), 2 );
730  delete i;
731  }
732 #endif
733 }
734 
735 //-----------------------------------------------------------------------
736 // QVector<QgsDataProvider*> QgsDirectoryItem::mProviders = QVector<QgsDataProvider*>();
740 
741 QgsDirectoryItem::QgsDirectoryItem( QgsDataItem* parent, const QString& name, const QString& path )
742  : QgsDataCollectionItem( parent, name, path )
743  , mDirPath( path )
744  , mFileSystemWatcher( 0 )
745  , mRefreshLater( false )
746 {
747  mType = Directory;
748  init();
749 }
750 
751 QgsDirectoryItem::QgsDirectoryItem( QgsDataItem* parent, const QString& name, const QString& dirPath, const QString& path )
752  : QgsDataCollectionItem( parent, name, path )
753  , mDirPath( dirPath )
754  , mFileSystemWatcher( 0 )
755  , mRefreshLater( false )
756 {
757  mType = Directory;
758  init();
759 }
760 
762 {
763 }
764 
766 {
767 }
768 
770 {
771  if ( state() == Populating )
772  return QgsDataItem::icon();
773  return iconDir();
774 }
775 
776 
778 {
780  QDir dir( mDirPath );
781 
782  QStringList entries = dir.entryList( QDir::AllDirs | QDir::NoDotAndDotDot, QDir::Name | QDir::IgnoreCase );
783  Q_FOREACH ( const QString& subdir, entries )
784  {
785  if ( mRefreshLater )
786  {
787  deleteLater( children );
788  return children;
789  }
790  QString subdirPath = dir.absoluteFilePath( subdir );
791  QgsDebugMsgLevel( QString( "creating subdir: %1" ).arg( subdirPath ), 2 );
792 
793  QString path = mPath + "/" + subdir; // may differ from subdirPath
794  QgsDirectoryItem *item = new QgsDirectoryItem( this, subdir, subdirPath, path );
795  // propagate signals up to top
796 
797  children.append( item );
798  }
799 
800  QStringList fileEntries = dir.entryList( QDir::Dirs | QDir::NoDotAndDotDot | QDir::Files, QDir::Name );
801  Q_FOREACH ( const QString& name, fileEntries )
802  {
803  if ( mRefreshLater )
804  {
805  deleteLater( children );
806  return children;
807  }
808 
809  QString path = dir.absoluteFilePath( name );
810  QFileInfo fileInfo( path );
811 
812  // vsizip support was added to GDAL/OGR 1.6 but GDAL_VERSION_NUM not available here
813  // so we assume it's available anyway
814  {
815  QgsDataItem * item = QgsZipItem::itemFromPath( this, path, name, mPath + "/" + name );
816  if ( item )
817  {
818  children.append( item );
819  continue;
820  }
821  }
822 
823  Q_FOREACH ( QgsDataItemProvider* provider, QgsDataItemProviderRegistry::instance()->providers() )
824  {
825  int capabilities = provider->capabilities();
826 
827  if ( !(( fileInfo.isFile() && ( capabilities & QgsDataProvider::File ) ) ||
828  ( fileInfo.isDir() && ( capabilities & QgsDataProvider::Dir ) ) ) )
829  {
830  continue;
831  }
832 
833  QgsDataItem * item = provider->createDataItem( path, this );
834  if ( item )
835  {
836  children.append( item );
837  }
838  }
839 
840  }
841 
842  return children;
843 }
844 
846 {
847  QgsDebugMsg( "Entered" );
849 
850  if ( state == Populated )
851  {
852  if ( !mFileSystemWatcher )
853  {
854  mFileSystemWatcher = new QFileSystemWatcher( this );
855  mFileSystemWatcher->addPath( mDirPath );
856  connect( mFileSystemWatcher, SIGNAL( directoryChanged( const QString & ) ), SLOT( directoryChanged() ) );
857  }
858  }
859  else if ( state == NotPopulated )
860  {
861  if ( mFileSystemWatcher )
862  {
863  delete mFileSystemWatcher;
864  mFileSystemWatcher = 0;
865  }
866  }
867 }
868 
870 {
871  QgsDebugMsg( "Entered" );
872  if ( state() == Populating )
873  {
874  // schedule to refresh later, because refres() simply returns if Populating
875  mRefreshLater = true;
876  }
877  else
878  {
879  refresh();
880  }
881 }
882 
884 {
885  QgsDebugMsg( QString( "mRefreshLater = %1" ).arg( mRefreshLater ) );
886 
887  if ( mRefreshLater )
888  {
889  QgsDebugMsg( "directory changed during createChidren() -> refresh() again" );
890  mRefreshLater = false;
891  setState( Populated );
892  refresh();
893  }
894  else
895  {
897  }
898 }
899 
901 {
902  //QgsDebugMsg ( mPath + " x " + other->mPath );
903  if ( type() != other->type() )
904  {
905  return false;
906  }
907  return ( path() == other->path() );
908 }
909 
911 {
912  return new QgsDirectoryParamWidget( mPath );
913 }
914 
916  : QTreeWidget( parent )
917 {
918  setRootIsDecorated( false );
919 
920  // name, size, date, permissions, owner, group, type
921  setColumnCount( 7 );
922  QStringList labels;
923  labels << tr( "Name" ) << tr( "Size" ) << tr( "Date" ) << tr( "Permissions" ) << tr( "Owner" ) << tr( "Group" ) << tr( "Type" );
924  setHeaderLabels( labels );
925 
927  QIcon iconDirectory = QIcon( style->standardPixmap( QStyle::SP_DirClosedIcon ) );
928  QIcon iconFile = QIcon( style->standardPixmap( QStyle::SP_FileIcon ) );
929  QIcon iconDirLink = QIcon( style->standardPixmap( QStyle::SP_DirLinkIcon ) );
930  QIcon iconFileLink = QIcon( style->standardPixmap( QStyle::SP_FileLinkIcon ) );
931 
933 
934  QDir dir( path );
935  QStringList entries = dir.entryList( QDir::AllEntries | QDir::NoDotAndDotDot, QDir::Name | QDir::IgnoreCase );
936  Q_FOREACH ( const QString& name, entries )
937  {
938  QFileInfo fi( dir.absoluteFilePath( name ) );
939  QStringList texts;
940  texts << name;
941  QString size;
942  if ( fi.size() > 1024 )
943  {
944  size = size.sprintf( "%.1f KiB", fi.size() / 1024.0 );
945  }
946  else if ( fi.size() > 1.048576e6 )
947  {
948  size = size.sprintf( "%.1f MiB", fi.size() / 1.048576e6 );
949  }
950  else
951  {
952  size = QString( "%1 B" ).arg( fi.size() );
953  }
954  texts << size;
955  texts << fi.lastModified().toString( Qt::SystemLocaleShortDate );
956  QString perm;
957  perm += fi.permission( QFile::ReadOwner ) ? 'r' : '-';
958  perm += fi.permission( QFile::WriteOwner ) ? 'w' : '-';
959  perm += fi.permission( QFile::ExeOwner ) ? 'x' : '-';
960  // QFile::ReadUser, QFile::WriteUser, QFile::ExeUser
961  perm += fi.permission( QFile::ReadGroup ) ? 'r' : '-';
962  perm += fi.permission( QFile::WriteGroup ) ? 'w' : '-';
963  perm += fi.permission( QFile::ExeGroup ) ? 'x' : '-';
964  perm += fi.permission( QFile::ReadOther ) ? 'r' : '-';
965  perm += fi.permission( QFile::WriteOther ) ? 'w' : '-';
966  perm += fi.permission( QFile::ExeOther ) ? 'x' : '-';
967  texts << perm;
968 
969  texts << fi.owner();
970  texts << fi.group();
971 
972  QString type;
973  QIcon icon;
974  if ( fi.isDir() && fi.isSymLink() )
975  {
976  type = tr( "folder" );
977  icon = iconDirLink;
978  }
979  else if ( fi.isDir() )
980  {
981  type = tr( "folder" );
982  icon = iconDirectory;
983  }
984  else if ( fi.isFile() && fi.isSymLink() )
985  {
986  type = tr( "file" );
987  icon = iconFileLink;
988  }
989  else if ( fi.isFile() )
990  {
991  type = tr( "file" );
992  icon = iconFile;
993  }
994 
995  texts << type;
996 
997  QTreeWidgetItem *item = new QTreeWidgetItem( texts );
998  item->setIcon( 0, icon );
999  items << item;
1000  }
1001 
1002  addTopLevelItems( items );
1003 
1004  // hide columns that are not requested
1005  QSettings settings;
1006  QList<QVariant> lst = settings.value( "/dataitem/directoryHiddenColumns" ).toList();
1007  Q_FOREACH ( const QVariant& colVariant, lst )
1008  {
1009  setColumnHidden( colVariant.toInt(), true );
1010  }
1011 }
1012 
1014 {
1015  if ( event->button() == Qt::RightButton )
1016  {
1017  // show the popup menu
1018  QMenu popupMenu;
1019 
1020  QStringList labels;
1021  labels << tr( "Name" ) << tr( "Size" ) << tr( "Date" ) << tr( "Permissions" ) << tr( "Owner" ) << tr( "Group" ) << tr( "Type" );
1022  for ( int i = 0; i < labels.count(); i++ )
1023  {
1024  QAction* action = popupMenu.addAction( labels[i], this, SLOT( showHideColumn() ) );
1025  action->setObjectName( QString::number( i ) );
1026  action->setCheckable( true );
1027  action->setChecked( !isColumnHidden( i ) );
1028  }
1029 
1030  popupMenu.exec( event->globalPos() );
1031  }
1032 }
1033 
1035 {
1036  QAction* action = qobject_cast<QAction*>( sender() );
1037  if ( !action )
1038  return; // something is wrong
1039 
1040  int columnIndex = action->objectName().toInt();
1041  setColumnHidden( columnIndex, !isColumnHidden( columnIndex ) );
1042 
1043  // save in settings
1044  QSettings settings;
1045  QList<QVariant> lst;
1046  for ( int i = 0; i < columnCount(); i++ )
1047  {
1048  if ( isColumnHidden( i ) )
1049  lst.append( QVariant( i ) );
1050  }
1051  settings.setValue( "/dataitem/directoryHiddenColumns", lst );
1052 }
1053 
1054 
1055 QgsErrorItem::QgsErrorItem( QgsDataItem* parent, const QString& error, const QString& path )
1056  : QgsDataItem( QgsDataItem::Error, parent, error, path )
1057 {
1058  mIconName = "/mIconDelete.png";
1059 
1060  setState( Populated ); // no more children
1061 }
1062 
1064 {
1065 }
1066 
1068  : QgsDataCollectionItem( parent, name, "favourites:" )
1069 {
1070  Q_UNUSED( path );
1071  mCapabilities |= Fast;
1072  mType = Favourites;
1073  mIconName = "/mIconFavourites.png";
1074  populate();
1075 }
1076 
1078 {
1079 }
1080 
1082 {
1084 
1085  QSettings settings;
1086  QStringList favDirs = settings.value( "/browser/favourites", QVariant() ).toStringList();
1087 
1088  Q_FOREACH ( const QString& favDir, favDirs )
1089  {
1090  QString pathName = pathComponent( favDir );
1091  QgsDataItem *item = new QgsDirectoryItem( this, favDir, favDir, mPath + "/" + pathName );
1092  if ( item )
1093  {
1094  children.append( item );
1095  }
1096  }
1097 
1098  return children;
1099 }
1100 
1102 {
1103  QSettings settings;
1104  QStringList favDirs = settings.value( "/browser/favourites" ).toStringList();
1105  favDirs.append( favDir );
1106  settings.setValue( "/browser/favourites", favDirs );
1107 
1108  if ( state() == Populated )
1109  {
1110  QString pathName = pathComponent( favDir );
1111  addChildItem( new QgsDirectoryItem( this, favDir, favDir, mPath + "/" + pathName ), true );
1112  }
1113 }
1114 
1116 {
1117  if ( !item )
1118  return;
1119 
1120  QSettings settings;
1121  QStringList favDirs = settings.value( "/browser/favourites" ).toStringList();
1122  favDirs.removeAll( item->dirPath() );
1123  settings.setValue( "/browser/favourites", favDirs );
1124 
1125  int idx = findItem( mChildren, item );
1126  if ( idx < 0 )
1127  {
1128  QgsDebugMsg( QString( "favourites item %1 not found" ).arg( item->path() ) );
1129  return;
1130  }
1131 
1132  if ( state() == Populated )
1133  deleteChildItem( mChildren[idx] );
1134 }
1135 
1136 //-----------------------------------------------------------------------
1139 
1140 
1141 QgsZipItem::QgsZipItem( QgsDataItem* parent, const QString& name, const QString& path )
1142  : QgsDataCollectionItem( parent, name, path )
1143 {
1144  mFilePath = path;
1145  init();
1146 }
1147 
1148 QgsZipItem::QgsZipItem( QgsDataItem* parent, const QString& name, const QString& filePath, const QString& path )
1149  : QgsDataCollectionItem( parent, name, path )
1150  , mFilePath( filePath )
1151 {
1152  init();
1153 }
1154 
1155 void QgsZipItem::init()
1156 {
1157  mType = Collection; //Zip??
1158  mIconName = "/mIconZip.png";
1160 
1161  if ( mProviderNames.size() == 0 )
1162  {
1163  // QStringList keys = QgsProviderRegistry::instance()->providerList();
1164  // only use GDAL and OGR providers as we use the VSIFILE mechanism
1165  QStringList keys;
1166  // keys << "ogr" << "gdal";
1167  keys << "gdal" << "ogr";
1168 
1170  for ( i = keys.begin(); i != keys.end(); ++i )
1171  {
1172  QString k( *i );
1173  QgsDebugMsg( "provider " + k );
1174  // some providers hangs with empty uri (Postgis) etc...
1175  // -> using libraries directly
1177  if ( library )
1178  {
1179  dataCapabilities_t * dataCapabilities = ( dataCapabilities_t * ) cast_to_fptr( library->resolve( "dataCapabilities" ) );
1180  if ( !dataCapabilities )
1181  {
1182  QgsDebugMsg( library->fileName() + " does not have dataCapabilities" );
1183  continue;
1184  }
1185  if ( dataCapabilities() == QgsDataProvider::NoDataCapabilities )
1186  {
1187  QgsDebugMsg( library->fileName() + " has NoDataCapabilities" );
1188  continue;
1189  }
1190  QgsDebugMsg( QString( "%1 dataCapabilities : %2" ).arg( library->fileName() ).arg( dataCapabilities() ) );
1191 
1192  dataItem_t * dataItem = ( dataItem_t * ) cast_to_fptr( library->resolve( "dataItem" ) );
1193  if ( ! dataItem )
1194  {
1195  QgsDebugMsg( library->fileName() + " does not have dataItem" );
1196  continue;
1197  }
1198 
1199  // mLibraries.append( library );
1200  mDataItemPtr.append( dataItem );
1201  mProviderNames.append( k );
1202  }
1203  else
1204  {
1205  //QgsDebugMsg ( "Cannot get provider " + k );
1206  }
1207  }
1208  }
1209 
1210 }
1211 
1213 {
1214 }
1215 
1216 // internal function to scan a vsidir (zip or tar file) recursively
1217 // GDAL trunk has this since r24423 (05/16/12) - VSIReadDirRecursive()
1218 // use a copy of the function internally for now,
1219 // but use char ** and CSLAddString, because CPLStringList was added in gdal-1.9
1220 char **VSIReadDirRecursive1( const char *pszPath )
1221 {
1222  // CPLStringList oFiles = NULL;
1223  char **papszOFiles = NULL;
1224  char **papszFiles1 = NULL;
1225  char **papszFiles2 = NULL;
1226  VSIStatBufL psStatBuf;
1227  CPLString osTemp1, osTemp2;
1228  int i, j;
1229  int nCount1, nCount2;
1230 
1231  // get listing
1232  papszFiles1 = VSIReadDir( pszPath );
1233  if ( ! papszFiles1 )
1234  return NULL;
1235 
1236  // get files and directories inside listing
1237  nCount1 = CSLCount( papszFiles1 );
1238  for ( i = 0; i < nCount1; i++ )
1239  {
1240  // build complete file name for stat
1241  osTemp1.clear();
1242  osTemp1.append( pszPath );
1243  osTemp1.append( "/" );
1244  osTemp1.append( papszFiles1[i] );
1245 
1246  // if is file, add it
1247  if ( VSIStatL( osTemp1.c_str(), &psStatBuf ) == 0 &&
1248  VSI_ISREG( psStatBuf.st_mode ) )
1249  {
1250  // oFiles.AddString( papszFiles1[i] );
1251  papszOFiles = CSLAddString( papszOFiles, papszFiles1[i] );
1252  }
1253  else if ( VSIStatL( osTemp1.c_str(), &psStatBuf ) == 0 &&
1254  VSI_ISDIR( psStatBuf.st_mode ) )
1255  {
1256  // add directory entry
1257  osTemp2.clear();
1258  osTemp2.append( papszFiles1[i] );
1259  osTemp2.append( "/" );
1260  // oFiles.AddString( osTemp2.c_str() );
1261  papszOFiles = CSLAddString( papszOFiles, osTemp2.c_str() );
1262 
1263  // recursively add files inside directory
1264  papszFiles2 = VSIReadDirRecursive1( osTemp1.c_str() );
1265  if ( papszFiles2 )
1266  {
1267  nCount2 = CSLCount( papszFiles2 );
1268  for ( j = 0; j < nCount2; j++ )
1269  {
1270  osTemp2.clear();
1271  osTemp2.append( papszFiles1[i] );
1272  osTemp2.append( "/" );
1273  osTemp2.append( papszFiles2[j] );
1274  // oFiles.AddString( osTemp2.c_str() );
1275  papszOFiles = CSLAddString( papszOFiles, osTemp2.c_str() );
1276  }
1277  CSLDestroy( papszFiles2 );
1278  }
1279  }
1280  }
1281  CSLDestroy( papszFiles1 );
1282 
1283  // return oFiles.StealList();
1284  return papszOFiles;
1285 }
1286 
1288 {
1290  QString tmpPath;
1291  QSettings settings;
1292  QString scanZipSetting = settings.value( "/qgis/scanZipInBrowser2", "basic" ).toString();
1293 
1294  mZipFileList.clear();
1295 
1296  QgsDebugMsgLevel( QString( "mFilePath = %1 path = %2 name= %3 scanZipSetting= %4 vsiPrefix= %5" ).arg( mFilePath, path(), name(), scanZipSetting, mVsiPrefix ), 2 );
1297 
1298  // if scanZipBrowser == no: skip to the next file
1299  if ( scanZipSetting == "no" )
1300  {
1301  return children;
1302  }
1303 
1304  // first get list of files
1305  getZipFileList();
1306 
1307  // loop over files inside zip
1308  Q_FOREACH ( const QString& fileName, mZipFileList )
1309  {
1310  QFileInfo info( fileName );
1311  tmpPath = mVsiPrefix + mFilePath + "/" + fileName;
1312  QgsDebugMsgLevel( "tmpPath = " + tmpPath, 3 );
1313 
1314  // Q_FOREACH( dataItem_t *dataItem, mDataItemPtr )
1315  for ( int i = 0; i < mProviderNames.size(); i++ )
1316  {
1317  // ugly hack to remove .dbf file if there is a .shp file
1318  if ( mProviderNames[i] == "ogr" )
1319  {
1320  if ( info.suffix().toLower() == "dbf" )
1321  {
1322  if ( mZipFileList.indexOf( fileName.left( fileName.count() - 4 ) + ".shp" ) != -1 )
1323  continue;
1324  }
1325  if ( info.completeSuffix().toLower() == "shp.xml" )
1326  {
1327  continue;
1328  }
1329  }
1330 
1331  // try to get data item from provider
1332  dataItem_t *dataItem = mDataItemPtr[i];
1333  if ( dataItem )
1334  {
1335  QgsDebugMsgLevel( QString( "trying to load item %1 with %2" ).arg( tmpPath, mProviderNames[i] ), 3 );
1336  QgsDataItem * item = dataItem( tmpPath, this );
1337  if ( item )
1338  {
1339  QgsDebugMsgLevel( "loaded item", 3 );
1340  // the item comes with zipped file name, set the name to relative path within zip file
1341  item->setName( fileName );
1342  children.append( item );
1343  break;
1344  }
1345  else
1346  {
1347  QgsDebugMsgLevel( "not loaded item", 3 );
1348  }
1349  }
1350  }
1351 
1352  }
1353 
1354  return children;
1355 }
1356 
1358 {
1359  return itemFromPath( parent, path, name, path );
1360 }
1361 
1362 QgsDataItem* QgsZipItem::itemFromPath( QgsDataItem* parent, const QString& filePath, const QString& name, const QString& path )
1363 {
1364  QSettings settings;
1365  QString scanZipSetting = settings.value( "/qgis/scanZipInBrowser2", "basic" ).toString();
1366  int zipFileCount = 0;
1367  QStringList zipFileList;
1368  QFileInfo fileInfo( filePath );
1369  QString vsiPrefix = QgsZipItem::vsiPrefix( filePath );
1370  QgsZipItem * zipItem = 0;
1371  bool populated = false;
1372 
1373  QgsDebugMsgLevel( QString( "path = %1 name= %2 scanZipSetting= %3 vsiPrefix= %4" ).arg( path, name, scanZipSetting, vsiPrefix ), 3 );
1374 
1375  // don't scan if scanZipBrowser == no
1376  if ( scanZipSetting == "no" )
1377  return 0;
1378 
1379  // don't scan if this file is not a /vsizip/ or /vsitar/ item
1380  if (( vsiPrefix != "/vsizip/" && vsiPrefix != "/vsitar/" ) )
1381  return 0;
1382 
1383  zipItem = new QgsZipItem( parent, name, filePath, path );
1384 
1385  if ( zipItem )
1386  {
1387  // force populate zipItem if it has less than 10 items and is not a .tgz or .tar.gz file (slow loading)
1388  // for other items populating will be delayed until item is opened
1389  // this might be polluting the tree with empty items but is necessary for performance reasons
1390  // could also accept all files smaller than a certain size and add options for file count and/or size
1391 
1392  // first get list of files inside .zip or .tar files
1393  if ( path.endsWith( ".zip", Qt::CaseInsensitive ) ||
1394  path.endsWith( ".tar", Qt::CaseInsensitive ) )
1395  {
1396  zipFileList = zipItem->getZipFileList();
1397  }
1398  // force populate if less than 10 items
1399  if ( zipFileList.count() > 0 && zipFileList.count() <= 10 )
1400  {
1401  zipItem->populate( zipItem->createChildren() );
1402  populated = true; // there is no QgsDataItem::isPopulated() function
1403  QgsDebugMsgLevel( QString( "Got zipItem with %1 children, path=%2, name=%3" ).arg( zipItem->rowCount() ).arg( zipItem->path(), zipItem->name() ), 3 );
1404  }
1405  else
1406  {
1407  QgsDebugMsgLevel( QString( "Delaying populating zipItem with path=%1, name=%2" ).arg( zipItem->path(), zipItem->name() ), 3 );
1408  }
1409  }
1410 
1411  // only display if has children or if is not populated
1412  if ( zipItem && ( !populated || zipItem->rowCount() > 1 ) )
1413  {
1414  QgsDebugMsgLevel( "returning zipItem", 3 );
1415  return zipItem;
1416  }
1417  // if 1 or 0 child found, create a single data item using the normal path or the full path given by QgsZipItem
1418  else
1419  {
1420  QString vsiPath = vsiPrefix + filePath;
1421  if ( zipItem )
1422  {
1423  QVector<QgsDataItem*> children = zipItem->children();
1424  if ( children.size() == 1 )
1425  {
1426  // take the name of the only child so we can get a normal data item from it
1427  QgsLayerItem *layerItem = qobject_cast<QgsLayerItem*>( children.first() );
1428  if ( layerItem )
1429  vsiPath = layerItem->uri();
1430  }
1431  zipFileCount = zipFileList.count();
1432  delete zipItem;
1433  }
1434 
1435  QgsDebugMsgLevel( QString( "will try to create a normal dataItem from filePath= %2 or vsiPath = %3" ).arg( filePath, vsiPath ), 3 );
1436 
1437  // try to open using registered providers (gdal and ogr)
1438  for ( int i = 0; i < mProviderNames.size(); i++ )
1439  {
1440  dataItem_t *dataItem = mDataItemPtr[i];
1441  if ( dataItem )
1442  {
1443  QgsDataItem *item = 0;
1444  // try first with normal path (Passthru)
1445  // this is to simplify .qml handling, and without this some tests will fail
1446  // (e.g. testZipItemVectorTransparency(), second test)
1447  if (( mProviderNames[i] == "ogr" ) ||
1448  ( mProviderNames[i] == "gdal" && zipFileCount == 1 ) )
1449  item = dataItem( filePath, parent );
1450  // try with /vsizip/
1451  if ( ! item )
1452  item = dataItem( vsiPath, parent );
1453  if ( item )
1454  return item;
1455  }
1456  }
1457  }
1458 
1459  return 0;
1460 }
1461 
1463 {
1464  if ( ! mZipFileList.isEmpty() )
1465  return mZipFileList;
1466 
1467  QString tmpPath;
1468  QSettings settings;
1469  QString scanZipSetting = settings.value( "/qgis/scanZipInBrowser2", "basic" ).toString();
1470 
1471  QgsDebugMsgLevel( QString( "mFilePath = %1 name= %2 scanZipSetting= %3 vsiPrefix= %4" ).arg( mFilePath, name(), scanZipSetting, mVsiPrefix ), 3 );
1472 
1473  // if scanZipBrowser == no: skip to the next file
1474  if ( scanZipSetting == "no" )
1475  {
1476  return mZipFileList;
1477  }
1478 
1479  // get list of files inside zip file
1480  QgsDebugMsgLevel( QString( "Open file %1 with gdal vsi" ).arg( mVsiPrefix + mFilePath ), 3 );
1481  char **papszSiblingFiles = VSIReadDirRecursive1( QString( mVsiPrefix + mFilePath ).toLocal8Bit().constData() );
1482  if ( papszSiblingFiles )
1483  {
1484  for ( int i = 0; i < CSLCount( papszSiblingFiles ); i++ )
1485  {
1486  tmpPath = papszSiblingFiles[i];
1487  QgsDebugMsgLevel( QString( "Read file %1" ).arg( tmpPath ), 3 );
1488  // skip directories (files ending with /)
1489  if ( tmpPath.right( 1 ) != "/" )
1490  mZipFileList << tmpPath;
1491  }
1492  CSLDestroy( papszSiblingFiles );
1493  }
1494  else
1495  {
1496  QgsDebugMsg( QString( "Error reading %1" ).arg( mFilePath ) );
1497  }
1498 
1499  return mZipFileList;
1500 }
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:359
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:231
int localeAwareCompare(const QString &other) const
QVector< QgsDataItem * > children() const
Definition: qgsdataitem.h:180
QString name() const
Definition: qgsdataitem.h:182
LayerType
Layers enum defining the types of layers that can be added to a map.
Definition: qgsmaplayer.h:55
QPixmap currentPixmap() const
void append(const T &value)
virtual Capabilities capabilities2() const
Definition: qgsdataitem.h:161
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:176
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:335
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()
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:390
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:229
virtual const QMetaObject * metaObject() const
State mState
Definition: qgsdataitem.h:219
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:312
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:472
virtual bool equal(const QgsDataItem *other)
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:477
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:402
#define QgsDebugMsgLevel(str, level)
Definition: qgslogger.h:34
bool isDir() const
QString mName
Definition: qgsdataitem.h:222
QStringList mZipFileList
Definition: qgsdataitem.h:479
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:104
void onFrameChanged()
Definition: qgsdataitem.cpp:71
Creating children in separate thread (populating or refreshing)
Definition: qgsdataitem.h:105
QString path() const
Definition: qgsdataitem.h:184
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:172
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()
QgsDirectoryParamWidget(const QString &path, QWidget *parent=NULL)
static QStringList mProviderNames
Definition: qgsdataitem.h:491
QAction * exec()
void setFuture(const QFuture< T > &future)
virtual bool equal(const QgsDataItem *other) override
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:373
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:216
void emitDataChanged()
virtual void setState(State state)
Set item state.
void setCheckable(bool)
virtual void addChildItem(QgsDataItem *child, bool refresh=false)
void setName(const QString &name)
Definition: qgsdataitem.h:183
static QVector< dataItem_t * > mDataItemPtr
Definition: qgsdataitem.h:490
Can create children. Even items without this capability may have children, but cannot create them...
Definition: qgsdataitem.h:149
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:227
QLibrary * providerLibrary(const QString &providerKey) const
#define Q_NOWARN_DEPRECATED_POP
Definition: qgis.h:391
QString mUri
The URI.
Definition: qgsdataitem.h:337
void waitForFinished()
void setHeaderLabels(const QStringList &labels)
QString & replace(int position, int n, QChar after)
static int findItem(QVector< QgsDataItem * > items, QgsDataItem *item)
void moveToThread(QThread *targetThread)
Move object and all its descendants to thread.
QVariant value(const QString &key, const QVariant &defaultValue) const
QgsAnimatedIcon(const QString &iconPath=QString::null)
Constructor.
Definition: qgsdataitem.cpp:46
T result() const
virtual Q_DECL_DEPRECATED Capability capabilities()
Definition: qgsdataitem.h:159
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:478
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
int count(const T &value) const
QgsMapLayer::LayerType mapLayerType()
Returns QgsMapLayer::LayerType.
QgsDataItem * mParent
Definition: qgsdataitem.h:217
bool deferredDelete()
The item is scheduled to be deleted.
Definition: qgsdataitem.h:213
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:221
QVector< QgsDataItem * > createChildren() override
Create children.
Item that represents a layer that can be opened with one of the providers.
Definition: qgsdataitem.h:282
void start()
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:241
virtual QgsDataItem * removeChildItem(QgsDataItem *child)
static Q_DECL_DEPRECATED QVector< QLibrary * > mLibraries
Definition: qgsdataitem.h:410
virtual void deleteChildItem(QgsDataItem *child)
QVector< QgsDataItem * > mChildren
Definition: qgsdataitem.h:218
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)
void setRootIsDecorated(bool show)
children created
Definition: qgsdataitem.h:106
LayerType mLayerType
The layer type.
Definition: qgsdataitem.h:339
virtual bool equal(const QgsDataItem *other) override
bool connect(const QObject *sender, const char *signal, const QObject *receiver, const char *method, Qt::ConnectionType type)
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:150
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:493
const QStringList & getZipFileList()
added in 2.10
Definition: qgsdataitem.h:297
const T value(const Key &key) const
void frameChanged()
Emitted when icon changed.