Skip to content

Commit

Permalink
Merge pull request #5914 from opengisch/qtwebdav_port
Browse files Browse the repository at this point in the history
Implement import of WebDAV folders
  • Loading branch information
nirvn authored Jan 13, 2025
2 parents 8f0b29e + e4cfc09 commit 3cccd35
Show file tree
Hide file tree
Showing 19 changed files with 1,461 additions and 83 deletions.
8 changes: 6 additions & 2 deletions src/core/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,8 @@ set(QFIELD_CORE_SRCS
valuemapmodel.cpp
valuemapmodelbase.cpp
vertexmodel.cpp
viewstatus.cpp)
viewstatus.cpp
webdavconnection.cpp)

set(QFIELD_CORE_HDRS
platforms/platformutilities.h
Expand Down Expand Up @@ -244,6 +245,7 @@ set(QFIELD_CORE_HDRS
valuemapmodelbase.h
vertexmodel.h
viewstatus.h
webdavconnection.h
${CMAKE_CURRENT_BINARY_DIR}/qfield.h)

list(APPEND QFIELD_CORE_SRCS permissions.cpp)
Expand Down Expand Up @@ -288,6 +290,7 @@ endif()

find_package(SQLite3 REQUIRED)
find_package(ZXing REQUIRED)
find_package(QtWebDAV REQUIRED)

add_library(qfield_core STATIC ${QFIELD_CORE_SRCS} ${QFIELD_CORE_HDRS})

Expand Down Expand Up @@ -367,7 +370,8 @@ target_link_libraries(
GDAL::GDAL
SQLite::SQLite3
Qca::qca
libzip::zip)
libzip::zip
QtWebDAV::QtWebDAV)

if(WITH_BLUETOOTH)
find_package(
Expand Down
1 change: 1 addition & 0 deletions src/core/focusstack.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ void FocusStack::setFocused( QObject *object )
{
mStackList.removeAll( object );
mStackList.append( object );
QMetaObject::invokeMethod( object, "forceActiveFocus", Qt::DirectConnection );
}

void FocusStack::setUnfocused( QObject *object )
Expand Down
20 changes: 17 additions & 3 deletions src/core/localfilesmodel.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
#include "platformutilities.h"
#include "qfieldcloudutils.h"
#include "qgismobileapp.h"
#include "webdavconnection.h"

#include <QDir>
#include <QFile>
Expand Down Expand Up @@ -59,6 +60,7 @@ QHash<int, QByteArray> LocalFilesModel::roleNames() const
roles[ItemSizeRole] = "ItemSize";
roles[ItemHasThumbnailRole] = "ItemHasThumbnail";
roles[ItemIsFavoriteRole] = "ItemIsFavorite";
roles[ItemHasWebdavConfigurationRole] = "ItemHasWebdavConfiguration";
return roles;
}

Expand Down Expand Up @@ -177,14 +179,14 @@ bool LocalFilesModel::isDeletedAllowedInCurrentPath() const
{
const QString path = currentPath();
const QString applicationDirectory = PlatformUtilities::instance()->applicationDirectory();
if ( !applicationDirectory.isEmpty() && path.startsWith( applicationDirectory + QDir::separator() ) )
if ( !applicationDirectory.isEmpty() && path.startsWith( applicationDirectory ) )
{
return true;
}
else
{
const QStringList additionalApplicationDirectories = PlatformUtilities::instance()->additionalApplicationDirectories();
if ( std::any_of( additionalApplicationDirectories.begin(), additionalApplicationDirectories.end(), [&path]( const QString &directory ) { return ( !directory.isEmpty() && path.startsWith( directory + QDir::separator() ) ); } ) )
if ( std::any_of( additionalApplicationDirectories.begin(), additionalApplicationDirectories.end(), [&path]( const QString &directory ) { return ( !directory.isEmpty() && path.startsWith( directory ) ); } ) )
{
return true;
}
Expand Down Expand Up @@ -237,10 +239,17 @@ void LocalFilesModel::reloadModel()
}

const QStringList favorites = QSettings().value( QStringLiteral( "qfieldFavorites" ), QStringList() ).toStringList();
QList<Item> favoriteItems;
for ( const QString &item : favorites )
{
mItems << Item( ItemMetaType::Favorite, ItemType::SimpleFolder, getCurrentTitleFromPath( item ), QString(), item );
if ( QFileInfo::exists( item ) )
{
favoriteItems << Item( ItemMetaType::Favorite, ItemType::SimpleFolder, getCurrentTitleFromPath( item ), QString(), item );
}
}

std::sort( favoriteItems.begin(), favoriteItems.end(), []( const Item &a, const Item &b ) { return a.title < b.title; } );
mItems.append( favoriteItems );
}
else
{
Expand Down Expand Up @@ -332,6 +341,11 @@ QVariant LocalFilesModel::data( const QModelIndex &index, int role ) const

case ItemIsFavoriteRole:
return mFavorites.contains( mItems[index.row()].path );

case ItemHasWebdavConfigurationRole:
{
return WebdavConnection::hasWebdavConfiguration( mItems[index.row()].path );
}
}

