18 #include <QApplication>
19 #include <QtConcurrentMap>
20 #include <QtConcurrentRun>
25 #include <QMouseEvent>
26 #include <QTreeWidget>
27 #include <QTreeWidgetItem>
38 #include "qgsconfig.h"
42 #include "cpl_string.h"
122 QStyle *style = QApplication::style();
123 icon = QIcon( style->standardPixmap( QStyle::SP_DirClosedIcon ) );
124 icon.addPixmap( style->standardPixmap( QStyle::SP_DirOpenIcon ),
125 QIcon::Normal, QIcon::On );
154 int QgsDataItem::mPopulatingCount = 0;
155 QMovie * QgsDataItem::mPopulatingMovie = 0;
156 QIcon QgsDataItem::mPopulatingIcon = QIcon();
162 , mCapabilities( NoCapabilities )
164 , mState( NotPopulated )
165 , mPopulated( false )
168 , mDeferredDelete( false )
169 , mFutureWatcher( 0 )
184 if ( mFutureWatcher && !mFutureWatcher->isFinished() )
187 QgsDebugMsg(
"mFutureWatcher not finished (should not happen) -> waitForFinished()" );
188 mDeferredDelete =
true;
189 mFutureWatcher->waitForFinished();
195 return QString(
string ).replace( QRegExp(
"[\\\\/]" ),
"|" );
210 if ( mFutureWatcher && !mFutureWatcher->isFinished() )
212 QgsDebugMsg(
"mFutureWatcher not finished -> schedule to delete later" );
213 mDeferredDelete =
true;
240 child->QObject::setParent( 0 );
249 return mPopulatingIcon;
251 if ( !
mIcon.isNull() )
291 QgsDebugMsg( QString(
"item %1 state changed %2 -> %3" ).arg( item->
path() ).arg( oldState ).arg( item->
state() ) );
297 return QVector<QgsDataItem*>();
315 if ( !mFutureWatcher )
317 mFutureWatcher =
new QFutureWatcher< QVector <QgsDataItem*> >( this );
319 connect( mFutureWatcher, SIGNAL( finished() ), SLOT(
childrenCreated() ) );
320 mFutureWatcher->setFuture( QtConcurrent::run( runCreateChildren,
this ) );
325 QVector<QgsDataItem*> QgsDataItem::runCreateChildren(
QgsDataItem* item )
331 QgsDebugMsg( QString(
"%1 children created in %2 ms" ).arg( children.size() ).arg( time.elapsed() ) );
338 child->
moveToThread( QApplication::instance()->thread() );
346 QgsDebugMsg( QString(
"path = %1 children.size() = %2" ).arg(
path() ).arg( mFutureWatcher->result().size() ) );
350 QgsDebugMsg(
"Item was scheduled to be deleted later" );
357 populate( mFutureWatcher->result() );
361 refresh( mFutureWatcher->result() );
363 disconnect( mFutureWatcher, SIGNAL( finished() ),
this, SLOT(
childrenCreated() ) );
408 if ( !mFutureWatcher )
410 mFutureWatcher =
new QFutureWatcher< QVector <QgsDataItem*> >( this );
412 connect( mFutureWatcher, SIGNAL( finished() ), SLOT(
childrenCreated() ) );
413 mFutureWatcher->setFuture( QtConcurrent::run( runCreateChildren,
this ) );
422 QVector<QgsDataItem*>
remove;
427 if (
findItem( children, child ) >= 0 )
429 remove.append( child );
474 disconnect(
this, 0,
mParent, 0 );
553 for (
int i = 0; i < items.size(); i++ )
555 Q_ASSERT_X( items[i],
"findItem", QString(
"item %1 is NULL" ).arg( i ).toAscii() );
557 if ( items[i]->
equal( item ) )
565 if ( metaObject()->className() == other->metaObject()->className() &&
575 mPopulatingIcon = QIcon( mPopulatingMovie->currentPixmap() );
589 QgsDebugMsg( QString(
"item %1 set state %2 -> %3" ).arg(
path() ).arg( this->
state() ).arg( state ) );
597 if ( !mPopulatingMovie )
600 mPopulatingMovie =
new QMovie( QApplication::instance() );
602 mPopulatingMovie->setCacheMode( QMovie::CacheAll );
603 connect( mPopulatingMovie, SIGNAL( frameChanged(
int ) ), SLOT(
setPopulatingIcon() ) );
605 connect( mPopulatingMovie, SIGNAL( frameChanged(
int ) ), SLOT(
emitDataChanged() ) );
607 mPopulatingMovie->setPaused(
false );
611 disconnect( mPopulatingMovie, SIGNAL( frameChanged(
int ) ),
this, SLOT(
emitDataChanged() ) );
613 if ( mPopulatingCount == 0 )
615 mPopulatingMovie->setPaused(
true );
631 , mProviderKey( providerKey )
633 , mLayerType( layerType )
644 default:
mIconName =
"/mIconLayer.png";
break;
686 QgsDebugMsgLevel( QString(
"delete child = 0x%0" ).arg(( qlonglong )i, 8, 16, QLatin1Char(
'0' ) ), 2 );
699 , mFileSystemWatcher( 0 )
700 , mRefreshLater( false )
708 , mDirPath( dirPath )
709 , mFileSystemWatcher( 0 )
710 , mRefreshLater( false )
722 QStringList::const_iterator i;
723 for ( i = keys.begin(); i != keys.end(); ++i )
732 if ( !dataCapabilities )
734 QgsDebugMsg( library->fileName() +
" does not have dataCapabilities" );
739 QgsDebugMsg( library->fileName() +
" has NoDataCapabilities" );
743 QgsDebugMsg( QString(
"%1 dataCapabilities : %2" ).arg( library->fileName() ).arg( dataCapabilities() ) );
770 QStringList entries = dir.entryList( QDir::AllDirs | QDir::NoDotAndDotDot, QDir::Name | QDir::IgnoreCase );
771 foreach ( QString subdir, entries )
778 QString subdirPath = dir.absoluteFilePath( subdir );
785 children.append( item );
788 QStringList fileEntries = dir.entryList( QDir::Dirs | QDir::NoDotAndDotDot | QDir::Files, QDir::Name );
789 foreach ( QString
name, fileEntries )
797 QString
path = dir.absoluteFilePath( name );
798 QFileInfo fileInfo( path );
806 children.append( item );
817 if ( !dataCapabilities )
833 QgsDebugMsg( library->fileName() +
" does not have dataItem" );
840 children.append( item );
855 if ( !mFileSystemWatcher )
857 mFileSystemWatcher =
new QFileSystemWatcher(
this );
858 mFileSystemWatcher->addPath(
mDirPath );
864 if ( mFileSystemWatcher )
866 delete mFileSystemWatcher;
867 mFileSystemWatcher = 0;
878 mRefreshLater =
true;
888 QgsDebugMsg( QString(
"mRefreshLater = %1" ).arg( mRefreshLater ) );
892 QgsDebugMsg(
"directory changed during createChidren() -> refresh() again" );
893 mRefreshLater =
false;
919 : QTreeWidget( parent )
921 setRootIsDecorated(
false );
926 labels <<
tr(
"Name" ) <<
tr(
"Size" ) <<
tr(
"Date" ) <<
tr(
"Permissions" ) <<
tr(
"Owner" ) <<
tr(
"Group" ) <<
tr(
"Type" );
927 setHeaderLabels( labels );
929 QStyle* style = QApplication::style();
930 QIcon iconDirectory = QIcon( style->standardPixmap( QStyle::SP_DirClosedIcon ) );
931 QIcon iconFile = QIcon( style->standardPixmap( QStyle::SP_FileIcon ) );
932 QIcon iconLink = QIcon( style->standardPixmap( QStyle::SP_FileLinkIcon ) );
934 QList<QTreeWidgetItem *> items;
937 QStringList entries = dir.entryList( QDir::AllEntries | QDir::NoDotAndDotDot, QDir::Name | QDir::IgnoreCase );
938 foreach ( QString name, entries )
940 QFileInfo fi( dir.absoluteFilePath( name ) );
944 if ( fi.size() > 1024 )
946 size = size.sprintf(
"%.1f KiB", fi.size() / 1024.0 );
948 else if ( fi.size() > 1.048576e6 )
950 size = size.sprintf(
"%.1f MiB", fi.size() / 1.048576e6 );
954 size = QString(
"%1 B" ).arg( fi.size() );
957 texts << fi.lastModified().toString( Qt::SystemLocaleShortDate );
959 perm += fi.permission( QFile::ReadOwner ) ?
'r' :
'-';
960 perm += fi.permission( QFile::WriteOwner ) ?
'w' :
'-';
961 perm += fi.permission( QFile::ExeOwner ) ?
'x' :
'-';
963 perm += fi.permission( QFile::ReadGroup ) ?
'r' :
'-';
964 perm += fi.permission( QFile::WriteGroup ) ?
'w' :
'-';
965 perm += fi.permission( QFile::ExeGroup ) ?
'x' :
'-';
966 perm += fi.permission( QFile::ReadOther ) ?
'r' :
'-';
967 perm += fi.permission( QFile::WriteOther ) ?
'w' :
'-';
968 perm += fi.permission( QFile::ExeOther ) ?
'x' :
'-';
978 type =
tr(
"folder" );
979 icon = iconDirectory;
981 else if ( fi.isFile() )
986 else if ( fi.isSymLink() )
994 QTreeWidgetItem *item =
new QTreeWidgetItem( texts );
995 item->setIcon( 0, icon );
999 addTopLevelItems( items );
1003 QList<QVariant> lst = settings.value(
"/dataitem/directoryHiddenColumns" ).toList();
1004 foreach ( QVariant colVariant, lst )
1006 setColumnHidden( colVariant.toInt(), true );
1012 if ( event->button() == Qt::RightButton )
1018 labels <<
tr(
"Name" ) <<
tr(
"Size" ) <<
tr(
"Date" ) <<
tr(
"Permissions" ) <<
tr(
"Owner" ) <<
tr(
"Group" ) <<
tr(
"Type" );
1019 for (
int i = 0; i < labels.count(); i++ )
1021 QAction* action = popupMenu.addAction( labels[i],
this, SLOT(
showHideColumn() ) );
1022 action->setObjectName( QString::number( i ) );
1023 action->setCheckable(
true );
1024 action->setChecked( !isColumnHidden( i ) );
1027 popupMenu.exec( event->globalPos() );
1033 QAction* action = qobject_cast<QAction*>( sender() );
1037 int columnIndex = action->objectName().toInt();
1038 setColumnHidden( columnIndex, !isColumnHidden( columnIndex ) );
1042 QList<QVariant> lst;
1043 for (
int i = 0; i < columnCount(); i++ )
1045 if ( isColumnHidden( i ) )
1046 lst.append( QVariant( i ) );
1048 settings.setValue(
"/dataitem/directoryHiddenColumns", lst );
1083 QStringList favDirs = settings.value(
"/browser/favourites", QVariant() ).toStringList();
1085 foreach ( QString favDir, favDirs )
1091 children.append( item );
1101 QStringList favDirs = settings.value(
"/browser/favourites" ).toStringList();
1102 favDirs.append( favDir );
1103 settings.setValue(
"/browser/favourites", favDirs );
1118 QStringList favDirs = settings.value(
"/browser/favourites" ).toStringList();
1119 favDirs.removeAll( item->
dirPath() );
1120 settings.setValue(
"/browser/favourites", favDirs );
1125 QgsDebugMsg( QString(
"favourites item %1 not found" ).arg( item->
path() ) );
1147 , mFilePath( filePath )
1152 void QgsZipItem::init()
1164 keys <<
"gdal" <<
"ogr";
1166 QStringList::const_iterator i;
1167 for ( i = keys.begin(); i != keys.end(); ++i )
1177 if ( !dataCapabilities )
1179 QgsDebugMsg( library->fileName() +
" does not have dataCapabilities" );
1184 QgsDebugMsg( library->fileName() +
" has NoDataCapabilities" );
1187 QgsDebugMsg( QString(
"%1 dataCapabilities : %2" ).arg( library->fileName() ).arg( dataCapabilities() ) );
1192 QgsDebugMsg( library->fileName() +
" does not have dataItem" );
1220 char **papszOFiles = NULL;
1221 char **papszFiles1 = NULL;
1222 char **papszFiles2 = NULL;
1223 VSIStatBufL psStatBuf;
1224 CPLString osTemp1, osTemp2;
1226 int nCount1, nCount2;
1229 papszFiles1 = VSIReadDir( pszPath );
1230 if ( ! papszFiles1 )
1234 nCount1 = CSLCount( papszFiles1 );
1235 for ( i = 0; i < nCount1; i++ )
1239 osTemp1.append( pszPath );
1240 osTemp1.append(
"/" );
1241 osTemp1.append( papszFiles1[i] );
1244 if ( VSIStatL( osTemp1.c_str(), &psStatBuf ) == 0 &&
1245 VSI_ISREG( psStatBuf.st_mode ) )
1248 papszOFiles = CSLAddString( papszOFiles, papszFiles1[i] );
1250 else if ( VSIStatL( osTemp1.c_str(), &psStatBuf ) == 0 &&
1251 VSI_ISDIR( psStatBuf.st_mode ) )
1255 osTemp2.append( papszFiles1[i] );
1256 osTemp2.append(
"/" );
1258 papszOFiles = CSLAddString( papszOFiles, osTemp2.c_str() );
1264 nCount2 = CSLCount( papszFiles2 );
1265 for ( j = 0; j < nCount2; j++ )
1268 osTemp2.append( papszFiles1[i] );
1269 osTemp2.append(
"/" );
1270 osTemp2.append( papszFiles2[j] );
1272 papszOFiles = CSLAddString( papszOFiles, osTemp2.c_str() );
1274 CSLDestroy( papszFiles2 );
1278 CSLDestroy( papszFiles1 );
1289 QString scanZipSetting = settings.value(
"/qgis/scanZipInBrowser2",
"basic" ).toString();
1296 if ( scanZipSetting ==
"no" )
1307 QFileInfo info( fileName );
1317 if ( info.suffix().toLower() ==
"dbf" )
1319 if (
mZipFileList.indexOf( fileName.left( fileName.count() - 4 ) +
".shp" ) != -1 )
1322 if ( info.completeSuffix().toLower() ==
"shp.xml" )
1339 children.append( item );
1362 QString scanZipSetting = settings.value(
"/qgis/scanZipInBrowser2",
"basic" ).toString();
1363 int zipFileCount = 0;
1364 QStringList zipFileList;
1365 QFileInfo fileInfo( filePath );
1368 bool populated =
false;
1370 QgsDebugMsgLevel( QString(
"path = %1 name= %2 scanZipSetting= %3 vsiPrefix= %4" ).arg( path ).arg( name ).arg( scanZipSetting ).arg( vsiPrefix ), 3 );
1373 if ( scanZipSetting ==
"no" )
1377 if (( vsiPrefix !=
"/vsizip/" && vsiPrefix !=
"/vsitar/" ) )
1380 zipItem =
new QgsZipItem( parent, name, filePath, path );
1390 if ( path.endsWith(
".zip", Qt::CaseInsensitive ) ||
1391 path.endsWith(
".tar", Qt::CaseInsensitive ) )
1396 if ( zipFileList.count() > 0 && zipFileList.count() <= 10 )
1400 QgsDebugMsgLevel( QString(
"Got zipItem with %1 children, path=%2, name=%3" ).arg( zipItem->
rowCount() ).arg( zipItem->
path() ).arg( zipItem->
name() ), 3 );
1404 QgsDebugMsgLevel( QString(
"Delaying populating zipItem with path=%1, name=%2" ).arg( zipItem->
path() ).arg( zipItem->
name() ), 3 );
1409 if ( zipItem && ( !populated || zipItem->
rowCount() > 1 ) )
1417 QString vsiPath = vsiPrefix + filePath;
1420 if ( zipItem->
children().size() == 1 )
1425 vsiPath = layerItem->
uri();
1427 zipFileCount = zipFileList.count();
1431 QgsDebugMsgLevel( QString(
"will try to create a normal dataItem from filePath= %2 or vsiPath = %3" ).arg( filePath ).arg( vsiPath ), 3 );
1445 item = dataItem( filePath, parent );
1448 item = dataItem( vsiPath, parent );
1465 QString scanZipSetting = settings.value(
"/qgis/scanZipInBrowser2",
"basic" ).toString();
1470 if ( scanZipSetting ==
"no" )
1478 if ( papszSiblingFiles )
1480 for (
int i = 0; i < CSLCount( papszSiblingFiles ); i++ )
1482 tmpPath = papszSiblingFiles[i];
1485 if ( tmpPath.right( 1 ) !=
"/" )
1488 CSLDestroy( papszSiblingFiles );