QGIS API Documentation  2.11.0-Master
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 
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 ).arg( mPath ).arg( mChildren.size() ), 2 );
227  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 
245 {
246  return QString( string ).replace( QRegExp( "[\\\\/]" ), "|" );
247 }
248 
250 {
251  QgsDebugMsg( "path = " + path() );
252  setParent( 0 ); // also disconnects parent
253  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  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  foreach ( QgsDataItem* child, mChildren )
287  {
288  if ( !child ) // should not happen
289  continue;
290  QgsDebugMsg( "moveToThread child " + child->path() );
291  child->QObject::setParent( 0 ); // 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 
313 void QgsDataItem::emitBeginInsertItems( QgsDataItem* parent, int first, int last )
314 {
315  emit beginInsertItems( parent, first, last );
316 }
318 {
319  emit endInsertItems();
320 }
321 void QgsDataItem::emitBeginRemoveItems( QgsDataItem* parent, int first, int last )
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  foreach ( QgsDataItem* child, children )
387  {
388  if ( !child ) // should not happen
389  continue;
390  QgsDebugMsg( "moveToThread child " + child->path() );
391  child->moveToThread( QApplication::instance()->thread() ); // moves also children
392  }
393  QgsDebugMsg( QString( "finished path %1: %2 children" ).arg( item->path() ).arg( children.size() ) );
394  return children;
395 }
396 
398 {
399  QgsDebugMsg( QString( "path = %1 children.size() = %2" ).arg( path() ).arg( mFutureWatcher->result().size() ) );
400 
401  if ( deferredDelete() )
402  {
403  QgsDebugMsg( "Item was scheduled to be deleted later" );
405  return;
406  }
407 
408  if ( mChildren.size() == 0 ) // usually populating but may also be refresh if originaly there were no children
409  {
410  populate( mFutureWatcher->result() );
411  }
412  else // refreshing
413  {
414  refresh( mFutureWatcher->result() );
415  }
416  disconnect( mFutureWatcher, SIGNAL( finished() ), this, SLOT( childrenCreated() ) );
417  emit dataChanged( this ); // to replace loading icon by normal icon
418 }
419 
421 {
422  QgsDebugMsg( "mPath = " + mPath );
423 
424  foreach ( QgsDataItem *child, children )
425  {
426  if ( !child ) // should not happen
427  continue;
428  // update after thread finished -> refresh
429  addChildItem( child, true );
430  }
431  setState( Populated );
432 }
433 
435 {
436  QgsDebugMsg( "mPath = " + mPath );
437 
438  foreach ( QgsDataItem *child, mChildren )
439  {
440  QgsDebugMsg( "remove " + child->path() );
441  child->depopulate(); // recursive
442  deleteChildItem( child );
443  }
445 }
446 
448 {
449  if ( state() == Populating )
450  return;
451 
452  QgsDebugMsg( "mPath = " + mPath );
453 
455  {
456  refresh( createChildren() );
457  }
458  else
459  {
460  setState( Populating );
461  if ( !mFutureWatcher )
462  {
463  mFutureWatcher = new QFutureWatcher< QVector <QgsDataItem*> >( this );
464  }
465  connect( mFutureWatcher, SIGNAL( finished() ), SLOT( childrenCreated() ) );
466  mFutureWatcher->setFuture( QtConcurrent::run( runCreateChildren, this ) );
467  }
468 }
469 
471 {
472  QgsDebugMsgLevel( "mPath = " + mPath, 2 );
473 
474  // Remove no more present children
475  QVector<QgsDataItem*> remove;
476  foreach ( QgsDataItem *child, mChildren )
477  {
478  if ( !child ) // should not happen
479  continue;
480  if ( findItem( children, child ) >= 0 )
481  continue;
482  remove.append( child );
483  }
484  foreach ( QgsDataItem *child, remove )
485  {
486  QgsDebugMsg( "remove " + child->path() );
487  deleteChildItem( child );
488  }
489 
490  // Add new children
491  foreach ( QgsDataItem *child, children )
492  {
493  if ( !child ) // should not happen
494  continue;
495 
496  int index = findItem( mChildren, child );
497  if ( index >= 0 )
498  {
499  // Refresh recursively (some providers may create more generations of descendants)
500  if ( !( child->capabilities2() & QgsDataItem::Fertile ) )
501  {
502  // The child cannot createChildren() itself
503  mChildren.value( index )->refresh( child->children() );
504  }
505 
506  child->deleteLater();
507  continue;
508  }
509  addChildItem( child, true );
510  }
511  setState( Populated );
512 }
513 
515 {
516  return mChildren.size();
517 }
519 {
520  return ( state() == Populated ? mChildren.count() > 0 : true );
521 }
522 
524 {
525  if ( mParent )
526  {
527  disconnect( this, 0, mParent, 0 );
528  }
529  if ( parent )
530  {
531  connect( this, SIGNAL( beginInsertItems( QgsDataItem*, int, int ) ),
532  parent, SLOT( emitBeginInsertItems( QgsDataItem*, int, int ) ) );
533  connect( this, SIGNAL( endInsertItems() ),
534  parent, SLOT( emitEndInsertItems() ) );
535  connect( this, SIGNAL( beginRemoveItems( QgsDataItem*, int, int ) ),
536  parent, SLOT( emitBeginRemoveItems( QgsDataItem*, int, int ) ) );
537  connect( this, SIGNAL( endRemoveItems() ),
538  parent, SLOT( emitEndRemoveItems() ) );
539  connect( this, SIGNAL( dataChanged( QgsDataItem* ) ),
540  parent, SLOT( emitDataChanged( QgsDataItem* ) ) );
541  connect( this, SIGNAL( stateChanged( QgsDataItem*, QgsDataItem::State ) ),
542  parent, SLOT( emitStateChanged( QgsDataItem*, QgsDataItem::State ) ) );
543  }
544  mParent = parent;
545 }
546 
547 void QgsDataItem::addChildItem( QgsDataItem * child, bool refresh )
548 {
549  Q_ASSERT( child );
550  QgsDebugMsg( QString( "path = %1 add child #%2 - %3 - %4" ).arg( mPath ).arg( mChildren.size() ).arg( child->mName ).arg( child->mType ) );
551 
552  int i;
553  if ( type() == Directory )
554  {
555  for ( i = 0; i < mChildren.size(); i++ )
556  {
557  // sort items by type, so directories are before data items
558  if ( mChildren[i]->mType == child->mType &&
559  mChildren[i]->mName.localeAwareCompare( child->mName ) > 0 )
560  break;
561  }
562  }
563  else
564  {
565  for ( i = 0; i < mChildren.size(); i++ )
566  {
567  if ( mChildren[i]->mName.localeAwareCompare( child->mName ) >= 0 )
568  break;
569  }
570  }
571 
572  if ( refresh )
573  emit beginInsertItems( this, i, i );
574 
575  mChildren.insert( i, child );
576  child->setParent( this );
577 
578  if ( refresh )
579  emit endInsertItems();
580 }
582 {
583  QgsDebugMsgLevel( "mName = " + child->mName, 2 );
584  int i = mChildren.indexOf( child );
585  Q_ASSERT( i >= 0 );
586  emit beginRemoveItems( this, i, i );
587  mChildren.remove( i );
588  child->deleteLater();
589  emit endRemoveItems();
590 }
591 
593 {
594  QgsDebugMsgLevel( "mName = " + child->mName, 2 );
595  int i = mChildren.indexOf( child );
596  Q_ASSERT( i >= 0 );
597  emit beginRemoveItems( this, i, i );
598  mChildren.remove( i );
599  emit endRemoveItems();
600  child->setParent( 0 );
601  return child;
602 }
603 
605 {
606  for ( int i = 0; i < items.size(); i++ )
607  {
608  Q_ASSERT_X( items[i], "findItem", QString( "item %1 is NULL" ).arg( i ).toAscii() );
609  QgsDebugMsgLevel( QString::number( i ) + " : " + items[i]->mPath + " x " + item->mPath, 2 );
610  if ( items[i]->equal( item ) )
611  return i;
612  }
613  return -1;
614 }
615 
616 bool QgsDataItem::equal( const QgsDataItem *other )
617 {
618  if ( metaObject()->className() == other->metaObject()->className() &&
619  mPath == other->path() )
620  {
621  return true;
622  }
623  return false;
624 }
625 
627 {
628  // for backward compatibility (if subclass set mPopulated directly)
629  // TODO: remove in 3.0
630  if ( mPopulated )
631  return Populated;
632  return mState;
633 }
634 
636 {
637  QgsDebugMsg( QString( "item %1 set state %2 -> %3" ).arg( path() ).arg( this->state() ).arg( state ) );
638  if ( state == mState )
639  return;
640 
641  State oldState = mState;
642 
643  if ( state == Populating ) // start loading
644  {
645  if ( !mPopulatingIcon )
646  {
647  // TODO: ensure that QgsAnimatedIcon is created on UI thread only
648  mPopulatingIcon = new QgsAnimatedIcon( QgsApplication::iconPath( "/mIconLoading.gif" ) );
649  }
650  mPopulatingIcon->connectFrameChanged( this, SLOT( emitDataChanged() ) );
651  }
652  else if ( mState == Populating && mPopulatingIcon ) // stop loading
653  {
654  mPopulatingIcon->disconnectFrameChanged( this, SLOT( emitDataChanged() ) );
655  }
656 
657  mState = state;
658  // for backward compatibility (if subclass access mPopulated directly)
659  // TODO: remove in 3.0
660  mPopulated = state == Populated;
661 
662  emit stateChanged( this, oldState );
663 }
664 
665 // ---------------------------------------------------------------------
666 
667 QgsLayerItem::QgsLayerItem( QgsDataItem* parent, QString name, QString path, QString uri, LayerType layerType, QString providerKey )
668  : QgsDataItem( Layer, parent, name, path )
669  , mProviderKey( providerKey )
670  , mUri( uri )
671  , mLayerType( layerType )
672 {
673  switch ( layerType )
674  {
675  case Point: mIconName = "/mIconPointLayer.svg"; break;
676  case Line: mIconName = "/mIconLineLayer.svg"; break;
677  case Polygon: mIconName = "/mIconPolygonLayer.svg"; break;
678  // TODO add a new icon for generic Vector layers
679  case Vector : mIconName = "/mIconPolygonLayer.svg"; break;
680  case TableLayer: mIconName = "/mIconTableLayer.png"; break;
681  case Raster: mIconName = "/mIconRaster.svg"; break;
682  default: mIconName = "/mIconLayer.png"; break;
683  }
684 }
685 
687 {
693 }
694 
695 bool QgsLayerItem::equal( const QgsDataItem *other )
696 {
697  //QgsDebugMsg ( mPath + " x " + other->mPath );
698  if ( type() != other->type() )
699  {
700  return false;
701  }
702  //const QgsLayerItem *o = qobject_cast<const QgsLayerItem *> ( other );
703  const QgsLayerItem *o = dynamic_cast<const QgsLayerItem *>( other );
704  if ( !o )
705  return false;
706 
707  return ( mPath == o->mPath && mName == o->mName && mUri == o->mUri && mProviderKey == o->mProviderKey );
708 }
709 
710 // ---------------------------------------------------------------------
712  : QgsDataItem( Collection, parent, name, path )
713 {
715  mIconName = "/mIconDbSchema.png";
716 }
717 
719 {
720  QgsDebugMsgLevel( "mName = " + mName + " mPath = " + mPath, 2 );
721 
722 // Do not delete children, children are deleted by QObject parent
723 #if 0
724  foreach ( QgsDataItem* i, mChildren )
725  {
726  QgsDebugMsgLevel( QString( "delete child = 0x%0" ).arg(( qlonglong )i, 8, 16, QLatin1Char( '0' ) ), 2 );
727  delete i;
728  }
729 #endif
730 }
731 
732 //-----------------------------------------------------------------------
733 // QVector<QgsDataProvider*> QgsDirectoryItem::mProviders = QVector<QgsDataProvider*>();
735 
737  : QgsDataCollectionItem( parent, name, path )
738  , mDirPath( path )
739  , mFileSystemWatcher( 0 )
740  , mRefreshLater( false )
741 {
742  mType = Directory;
743  init();
744 }
745 
747  : QgsDataCollectionItem( parent, name, path )
748  , mDirPath( dirPath )
749  , mFileSystemWatcher( 0 )
750  , mRefreshLater( false )
751 {
752  mType = Directory;
753  init();
754 }
755 
757 {
758 }
759 
761 {
762 }
763 
765 {
766  if ( state() == Populating )
767  return QgsDataItem::icon();
768  return iconDir();
769 }
770 
771 
773 {
775  QDir dir( mDirPath );
776  QSettings settings;
777 
778  QStringList entries = dir.entryList( QDir::AllDirs | QDir::NoDotAndDotDot, QDir::Name | QDir::IgnoreCase );
779  foreach ( QString subdir, entries )
780  {
781  if ( mRefreshLater )
782  {
783  deleteLater( children );
784  return children;
785  }
786  QString subdirPath = dir.absoluteFilePath( subdir );
787  QgsDebugMsgLevel( QString( "creating subdir: %1" ).arg( subdirPath ), 2 );
788 
789  QString path = mPath + "/" + subdir; // may differ from subdirPath
790  QgsDirectoryItem *item = new QgsDirectoryItem( this, subdir, subdirPath, path );
791  // propagate signals up to top
792 
793  children.append( item );
794  }
795 
796  QStringList fileEntries = dir.entryList( QDir::Dirs | QDir::NoDotAndDotDot | QDir::Files, QDir::Name );
797  foreach ( QString name, fileEntries )
798  {
799  if ( mRefreshLater )
800  {
801  deleteLater( children );
802  return children;
803  }
804 
805  QString path = dir.absoluteFilePath( name );
806  QFileInfo fileInfo( path );
807 
808  // vsizip support was added to GDAL/OGR 1.6 but GDAL_VERSION_NUM not available here
809  // so we assume it's available anyway
810  {
811  QgsDataItem * item = QgsZipItem::itemFromPath( this, path, name, mPath + "/" + name );
812  if ( item )
813  {
814  children.append( item );
815  continue;
816  }
817  }
818 
819  foreach ( QgsDataItemProvider* provider, QgsDataItemProviderRegistry::instance()->providers() )
820  {
821  int capabilities = provider->capabilities();
822 
823  if ( !(( fileInfo.isFile() && ( capabilities & QgsDataProvider::File ) ) ||
824  ( fileInfo.isDir() && ( capabilities & QgsDataProvider::Dir ) ) ) )
825  {
826  continue;
827  }
828 
829  QgsDataItem * item = provider->createDataItem( path, this );
830  if ( item )
831  {
832  children.append( item );
833  }
834  }
835 
836  }
837 
838  return children;
839 }
840 
842 {
843  QgsDebugMsg( "Entered" );
845 
846  if ( state == Populated )
847  {
848  if ( !mFileSystemWatcher )
849  {
850  mFileSystemWatcher = new QFileSystemWatcher( this );
851  mFileSystemWatcher->addPath( mDirPath );
852  connect( mFileSystemWatcher, SIGNAL( directoryChanged( const QString & ) ), SLOT( directoryChanged() ) );
853  }
854  }
855  else if ( state == NotPopulated )
856  {
857  if ( mFileSystemWatcher )
858  {
859  delete mFileSystemWatcher;
860  mFileSystemWatcher = 0;
861  }
862  }
863 }
864 
866 {
867  QgsDebugMsg( "Entered" );
868  if ( state() == Populating )
869  {
870  // schedule to refresh later, because refres() simply returns if Populating
871  mRefreshLater = true;
872  }
873  else
874  {
875  refresh();
876  }
877 }
878 
880 {
881  QgsDebugMsg( QString( "mRefreshLater = %1" ).arg( mRefreshLater ) );
882 
883  if ( mRefreshLater )
884  {
885  QgsDebugMsg( "directory changed during createChidren() -> refresh() again" );
886  mRefreshLater = false;
887  setState( Populated );
888  refresh();
889  }
890  else
891  {
893  }
894 }
895 
897 {
898  //QgsDebugMsg ( mPath + " x " + other->mPath );
899  if ( type() != other->type() )
900  {
901  return false;
902  }
903  return ( path() == other->path() );
904 }
905 
907 {
908  return new QgsDirectoryParamWidget( mPath );
909 }
910 
912  : QTreeWidget( parent )
913 {
914  setRootIsDecorated( false );
915 
916  // name, size, date, permissions, owner, group, type
917  setColumnCount( 7 );
918  QStringList labels;
919  labels << tr( "Name" ) << tr( "Size" ) << tr( "Date" ) << tr( "Permissions" ) << tr( "Owner" ) << tr( "Group" ) << tr( "Type" );
920  setHeaderLabels( labels );
921 
923  QIcon iconDirectory = QIcon( style->standardPixmap( QStyle::SP_DirClosedIcon ) );
924  QIcon iconFile = QIcon( style->standardPixmap( QStyle::SP_FileIcon ) );
925  QIcon iconDirLink = QIcon( style->standardPixmap( QStyle::SP_DirLinkIcon ) );
926  QIcon iconFileLink = QIcon( style->standardPixmap( QStyle::SP_FileLinkIcon ) );
927 
929 
930  QDir dir( path );
931  QStringList entries = dir.entryList( QDir::AllEntries | QDir::NoDotAndDotDot, QDir::Name | QDir::IgnoreCase );
932  foreach ( QString name, entries )
933  {
934  QFileInfo fi( dir.absoluteFilePath( name ) );
935  QStringList texts;
936  texts << name;
937  QString size;
938  if ( fi.size() > 1024 )
939  {
940  size = size.sprintf( "%.1f KiB", fi.size() / 1024.0 );
941  }
942  else if ( fi.size() > 1.048576e6 )
943  {
944  size = size.sprintf( "%.1f MiB", fi.size() / 1.048576e6 );
945  }
946  else
947  {
948  size = QString( "%1 B" ).arg( fi.size() );
949  }
950  texts << size;
951  texts << fi.lastModified().toString( Qt::SystemLocaleShortDate );
952  QString perm;
953  perm += fi.permission( QFile::ReadOwner ) ? 'r' : '-';
954  perm += fi.permission( QFile::WriteOwner ) ? 'w' : '-';
955  perm += fi.permission( QFile::ExeOwner ) ? 'x' : '-';
956  // QFile::ReadUser, QFile::WriteUser, QFile::ExeUser
957  perm += fi.permission( QFile::ReadGroup ) ? 'r' : '-';
958  perm += fi.permission( QFile::WriteGroup ) ? 'w' : '-';
959  perm += fi.permission( QFile::ExeGroup ) ? 'x' : '-';
960  perm += fi.permission( QFile::ReadOther ) ? 'r' : '-';
961  perm += fi.permission( QFile::WriteOther ) ? 'w' : '-';
962  perm += fi.permission( QFile::ExeOther ) ? 'x' : '-';
963  texts << perm;
964 
965  texts << fi.owner();
966  texts << fi.group();
967 
968  QString type;
969  QIcon icon;
970  if ( fi.isDir() && fi.isSymLink() )
971  {
972  type = tr( "folder" );
973  icon = iconDirLink;
974  }
975  else if ( fi.isDir() )
976  {
977  type = tr( "folder" );
978  icon = iconDirectory;
979  }
980  else if ( fi.isFile() && fi.isSymLink() )
981  {
982  type = tr( "file" );
983  icon = iconFileLink;
984  }
985  else if ( fi.isFile() )
986  {
987  type = tr( "file" );
988  icon = iconFile;
989  }
990 
991  texts << type;
992 
993  QTreeWidgetItem *item = new QTreeWidgetItem( texts );
994  item->setIcon( 0, icon );
995  items << item;
996  }
997 
998  addTopLevelItems( items );
999 
1000  // hide columns that are not requested
1001  QSettings settings;
1002  QList<QVariant> lst = settings.value( "/dataitem/directoryHiddenColumns" ).toList();
1003  foreach ( QVariant colVariant, lst )
1004  {
1005  setColumnHidden( colVariant.toInt(), true );
1006  }
1007 }
1008 
1010 {
1011  if ( event->button() == Qt::RightButton )
1012  {
1013  // show the popup menu
1014  QMenu popupMenu;
1015 
1016  QStringList labels;
1017  labels << tr( "Name" ) << tr( "Size" ) << tr( "Date" ) << tr( "Permissions" ) << tr( "Owner" ) << tr( "Group" ) << tr( "Type" );
1018  for ( int i = 0; i < labels.count(); i++ )
1019  {
1020  QAction* action = popupMenu.addAction( labels[i], this, SLOT( showHideColumn() ) );
1021  action->setObjectName( QString::number( i ) );
1022  action->setCheckable( true );
1023  action->setChecked( !isColumnHidden( i ) );
1024  }
1025 
1026  popupMenu.exec( event->globalPos() );
1027  }
1028 }
1029 
1031 {
1032  QAction* action = qobject_cast<QAction*>( sender() );
1033  if ( !action )
1034  return; // something is wrong
1035 
1036  int columnIndex = action->objectName().toInt();
1037  setColumnHidden( columnIndex, !isColumnHidden( columnIndex ) );
1038 
1039  // save in settings
1040  QSettings settings;
1041  QList<QVariant> lst;
1042  for ( int i = 0; i < columnCount(); i++ )
1043  {
1044  if ( isColumnHidden( i ) )
1045  lst.append( QVariant( i ) );
1046  }
1047  settings.setValue( "/dataitem/directoryHiddenColumns", lst );
1048 }
1049 
1050 
1052  : QgsDataItem( QgsDataItem::Error, parent, error, path )
1053 {
1054  mIconName = "/mIconDelete.png";
1055 
1056  setState( Populated ); // no more children
1057 }
1058 
1060 {
1061 }
1062 
1064  : QgsDataCollectionItem( parent, name, "favourites:" )
1065 {
1066  Q_UNUSED( path );
1067  mCapabilities |= Fast;
1068  mType = Favourites;
1069  mIconName = "/mIconFavourites.png";
1070  populate();
1071 }
1072 
1074 {
1075 }
1076 
1078 {
1080 
1081  QSettings settings;
1082  QStringList favDirs = settings.value( "/browser/favourites", QVariant() ).toStringList();
1083 
1084  foreach ( QString favDir, favDirs )
1085  {
1086  QString pathName = pathComponent( favDir );
1087  QgsDataItem *item = new QgsDirectoryItem( this, favDir, favDir, mPath + "/" + pathName );
1088  if ( item )
1089  {
1090  children.append( item );
1091  }
1092  }
1093 
1094  return children;
1095 }
1096 
1098 {
1099  QSettings settings;
1100  QStringList favDirs = settings.value( "/browser/favourites" ).toStringList();
1101  favDirs.append( favDir );
1102  settings.setValue( "/browser/favourites", favDirs );
1103 
1104  if ( state() == Populated )
1105  {
1106  QString pathName = pathComponent( favDir );
1107  addChildItem( new QgsDirectoryItem( this, favDir, favDir, mPath + "/" + pathName ), true );
1108  }
1109 }
1110 
1112 {
1113  if ( !item )
1114  return;
1115 
1116  QSettings settings;
1117  QStringList favDirs = settings.value( "/browser/favourites" ).toStringList();
1118  favDirs.removeAll( item->dirPath() );
1119  settings.setValue( "/browser/favourites", favDirs );
1120 
1121  int idx = findItem( mChildren, item );
1122  if ( idx < 0 )
1123  {
1124  QgsDebugMsg( QString( "favourites item %1 not found" ).arg( item->path() ) );
1125  return;
1126  }
1127 
1128  if ( state() == Populated )
1129  deleteChildItem( mChildren[idx] );
1130 }
1131 
1132 //-----------------------------------------------------------------------
1135 
1136 
1138  : QgsDataCollectionItem( parent, name, path )
1139 {
1140  mFilePath = path;
1141  init();
1142 }
1143 
1145  : QgsDataCollectionItem( parent, name, path )
1146  , mFilePath( filePath )
1147 {
1148  init();
1149 }
1150 
1151 void QgsZipItem::init()
1152 {
1153  mType = Collection; //Zip??
1154  mIconName = "/mIconZip.png";
1156 
1157  if ( mProviderNames.size() == 0 )
1158  {
1159  // QStringList keys = QgsProviderRegistry::instance()->providerList();
1160  // only use GDAL and OGR providers as we use the VSIFILE mechanism
1161  QStringList keys;
1162  // keys << "ogr" << "gdal";
1163  keys << "gdal" << "ogr";
1164 
1166  for ( i = keys.begin(); i != keys.end(); ++i )
1167  {
1168  QString k( *i );
1169  QgsDebugMsg( "provider " + k );
1170  // some providers hangs with empty uri (Postgis) etc...
1171  // -> using libraries directly
1173  if ( library )
1174  {
1175  dataCapabilities_t * dataCapabilities = ( dataCapabilities_t * ) cast_to_fptr( library->resolve( "dataCapabilities" ) );
1176  if ( !dataCapabilities )
1177  {
1178  QgsDebugMsg( library->fileName() + " does not have dataCapabilities" );
1179  continue;
1180  }
1181  if ( dataCapabilities() == QgsDataProvider::NoDataCapabilities )
1182  {
1183  QgsDebugMsg( library->fileName() + " has NoDataCapabilities" );
1184  continue;
1185  }
1186  QgsDebugMsg( QString( "%1 dataCapabilities : %2" ).arg( library->fileName() ).arg( dataCapabilities() ) );
1187 
1188  dataItem_t * dataItem = ( dataItem_t * ) cast_to_fptr( library->resolve( "dataItem" ) );
1189  if ( ! dataItem )
1190  {
1191  QgsDebugMsg( library->fileName() + " does not have dataItem" );
1192  continue;
1193  }
1194 
1195  // mLibraries.append( library );
1196  mDataItemPtr.append( dataItem );
1197  mProviderNames.append( k );
1198  }
1199  else
1200  {
1201  //QgsDebugMsg ( "Cannot get provider " + k );
1202  }
1203  }
1204  }
1205 
1206 }
1207 
1209 {
1210 }
1211 
1212 // internal function to scan a vsidir (zip or tar file) recursively
1213 // GDAL trunk has this since r24423 (05/16/12) - VSIReadDirRecursive()
1214 // use a copy of the function internally for now,
1215 // but use char ** and CSLAddString, because CPLStringList was added in gdal-1.9
1216 char **VSIReadDirRecursive1( const char *pszPath )
1217 {
1218  // CPLStringList oFiles = NULL;
1219  char **papszOFiles = NULL;
1220  char **papszFiles1 = NULL;
1221  char **papszFiles2 = NULL;
1222  VSIStatBufL psStatBuf;
1223  CPLString osTemp1, osTemp2;
1224  int i, j;
1225  int nCount1, nCount2;
1226 
1227  // get listing
1228  papszFiles1 = VSIReadDir( pszPath );
1229  if ( ! papszFiles1 )
1230  return NULL;
1231 
1232  // get files and directories inside listing
1233  nCount1 = CSLCount( papszFiles1 );
1234  for ( i = 0; i < nCount1; i++ )
1235  {
1236  // build complete file name for stat
1237  osTemp1.clear();
1238  osTemp1.append( pszPath );
1239  osTemp1.append( "/" );
1240  osTemp1.append( papszFiles1[i] );
1241 
1242  // if is file, add it
1243  if ( VSIStatL( osTemp1.c_str(), &psStatBuf ) == 0 &&
1244  VSI_ISREG( psStatBuf.st_mode ) )
1245  {
1246  // oFiles.AddString( papszFiles1[i] );
1247  papszOFiles = CSLAddString( papszOFiles, papszFiles1[i] );
1248  }
1249  else if ( VSIStatL( osTemp1.c_str(), &psStatBuf ) == 0 &&
1250  VSI_ISDIR( psStatBuf.st_mode ) )
1251  {
1252  // add directory entry
1253  osTemp2.clear();
1254  osTemp2.append( papszFiles1[i] );
1255  osTemp2.append( "/" );
1256  // oFiles.AddString( osTemp2.c_str() );
1257  papszOFiles = CSLAddString( papszOFiles, osTemp2.c_str() );
1258 
1259  // recursively add files inside directory
1260  papszFiles2 = VSIReadDirRecursive1( osTemp1.c_str() );
1261  if ( papszFiles2 )
1262  {
1263  nCount2 = CSLCount( papszFiles2 );
1264  for ( j = 0; j < nCount2; j++ )
1265  {
1266  osTemp2.clear();
1267  osTemp2.append( papszFiles1[i] );
1268  osTemp2.append( "/" );
1269  osTemp2.append( papszFiles2[j] );
1270  // oFiles.AddString( osTemp2.c_str() );
1271  papszOFiles = CSLAddString( papszOFiles, osTemp2.c_str() );
1272  }
1273  CSLDestroy( papszFiles2 );
1274  }
1275  }
1276  }
1277  CSLDestroy( papszFiles1 );
1278 
1279  // return oFiles.StealList();
1280  return papszOFiles;
1281 }
1282 
1284 {
1286  QString tmpPath;
1287  QSettings settings;
1288  QString scanZipSetting = settings.value( "/qgis/scanZipInBrowser2", "basic" ).toString();
1289 
1290  mZipFileList.clear();
1291 
1292  QgsDebugMsgLevel( QString( "mFilePath = %1 path = %2 name= %3 scanZipSetting= %4 vsiPrefix= %5" ).arg( mFilePath ).arg( path() ).arg( name() ).arg( scanZipSetting ).arg( mVsiPrefix ), 2 );
1293 
1294  // if scanZipBrowser == no: skip to the next file
1295  if ( scanZipSetting == "no" )
1296  {
1297  return children;
1298  }
1299 
1300  // first get list of files
1301  getZipFileList();
1302 
1303  // loop over files inside zip
1304  foreach ( QString fileName, mZipFileList )
1305  {
1306  QFileInfo info( fileName );
1307  tmpPath = mVsiPrefix + mFilePath + "/" + fileName;
1308  QgsDebugMsgLevel( "tmpPath = " + tmpPath, 3 );
1309 
1310  // foreach( dataItem_t *dataItem, mDataItemPtr )
1311  for ( int i = 0; i < mProviderNames.size(); i++ )
1312  {
1313  // ugly hack to remove .dbf file if there is a .shp file
1314  if ( mProviderNames[i] == "ogr" )
1315  {
1316  if ( info.suffix().toLower() == "dbf" )
1317  {
1318  if ( mZipFileList.indexOf( fileName.left( fileName.count() - 4 ) + ".shp" ) != -1 )
1319  continue;
1320  }
1321  if ( info.completeSuffix().toLower() == "shp.xml" )
1322  {
1323  continue;
1324  }
1325  }
1326 
1327  // try to get data item from provider
1328  dataItem_t *dataItem = mDataItemPtr[i];
1329  if ( dataItem )
1330  {
1331  QgsDebugMsgLevel( QString( "trying to load item %1 with %2" ).arg( tmpPath ).arg( mProviderNames[i] ), 3 );
1332  QgsDataItem * item = dataItem( tmpPath, this );
1333  if ( item )
1334  {
1335  QgsDebugMsgLevel( "loaded item", 3 );
1336  // the item comes with zipped file name, set the name to relative path within zip file
1337  item->setName( fileName );
1338  children.append( item );
1339  break;
1340  }
1341  else
1342  {
1343  QgsDebugMsgLevel( "not loaded item", 3 );
1344  }
1345  }
1346  }
1347 
1348  }
1349 
1350  return children;
1351 }
1352 
1354 {
1355  return itemFromPath( parent, path, name, path );
1356 }
1357 
1359 {
1360  QSettings settings;
1361  QString scanZipSetting = settings.value( "/qgis/scanZipInBrowser2", "basic" ).toString();
1362  int zipFileCount = 0;
1363  QStringList zipFileList;
1364  QFileInfo fileInfo( filePath );
1365  QString vsiPrefix = QgsZipItem::vsiPrefix( filePath );
1366  QgsZipItem * zipItem = 0;
1367  bool populated = false;
1368 
1369  QgsDebugMsgLevel( QString( "path = %1 name= %2 scanZipSetting= %3 vsiPrefix= %4" ).arg( path ).arg( name ).arg( scanZipSetting ).arg( vsiPrefix ), 3 );
1370 
1371  // don't scan if scanZipBrowser == no
1372  if ( scanZipSetting == "no" )
1373  return 0;
1374 
1375  // don't scan if this file is not a /vsizip/ or /vsitar/ item
1376  if (( vsiPrefix != "/vsizip/" && vsiPrefix != "/vsitar/" ) )
1377  return 0;
1378 
1379  zipItem = new QgsZipItem( parent, name, filePath, path );
1380 
1381  if ( zipItem )
1382  {
1383  // force populate zipItem if it has less than 10 items and is not a .tgz or .tar.gz file (slow loading)
1384  // for other items populating will be delayed until item is opened
1385  // this might be polluting the tree with empty items but is necessary for performance reasons
1386  // could also accept all files smaller than a certain size and add options for file count and/or size
1387 
1388  // first get list of files inside .zip or .tar files
1389  if ( path.endsWith( ".zip", Qt::CaseInsensitive ) ||
1390  path.endsWith( ".tar", Qt::CaseInsensitive ) )
1391  {
1392  zipFileList = zipItem->getZipFileList();
1393  }
1394  // force populate if less than 10 items
1395  if ( zipFileList.count() > 0 && zipFileList.count() <= 10 )
1396  {
1397  zipItem->populate( zipItem->createChildren() );
1398  populated = true; // there is no QgsDataItem::isPopulated() function
1399  QgsDebugMsgLevel( QString( "Got zipItem with %1 children, path=%2, name=%3" ).arg( zipItem->rowCount() ).arg( zipItem->path() ).arg( zipItem->name() ), 3 );
1400  }
1401  else
1402  {
1403  QgsDebugMsgLevel( QString( "Delaying populating zipItem with path=%1, name=%2" ).arg( zipItem->path() ).arg( zipItem->name() ), 3 );
1404  }
1405  }
1406 
1407  // only display if has children or if is not populated
1408  if ( zipItem && ( !populated || zipItem->rowCount() > 1 ) )
1409  {
1410  QgsDebugMsgLevel( "returning zipItem", 3 );
1411  return zipItem;
1412  }
1413  // if 1 or 0 child found, create a single data item using the normal path or the full path given by QgsZipItem
1414  else
1415  {
1416  QString vsiPath = vsiPrefix + filePath;
1417  if ( zipItem )
1418  {
1419  if ( zipItem->children().size() == 1 )
1420  {
1421  // take the name of the only child so we can get a normal data item from it
1422  QgsLayerItem *layerItem = qobject_cast<QgsLayerItem*>( zipItem->children().first() );
1423  if ( layerItem )
1424  vsiPath = layerItem->uri();
1425  }
1426  zipFileCount = zipFileList.count();
1427  delete zipItem;
1428  }
1429 
1430  QgsDebugMsgLevel( QString( "will try to create a normal dataItem from filePath= %2 or vsiPath = %3" ).arg( filePath ).arg( vsiPath ), 3 );
1431 
1432  // try to open using registered providers (gdal and ogr)
1433  for ( int i = 0; i < mProviderNames.size(); i++ )
1434  {
1435  dataItem_t *dataItem = mDataItemPtr[i];
1436  if ( dataItem )
1437  {
1438  QgsDataItem *item = 0;
1439  // try first with normal path (Passthru)
1440  // this is to simplify .qml handling, and without this some tests will fail
1441  // (e.g. testZipItemVectorTransparency(), second test)
1442  if (( mProviderNames[i] == "ogr" ) ||
1443  ( mProviderNames[i] == "gdal" && zipFileCount == 1 ) )
1444  item = dataItem( filePath, parent );
1445  // try with /vsizip/
1446  if ( ! item )
1447  item = dataItem( vsiPath, parent );
1448  if ( item )
1449  return item;
1450  }
1451  }
1452  }
1453 
1454  return 0;
1455 }
1456 
1458 {
1459  if ( ! mZipFileList.isEmpty() )
1460  return mZipFileList;
1461 
1462  QString tmpPath;
1463  QSettings settings;
1464  QString scanZipSetting = settings.value( "/qgis/scanZipInBrowser2", "basic" ).toString();
1465 
1466  QgsDebugMsgLevel( QString( "mFilePath = %1 name= %2 scanZipSetting= %3 vsiPrefix= %4" ).arg( mFilePath ).arg( name() ).arg( scanZipSetting ).arg( mVsiPrefix ), 3 );
1467 
1468  // if scanZipBrowser == no: skip to the next file
1469  if ( scanZipSetting == "no" )
1470  {
1471  return mZipFileList;
1472  }
1473 
1474  // get list of files inside zip file
1475  QgsDebugMsgLevel( QString( "Open file %1 with gdal vsi" ).arg( mVsiPrefix + mFilePath ), 3 );
1476  char **papszSiblingFiles = VSIReadDirRecursive1( QString( mVsiPrefix + mFilePath ).toLocal8Bit().constData() );
1477  if ( papszSiblingFiles )
1478  {
1479  for ( int i = 0; i < CSLCount( papszSiblingFiles ); i++ )
1480  {
1481  tmpPath = papszSiblingFiles[i];
1482  QgsDebugMsgLevel( QString( "Read file %1" ).arg( tmpPath ), 3 );
1483  // skip directories (files ending with /)
1484  if ( tmpPath.right( 1 ) != "/" )
1485  mZipFileList << tmpPath;
1486  }
1487  CSLDestroy( papszSiblingFiles );
1488  }
1489  else
1490  {
1491  QgsDebugMsg( QString( "Error reading %1" ).arg( mFilePath ) );
1492  }
1493 
1494  return mZipFileList;
1495 }
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:348
QgsDirectoryParamWidget(QString path, QWidget *parent=NULL)
void clear()
void beginInsertItems(QgsDataItem *parent, int first, int last)
static unsigned index
void removeDirectory(QgsDirectoryItem *item)
virtual void childrenCreated()
static QgsDataItemProviderRegistry * instance()
virtual void childrenCreated() override
virtual void refresh()
void dataChanged(QgsDataItem *item)
static void deleteLater(QVector< QgsDataItem * > &items)
bool contains(const Key &key) const
QgsFavouritesItem(QgsDataItem *parent, QString name, QString path=QString())
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
static QgsProviderRegistry * instance(QString pluginPath=QString::null)
means of accessing canonical single instance
#define QgsDebugMsg(str)
Definition: qgslogger.h:33
static QString iconPath(QString iconFile)
Returns path to the desired icon file.
QString mProviderKey
Definition: qgsdataitem.h:329
void addPath(const QString &path)
int indexOf(const T &value, int from) const
void addDirectory(QString favIcon)
QgsDataItem(QgsDataItem::Type type, QgsDataItem *parent, QString name, QString path)
Create new data item.
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()
virtual QIcon icon()
void addAction(QAction *action)
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
QgsLayerItem(QgsDataItem *parent, QString name, QString path, QString uri, LayerType layerType, QString providerKey)
virtual void populate(QVector< QgsDataItem * > children)
virtual void depopulate()
Remove children recursively and set as not populated.
const QPixmap * icon() const
static const QIcon & iconPolygon()
T & first()
QThread * thread() const
QgsErrorItem(QgsDataItem *parent, QString error, QString path)
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 iconPath(QString iconFile)
QString uri()
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:461
virtual bool equal(const QgsDataItem *other)
bool isFile() const
void setValue(const QString &key, const QVariant &value)
static const QIcon & iconDataCollection()
QSize size() const
QgsDirectoryItem(QgsDataItem *parent, QString name, QString path)
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:466
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:391
#define QgsDebugMsgLevel(str, level)
Definition: qgslogger.h:34
bool isDir() const
static QString vsiPrefix(QString uri)
Definition: qgsdataitem.h:482
QString mName
Definition: qgsdataitem.h:222
QStringList mZipFileList
Definition: qgsdataitem.h:468
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.
void deleteLater()
bool hasChildren()
static QStringList mProviderNames
Definition: qgsdataitem.h:480
QAction * exec()
void setFuture(const QFuture< T > &future)
virtual bool equal(const QgsDataItem *other) override
void setColumnCount(int columns)
virtual QIcon icon() override
A directory: contains subdirectories and layers.
Definition: qgsdataitem.h:362
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)
QgsDataCollectionItem(QgsDataItem *parent, QString name, QString path=QString::null)
void mousePressEvent(QMouseEvent *event) override
void setCacheMode(CacheMode mode)
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:479
Can create children. Even items without this capability may have children, but cannot create them...
Definition: qgsdataitem.h:149
void emitBeginInsertItems(QgsDataItem *parent, int first, int last)
static const QIcon & iconTable()
QString mPath
Definition: qgsdataitem.h:227
QLibrary * providerLibrary(const QString &providerKey) const
QString mUri
Definition: qgsdataitem.h:330
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
QStringList toStringList() const
void * resolve(const char *symbol)
QStyle * style()
QVector< QgsDataItem * > createChildren() override
Create children.
QString mVsiPrefix
Definition: qgsdataitem.h:467
bool isNull() const
QgsZipItem(QgsDataItem *parent, QString name, QString path)
QStringList entryList(QFlags< QDir::Filter > filters, QFlags< QDir::SortFlag > sort) const
static Q_DECL_DEPRECATED QVector< QLibrary * > mLibraries
Definition: qgsdataitem.h:399
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()
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:323
virtual QgsDataItem * removeChildItem(QgsDataItem *child)
virtual void deleteChildItem(QgsDataItem *child)
QVector< QgsDataItem * > mChildren
Definition: qgsdataitem.h:218
void emitEndRemoveItems()
void emitBeginRemoveItems(QgsDataItem *parent, int first, int last)
void setRootIsDecorated(bool show)
children created
Definition: qgsdataitem.h:106
LayerType mLayerType
Definition: qgsdataitem.h:331
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)
const QStringList & getZipFileList()
added in 2.10
Definition: qgsdataitem.h:297
const T value(const Key &key) const
void frameChanged()
Emitted when icon changed.