return QVariant();
Expand Down
1 change: 1 addition & 0 deletions src/core/localfilesmodel.h
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,7 @@ class LocalFilesModel : public QAbstractListModel
ItemSizeRole,
ItemHasThumbnailRole,
ItemIsFavoriteRole,
ItemHasWebdavConfigurationRole,
};
Q_ENUM( Role )

Expand Down
37 changes: 27 additions & 10 deletions src/core/platforms/platformutilities.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@
#include <QMargins>
#include <QQuickWindow>
#include <QStandardPaths>
#include <QStorageInfo>
#include <QTimer>
#include <QUrl>
#include <QtGui/qpa/qplatformwindow.h>
Expand Down Expand Up @@ -97,14 +98,18 @@ void PlatformUtilities::afterUpdate()
const QStringList dirs = appDataDirs();
for ( const QString &dir : dirs )
{
QDir appDir( dir );
appDir.mkpath( QStringLiteral( "proj" ) );
appDir.mkpath( QStringLiteral( "auth" ) );
appDir.mkpath( QStringLiteral( "fonts" ) );
appDir.mkpath( QStringLiteral( "basemaps" ) );
appDir.mkpath( QStringLiteral( "logs" ) );
appDir.mkpath( QStringLiteral( "plugins" ) );
QDir appDataDir( dir );
appDataDir.mkpath( QStringLiteral( "proj" ) );
appDataDir.mkpath( QStringLiteral( "auth" ) );
appDataDir.mkpath( QStringLiteral( "fonts" ) );
appDataDir.mkpath( QStringLiteral( "basemaps" ) );
appDataDir.mkpath( QStringLiteral( "logs" ) );
appDataDir.mkpath( QStringLiteral( "plugins" ) );
}

QDir applicationDir( applicationDirectory() );
applicationDir.mkpath( QStringLiteral( "Imported Projects" ) );
applicationDir.mkpath( QStringLiteral( "Imported Datasets" ) );
}

QString PlatformUtilities::systemSharedDataLocation() const
Expand Down Expand Up @@ -153,7 +158,7 @@ void PlatformUtilities::loadQgsProject() const

QStringList PlatformUtilities::appDataDirs() const
{
return QStringList() << QStandardPaths::standardLocations( QStandardPaths::DocumentsLocation ).first() + QStringLiteral( "/QField/" );
return QStringList() << QStandardPaths::standardLocations( QStandardPaths::DocumentsLocation ).first() + QStringLiteral( "/QField Documents/QField/" );
}

