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