Skip to content

Commit

Permalink
[External Storage] Define API and implement SimpleCopy backlend (#43882)
Browse files Browse the repository at this point in the history
* [External Storage] Define API

* [External Storage] Add QgsCopyFileTask

* [External Storage] Add SimpleCopy backend

* change SIP_CONCAT_PARTS to fix compilation

* Add ContentStatus enum in Qgis class

* Add test for QgsCopyFileTask

* Move addTask after signals connect

* fix header

Co-authored-by: Paul Blottiere <blottiere.paul@gmail.com>

* s/store/stores

Co-authored-by: Paul Blottiere <blottiere.paul@gmail.com>

* s/Fetch/Fetches

Co-authored-by: Paul Blottiere <blottiere.paul@gmail.com>

* fix typos

Co-authored-by: Paul Blottiere <blottiere.paul@gmail.com>

* s/authentification/authentication

* change comment singleton

* use unique_ptr for projectexternalstorage instance

* fix cppcheck

* Add StartLater / StartImmediately distinction

* Add enum ActionStart

* s/OnGoing/Running/g

* constify externalStorageFromType

* Fix SIP

Co-authored-by: Paul Blottiere <blottiere.paul@gmail.com>
  • Loading branch information
3nids and pblottiere committed Jul 30, 2021
2 parents 1bd8f5c + 9d732a2 commit af9a72e
Show file tree
Hide file tree
Showing 29 changed files with 1,771 additions and 26 deletions.
2 changes: 1 addition & 1 deletion CMakeLists.txt
Expand Up @@ -941,7 +941,7 @@ if (WITH_CORE AND WITH_BINDINGS AND NOT WITH_QT6)
include(SIPMacros)

set(SIP_INCLUDES ${PYQT_SIP_DIR} ${CMAKE_SOURCE_DIR}/python)
set(SIP_CONCAT_PARTS 14)
set(SIP_CONCAT_PARTS 16)

if (NOT BINDINGS_GLOBAL_INSTALL)
set(Python_SITEARCH ${QGIS_DATA_DIR}/python)
Expand Down
23 changes: 16 additions & 7 deletions python/core/auto_additions/qgis.py
Expand Up @@ -349,17 +349,17 @@
Qgis.DriveType.__doc__ = 'Drive types\n\n.. versionadded:: 3.20\n\n' + '* ``Unknown``: ' + Qgis.DriveType.Unknown.__doc__ + '\n' + '* ``Invalid``: ' + Qgis.DriveType.Invalid.__doc__ + '\n' + '* ``Removable``: ' + Qgis.DriveType.Removable.__doc__ + '\n' + '* ``Fixed``: ' + Qgis.DriveType.Fixed.__doc__ + '\n' + '* ``Remote``: ' + Qgis.DriveType.Remote.__doc__ + '\n' + '* ``CdRom``: ' + Qgis.DriveType.CdRom.__doc__ + '\n' + '* ``RamDisk``: ' + Qgis.DriveType.RamDisk.__doc__
# --
Qgis.DriveType.baseClass = Qgis
QgsNetworkContentFetcherRegistry.FetchingMode = Qgis.FetchingMode
QgsNetworkContentFetcherRegistry.FetchingMode = Qgis.ActionStart
# monkey patching scoped based enum
QgsNetworkContentFetcherRegistry.DownloadLater = Qgis.FetchingMode.FetchLater
QgsNetworkContentFetcherRegistry.DownloadLater = Qgis.ActionStart.Deferred
QgsNetworkContentFetcherRegistry.DownloadLater.is_monkey_patched = True
QgsNetworkContentFetcherRegistry.DownloadLater.__doc__ = "Do not start immediately the fetching"
QgsNetworkContentFetcherRegistry.DownloadImmediately = Qgis.FetchingMode.FetchImmediately
QgsNetworkContentFetcherRegistry.DownloadLater.__doc__ = "Do not start immediately the action"
QgsNetworkContentFetcherRegistry.DownloadImmediately = Qgis.ActionStart.Immediate
QgsNetworkContentFetcherRegistry.DownloadImmediately.is_monkey_patched = True
QgsNetworkContentFetcherRegistry.DownloadImmediately.__doc__ = "The fetching will start immediately"
Qgis.FetchingMode.__doc__ = 'Enum to determine when a fetching operation would begin\n\n.. versionadded:: 3.22\n\n' + '* ``DownloadLater``: ' + Qgis.FetchingMode.FetchLater.__doc__ + '\n' + '* ``DownloadImmediately``: ' + Qgis.FetchingMode.FetchImmediately.__doc__
QgsNetworkContentFetcherRegistry.DownloadImmediately.__doc__ = "Action will start immediately"
Qgis.ActionStart.__doc__ = 'Enum to determine when an operation would begin\n\n.. versionadded:: 3.22\n\n' + '* ``DownloadLater``: ' + Qgis.ActionStart.Deferred.__doc__ + '\n' + '* ``DownloadImmediately``: ' + Qgis.ActionStart.Immediate.__doc__
# --
Qgis.FetchingMode.baseClass = Qgis
Qgis.ActionStart.baseClass = Qgis
# monkey patching scoped based enum
Qgis.UnplacedLabelVisibility.FollowEngineSetting.__doc__ = "Respect the label engine setting"
Qgis.UnplacedLabelVisibility.NeverShow.__doc__ = "Never show unplaced labels, regardless of the engine setting"
Expand Down Expand Up @@ -490,6 +490,15 @@
# --
Qgis.VertexMarkerType.baseClass = Qgis
# monkey patching scoped based enum
Qgis.ContentStatus.NotStarted.__doc__ = "Content fetching/storing has not started yet"
Qgis.ContentStatus.Running.__doc__ = "Content fetching/storing is in progress"
Qgis.ContentStatus.Finished.__doc__ = "Content fetching/storing is finished and successful"
Qgis.ContentStatus.Failed.__doc__ = "Content fetching/storing has failed"
Qgis.ContentStatus.Canceled.__doc__ = "Content fetching/storing has been canceled"
Qgis.ContentStatus.__doc__ = 'Status for fetched or stored content\n\n.. versionadded:: 3.22\n\n' + '* ``NotStarted``: ' + Qgis.ContentStatus.NotStarted.__doc__ + '\n' + '* ``Running``: ' + Qgis.ContentStatus.Running.__doc__ + '\n' + '* ``Finished``: ' + Qgis.ContentStatus.Finished.__doc__ + '\n' + '* ``Failed``: ' + Qgis.ContentStatus.Failed.__doc__ + '\n' + '* ``Canceled``: ' + Qgis.ContentStatus.Canceled.__doc__
# --
Qgis.ContentStatus.baseClass = Qgis
# monkey patching scoped based enum
Qgis.BabelFormatCapability.Import.__doc__ = "Format supports importing"
Qgis.BabelFormatCapability.Export.__doc__ = "Format supports exporting"
Qgis.BabelFormatCapability.Waypoints.__doc__ = "Format supports waypoints"
Expand Down
210 changes: 210 additions & 0 deletions python/core/auto_generated/externalstorage/qgsexternalstorage.sip.in
@@ -0,0 +1,210 @@
/************************************************************************
* This file has been generated automatically from *
* *
* src/core/externalstorage/qgsexternalstorage.h *
* *
* Do not edit manually ! Edit header and run scripts/sipify.pl again *
************************************************************************/





class QgsExternalStorage
{
%Docstring(signature="appended")
Abstract interface for external storage - to be implemented by various backends
and registered in :py:class:`QgsExternalStorageRegistry`.

.. versionadded:: 3.22
%End

%TypeHeaderCode
#include "qgsexternalstorage.h"
%End
public:

virtual ~QgsExternalStorage();

virtual QString type() const = 0;
%Docstring
Unique identifier of the external storage type.
%End

QgsExternalStorageStoredContent *store( const QString &filePath, const QString &url, const QString &authCfg = QString(), Qgis::ActionStart storingMode = Qgis::ActionStart::Deferred ) const /Factory/;
%Docstring
Stores file ``filePath`` to the ``url`` for this project external storage.
Storing process is run in background.
Returns a :py:class:`QgsExternalStorageStoredContent` to follow the status of the stored resource.

``storingMode`` defines if the download will start immediately or shall be manually triggered
calling :py:func:`QgsExternalStorageStoredContent.store()`. User should use
Qgis.ActionStart.Deferred if he needs to connect the :py:func:`~QgsExternalStorage.stored` signal.

After using this method, user wait for :py:func:`QgsExternalStorageStoredContent.stored()`,
:py:func:`QgsExternalStorageStoredContent.errorOccurred()` or :py:func:`QgsExternalStorageStoredContent.canceled()` signals.

It's possible to give ``authCfg`` authentication configuration id in case its needed.

Caller takes ownership of the returned symbol.
%End

QgsExternalStorageFetchedContent *fetch( const QString &url, const QString &authCfg = QString(), Qgis::ActionStart fetchingMode = Qgis::ActionStart::Deferred ) const /Factory/;
%Docstring
Fetches file from ``url`` for this project external storage.
Fetching process is run in background.
Returns a :py:class:`QgsExternalStorageFetchedContent` to follow the status of the fetched resource.

``fetchingMode`` defines if the download will start immediately or shall be manually triggered
calling :py:func:`QgsExternalStorageFetchedContent.fetch()`. User should use
Qgis.ActionStart.Deferred if he needs to connect the :py:func:`~QgsExternalStorage.fetched` signal.

After using this method, user should wait for :py:func:`QgsExternalStorageStoredContent.fetched()`,
:py:func:`QgsExternalStorageStoredContent.errorOccurred()` or :py:func:`QgsExternalStorageStoredContent.canceled()` signals.

It's possible to give ``authCfg`` authentication configuration id in case its needed.
%End

protected:

virtual QgsExternalStorageStoredContent *doStore( const QString &filePath, const QString &url, const QString &authCfg = QString() ) const = 0 /Factory/;
%Docstring
Stores file ``filePath`` to the ``url`` using ``authCfg`` authentication for this project external storage.

.. seealso:: :py:func:`QgsExternalStorage.store`
%End

virtual QgsExternalStorageFetchedContent *doFetch( const QString &url, const QString &authCfg = QString() ) const = 0 /Factory/;
%Docstring
Fetches file from ``url`` using ``authCfg`` for this project external storage.

.. seealso:: :py:func:`QgsExternalStorage.fetch`
%End
};

class QgsExternalStorageContent : QObject
{
%Docstring(signature="appended")
Base class for QgsExternalStorage stored and fetched content

.. versionadded:: 3.22
%End

%TypeHeaderCode
#include "qgsexternalstorage.h"
%End
public:

Qgis::ContentStatus status() const;
%Docstring
Returns content status
%End

const QString &errorString() const;
%Docstring
Returns error textual description if an error occured and :py:func:`~QgsExternalStorageContent.status` returns Failed
%End

public slots:

virtual void cancel();
%Docstring
Cancels content fetching/storing
%End
signals:

void errorOccurred( const QString &errorString );
%Docstring
The signal is emitted when an error occurred. ``errorString`` is a textual description of the error
%End

void progressChanged( double progress );
%Docstring
The signal is emitted whenever content fetching/storing estimated progression value ``progress`` has changed.
``progress`` value is between 0 and 100.
%End

void canceled();
%Docstring
The signal is emitted when content fetching/storing has been canceled
%End

protected:

void reportError( const QString &errorMsg );
%Docstring
Update content according to given ``errorMsg`` error message
Inherited classes should call this method whenever they meet an error.
%End

};

class QgsExternalStorageFetchedContent : QgsExternalStorageContent
{
%Docstring(signature="appended")
Class for :py:class:`QgsExternalStorage` fetched content

.. versionadded:: 3.22
%End

%TypeHeaderCode
#include "qgsexternalstorage.h"
%End
public:

virtual QString filePath() const = 0;
%Docstring
Returns fetched resource file path
%End

virtual void fetch() = 0;
%Docstring
Starts fetching
%End

signals:

void fetched();
%Docstring
The signal is emitted when the resource has successfully been fetched
%End
};

class QgsExternalStorageStoredContent : QgsExternalStorageContent
{
%Docstring(signature="appended")
Class for :py:class:`QgsExternalStorage` stored content

.. versionadded:: 3.22
%End

%TypeHeaderCode
#include "qgsexternalstorage.h"
%End
public:

virtual QString url() const = 0;
%Docstring
Returns stored resource URL
%End

virtual void store() = 0;
%Docstring
Starts storing
%End

signals:

void stored();
%Docstring
The signal is emitted when the resource has successfully been stored
%End
};

/************************************************************************
* This file has been generated automatically from *
* *
* src/core/externalstorage/qgsexternalstorage.h *
* *
* Do not edit manually ! Edit header and run scripts/sipify.pl again *
************************************************************************/
@@ -0,0 +1,65 @@
/************************************************************************
* This file has been generated automatically from *
* *
* src/core/externalstorage/qgsexternalstorageregistry.h *
* *
* Do not edit manually ! Edit header and run scripts/sipify.pl again *
************************************************************************/





class QgsExternalStorageRegistry
{
%Docstring(signature="appended")
Registry of external storage backends used by :py:class:`QgsExternalResourceWidget`

:py:class:`QgsExternalStorageRegistry` is not usually directly created, but rather accessed through
:py:func:`QgsApplication.projectStorageRegistry()`.

.. versionadded:: 3.22
%End

%TypeHeaderCode
#include "qgsexternalstorageregistry.h"
%End
public:

QgsExternalStorageRegistry();
%Docstring
Constructor - creates a registry of external storage backends
%End

~QgsExternalStorageRegistry();

QgsExternalStorage *externalStorageFromType( const QString &type ) const;
%Docstring
Returns external storage implementation if the storage ``type`` matches one.
Returns None otherwise
%End

QList<QgsExternalStorage *> externalStorages() const;
%Docstring
Returns a list of registered project storage implementations
%End

void registerExternalStorage( QgsExternalStorage *storage /Transfer/ );
%Docstring
Registers a ``storage`` backend and takes ownership of it
%End

void unregisterExternalStorage( QgsExternalStorage *storage );
%Docstring
Unregisters a ``storage`` backend and destroys its instance
%End

};

/************************************************************************
* This file has been generated automatically from *
* *
* src/core/externalstorage/qgsexternalstorageregistry.h *
* *
* Do not edit manually ! Edit header and run scripts/sipify.pl again *
************************************************************************/
Expand Up @@ -103,7 +103,7 @@ Create the registry for temporary downloaded files

~QgsNetworkContentFetcherRegistry();

const QgsFetchedContent *fetch( const QString &url, Qgis::FetchingMode fetchingMode = Qgis::FetchingMode::FetchLater );
const QgsFetchedContent *fetch( const QString &url, Qgis::ActionStart fetchingMode = Qgis::ActionStart::Deferred );
%Docstring
Initialize a download for the given URL

Expand Down
15 changes: 12 additions & 3 deletions python/core/auto_generated/qgis.sip.in
Expand Up @@ -261,10 +261,10 @@ The development version
RamDisk,
};

enum class FetchingMode
enum class ActionStart
{
FetchLater,
FetchImmediately,
Deferred,
Immediate,
};

enum class UnplacedLabelVisibility
Expand Down Expand Up @@ -351,6 +351,15 @@ The development version
NoMarker,
};

enum class ContentStatus
{
NotStarted,
Running,
Finished,
Failed,
Canceled,
};

enum class BabelFormatCapability
{
Import,
Expand Down
7 changes: 7 additions & 0 deletions python/core/auto_generated/qgsapplication.sip.in
Expand Up @@ -920,6 +920,13 @@ Gets the registry of available scalebar renderers.
Returns registry of available project storage implementations.

.. versionadded:: 3.2
%End

static QgsExternalStorageRegistry *externalStorageRegistry() /KeepReference/;
%Docstring
Returns registry of available external storage implementations.

.. versionadded:: 3.20
%End

static QgsLocalizedDataPathRegistry *localizedDataPathRegistry() /KeepReference/;
Expand Down

0 comments on commit af9a72e

Please sign in to comment.