QStringList PlatformUtilities::availableGrids() const
Expand Down Expand Up @@ -208,7 +213,7 @@ bool PlatformUtilities::renameFile( const QString &oldFilePath, const QString &n

QString PlatformUtilities::applicationDirectory() const
{
return QStandardPaths::standardLocations( QStandardPaths::DocumentsLocation ).first() + QStringLiteral( "/QField/" );
return QStandardPaths::standardLocations( QStandardPaths::DocumentsLocation ).first() + QStringLiteral( "/QField Documents/" );
}

QStringList PlatformUtilities::additionalApplicationDirectories() const
Expand All @@ -218,7 +223,19 @@ QStringList PlatformUtilities::additionalApplicationDirectories() const

QStringList PlatformUtilities::rootDirectories() const
{
return QStringList() << QString();
QStringList rootDirectories;
rootDirectories << QDir::homePath();
for ( const QStorageInfo &volume : QStorageInfo::mountedVolumes() )
{
if ( volume.isReady() && !volume.isReadOnly() )
{
if ( volume.fileSystemType() != QLatin1String( "tmpfs" ) && !volume.rootPath().startsWith( QLatin1String( "/boot" ) ) )
{
rootDirectories << volume.rootPath();
}
}
}
return rootDirectories;
}

void PlatformUtilities::importProjectFolder() const
Expand Down
2 changes: 1 addition & 1 deletion src/core/platforms/platformutilities.h
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,7 @@ class QFIELD_CORE_EXPORT PlatformUtilities : public QObject
/**
* The main application directory within which projects and datasets can be imported.
*/
virtual QString applicationDirectory() const;
Q_INVOKABLE virtual QString applicationDirectory() const;

/**
* Secondary application directories which can be used by individual platforms.
Expand Down
2 changes: 2 additions & 0 deletions src/core/qgismobileapp.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,7 @@
#include "urlutils.h"
#include "valuemapmodel.h"
#include "vertexmodel.h"
#include "webdavconnection.h"

#include <QDateTime>
#include <QFileInfo>
Expand Down Expand Up @@ -511,6 +512,7 @@ void QgisMobileapp::initDeclarative( QQmlEngine *engine )
qmlRegisterType<Positioning>( "org.qfield", 1, 0, "Positioning" );
qmlRegisterType<PositioningInformationModel>( "org.qfield", 1, 0, "PositioningInformationModel" );
qmlRegisterType<PositioningDeviceModel>( "org.qfield", 1, 0, "PositioningDeviceModel" );
qmlRegisterType<WebdavConnection>( "org.qfield", 1, 0, "WebdavConnection" );
qmlRegisterType<AudioRecorder>( "org.qfield", 1, 0, "AudioRecorder" );
qmlRegisterType<BarcodeDecoder>( "org.qfield", 1, 0, "BarcodeDecoder" );
qmlRegisterType<CameraPermission>( "org.qfield", 1, 0, "QfCameraPermission" );
Expand Down
6 changes: 6 additions & 0 deletions src/core/utils/fileutils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,12 @@ bool FileUtils::isImageMimeTypeSupported( const QString &mimeType )
return QImageReader::supportedMimeTypes().contains( mimeType.toLatin1() );
}

QString FileUtils::absolutePath( const QString &filePath )
{
QFileInfo fileInfo( filePath );
return fileInfo.absolutePath();
}

QString FileUtils::fileName( const QString &filePath )
{
QFileInfo fileInfo( filePath );
Expand Down
6 changes: 4 additions & 2 deletions src/core/utils/fileutils.h
Original file line number Diff line number Diff line change
Expand Up @@ -40,14 +40,16 @@ class QFIELD_CORE_EXPORT FileUtils : public QObject
Q_INVOKABLE static QString mimeTypeName( const QString &filePath );
//! Returns TRUE if the provided mimetype is a supported image
Q_INVOKABLE static bool isImageMimeTypeSupported( const QString &mimeType );
//! Returns the filename of a filepath - if no file name exists it's empty
//! Returns the filename of a \a filePath - if no file name exists it's empty
Q_INVOKABLE static QString fileName( const QString &filePath );
//! Returns true if the file exists (false if it's a directory)
//! Returns true if the \a filePath exists (false if it's a directory)
Q_INVOKABLE static bool fileExists( const QString &filePath );
//! Returns the suffix (extension)
Q_INVOKABLE static QString fileSuffix( const QString &filePath );
//! Returns a human-friendly size from bytes
Q_INVOKABLE static QString representFileSize( qint64 bytes );
//! Returns the absolute path of tghe folder containing the \a filePath.
Q_INVOKABLE static QString absolutePath( const QString &filePath );

/**
* Insures that a given image's width and height are restricted to a maximum size.
Expand Down
Loading

1 comment on commit 3cccd35

@qfield-fairy
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.