Merge lp:~michihenning/storage-framework/api2 into lp:storage-framework/devel

Proposed by Michi Henning
Status: Merged
Approved by: James Henstridge
Approved revision: 82
Merged at revision: 69
Proposed branch: lp:~michihenning/storage-framework/api2
Merge into: lp:storage-framework/devel
Diff against target: 6643 lines (+6158/-34)
63 files modified
CMakeLists.txt (+4/-3)
debian/changelog (+7/-0)
debian/control (+10/-0)
debian/control.in (+9/-0)
debian/libstorage-framework-qt-client-1-0.install (+1/-1)
debian/libstorage-framework-qt-client-2-0.install (+1/-0)
include/unity/storage/CMakeLists.txt (+4/-0)
include/unity/storage/internal/ItemMetadata.h (+3/-0)
include/unity/storage/internal/dbusmarshal.h (+0/-3)
include/unity/storage/qt/Account.h (+103/-0)
include/unity/storage/qt/AccountsJob.h (+80/-0)
include/unity/storage/qt/CMakeLists.txt (+17/-1)
include/unity/storage/qt/ConflictPolicy.h (+32/-0)
include/unity/storage/qt/Downloader.h (+68/-0)
include/unity/storage/qt/Item.h (+142/-0)
include/unity/storage/qt/ItemJob.h (+75/-0)
include/unity/storage/qt/ItemListJob.h (+77/-0)
include/unity/storage/qt/Runtime.h (+80/-0)
include/unity/storage/qt/StorageError.h (+87/-0)
include/unity/storage/qt/Uploader.h (+72/-0)
include/unity/storage/qt/VoidJob.h (+56/-0)
include/unity/storage/qt/client/CMakeLists.txt (+3/-4)
include/unity/storage/qt/internal/AccountImpl.h (+99/-0)
include/unity/storage/qt/internal/AccountsJobImpl.h (+70/-0)
include/unity/storage/qt/internal/Handler.h (+93/-0)
include/unity/storage/qt/internal/HandlerBase.h (+64/-0)
include/unity/storage/qt/internal/ItemImpl.h (+99/-0)
include/unity/storage/qt/internal/ItemJobImpl.h (+84/-0)
include/unity/storage/qt/internal/ItemListJobImpl.h (+83/-0)
include/unity/storage/qt/internal/RuntimeImpl.h (+85/-0)
include/unity/storage/qt/internal/StorageErrorImpl.h (+85/-0)
include/unity/storage/qt/internal/unmarshal_error.h (+39/-0)
include/unity/storage/qt/internal/validate.h (+44/-0)
src/qt/Account.cpp (+148/-0)
src/qt/AccountsJob.cpp (+68/-0)
src/qt/CMakeLists.txt (+82/-0)
src/qt/Item.cpp (+230/-0)
src/qt/ItemJob.cpp (+62/-0)
src/qt/ItemListJob.cpp (+57/-0)
src/qt/Runtime.cpp (+87/-0)
src/qt/StorageError.cpp (+98/-0)
src/qt/client/CMakeLists.txt (+11/-11)
src/qt/client/storage-framework-qt-client-1.pc.in (+6/-0)
src/qt/client/storage-framework-qt-local-client.pc.in (+0/-6)
src/qt/internal/AccountImpl.cpp (+226/-0)
src/qt/internal/AccountsJobImpl.cpp (+183/-0)
src/qt/internal/HandlerBase.cpp (+59/-0)
src/qt/internal/ItemImpl.cpp (+248/-0)
src/qt/internal/ItemJobImpl.cpp (+138/-0)
src/qt/internal/ItemListJobImpl.cpp (+148/-0)
src/qt/internal/RuntimeImpl.cpp (+168/-0)
src/qt/internal/StorageErrorImpl.cpp (+230/-0)
src/qt/internal/unmarshal_error.cpp (+131/-0)
src/qt/internal/validate.cpp (+170/-0)
tests/CMakeLists.txt (+1/-0)
tests/headers/CMakeLists.txt (+1/-0)
tests/remote-client-v1/CMakeLists.txt (+5/-5)
tests/remote-client-v1/remote-client-v1_test.cpp (+1/-0)
tests/remote-client/CMakeLists.txt (+20/-0)
tests/remote-client/MockProvider.cpp (+237/-0)
tests/remote-client/MockProvider.h (+96/-0)
tests/remote-client/remote-client_test.cpp (+1470/-0)
tests/utils/ProviderFixture.cpp (+1/-0)
To merge this branch: bzr merge lp:~michihenning/storage-framework/api2
Reviewer Review Type Date Requested Status
unity-api-1-bot continuous-integration Approve
James Henstridge Approve
Review via email: mp+304599@code.launchpad.net

Commit message

Started implementation of v2 API.

Description of the change

New API. Bulk of internal implementation is there. Need to flesh out the methods on Item mostly now. Also still a bunch of review comments to apply.

To post a comment you must log in.
Revision history for this message
Xavi Garcia (xavi-garcia-mena) wrote :

As discussed in the standup, a couple of things I saw taking a quick look:

The following signals:
    void statusChanged(Status status) const;
    void error(StorageError const& e) const;
    void finished(Uploader const& uploader) const;
Can be found on the Uploader and UploadJob.

It's a bit confusing if we need to connect to both, or just connection to the one in the Job or the Uploader is just fine.

And the second one is about the signal declaration itself.
I had issues related to this a few weeks ago.

For example the signal:

enum class Status { Loading, Finished, Error };
void statusChanged(Status status) const;

should be:
void statusChanged(UploadJob::Status status) const;

and I should verify, but maybe Qt needs it to be:
void statusChanged(unity::storage::qt::UploadJob::Status status) const;

if not, when creating the moc code it does not understand the enum and we cannot access it from QML or, for example QSignalSpy. In fact the issue I've got was with QSignalSpy, when trying to convert from QVariant to the enum class.

Revision history for this message
Michi Henning (michihenning) wrote :

Thanks for the comments Xavi! I've ditched the upload and download job classes. The uploader and downloader will return a disconnected non-working socket and make it valid once the dbus reply with the file descriptor trickles in.

I've added qualified names to the headers where I think they are needed. Could you let me know whether that looks OK please?

Revision history for this message
Albert Astals Cid (aacid) wrote :

you seem to be missing lots of NOTIFY stuff in the properties
i.e.
 Q_PROPERTY(unity::Storage::qt::StorageError error READ error)
will change at some point i guess?

Other properties seem to be missing CONSTANT, e.g.
 Q_PROPERTY(QString READ description)

QML will complain if using properties that are read but don't have neither CONSTANT nor NOTIFY

Revision history for this message
Lukáš Tinkl (lukas-kde) wrote :

Apart from what Albert said above, I see a few high level problems:
- exposing private members in the public headers, that's asking for ABI breakage sooner or later; wrap them using the pimpl idiom and use QScopedPointer to manage them
- QDBus* stuff shouldn't be part of the API (not "consumable" from QML at all)
- if you use custom enums in the signals signatures, you need to Q_DECLARE_METATYPE on them, otherwise they won't work (http://doc.qt.io/qt-5/qmetatype.html#Q_DECLARE_METATYPE)
- a curious question, why do you combine different stuff from C++11, boost and Qt? (like boost::future when there's std::future or even QFuture; std::shared_ptr vs. QSharedPointer etc; or std::map together with QString, when using QMap<QString,QString> would be the logical solution)
- you are using Q_ENUM (http://doc.qt.io/qt-5/qobject.html#Q_ENUM) which is available only from Qt 5.5 -> won't work on vivid; same for Q_GADGET afaik
- for the hash() function, please see http://doc.qt.io/qt-5/qhash.html#the-qhash-hashing-function

Revision history for this message
Michi Henning (michihenning) wrote :

Hi Lukáš,

my apologies, I suspect the message got lost in translation. The *only* headers that matter for the v2 API are the ones in include/unity/storage/qt. Ignore any headers in subduers of this. (The new API does not use boost, does not use futures, etc.

We are not targeting Vivid, so Q_GADGET and Q_ENUM OK.

I'll check the hash function, thanks! The one that is there will do the job with std::unordered_map. I'll have to read up on how the equivalent is meant to work in Qt.

Revision history for this message
Michi Henning (michihenning) wrote :

Hi Lukáš,

my apologies, I suspect the message got lost in translation. The *only* headers that matter for the v2 API are the ones in include/unity/storage/qt. Ignore any headers in subduers of this. (The new API does not use boost, does not use futures, etc.

We are not targeting Vivid, so Q_GADGET and Q_ENUM OK.

I'll check the hash function, thanks! The one that is there will do the job with std::unordered_map. I just had a brief look, and it seems it'll be easy enough to have a Qt-compatible hash function as well, so that'll be easy to fix. Thanks for pointing this out!

Revision history for this message
Michi Henning (michihenning) wrote :

> Ignore any headers in subduers of this.

Bloody auto-correct :-(

That was meant to say "subdirs".

Here is the list of headers as they currently stand, all in include/unity/storage/qt:

Account.h
AccountsJob.h
ConflictPolicy.h
Downloader.h
Item.h
ItemJob.h
ItemListJob.h
Runtime.h
StorageError.h
Uploader.h
VoidJob.h

Revision history for this message
unity-api-1-bot (unity-api-1-bot) wrote :

FAILED: Continuous integration, rev:69
No commit message was specified in the merge proposal. Click on the following link and set the commit message (if you want a jenkins rebuild you need to trigger it yourself):
https://code.launchpad.net/~michihenning/storage-framework/api2/+merge/304599/+edit-commit-message

https://jenkins.canonical.com/unity-api-1/job/lp-storage-framework-ci/110/
Executed test runs:
    FAILURE: https://jenkins.canonical.com/unity-api-1/job/build/685/console
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build-0-fetch/691
    FAILURE: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=amd64,release=vivid+overlay/504/console
    FAILURE: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=amd64,release=xenial+overlay/504/console
    FAILURE: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=amd64,release=yakkety/504/console
    FAILURE: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=armhf,release=vivid+overlay/504/console
    FAILURE: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=armhf,release=xenial+overlay/504/console
    FAILURE: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=armhf,release=yakkety/504/console
    FAILURE: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=i386,release=vivid+overlay/504/console
    FAILURE: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=i386,release=xenial+overlay/504/console
    FAILURE: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=i386,release=yakkety/504/console

Click here to trigger a rebuild:
https://jenkins.canonical.com/unity-api-1/job/lp-storage-framework-ci/110/rebuild

review: Needs Fixing (continuous-integration)
70. By Michi Henning

Comment changes to mark review items.

71. By Michi Henning

Whitespace fixes. Trying qualified name for failing bus_path() call.

Revision history for this message
unity-api-1-bot (unity-api-1-bot) wrote :

FAILED: Continuous integration, rev:70
No commit message was specified in the merge proposal. Click on the following link and set the commit message (if you want a jenkins rebuild you need to trigger it yourself):
https://code.launchpad.net/~michihenning/storage-framework/api2/+merge/304599/+edit-commit-message

https://jenkins.canonical.com/unity-api-1/job/lp-storage-framework-ci/111/
Executed test runs:
    FAILURE: https://jenkins.canonical.com/unity-api-1/job/build/688/console
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build-0-fetch/694
    FAILURE: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=amd64,release=vivid+overlay/507/console
    FAILURE: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=amd64,release=xenial+overlay/507/console
    FAILURE: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=amd64,release=yakkety/507/console
    FAILURE: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=armhf,release=vivid+overlay/507/console
    ABORTED: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=armhf,release=xenial+overlay/507/console
    ABORTED: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=armhf,release=yakkety/507/console
    FAILURE: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=i386,release=vivid+overlay/507/console
    FAILURE: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=i386,release=xenial+overlay/507/console
    FAILURE: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=i386,release=yakkety/507/console

Click here to trigger a rebuild:
https://jenkins.canonical.com/unity-api-1/job/lp-storage-framework-ci/111/rebuild

review: Needs Fixing (continuous-integration)
72. By Michi Henning

Trying this->bus_path();

Revision history for this message
unity-api-1-bot (unity-api-1-bot) wrote :

FAILED: Continuous integration, rev:71
No commit message was specified in the merge proposal. Click on the following link and set the commit message (if you want a jenkins rebuild you need to trigger it yourself):
https://code.launchpad.net/~michihenning/storage-framework/api2/+merge/304599/+edit-commit-message

https://jenkins.canonical.com/unity-api-1/job/lp-storage-framework-ci/112/
Executed test runs:
    FAILURE: https://jenkins.canonical.com/unity-api-1/job/build/689/console
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build-0-fetch/695
    FAILURE: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=amd64,release=vivid+overlay/508/console
    FAILURE: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=amd64,release=xenial+overlay/508/console
    FAILURE: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=amd64,release=yakkety/508/console
    FAILURE: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=armhf,release=vivid+overlay/508/console
    ABORTED: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=armhf,release=xenial+overlay/508/console
    FAILURE: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=armhf,release=yakkety/508/console
    FAILURE: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=i386,release=vivid+overlay/508/console
    FAILURE: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=i386,release=xenial+overlay/508/console
    FAILURE: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=i386,release=yakkety/508/console

Click here to trigger a rebuild:
https://jenkins.canonical.com/unity-api-1/job/lp-storage-framework-ci/112/rebuild

review: Needs Fixing (continuous-integration)
Revision history for this message
unity-api-1-bot (unity-api-1-bot) wrote :

FAILED: Continuous integration, rev:72
No commit message was specified in the merge proposal. Click on the following link and set the commit message (if you want a jenkins rebuild you need to trigger it yourself):
https://code.launchpad.net/~michihenning/storage-framework/api2/+merge/304599/+edit-commit-message

https://jenkins.canonical.com/unity-api-1/job/lp-storage-framework-ci/113/
Executed test runs:
    FAILURE: https://jenkins.canonical.com/unity-api-1/job/build/690/console
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build-0-fetch/696
    FAILURE: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=amd64,release=vivid+overlay/509/console
    FAILURE: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=amd64,release=xenial+overlay/509/console
    FAILURE: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=amd64,release=yakkety/509/console
    FAILURE: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=armhf,release=vivid+overlay/509/console
    ABORTED: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=armhf,release=xenial+overlay/509/console
    ABORTED: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=armhf,release=yakkety/509/console
    FAILURE: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=i386,release=vivid+overlay/509/console
    FAILURE: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=i386,release=xenial+overlay/509/console
    FAILURE: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=i386,release=yakkety/509/console

Click here to trigger a rebuild:
https://jenkins.canonical.com/unity-api-1/job/lp-storage-framework-ci/113/rebuild

review: Needs Fixing (continuous-integration)
73. By Michi Henning

bus_path() -> impossible_name() for testing.

Revision history for this message
unity-api-1-bot (unity-api-1-bot) wrote :

FAILED: Continuous integration, rev:73
No commit message was specified in the merge proposal. Click on the following link and set the commit message (if you want a jenkins rebuild you need to trigger it yourself):
https://code.launchpad.net/~michihenning/storage-framework/api2/+merge/304599/+edit-commit-message

https://jenkins.canonical.com/unity-api-1/job/lp-storage-framework-ci/114/
Executed test runs:
    FAILURE: https://jenkins.canonical.com/unity-api-1/job/build/692/console
    FAILURE: https://jenkins.canonical.com/unity-api-1/job/build-0-fetch/698/console

Click here to trigger a rebuild:
https://jenkins.canonical.com/unity-api-1/job/lp-storage-framework-ci/114/rebuild

review: Needs Fixing (continuous-integration)
Revision history for this message
unity-api-1-bot (unity-api-1-bot) wrote :

FAILED: Continuous integration, rev:73
No commit message was specified in the merge proposal. Click on the following link and set the commit message (if you want a jenkins rebuild you need to trigger it yourself):
https://code.launchpad.net/~michihenning/storage-framework/api2/+merge/304599/+edit-commit-message

https://jenkins.canonical.com/unity-api-1/job/lp-storage-framework-ci/115/
Executed test runs:
    FAILURE: https://jenkins.canonical.com/unity-api-1/job/build/693/console
    FAILURE: https://jenkins.canonical.com/unity-api-1/job/build-0-fetch/699/console

Click here to trigger a rebuild:
https://jenkins.canonical.com/unity-api-1/job/lp-storage-framework-ci/115/rebuild

review: Needs Fixing (continuous-integration)
Revision history for this message
unity-api-1-bot (unity-api-1-bot) wrote :

FAILED: Continuous integration, rev:73
No commit message was specified in the merge proposal. Click on the following link and set the commit message (if you want a jenkins rebuild you need to trigger it yourself):
https://code.launchpad.net/~michihenning/storage-framework/api2/+merge/304599/+edit-commit-message

https://jenkins.canonical.com/unity-api-1/job/lp-storage-framework-ci/116/
Executed test runs:
    FAILURE: https://jenkins.canonical.com/unity-api-1/job/build/694/console
    FAILURE: https://jenkins.canonical.com/unity-api-1/job/build-0-fetch/700/console

Click here to trigger a rebuild:
https://jenkins.canonical.com/unity-api-1/job/lp-storage-framework-ci/116/rebuild

review: Needs Fixing (continuous-integration)
74. By Michi Henning

impossible_name() -> object_path()

Revision history for this message
unity-api-1-bot (unity-api-1-bot) wrote :
review: Needs Fixing (continuous-integration)
75. By Michi Henning

Q_ENUM -> Q_ENUIMS for Vivid. Disabled check for connection
state when creating the runtime.

Revision history for this message
unity-api-1-bot (unity-api-1-bot) wrote :
review: Needs Fixing (continuous-integration)
76. By Michi Henning

Fixed compilation error on Vivid. More warning suppressions for Arm.

77. By Michi Henning

Fixed wrong location for installing pc file.

Revision history for this message
unity-api-1-bot (unity-api-1-bot) wrote :
review: Needs Fixing (continuous-integration)
78. By Michi Henning

Added missing Q_DECLARE_METATYPE

Revision history for this message
unity-api-1-bot (unity-api-1-bot) wrote :

FAILED: Continuous integration, rev:77
https://jenkins.canonical.com/unity-api-1/job/lp-storage-framework-ci/120/
Executed test runs:
    FAILURE: https://jenkins.canonical.com/unity-api-1/job/build/709/console
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build-0-fetch/715
    FAILURE: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=amd64,release=vivid+overlay/523/console
    ABORTED: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=amd64,release=xenial+overlay/523/console
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=amd64,release=yakkety/523
        deb: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=amd64,release=yakkety/523/artifact/output/*zip*/output.zip
    FAILURE: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=armhf,release=vivid+overlay/523/console
    ABORTED: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=armhf,release=xenial+overlay/523/console
    ABORTED: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=armhf,release=yakkety/523/console
    FAILURE: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=i386,release=vivid+overlay/523/console
    ABORTED: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=i386,release=xenial+overlay/523/console
    ABORTED: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=i386,release=yakkety/523/console

Click here to trigger a rebuild:
https://jenkins.canonical.com/unity-api-1/job/lp-storage-framework-ci/120/rebuild

review: Needs Fixing (continuous-integration)
79. By Michi Henning

Another missing Q_DECLARE_METATYPE

Revision history for this message
unity-api-1-bot (unity-api-1-bot) wrote :

FAILED: Continuous integration, rev:78
https://jenkins.canonical.com/unity-api-1/job/lp-storage-framework-ci/121/
Executed test runs:
    FAILURE: https://jenkins.canonical.com/unity-api-1/job/build/710/console
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build-0-fetch/716
    FAILURE: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=amd64,release=vivid+overlay/524/console
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=amd64,release=xenial+overlay/524
        deb: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=amd64,release=xenial+overlay/524/artifact/output/*zip*/output.zip
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=amd64,release=yakkety/524
        deb: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=amd64,release=yakkety/524/artifact/output/*zip*/output.zip
    FAILURE: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=armhf,release=vivid+overlay/524/console
    ABORTED: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=armhf,release=xenial+overlay/524/console
    ABORTED: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=armhf,release=yakkety/524/console
    FAILURE: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=i386,release=vivid+overlay/524/console
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=i386,release=xenial+overlay/524
        deb: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=i386,release=xenial+overlay/524/artifact/output/*zip*/output.zip
    ABORTED: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=i386,release=yakkety/524/console

Click here to trigger a rebuild:
https://jenkins.canonical.com/unity-api-1/job/lp-storage-framework-ci/121/rebuild

review: Needs Fixing (continuous-integration)
80. By Michi Henning

More Q_DECLARE_METATYPE :-(

Revision history for this message
unity-api-1-bot (unity-api-1-bot) wrote :

FAILED: Continuous integration, rev:79
https://jenkins.canonical.com/unity-api-1/job/lp-storage-framework-ci/122/
Executed test runs:
    FAILURE: https://jenkins.canonical.com/unity-api-1/job/build/711/console
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build-0-fetch/717
    FAILURE: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=amd64,release=vivid+overlay/525/console
    ABORTED: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=amd64,release=xenial+overlay/525/console
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=amd64,release=yakkety/525
        deb: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=amd64,release=yakkety/525/artifact/output/*zip*/output.zip
    FAILURE: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=armhf,release=vivid+overlay/525/console
    ABORTED: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=armhf,release=xenial+overlay/525/console
    ABORTED: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=armhf,release=yakkety/525/console
    FAILURE: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=i386,release=vivid+overlay/525/console
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=i386,release=xenial+overlay/525
        deb: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=i386,release=xenial+overlay/525/artifact/output/*zip*/output.zip
    ABORTED: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=i386,release=yakkety/525/console

Click here to trigger a rebuild:
https://jenkins.canonical.com/unity-api-1/job/lp-storage-framework-ci/122/rebuild

review: Needs Fixing (continuous-integration)
Revision history for this message
unity-api-1-bot (unity-api-1-bot) wrote :

PASSED: Continuous integration, rev:80
https://jenkins.canonical.com/unity-api-1/job/lp-storage-framework-ci/123/
Executed test runs:
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build/712
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build-0-fetch/718
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=amd64,release=vivid+overlay/526
        deb: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=amd64,release=vivid+overlay/526/artifact/output/*zip*/output.zip
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=amd64,release=xenial+overlay/526
        deb: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=amd64,release=xenial+overlay/526/artifact/output/*zip*/output.zip
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=amd64,release=yakkety/526
        deb: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=amd64,release=yakkety/526/artifact/output/*zip*/output.zip
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=armhf,release=vivid+overlay/526
        deb: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=armhf,release=vivid+overlay/526/artifact/output/*zip*/output.zip
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=armhf,release=xenial+overlay/526
        deb: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=armhf,release=xenial+overlay/526/artifact/output/*zip*/output.zip
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=armhf,release=yakkety/526
        deb: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=armhf,release=yakkety/526/artifact/output/*zip*/output.zip
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=i386,release=vivid+overlay/526
        deb: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=i386,release=vivid+overlay/526/artifact/output/*zip*/output.zip
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=i386,release=xenial+overlay/526
        deb: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=i386,release=xenial+overlay/526/artifact/output/*zip*/output.zip
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=i386,release=yakkety/526
        deb: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=i386,release=yakkety/526/artifact/output/*zip*/output.zip

Click here to trigger a rebuild:
https://jenkins.canonical.com/unity-api-1/job/lp-storage-framework-ci/123/rebuild

review: Approve (continuous-integration)
Revision history for this message
James Henstridge (jamesh) wrote :

As discussed previously, we'll fix most of the issues from yesterday's review post merge.

Things I'd like you to fix before hand though are:

1. You've removed the logic to generate .pc files for the old v1 client libraries and instead used copies with /home/michi/src/storage-framework/api2/build/install/ substituted in as the install prefix. This will cause compile and link failures for any code trying to link to those libraries. Please switch back to generating them from a .pc.in file using configure_file().

2. Don't piggy back on the libstorage-framework-qt-client-1 binary package for the new library: add a new binary package, and add it as a dependency for storage-framework-client-dev. It's better to take the effort to do this now rather than have binary packages built against the new library break when we change things around in future.

2. The headers for the new and old client libraries are mixed together. Ideally they'd be separate, but it probably isn't worth spending time to change, given we want a fairly short change over.

review: Needs Fixing
81. By Michi Henning

Separated old and new header install location.
Added new binary package for v2 client API.
Fix broken pkgconfig files.
Bumped project version.
Updated changelog.

82. By Michi Henning

A few more packaging fixes.

Revision history for this message
unity-api-1-bot (unity-api-1-bot) wrote :

PASSED: Continuous integration, rev:82
https://jenkins.canonical.com/unity-api-1/job/lp-storage-framework-ci/124/
Executed test runs:
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build/714
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build-0-fetch/720
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=amd64,release=vivid+overlay/528
        deb: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=amd64,release=vivid+overlay/528/artifact/output/*zip*/output.zip
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=amd64,release=xenial+overlay/528
        deb: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=amd64,release=xenial+overlay/528/artifact/output/*zip*/output.zip
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=amd64,release=yakkety/528
        deb: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=amd64,release=yakkety/528/artifact/output/*zip*/output.zip
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=armhf,release=vivid+overlay/528
        deb: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=armhf,release=vivid+overlay/528/artifact/output/*zip*/output.zip
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=armhf,release=xenial+overlay/528
        deb: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=armhf,release=xenial+overlay/528/artifact/output/*zip*/output.zip
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=armhf,release=yakkety/528
        deb: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=armhf,release=yakkety/528/artifact/output/*zip*/output.zip
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=i386,release=vivid+overlay/528
        deb: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=i386,release=vivid+overlay/528/artifact/output/*zip*/output.zip
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=i386,release=xenial+overlay/528
        deb: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=i386,release=xenial+overlay/528/artifact/output/*zip*/output.zip
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=i386,release=yakkety/528
        deb: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=i386,release=yakkety/528/artifact/output/*zip*/output.zip

Click here to trigger a rebuild:
https://jenkins.canonical.com/unity-api-1/job/lp-storage-framework-ci/124/rebuild

review: Approve (continuous-integration)
Revision history for this message
James Henstridge (jamesh) wrote :

Looks good.

review: Approve
Revision history for this message
unity-api-1-bot (unity-api-1-bot) wrote :

PASSED: Continuous integration, rev:84
https://jenkins.canonical.com/unity-api-1/job/lp-storage-framework-ci/125/
Executed test runs:
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build/726
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build-0-fetch/732
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=amd64,release=vivid+overlay/540
        deb: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=amd64,release=vivid+overlay/540/artifact/output/*zip*/output.zip
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=amd64,release=xenial+overlay/540
        deb: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=amd64,release=xenial+overlay/540/artifact/output/*zip*/output.zip
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=amd64,release=yakkety/540
        deb: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=amd64,release=yakkety/540/artifact/output/*zip*/output.zip
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=armhf,release=vivid+overlay/540
        deb: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=armhf,release=vivid+overlay/540/artifact/output/*zip*/output.zip
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=armhf,release=xenial+overlay/540
        deb: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=armhf,release=xenial+overlay/540/artifact/output/*zip*/output.zip
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=armhf,release=yakkety/540
        deb: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=armhf,release=yakkety/540/artifact/output/*zip*/output.zip
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=i386,release=vivid+overlay/540
        deb: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=i386,release=vivid+overlay/540/artifact/output/*zip*/output.zip
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=i386,release=xenial+overlay/540
        deb: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=i386,release=xenial+overlay/540/artifact/output/*zip*/output.zip
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=i386,release=yakkety/540
        deb: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=i386,release=yakkety/540/artifact/output/*zip*/output.zip

Click here to trigger a rebuild:
https://jenkins.canonical.com/unity-api-1/job/lp-storage-framework-ci/125/rebuild

review: Approve (continuous-integration)

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'CMakeLists.txt'
2--- CMakeLists.txt 2016-09-03 00:53:43 +0000
3+++ CMakeLists.txt 2016-09-21 05:03:46 +0000
4@@ -5,13 +5,13 @@
5 endif()
6
7 cmake_minimum_required(VERSION 3.0.2)
8-project(storage-framework VERSION "0.1" LANGUAGES C CXX)
9+project(storage-framework VERSION "0.2" LANGUAGES C CXX)
10
11 # These variables should be incremented when we wish to create a new
12 # source incompatible version of the the library where users of the
13-# old API could will not compile against the new one. It is not
14+# old API will not compile against the new one. It is not
15 # necessary to increment this for ABI breaks that are source compatible.
16-set(SF_CLIENT_API_VERSION "1")
17+set(SF_CLIENT_API_VERSION "2")
18 set(SF_PROVIDER_API_VERSION "1")
19
20 # These two should be incremented when the ABI changes.
21@@ -132,6 +132,7 @@
22 qt-client-lib-common
23 storage-framework-common-internal
24 storage-framework-qt-client
25+ storage-framework-qt-client-v2
26 storage-framework-qt-local-client
27 sf-provider-objects
28 storage-framework-provider
29
30=== modified file 'debian/changelog'
31--- debian/changelog 2016-08-04 07:20:09 +0000
32+++ debian/changelog 2016-09-21 05:03:46 +0000
33@@ -1,3 +1,10 @@
34+storage-framework (0.2) UNRELEASED; urgency=medium
35+
36+ [ Michi Henning ]
37+ * Added v2 of the client-side API.
38+
39+ -- Michi Henning <michi.henning@canonical.com> Wed, 21 Sep 2016 14:36:15 +1000
40+
41 storage-framework (0.1+16.10.20160804.1-0ubuntu1) yakkety; urgency=medium
42
43 [ Michi Henning ]
44
45=== modified file 'debian/control'
46--- debian/control 2016-08-04 07:20:09 +0000
47+++ debian/control 2016-09-21 05:03:46 +0000
48@@ -49,6 +49,15 @@
49 Pre-Depends: ${misc:Pre-Depends},
50 Depends: ${misc:Depends},
51 ${shlibs:Depends},
52+Description: Client library for the Storage Framework (API v1, soon to be removed)
53+ Runtime support for storage framework clients.
54+
55+Package: libstorage-framework-qt-client-2-0
56+Architecture: any
57+Multi-Arch: same
58+Pre-Depends: ${misc:Pre-Depends},
59+Depends: ${misc:Depends},
60+ ${shlibs:Depends},
61 Description: Client library for the Storage Framework
62 Runtime support for storage framework clients.
63
64@@ -70,6 +79,7 @@
65 Multi-Arch: same
66 Pre-Depends: ${misc:Pre-Depends},
67 Depends: libstorage-framework-qt-client-1-0 (= ${binary:Version}),
68+ libstorage-framework-qt-client-2-0 (= ${binary:Version}),
69 libstorage-framework-qt-local-client-1-0 (= ${binary:Version}),
70 qtbase5-dev,
71 ${misc:Depends},
72
73=== modified file 'debian/control.in'
74--- debian/control.in 2016-08-02 03:36:58 +0000
75+++ debian/control.in 2016-09-21 05:03:46 +0000
76@@ -44,6 +44,15 @@
77 Pre-Depends: ${misc:Pre-Depends},
78 Depends: ${misc:Depends},
79 ${shlibs:Depends},
80+Description: Client library for the Storage Framework (API v1, soon to be removed)
81+ Runtime support for storage framework clients.
82+
83+Package: libstorage-framework-qt-client-2-0
84+Architecture: any
85+Multi-Arch: same
86+Pre-Depends: ${misc:Pre-Depends},
87+Depends: ${misc:Depends},
88+ ${shlibs:Depends},
89 Description: Client library for the Storage Framework
90 Runtime support for storage framework clients.
91
92
93=== modified file 'debian/libstorage-framework-qt-client-1-0.install'
94--- debian/libstorage-framework-qt-client-1-0.install 2016-07-11 04:06:04 +0000
95+++ debian/libstorage-framework-qt-client-1-0.install 2016-09-21 05:03:46 +0000
96@@ -1,1 +1,1 @@
97-usr/lib/*/libstorage-framework-qt-client-*.so.*
98+usr/lib/*/libstorage-framework-qt-client-1.so.*
99
100=== added file 'debian/libstorage-framework-qt-client-2-0.install'
101--- debian/libstorage-framework-qt-client-2-0.install 1970-01-01 00:00:00 +0000
102+++ debian/libstorage-framework-qt-client-2-0.install 2016-09-21 05:03:46 +0000
103@@ -0,0 +1,1 @@
104+usr/lib/*/libstorage-framework-qt-client-2.so.*
105
106=== modified file 'include/unity/storage/CMakeLists.txt'
107--- include/unity/storage/CMakeLists.txt 2016-07-11 03:28:40 +0000
108+++ include/unity/storage/CMakeLists.txt 2016-09-21 05:03:46 +0000
109@@ -7,5 +7,9 @@
110 install(FILES ${common_headers}
111 DESTINATION ${provider_base_includedir}/${includeprefix})
112
113+# Deprecated client API v1 install
114+install(FILES ${common_headers}
115+ DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/storage-framework-client-1/${includeprefix})
116+
117 add_subdirectory(provider)
118 add_subdirectory(qt)
119
120=== modified file 'include/unity/storage/internal/ItemMetadata.h'
121--- include/unity/storage/internal/ItemMetadata.h 2016-08-25 23:56:02 +0000
122+++ include/unity/storage/internal/ItemMetadata.h 2016-09-21 05:03:46 +0000
123@@ -49,3 +49,6 @@
124 } // namespace internal
125 } // namespace storage
126 } // namespace unity
127+
128+Q_DECLARE_METATYPE(unity::storage::internal::ItemMetadata)
129+Q_DECLARE_METATYPE(QList<unity::storage::internal::ItemMetadata>)
130
131=== modified file 'include/unity/storage/internal/dbusmarshal.h'
132--- include/unity/storage/internal/dbusmarshal.h 2016-08-11 06:53:25 +0000
133+++ include/unity/storage/internal/dbusmarshal.h 2016-09-21 05:03:46 +0000
134@@ -39,6 +39,3 @@
135 } // namespace internal
136 } // storage
137 } // unity
138-
139-Q_DECLARE_METATYPE(unity::storage::internal::ItemMetadata)
140-Q_DECLARE_METATYPE(QList<unity::storage::internal::ItemMetadata>)
141
142=== added file 'include/unity/storage/qt/Account.h'
143--- include/unity/storage/qt/Account.h 1970-01-01 00:00:00 +0000
144+++ include/unity/storage/qt/Account.h 2016-09-21 05:03:46 +0000
145@@ -0,0 +1,103 @@
146+/*
147+ * Copyright (C) 2016 Canonical Ltd
148+ *
149+ * This program is free software: you can redistribute it and/or modify
150+ * it under the terms of the GNU Lesser General Public License version 3 as
151+ * published by the Free Software Foundation.
152+ *
153+ * This program is distributed in the hope that it will be useful,
154+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
155+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
156+ * GNU Lesser General Public License for more details.
157+ *
158+ * You should have received a copy of the GNU Lesser General Public License
159+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
160+ *
161+ * Authors: Michi Henning <michi.henning@canonical.com>
162+ */
163+
164+#pragma once
165+
166+#include <QMetaType>
167+
168+#include <memory>
169+
170+namespace unity
171+{
172+namespace storage
173+{
174+namespace qt
175+{
176+namespace internal
177+{
178+
179+class AccountImpl;
180+class ItemImpl;
181+
182+}
183+
184+class ItemJob;
185+class ItemListJob;
186+
187+class Q_DECL_EXPORT Account final
188+{
189+ Q_GADGET
190+ Q_PROPERTY(bool READ isValid CONSTANT FINAL)
191+ Q_PROPERTY(QString READ owner CONSTANT FINAL)
192+ Q_PROPERTY(QString READ ownerId CONSTANT FINAL)
193+ Q_PROPERTY(QString READ description CONSTANT FINAL)
194+
195+public:
196+ Account();
197+ Account(Account const&);
198+ Account(Account&&);
199+ ~Account();
200+ Account& operator=(Account const&);
201+ Account& operator=(Account&&);
202+
203+ bool isValid() const;
204+ QString owner() const;
205+ QString ownerId() const;
206+ QString description() const;
207+
208+ Q_INVOKABLE ItemListJob* roots() const;
209+ Q_INVOKABLE ItemJob* get(QString const& itemId) const;
210+
211+ bool operator==(Account const&) const;
212+ bool operator!=(Account const&) const;
213+ bool operator<(Account const&) const;
214+ bool operator<=(Account const&) const;
215+ bool operator>(Account const&) const;
216+ bool operator>=(Account const&) const;
217+
218+ size_t hash() const;
219+
220+private:
221+ Account(std::shared_ptr<internal::AccountImpl> const& p);
222+
223+ std::shared_ptr<internal::AccountImpl> p_;
224+
225+ friend class internal::AccountImpl;
226+ friend class internal::ItemImpl;
227+};
228+
229+} // namespace qt
230+} // namespace storage
231+} // namespace unity
232+
233+namespace std
234+{
235+
236+template<> struct Q_DECL_EXPORT hash<unity::storage::qt::Account>
237+{
238+ std::size_t operator()(unity::storage::qt::Account const& a)
239+ {
240+ return a.hash();
241+ }
242+};
243+
244+} // namespace std
245+
246+// Note: qHash(Account) does *not* return the same hash value is std::hash<Account> because
247+// std:hash() returns size_t (typically 64 bits), but qHash() returns uint (typically 32 bits).
248+uint Q_DECL_EXPORT qHash(unity::storage::qt::Account const& acc);
249
250=== added file 'include/unity/storage/qt/AccountsJob.h'
251--- include/unity/storage/qt/AccountsJob.h 1970-01-01 00:00:00 +0000
252+++ include/unity/storage/qt/AccountsJob.h 2016-09-21 05:03:46 +0000
253@@ -0,0 +1,80 @@
254+/*
255+ * Copyright (C) 2016 Canonical Ltd
256+ *
257+ * This program is free software: you can redistribute it and/or modify
258+ * it under the terms of the GNU Lesser General Public License version 3 as
259+ * published by the Free Software Foundation.
260+ *
261+ * This program is distributed in the hope that it will be useful,
262+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
263+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
264+ * GNU Lesser General Public License for more details.
265+ *
266+ * You should have received a copy of the GNU Lesser General Public License
267+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
268+ *
269+ * Authors: Michi Henning <michi.henning@canonical.com>
270+ */
271+
272+#pragma once
273+
274+#include <unity/storage/qt/Account.h>
275+#include <unity/storage/qt/StorageError.h>
276+
277+#include <QMetaType>
278+#include <QObject>
279+
280+namespace unity
281+{
282+namespace storage
283+{
284+namespace qt
285+{
286+namespace internal
287+{
288+
289+class AccountsJobImpl;
290+class RuntimeImpl;
291+
292+} // namespace internal
293+
294+class Account;
295+class Runtime;
296+class StorageError;
297+
298+class Q_DECL_EXPORT AccountsJob final : public QObject
299+{
300+ Q_OBJECT
301+ Q_PROPERTY(bool isValid READ isValid FINAL)
302+ Q_PROPERTY(unity::storage::qt::AccountsJob::Status status READ status NOTIFY statusChanged FINAL)
303+ Q_PROPERTY(unity::storage::qt::StorageError error READ error FINAL)
304+ Q_PROPERTY(QList<unity::storage::qt::Account> accounts READ accounts FINAL)
305+
306+public:
307+ enum Status { Loading, Finished, Error };
308+ Q_ENUMS(Status)
309+
310+ virtual ~AccountsJob();
311+
312+ bool isValid() const;
313+ Status status() const;
314+ StorageError error() const;
315+ QList<Account> accounts() const;
316+
317+Q_SIGNALS:
318+ void statusChanged(unity::storage::qt::AccountsJob::Status status) const;
319+
320+private:
321+ AccountsJob(std::shared_ptr<internal::RuntimeImpl> const& runtime);
322+ AccountsJob(StorageError const& error);
323+
324+ std::unique_ptr<internal::AccountsJobImpl> const p_;
325+
326+ friend class internal::RuntimeImpl;
327+};
328+
329+} // namespace qt
330+} // namespace storage
331+} // namespace unity
332+
333+Q_DECLARE_METATYPE(unity::storage::qt::AccountsJob::Status)
334
335=== modified file 'include/unity/storage/qt/CMakeLists.txt'
336--- include/unity/storage/qt/CMakeLists.txt 2016-05-23 02:27:16 +0000
337+++ include/unity/storage/qt/CMakeLists.txt 2016-09-21 05:03:46 +0000
338@@ -1,1 +1,17 @@
339-add_subdirectory(client)
340+add_subdirectory(client) # Old (v1) API
341+
342+set(includeprefix unity/storage/qt)
343+file(GLOB public_hdrs *.h)
344+set(convenience_hdr ${CMAKE_CURRENT_BINARY_DIR}/client-api.h)
345+
346+add_custom_command(
347+ OUTPUT ${convenience_hdr}
348+ COMMAND ${CMAKE_SOURCE_DIR}/tools/create_globalheader.py
349+ ${convenience_hdr} ${includeprefix} ${CMAKE_CURRENT_SOURCE_DIR}
350+ DEPENDS ${public_hdrs})
351+
352+add_custom_target(qt-client-all-headers ALL DEPENDS ${convenience_hdr})
353+
354+install(
355+ FILES ${public_hdrs} ${convenience_hdr}
356+ DESTINATION ${client_base_includedir}/${includeprefix})
357
358=== added file 'include/unity/storage/qt/ConflictPolicy.h'
359--- include/unity/storage/qt/ConflictPolicy.h 1970-01-01 00:00:00 +0000
360+++ include/unity/storage/qt/ConflictPolicy.h 2016-09-21 05:03:46 +0000
361@@ -0,0 +1,32 @@
362+/*
363+ * Copyright (C) 2016 Canonical Ltd
364+ *
365+ * This program is free software: you can redistribute it and/or modify
366+ * it under the terms of the GNU Lesser General Public License version 3 as
367+ * published by the Free Software Foundation.
368+ *
369+ * This program is distributed in the hope that it will be useful,
370+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
371+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
372+ * GNU Lesser General Public License for more details.
373+ *
374+ * You should have received a copy of the GNU Lesser General Public License
375+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
376+ *
377+ * Authors: Michi Henning <michi.henning@canonical.com>
378+ */
379+
380+#pragma once
381+
382+namespace unity
383+{
384+namespace storage
385+{
386+namespace qt
387+{
388+
389+enum class ConflictPolicy { ErrorIfConflict, Overwrite };
390+
391+} // namespace qt
392+} // namespace storage
393+} // namespace unity
394
395=== added file 'include/unity/storage/qt/Downloader.h'
396--- include/unity/storage/qt/Downloader.h 1970-01-01 00:00:00 +0000
397+++ include/unity/storage/qt/Downloader.h 2016-09-21 05:03:46 +0000
398@@ -0,0 +1,68 @@
399+/*
400+ * Copyright (C) 2016 Canonical Ltd
401+ *
402+ * This program is free software: you can redistribute it and/or modify
403+ * it under the terms of the GNU Lesser General Public License version 3 as
404+ * published by the Free Software Foundation.
405+ *
406+ * This program is distributed in the hope that it will be useful,
407+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
408+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
409+ * GNU Lesser General Public License for more details.
410+ *
411+ * You should have received a copy of the GNU Lesser General Public License
412+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
413+ *
414+ * Authors: Michi Henning <michi.henning@canonical.com>
415+ */
416+
417+#pragma once
418+
419+#include <QIODevice>
420+
421+namespace unity
422+{
423+namespace storage
424+{
425+namespace qt
426+{
427+
428+class Item;
429+class StorageError;
430+
431+class Q_DECL_EXPORT Downloader final : public QIODevice
432+{
433+ Q_OBJECT
434+ Q_PROPERTY(bool isValid READ isValid FINAL) // TODO: Need notify and constant where appropriate
435+ Q_PROPERTY(unity::Storage::qt::Downloader::Status status READ status NOTIFY statusChanged FINAL)
436+ Q_PROPERTY(unity::Storage::qt::StorageError error READ error FINAL)
437+ Q_PROPERTY(unity::Storage::qt::Item item READ item FINAL)
438+
439+public:
440+ enum Status { Loading, Ready, Cancelled, Finished, Error };
441+ Q_ENUMS(Status)
442+
443+ Downloader();
444+ virtual ~Downloader();
445+
446+ bool isValid();
447+ Status status() const;
448+ StorageError error() const;
449+ Item item() const;
450+
451+ Q_INVOKABLE void finishDownload(); // TODO: finish()
452+ Q_INVOKABLE void cancel();
453+
454+ // TODO: will probably need QML invokable methods for reading and writing to/from QIODevice
455+
456+Q_SIGNALS:
457+ void statusChanged(unity::storage::qt::Downloader::Status status) const;
458+
459+protected:
460+ virtual qint64 readData(char* data, qint64 maxSize) override;
461+ virtual qint64 writeData(char const* data, qint64 maxSize) override;
462+};
463+
464+} // namespace qt
465+} // namespace storage
466+} // namespace unity
467
468=== added file 'include/unity/storage/qt/Item.h'
469--- include/unity/storage/qt/Item.h 1970-01-01 00:00:00 +0000
470+++ include/unity/storage/qt/Item.h 2016-09-21 05:03:46 +0000
471@@ -0,0 +1,142 @@
472+/*
473+ * Copyright (C) 2016 Canonical Ltd
474+ *
475+ * This program is free software: you can redistribute it and/or modify
476+ * it under the terms of the GNU Lesser General Public License version 3 as
477+ * published by the Free Software Foundation.
478+ *
479+ * This program is distributed in the hope that it will be useful,
480+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
481+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
482+ * GNU Lesser General Public License for more details.
483+ *
484+ * You should have received a copy of the GNU Lesser General Public License
485+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
486+ *
487+ * Authors: Michi Henning <michi.henning@canonical.com>
488+ */
489+
490+#pragma once
491+
492+#include <unity/storage/qt/ConflictPolicy.h>
493+
494+#pragma GCC diagnostic push
495+#pragma GCC diagnostic ignored "-Wcast-align"
496+#pragma GCC diagnostic ignored "-Wctor-dtor-privacy"
497+#include <QDateTime>
498+#include <QVariantMap>
499+#pragma GCC diagnostic pop
500+
501+#include <memory>
502+
503+namespace unity
504+{
505+namespace storage
506+{
507+namespace qt
508+{
509+namespace internal
510+{
511+
512+class ItemImpl;
513+
514+} // namespace internal
515+
516+class Account;
517+class Downloader;
518+class IntJob;
519+class ItemJob;
520+class ItemListJob;
521+class Uploader;
522+class VoidJob;
523+
524+class Q_DECL_EXPORT Item final
525+{
526+ Q_GADGET
527+ Q_PROPERTY(QString itemId READ itemId CONSTANT FINAL)
528+ Q_PROPERTY(QString name READ name CONSTANT FINAL)
529+ Q_PROPERTY(unity::storage::qt::Account account READ account CONSTANT FINAL)
530+ Q_PROPERTY(QString etag READ etag CONSTANT FINAL)
531+ Q_PROPERTY(unity::storage::qt::Item::Type type READ type CONSTANT FINAL)
532+ Q_PROPERTY(QVariantMap metadata READ metadata CONSTANT FINAL)
533+ Q_PROPERTY(QDateTime lastModifiedTime READ lastModifiedTime CONSTANT FINAL)
534+ Q_PROPERTY(QVector<QString> parentIds READ parentIds CONSTANT FINAL)
535+
536+public:
537+ Item();
538+ Item(Item const&);
539+ Item(Item&&);
540+ ~Item();
541+ Item& operator=(Item const&);
542+ Item& operator=(Item&&);
543+
544+ enum Type { File, Folder, Root };
545+ Q_ENUMS(Type)
546+
547+ bool isValid() const;
548+ QString itemId() const;
549+ QString name() const;
550+ Account account() const;
551+ QString etag() const;
552+ Type type() const;
553+ QVariantMap metadata() const;
554+ QDateTime lastModifiedTime() const;
555+ QVector<QString> parentIds() const; // TODO: should be QList
556+
557+ Q_INVOKABLE ItemListJob* parents() const;
558+ Q_INVOKABLE ItemJob* copy(Item const& newParent, QString const& newName) const;
559+ Q_INVOKABLE ItemJob* move(Item const& newParent, QString const& newName) const;
560+ Q_INVOKABLE VoidJob* deleteItem() const;
561+
562+ Q_INVOKABLE Uploader* createUploader(ConflictPolicy policy, qint64 sizeInBytes) const;
563+ Q_INVOKABLE Downloader* createDownloader() const;
564+
565+ Q_INVOKABLE ItemListJob* list() const;
566+ Q_INVOKABLE ItemListJob* lookup(QString const& name) const;
567+ Q_INVOKABLE ItemJob* createFolder(QString const& name) const;
568+ Q_INVOKABLE Uploader* createFile(QString const& name) const;
569+
570+ Q_INVOKABLE IntJob* freeSpaceBytes() const;
571+ Q_INVOKABLE IntJob* usedSpaceBytes() const;
572+
573+ bool operator==(Item const&) const;
574+ bool operator!=(Item const&) const;
575+ bool operator<(Item const&) const;
576+ bool operator<=(Item const&) const;
577+ bool operator>(Item const&) const;
578+ bool operator>=(Item const&) const;
579+
580+ size_t hash() const;
581+
582+private:
583+ Item(std::shared_ptr<internal::ItemImpl> const&);
584+
585+ std::shared_ptr<internal::ItemImpl> p_;
586+
587+ friend class internal::ItemImpl;
588+};
589+
590+} // namespace qt
591+} // namespace storage
592+} // namespace unity
593+
594+Q_DECLARE_METATYPE(unity::storage::qt::Item)
595+Q_DECLARE_METATYPE(QList<unity::storage::qt::Item>)
596+Q_DECLARE_METATYPE(unity::storage::qt::Item::Type)
597+
598+namespace std
599+{
600+
601+template<> struct Q_DECL_EXPORT hash<unity::storage::qt::Item>
602+{
603+ std::size_t operator()(unity::storage::qt::Item const& i)
604+ {
605+ return i.hash();
606+ }
607+};
608+
609+} // namespace std
610+
611+// Note: qHash(Item) does *not* return the same hash value is std::hash<Item> because
612+// std:hash() returns size_t (typically 64 bits), but qHash() returns uint (typically 32 bits).
613+uint Q_DECL_EXPORT qHash(unity::storage::qt::Item const& i);
614
615=== added file 'include/unity/storage/qt/ItemJob.h'
616--- include/unity/storage/qt/ItemJob.h 1970-01-01 00:00:00 +0000
617+++ include/unity/storage/qt/ItemJob.h 2016-09-21 05:03:46 +0000
618@@ -0,0 +1,75 @@
619+/*
620+ * Copyright (C) 2016 Canonical Ltd
621+ *
622+ * This program is free software: you can redistribute it and/or modify
623+ * it under the terms of the GNU Lesser General Public License version 3 as
624+ * published by the Free Software Foundation.
625+ *
626+ * This program is distributed in the hope that it will be useful,
627+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
628+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
629+ * GNU Lesser General Public License for more details.
630+ *
631+ * You should have received a copy of the GNU Lesser General Public License
632+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
633+ *
634+ * Authors: Michi Henning <michi.henning@canonical.com>
635+ */
636+
637+#pragma once
638+
639+#include <unity/storage/qt/Item.h>
640+
641+#include <QObject>
642+
643+namespace unity
644+{
645+namespace storage
646+{
647+namespace qt
648+{
649+namespace internal
650+{
651+
652+class ItemJobImpl;
653+
654+} // namespace internal
655+
656+class Item;
657+class StorageError;
658+
659+class Q_DECL_EXPORT ItemJob final : public QObject
660+{
661+ Q_OBJECT
662+ Q_PROPERTY(bool isValid READ isValid FINAL)
663+ Q_PROPERTY(unity::storage::qt::ItemJob::Status status READ status NOTIFY statusChanged FINAL)
664+ Q_PROPERTY(unity::storage::qt::StorageError error READ error FINAL)
665+ Q_PROPERTY(unity::storage::qt::Item item READ item FINAL)
666+
667+public:
668+ virtual ~ItemJob();
669+
670+ enum Status { Loading, Finished, Error };
671+ Q_ENUMS(Status)
672+
673+ bool isValid() const;
674+ Status status() const;
675+ StorageError error() const;
676+ Item item() const;
677+
678+Q_SIGNALS:
679+ void statusChanged(unity::storage::qt::ItemJob::Status status) const;
680+
681+private:
682+ ItemJob(std::unique_ptr<internal::ItemJobImpl> p);
683+
684+ std::unique_ptr<internal::ItemJobImpl> const p_;
685+
686+ friend class internal::ItemJobImpl;
687+};
688+
689+} // namespace qt
690+} // namespace storage
691+} // namespace unity
692+
693+Q_DECLARE_METATYPE(unity::storage::qt::ItemJob::Status)
694
695=== added file 'include/unity/storage/qt/ItemListJob.h'
696--- include/unity/storage/qt/ItemListJob.h 1970-01-01 00:00:00 +0000
697+++ include/unity/storage/qt/ItemListJob.h 2016-09-21 05:03:46 +0000
698@@ -0,0 +1,77 @@
699+/*
700+ * Copyright (C) 2016 Canonical Ltd
701+ *
702+ * This program is free software: you can redistribute it and/or modify
703+ * it under the terms of the GNU Lesser General Public License version 3 as
704+ * published by the Free Software Foundation.
705+ *
706+ * This program is distributed in the hope that it will be useful,
707+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
708+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
709+ * GNU Lesser General Public License for more details.
710+ *
711+ * You should have received a copy of the GNU Lesser General Public License
712+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
713+ *
714+ * Authors: Michi Henning <michi.henning@canonical.com>
715+ */
716+
717+#pragma once
718+
719+#pragma GCC diagnostic push
720+#pragma GCC diagnostic ignored "-Wcast-align"
721+#include <QObject>
722+#pragma GCC diagnostic pop
723+
724+#include <memory>
725+
726+namespace unity
727+{
728+namespace storage
729+{
730+namespace qt
731+{
732+namespace internal
733+{
734+
735+class ItemListJobImpl;
736+
737+} // namespace internal
738+
739+class Item;
740+class StorageError;
741+
742+class Q_DECL_EXPORT ItemListJob final : public QObject
743+{
744+ Q_OBJECT
745+ Q_PROPERTY(bool isValid READ isValid FINAL)
746+ Q_PROPERTY(unity::storage::qt::ItemListJob::Status status READ status NOTIFY statusChanged FINAL)
747+ Q_PROPERTY(unity::storage::qt::StorageError error READ error FINAL)
748+
749+public:
750+ virtual ~ItemListJob();
751+
752+ enum Status { Loading, Finished, Error };
753+ Q_ENUMS(Status)
754+
755+ bool isValid() const;
756+ Status status() const;
757+ StorageError error() const;
758+
759+Q_SIGNALS:
760+ void statusChanged(unity::storage::qt::ItemListJob::Status status) const;
761+ void itemsReady(QList<unity::storage::qt::Item> const& items) const;
762+
763+private:
764+ ItemListJob(std::unique_ptr<internal::ItemListJobImpl> p);
765+
766+ std::unique_ptr<internal::ItemListJobImpl> const p_;
767+
768+ friend class internal::ItemListJobImpl;
769+};
770+
771+} // namespace qt
772+} // namespace storage
773+} // namespace unity
774+
775+Q_DECLARE_METATYPE(unity::storage::qt::ItemListJob::Status)
776
777=== added file 'include/unity/storage/qt/Runtime.h'
778--- include/unity/storage/qt/Runtime.h 1970-01-01 00:00:00 +0000
779+++ include/unity/storage/qt/Runtime.h 2016-09-21 05:03:46 +0000
780@@ -0,0 +1,80 @@
781+/*
782+ * Copyright (C) 2016 Canonical Ltd
783+ *
784+ * This program is free software: you can redistribute it and/or modify
785+ * it under the terms of the GNU Lesser General Public License version 3 as
786+ * published by the Free Software Foundation.
787+ *
788+ * This program is distributed in the hope that it will be useful,
789+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
790+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
791+ * GNU Lesser General Public License for more details.
792+ *
793+ * You should have received a copy of the GNU Lesser General Public License
794+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
795+ *
796+ * Authors: Michi Henning <michi.henning@canonical.com>
797+ */
798+
799+#pragma once
800+
801+#include <unity/storage/qt/Account.h>
802+#include <unity/storage/qt/StorageError.h>
803+
804+#pragma GCC diagnostic push
805+#pragma GCC diagnostic ignored "-Wcast-align"
806+#pragma GCC diagnostic ignored "-Wctor-dtor-privacy"
807+#include <QDBusConnection>
808+#pragma GCC diagnostic pop
809+
810+#include <memory>
811+
812+class QDBusConnection;
813+
814+namespace unity
815+{
816+namespace storage
817+{
818+namespace qt
819+{
820+namespace internal
821+{
822+
823+class RuntimeImpl;
824+
825+} // namespace internal
826+
827+class AccountsJob;
828+
829+class Q_DECL_EXPORT Runtime final : public QObject
830+{
831+ Q_PROPERTY(bool isValid READ isValid FINAL)
832+ Q_PROPERTY(unity::storage::StorageError error READ FINAL)
833+ Q_PROPERTY(QDBusConnection connection READ connection FINAL)
834+public:
835+ Runtime(QObject* parent = nullptr);
836+ Runtime(QDBusConnection const& bus, QObject* parent = nullptr);
837+ virtual ~Runtime();
838+
839+ bool isValid() const;
840+ StorageError error() const;
841+ QDBusConnection connection() const;
842+ StorageError shutdown();
843+ Q_INVOKABLE AccountsJob* accounts() const;
844+
845+ // TODO: Get rid of two-argument version and default trailing params.
846+ // TODO: can be const methods.
847+ Account make_test_account(QString const& bus_name, QString const& object_path);
848+ Account make_test_account(QString const& bus_name,
849+ QString const& object_path,
850+ QString const& owner_id,
851+ QString const& owner,
852+ QString const& description);
853+
854+private:
855+ std::shared_ptr<internal::RuntimeImpl> p_;
856+};
857+
858+} // namespace qt
859+} // namespace storage
860+} // namespace unity
861
862=== added file 'include/unity/storage/qt/StorageError.h'
863--- include/unity/storage/qt/StorageError.h 1970-01-01 00:00:00 +0000
864+++ include/unity/storage/qt/StorageError.h 2016-09-21 05:03:46 +0000
865@@ -0,0 +1,87 @@
866+/*
867+ * Copyright (C) 2016 Canonical Ltd
868+ *
869+ * This program is free software: you can redistribute it and/or modify
870+ * it under the terms of the GNU Lesser General Public License version 3 as
871+ * published by the Free Software Foundation.
872+ *
873+ * This program is distributed in the hope that it will be useful,
874+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
875+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
876+ * GNU Lesser General Public License for more details.
877+ *
878+ * You should have received a copy of the GNU Lesser General Public License
879+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
880+ *
881+ * Authors: Michi Henning <michi.henning@canonical.com>
882+ */
883+
884+#pragma once
885+
886+#include <QMetaType>
887+#include <QString>
888+
889+#include <memory>
890+
891+namespace unity
892+{
893+namespace storage
894+{
895+namespace qt
896+{
897+namespace internal
898+{
899+
900+class StorageErrorImpl;
901+
902+}
903+
904+class Q_DECL_EXPORT StorageError final
905+{
906+ Q_GADGET
907+ Q_PROPERTY(unity::storage::qt::StorageError::Type type READ type FINAL)
908+ Q_PROPERTY(QString name READ name FINAL)
909+ Q_PROPERTY(QString message READ message FINAL)
910+ Q_PROPERTY(QString errorString READ errorString FINAL)
911+
912+ Q_PROPERTY(QString itemId READ itemId FINAL)
913+ Q_PROPERTY(QString itemName READ itemName FINAL)
914+ Q_PROPERTY(int errorCode READ errorCode FINAL)
915+
916+public:
917+ StorageError();
918+ StorageError(StorageError const&);
919+ StorageError(StorageError&&);
920+ ~StorageError();
921+ StorageError& operator=(StorageError const&);
922+ StorageError& operator=(StorageError&&);
923+
924+ enum Type
925+ {
926+ NoError, LocalCommsError, RemoteCommsError, Deleted, RuntimeDestroyed, NotExists,
927+ Exists, Conflict, PermissionDenied, Cancelled, LogicError, InvalidArgument, ResourceError,
928+ QuotaExceeded,
929+ __LAST_STORAGE_ERROR
930+ };
931+ Q_ENUMS(Type)
932+
933+ Type type() const;
934+ QString name() const;
935+ QString message() const;
936+ QString errorString() const;
937+
938+ QString itemId() const;
939+ QString itemName() const;
940+ int errorCode() const;
941+
942+private:
943+ StorageError(std::unique_ptr<internal::StorageErrorImpl>);
944+
945+ std::unique_ptr<internal::StorageErrorImpl> p_;
946+
947+ friend class internal::StorageErrorImpl;
948+};
949+
950+} // namespace qt
951+} // namespace storage
952+} // namespace unity
953
954=== added file 'include/unity/storage/qt/Uploader.h'
955--- include/unity/storage/qt/Uploader.h 1970-01-01 00:00:00 +0000
956+++ include/unity/storage/qt/Uploader.h 2016-09-21 05:03:46 +0000
957@@ -0,0 +1,72 @@
958+/*
959+ * Copyright (C) 2016 Canonical Ltd
960+ *
961+ * This program is free software: you can redistribute it and/or modify
962+ * it under the terms of the GNU Lesser General Public License version 3 as
963+ * published by the Free Software Foundation.
964+ *
965+ * This program is distributed in the hope that it will be useful,
966+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
967+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
968+ * GNU Lesser General Public License for more details.
969+ *
970+ * You should have received a copy of the GNU Lesser General Public License
971+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
972+ *
973+ * Authors: Michi Henning <michi.henning@canonical.com>
974+ */
975+
976+#pragma once
977+
978+#include <unity/storage/common.h>
979+
980+#include <QIODevice>
981+
982+namespace unity
983+{
984+namespace storage
985+{
986+namespace qt
987+{
988+
989+class Item;
990+class StorageError;
991+
992+class Q_DECL_EXPORT Uploader final : public QIODevice
993+{
994+ Q_OBJECT
995+ Q_PROPERTY(bool isValid READ isValid FINAL) // TODO: Need notify
996+ Q_PROPERTY(unity::storage::qt::Uploader::Status status READ status FINAL)
997+ Q_PROPERTY(unity::storage::qt::StorageError READ error FINAL)
998+ Q_PROPERTY(unity::storage::qt::ConflictPolicy policy READ policy FINAL)
999+ Q_PROPERTY(qint64 sizeInBytes READ sizeInBytes FINAL)
1000+ Q_PROPERTY(unity::storage::qt::Item item READ item FINAL)
1001+
1002+public:
1003+ enum Status { Loading, Cancelled, Finished, Error };
1004+ Q_ENUMS(Status)
1005+
1006+ Uploader();
1007+ virtual ~Uploader();
1008+
1009+ bool isValid() const;
1010+ Status status() const;
1011+ StorageError error() const;
1012+ ConflictPolicy policy() const;
1013+ qint64 sizeInBytes() const;
1014+ Item item() const;
1015+
1016+ Q_INVOKABLE void finishUpload();
1017+ Q_INVOKABLE void cancel();
1018+
1019+Q_SIGNALS:
1020+ void statusChanged(unity::storage::qt::Uploader::Status status) const;
1021+
1022+protected:
1023+ virtual qint64 readData(char* data, qint64 maxSize) override;
1024+ virtual qint64 writeData(char const* data, qint64 maxSize) override;
1025+};
1026+
1027+} // namespace qt
1028+} // namespace storage
1029+} // namespace unity
1030
1031=== added file 'include/unity/storage/qt/VoidJob.h'
1032--- include/unity/storage/qt/VoidJob.h 1970-01-01 00:00:00 +0000
1033+++ include/unity/storage/qt/VoidJob.h 2016-09-21 05:03:46 +0000
1034@@ -0,0 +1,56 @@
1035+/*
1036+ * Copyright (C) 2016 Canonical Ltd
1037+ *
1038+ * This program is free software: you can redistribute it and/or modify
1039+ * it under the terms of the GNU Lesser General Public License version 3 as
1040+ * published by the Free Software Foundation.
1041+ *
1042+ * This program is distributed in the hope that it will be useful,
1043+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
1044+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1045+ * GNU Lesser General Public License for more details.
1046+ *
1047+ * You should have received a copy of the GNU Lesser General Public License
1048+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1049+ *
1050+ * Authors: Michi Henning <michi.henning@canonical.com>
1051+ */
1052+
1053+#pragma once
1054+
1055+#include <QObject>
1056+
1057+namespace unity
1058+{
1059+namespace storage
1060+{
1061+namespace qt
1062+{
1063+
1064+class StorageError;
1065+
1066+class Q_DECL_EXPORT VoidJob final : public QObject
1067+{
1068+ // TODO: notify, CONSTANT where needed
1069+ Q_OBJECT
1070+ Q_PROPERTY(bool READ isValid FINAL)
1071+ Q_PROPERTY(unity::storage::qt::VoidJob::Status READ status NOTIFY statusChanged FINAL)
1072+ Q_PROPERTY(unity::storage::qt::StorageError READ error FINAL)
1073+
1074+public:
1075+ virtual ~VoidJob();
1076+
1077+ enum Status { Loading, Finished, Error };
1078+ Q_ENUMS(Status)
1079+
1080+ bool isValid() const;
1081+ Status status() const;
1082+ StorageError error() const;
1083+
1084+Q_SIGNALS:
1085+ void statusChanged(unity::storage::qt::VoidJob::Status status) const;
1086+};
1087+
1088+} // namespace qt
1089+} // namespace storage
1090+} // namespace unity
1091
1092=== modified file 'include/unity/storage/qt/client/CMakeLists.txt'
1093--- include/unity/storage/qt/client/CMakeLists.txt 2016-07-11 03:28:40 +0000
1094+++ include/unity/storage/qt/client/CMakeLists.txt 2016-09-21 05:03:46 +0000
1095@@ -8,8 +8,7 @@
1096 ${convenience_hdr} ${includeprefix} ${CMAKE_CURRENT_SOURCE_DIR}
1097 DEPENDS ${public_hdrs})
1098
1099-add_custom_target(qt-client-all-headers ALL DEPENDS ${convenience_hdr})
1100+add_custom_target(qt-client-all-headers-v1 ALL DEPENDS ${convenience_hdr})
1101
1102-install(
1103- FILES ${public_hdrs} ${convenience_hdr}
1104- DESTINATION ${client_base_includedir}/${includeprefix})
1105+install(FILES ${public_hdrs} ${convenience_hdr}
1106+ DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/storage-framework-client-1/${includeprefix})
1107
1108=== added directory 'include/unity/storage/qt/internal'
1109=== added file 'include/unity/storage/qt/internal/AccountImpl.h'
1110--- include/unity/storage/qt/internal/AccountImpl.h 1970-01-01 00:00:00 +0000
1111+++ include/unity/storage/qt/internal/AccountImpl.h 2016-09-21 05:03:46 +0000
1112@@ -0,0 +1,99 @@
1113+/*
1114+ * Copyright (C) 2016 Canonical Ltd
1115+ *
1116+ * This program is free software: you can redistribute it and/or modify
1117+ * it under the terms of the GNU Lesser General Public License version 3 as
1118+ * published by the Free Software Foundation.
1119+ *
1120+ * This program is distributed in the hope that it will be useful,
1121+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
1122+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1123+ * GNU Lesser General Public License for more details.
1124+ *
1125+ * You should have received a copy of the GNU Lesser General Public License
1126+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1127+ *
1128+ * Authors: Michi Henning <michi.henning@canonical.com>
1129+ */
1130+
1131+#pragma once
1132+
1133+#include <unity/storage/qt/Item.h>
1134+
1135+#include <QString>
1136+
1137+#include <memory>
1138+
1139+class ProviderInterface;
1140+
1141+namespace unity
1142+{
1143+namespace storage
1144+{
1145+namespace qt
1146+{
1147+namespace internal
1148+{
1149+
1150+class RuntimeImpl;
1151+
1152+class AccountImpl : public std::enable_shared_from_this<AccountImpl>
1153+{
1154+public:
1155+ AccountImpl();
1156+ AccountImpl(AccountImpl const&) = default;
1157+ AccountImpl(AccountImpl&&) = default;
1158+ ~AccountImpl() = default;
1159+ AccountImpl& operator=(AccountImpl const&) = default;
1160+ AccountImpl& operator=(AccountImpl&&) = default;
1161+
1162+ QString ownerId() const;
1163+ QString owner() const;
1164+ QString description() const;
1165+
1166+ ItemListJob* roots() const;
1167+ ItemJob* get(QString const& itemId) const;
1168+
1169+ bool operator==(AccountImpl const&) const;
1170+ bool operator!=(AccountImpl const&) const;
1171+ bool operator<(AccountImpl const&) const;
1172+ bool operator<=(AccountImpl const&) const;
1173+ bool operator>(AccountImpl const&) const;
1174+ bool operator>=(AccountImpl const&) const;
1175+
1176+ size_t hash() const;
1177+
1178+ //std::shared_ptr<RuntimeImpl> runtime() const;
1179+ std::shared_ptr<ProviderInterface> provider() const;
1180+
1181+ static Account make_account(std::shared_ptr<RuntimeImpl> const& runtime,
1182+ QString const& bus_name,
1183+ QString const& object_path,
1184+ QString const& owner_id,
1185+ QString const& owner,
1186+ QString const& description);
1187+
1188+private:
1189+ AccountImpl(std::shared_ptr<RuntimeImpl> const& runtime,
1190+ QString const& bus_name,
1191+ QString const& object_path,
1192+ QString const& owner_id,
1193+ QString const& owner,
1194+ QString const& description);
1195+
1196+ bool is_valid_;
1197+ QString bus_name_;
1198+ QString object_path_;
1199+ QString owner_id_;
1200+ QString owner_;
1201+ QString description_;
1202+ std::weak_ptr<RuntimeImpl> runtime_;
1203+ std::shared_ptr<ProviderInterface> provider_;
1204+
1205+ friend class unity::storage::qt::Account;
1206+};
1207+
1208+} // namespace internal
1209+} // namespace qt
1210+} // namespace storage
1211+} // namespace unity
1212
1213=== added file 'include/unity/storage/qt/internal/AccountsJobImpl.h'
1214--- include/unity/storage/qt/internal/AccountsJobImpl.h 1970-01-01 00:00:00 +0000
1215+++ include/unity/storage/qt/internal/AccountsJobImpl.h 2016-09-21 05:03:46 +0000
1216@@ -0,0 +1,70 @@
1217+/*
1218+ * Copyright (C) 2016 Canonical Ltd
1219+ *
1220+ * This program is free software: you can redistribute it and/or modify
1221+ * it under the terms of the GNU Lesser General Public License version 3 as
1222+ * published by the Free Software Foundation.
1223+ *
1224+ * This program is distributed in the hope that it will be useful,
1225+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
1226+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1227+ * GNU Lesser General Public License for more details.
1228+ *
1229+ * You should have received a copy of the GNU Lesser General Public License
1230+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1231+ *
1232+ * Authors: Michi Henning <michi.henning@canonical.com>
1233+ */
1234+
1235+#pragma once
1236+
1237+#include <unity/storage/qt/AccountsJob.h>
1238+
1239+#include <QTimer>
1240+
1241+namespace unity
1242+{
1243+namespace storage
1244+{
1245+namespace qt
1246+{
1247+namespace internal
1248+{
1249+
1250+class AccountsJobImpl : public QObject
1251+{
1252+ Q_OBJECT
1253+public:
1254+ AccountsJobImpl(AccountsJob* public_instance, std::shared_ptr<RuntimeImpl> const& runtime);
1255+ AccountsJobImpl(AccountsJob* public_instance, StorageError const& error);
1256+ virtual ~AccountsJobImpl() = default;
1257+
1258+ bool isValid() const;
1259+ AccountsJob::Status status() const;
1260+ StorageError error() const;
1261+ QList<Account> accounts() const;
1262+
1263+private Q_SLOTS:
1264+ void manager_ready();
1265+ void timeout();
1266+
1267+private:
1268+ std::shared_ptr<RuntimeImpl> get_runtime(QString const& method) const;
1269+ void initialize_accounts();
1270+ AccountsJob::Status emit_status_changed(AccountsJob::Status new_status) const;
1271+
1272+ AccountsJob* const public_instance_;
1273+
1274+ AccountsJob::Status status_;
1275+ StorageError error_;
1276+ QList<unity::storage::qt::Account> accounts_;
1277+ std::weak_ptr<RuntimeImpl> const runtime_;
1278+ QTimer timer_;
1279+
1280+ friend class unity::storage::qt::AccountsJob;
1281+};
1282+
1283+} // namespace internal
1284+} // namespace qt
1285+} // namespace storage
1286+} // namespace unity
1287
1288=== added file 'include/unity/storage/qt/internal/Handler.h'
1289--- include/unity/storage/qt/internal/Handler.h 1970-01-01 00:00:00 +0000
1290+++ include/unity/storage/qt/internal/Handler.h 2016-09-21 05:03:46 +0000
1291@@ -0,0 +1,93 @@
1292+/*
1293+ * Copyright (C) 2016 Canonical Ltd
1294+ *
1295+ * This program is free software: you can redistribute it and/or modify
1296+ * it under the terms of the GNU Lesser General Public License version 3 as
1297+ * published by the Free Software Foundation.
1298+ *
1299+ * This program is distributed in the hope that it will be useful,
1300+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
1301+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1302+ * GNU Lesser General Public License for more details.
1303+ *
1304+ * You should have received a copy of the GNU Lesser General Public License
1305+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1306+ *
1307+ * Authors: Michi Henning <michi.henning@canonical.com>
1308+ */
1309+
1310+#pragma once
1311+
1312+#include <unity/storage/qt/internal/HandlerBase.h>
1313+#include <unity/storage/qt/internal/StorageErrorImpl.h>
1314+#include <unity/storage/qt/internal/unmarshal_error.h>
1315+
1316+#include <QDBusPendingReply>
1317+#include <QDebug>
1318+
1319+#include <cassert>
1320+
1321+namespace unity
1322+{
1323+namespace storage
1324+{
1325+namespace qt
1326+{
1327+namespace internal
1328+{
1329+
1330+template<typename T>
1331+class Handler : public HandlerBase
1332+{
1333+public:
1334+ template<typename ... DBusArgs>
1335+ Handler(QObject* parent,
1336+ QDBusPendingReply<DBusArgs...> const& reply,
1337+ std::function<void(decltype(reply)&)> const& success_closure,
1338+ std::function<void(StorageError const&)> const& error_closure)
1339+ : HandlerBase(parent,
1340+ reply,
1341+ [this, success_closure, error_closure](QDBusPendingCallWatcher& call)
1342+ {
1343+ if (call.isError())
1344+ {
1345+ auto e = unmarshal_error(call);
1346+ switch (e.type())
1347+ {
1348+ case StorageError::NoError:
1349+ {
1350+ // LCOV_EXCL_START
1351+ QString msg = "impossible provider exception: " + e.errorString();
1352+ qCritical() << msg;
1353+ e = StorageErrorImpl::local_comms_error(msg);
1354+ break;
1355+ // LCOV_EXCL_STOP
1356+ }
1357+ case StorageError::LocalCommsError:
1358+ case StorageError::RemoteCommsError:
1359+ case StorageError::ResourceError:
1360+ {
1361+ // Log these errors because they are unexpected.
1362+ qCritical() << "provider exception:" << e.errorString();
1363+ break;
1364+ }
1365+ default:
1366+ {
1367+ // All other errors are not logged.
1368+ break;
1369+ }
1370+ }
1371+ error_closure(e);
1372+ return;
1373+ }
1374+ QDBusPendingReply<DBusArgs...> r = call;
1375+ success_closure(call);
1376+ })
1377+ {
1378+ }
1379+};
1380+
1381+} // namespace internal
1382+} // namespace qt
1383+} // namespace storage
1384+} // namespace unity
1385
1386=== added file 'include/unity/storage/qt/internal/HandlerBase.h'
1387--- include/unity/storage/qt/internal/HandlerBase.h 1970-01-01 00:00:00 +0000
1388+++ include/unity/storage/qt/internal/HandlerBase.h 2016-09-21 05:03:46 +0000
1389@@ -0,0 +1,64 @@
1390+/*
1391+ * Copyright (C) 2016 Canonical Ltd
1392+ *
1393+ * This program is free software: you can redistribute it and/or modify
1394+ * it under the terms of the GNU Lesser General Public License version 3 as
1395+ * published by the Free Software Foundation.
1396+ *
1397+ * This program is distributed in the hope that it will be useful,
1398+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
1399+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1400+ * GNU Lesser General Public License for more details.
1401+ *
1402+ * You should have received a copy of the GNU Lesser General Public License
1403+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1404+ *
1405+ * Authors: Michi Henning <michi.henning@canonical.com>
1406+ */
1407+
1408+#pragma once
1409+
1410+#pragma GCC diagnostic push
1411+#pragma GCC diagnostic ignored "-Wcast-align"
1412+#pragma GCC diagnostic ignored "-Wctor-dtor-privacy"
1413+#pragma GCC diagnostic ignored "-Wswitch-default"
1414+#include <QDBusPendingCallWatcher>
1415+#include <QObject>
1416+#pragma GCC diagnostic pop
1417+
1418+#include <functional>
1419+
1420+class QDBusPendingCall;
1421+
1422+namespace unity
1423+{
1424+namespace storage
1425+{
1426+namespace qt
1427+{
1428+namespace internal
1429+{
1430+
1431+class HandlerBase : public QObject
1432+{
1433+ Q_OBJECT
1434+
1435+public:
1436+ HandlerBase(QObject* parent,
1437+ QDBusPendingCall const& call,
1438+ std::function<void(QDBusPendingCallWatcher&)> const& closure);
1439+
1440+public Q_SLOTS:
1441+ void finished(QDBusPendingCallWatcher* call);
1442+
1443+protected:
1444+ QDBusPendingCallWatcher watcher_;
1445+
1446+private:
1447+ std::function<void(QDBusPendingCallWatcher&)> closure_;
1448+};
1449+
1450+} // namespace internal
1451+} // namespace qt
1452+} // namespace storage
1453+} // namespace unity
1454
1455=== added file 'include/unity/storage/qt/internal/ItemImpl.h'
1456--- include/unity/storage/qt/internal/ItemImpl.h 1970-01-01 00:00:00 +0000
1457+++ include/unity/storage/qt/internal/ItemImpl.h 2016-09-21 05:03:46 +0000
1458@@ -0,0 +1,99 @@
1459+/*
1460+ * Copyright (C) 2016 Canonical Ltd
1461+ *
1462+ * This program is free software: you can redistribute it and/or modify
1463+ * it under the terms of the GNU Lesser General Public License version 3 as
1464+ * published by the Free Software Foundation.
1465+ *
1466+ * This program is distributed in the hope that it will be useful,
1467+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
1468+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1469+ * GNU Lesser General Public License for more details.
1470+ *
1471+ * You should have received a copy of the GNU Lesser General Public License
1472+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1473+ *
1474+ * Authors: Michi Henning <michi.henning@canonical.com>
1475+ */
1476+
1477+#pragma once
1478+
1479+#include <unity/storage/internal/ItemMetadata.h>
1480+#include <unity/storage/qt/Account.h>
1481+#include <unity/storage/qt/Item.h>
1482+
1483+namespace unity
1484+{
1485+namespace storage
1486+{
1487+namespace qt
1488+{
1489+namespace internal
1490+{
1491+
1492+class AccountImpl;
1493+class RuntimeImpl;
1494+
1495+class ItemImpl : public std::enable_shared_from_this<ItemImpl>
1496+{
1497+public:
1498+ ItemImpl();
1499+ ItemImpl(storage::internal::ItemMetadata const& md,
1500+ std::shared_ptr<AccountImpl> const& account);
1501+ ItemImpl(ItemImpl const&) = default;
1502+ ItemImpl(ItemImpl&&) = delete;
1503+ ~ItemImpl() = default;
1504+ ItemImpl& operator=(ItemImpl const&) = default;
1505+ ItemImpl& operator=(ItemImpl&&) = delete;
1506+
1507+ QString itemId() const;
1508+ QString name() const;
1509+ Account account() const;
1510+ //Item root() const;
1511+ QString etag() const;
1512+ Item::Type type() const;
1513+ QVariantMap metadata() const;
1514+ QDateTime lastModifiedTime() const;
1515+ QVector<QString> parentIds() const;
1516+
1517+ ItemListJob* parents() const;
1518+ ItemJob* copy(Item const& newParent, QString const& newName) const;
1519+ ItemJob* move(Item const& newParent, QString const& newName) const;
1520+ VoidJob* deleteItem() const;
1521+ Uploader* createUploader(ConflictPolicy policy, qint64 sizeInBytes) const;
1522+ Downloader* createDownloader() const;
1523+ ItemListJob* list() const;
1524+ ItemListJob* lookup(QString const& name) const;
1525+ ItemJob* createFolder(QString const& name) const;
1526+ Uploader* createFile(QString const& name) const;
1527+ IntJob* freeSpaceBytes() const;
1528+ IntJob* usedSpaceBytes() const;
1529+
1530+ bool operator==(ItemImpl const&) const;
1531+ bool operator!=(ItemImpl const&) const;
1532+ bool operator<(ItemImpl const&) const;
1533+ bool operator<=(ItemImpl const&) const;
1534+ bool operator>(ItemImpl const&) const;
1535+ bool operator>=(ItemImpl const&) const;
1536+
1537+ size_t hash() const;
1538+
1539+ static Item make_item(QString const& method,
1540+ storage::internal::ItemMetadata const& md,
1541+ std::shared_ptr<AccountImpl> const& account);
1542+
1543+private:
1544+ //std::shared_ptr<RuntimeImpl> get_runtime(QString const& method) const;
1545+
1546+ bool is_valid_;
1547+ storage::internal::ItemMetadata md_;
1548+ std::shared_ptr<AccountImpl> account_;
1549+ //std::shared_ptr<RootImpl> root_;
1550+
1551+ friend class unity::storage::qt::Item;
1552+};
1553+
1554+} // namespace internal
1555+} // namespace qt
1556+} // namespace storage
1557+} // namespace unity
1558
1559=== added file 'include/unity/storage/qt/internal/ItemJobImpl.h'
1560--- include/unity/storage/qt/internal/ItemJobImpl.h 1970-01-01 00:00:00 +0000
1561+++ include/unity/storage/qt/internal/ItemJobImpl.h 2016-09-21 05:03:46 +0000
1562@@ -0,0 +1,84 @@
1563+/*
1564+ * Copyright (C) 2016 Canonical Ltd
1565+ *
1566+ * This program is free software: you can redistribute it and/or modify
1567+ * it under the terms of the GNU Lesser General Public License version 3 as
1568+ * published by the Free Software Foundation.
1569+ *
1570+ * This program is distributed in the hope that it will be useful,
1571+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
1572+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1573+ * GNU Lesser General Public License for more details.
1574+ *
1575+ * You should have received a copy of the GNU Lesser General Public License
1576+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1577+ *
1578+ * Authors: Michi Henning <michi.henning@canonical.com>
1579+ */
1580+
1581+#pragma once
1582+
1583+#include <unity/storage/qt/ItemJob.h>
1584+
1585+#include <unity/storage/qt/Account.h>
1586+#include <unity/storage/qt/internal/Handler.h>
1587+#include <unity/storage/qt/StorageError.h>
1588+
1589+namespace unity
1590+{
1591+namespace storage
1592+{
1593+namespace internal
1594+{
1595+
1596+class ItemMetadata;
1597+
1598+}
1599+
1600+namespace qt
1601+{
1602+namespace internal
1603+{
1604+
1605+class RuntimeImpl;
1606+
1607+class ItemJobImpl : public QObject
1608+{
1609+ Q_OBJECT
1610+public:
1611+ virtual ~ItemJobImpl() = default;
1612+
1613+ bool isValid() const;
1614+ ItemJob::Status status() const;
1615+ StorageError error() const;
1616+ Item item() const;
1617+
1618+ static ItemJob* make_item_job(std::shared_ptr<AccountImpl> const& account,
1619+ QString const& method,
1620+ QDBusPendingReply<storage::internal::ItemMetadata> const& reply,
1621+ std::function<void(storage::internal::ItemMetadata const&)> const& validate);
1622+ static ItemJob* make_item_job(StorageError const& e);
1623+
1624+private:
1625+ ItemJobImpl(std::shared_ptr<AccountImpl> const& account,
1626+ QString const& method,
1627+ QDBusPendingReply<storage::internal::ItemMetadata> const& reply,
1628+ std::function<void(storage::internal::ItemMetadata const&)> const& validate);
1629+ ItemJobImpl(StorageError const& e);
1630+
1631+ ItemJob::Status emit_status_changed(ItemJob::Status new_status) const;
1632+
1633+ ItemJob* public_instance_;
1634+
1635+ ItemJob::Status status_;
1636+ StorageError error_;
1637+ QString method_;
1638+ std::shared_ptr<AccountImpl> account_;
1639+ std::function<void(storage::internal::ItemMetadata const&)> validate_;
1640+ Item item_;
1641+};
1642+
1643+} // namespace internal
1644+} // namespace qt
1645+} // namespace storage
1646+} // namespace unity
1647
1648=== added file 'include/unity/storage/qt/internal/ItemListJobImpl.h'
1649--- include/unity/storage/qt/internal/ItemListJobImpl.h 1970-01-01 00:00:00 +0000
1650+++ include/unity/storage/qt/internal/ItemListJobImpl.h 2016-09-21 05:03:46 +0000
1651@@ -0,0 +1,83 @@
1652+/*
1653+ * Copyright (C) 2016 Canonical Ltd
1654+ *
1655+ * This program is free software: you can redistribute it and/or modify
1656+ * it under the terms of the GNU Lesser General Public License version 3 as
1657+ * published by the Free Software Foundation.
1658+ *
1659+ * This program is distributed in the hope that it will be useful,
1660+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
1661+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1662+ * GNU Lesser General Public License for more details.
1663+ *
1664+ * You should have received a copy of the GNU Lesser General Public License
1665+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1666+ *
1667+ * Authors: Michi Henning <michi.henning@canonical.com>
1668+ */
1669+
1670+#pragma once
1671+
1672+#include <unity/storage/qt/ItemListJob.h>
1673+
1674+#include <unity/storage/qt/Account.h>
1675+#include <unity/storage/qt/internal/Handler.h>
1676+#include <unity/storage/qt/StorageError.h>
1677+
1678+namespace unity
1679+{
1680+namespace storage
1681+{
1682+namespace internal
1683+{
1684+
1685+class ItemMetadata;
1686+
1687+}
1688+
1689+namespace qt
1690+{
1691+namespace internal
1692+{
1693+
1694+class RuntimeImpl;
1695+
1696+class ItemListJobImpl : public QObject
1697+{
1698+ Q_OBJECT
1699+public:
1700+ virtual ~ItemListJobImpl() = default;
1701+
1702+ bool isValid() const;
1703+ ItemListJob::Status status() const;
1704+ StorageError error() const;
1705+
1706+ static ItemListJob* make_item_list_job(std::shared_ptr<AccountImpl> const& account,
1707+ QString const& method,
1708+ QDBusPendingReply<QList<storage::internal::ItemMetadata>> const& reply,
1709+ std::function<void(storage::internal::ItemMetadata const&)> const& validate);
1710+ static ItemListJob* make_item_list_job(StorageError const& error);
1711+
1712+private:
1713+ ItemListJobImpl(std::shared_ptr<AccountImpl> const& account,
1714+ QString const& method,
1715+ QDBusPendingReply<QList<storage::internal::ItemMetadata>> const& reply,
1716+ std::function<void(storage::internal::ItemMetadata const&)> const& validate);
1717+ ItemListJobImpl(StorageError const& error);
1718+
1719+ ItemListJob::Status emit_status_changed(ItemListJob::Status new_status) const;
1720+ void emit_items_ready(QList<unity::storage::qt::Item> const& items) const;
1721+
1722+ ItemListJob* public_instance_;
1723+
1724+ ItemListJob::Status status_;
1725+ StorageError error_;
1726+ QString method_;
1727+ std::shared_ptr<AccountImpl> account_;
1728+ std::function<void(storage::internal::ItemMetadata const&)> validate_;
1729+};
1730+
1731+} // namespace internal
1732+} // namespace qt
1733+} // namespace storage
1734+} // namespace unity
1735
1736=== added file 'include/unity/storage/qt/internal/RuntimeImpl.h'
1737--- include/unity/storage/qt/internal/RuntimeImpl.h 1970-01-01 00:00:00 +0000
1738+++ include/unity/storage/qt/internal/RuntimeImpl.h 2016-09-21 05:03:46 +0000
1739@@ -0,0 +1,85 @@
1740+/*
1741+ * Copyright (C) 2016 Canonical Ltd
1742+ *
1743+ * This program is free software: you can redistribute it and/or modify
1744+ * it under the terms of the GNU Lesser General Public License version 3 as
1745+ * published by the Free Software Foundation.
1746+ *
1747+ * This program is distributed in the hope that it will be useful,
1748+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
1749+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1750+ * GNU Lesser General Public License for more details.
1751+ *
1752+ * You should have received a copy of the GNU Lesser General Public License
1753+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1754+ *
1755+ * Authors: Michi Henning <michi.henning@canonical.com>
1756+ */
1757+
1758+#pragma once
1759+
1760+#include <unity/storage/qt/Account.h>
1761+#include <unity/storage/qt/StorageError.h>
1762+
1763+#include <OnlineAccounts/Manager>
1764+
1765+#pragma GCC diagnostic push
1766+#pragma GCC diagnostic ignored "-Wcast-align"
1767+#pragma GCC diagnostic ignored "-Wctor-dtor-privacy"
1768+#include <QDBusConnection>
1769+#pragma GCC diagnostic pop
1770+
1771+namespace unity
1772+{
1773+namespace storage
1774+{
1775+namespace qt
1776+{
1777+
1778+class AccountsJob;
1779+class Runtime;
1780+
1781+namespace internal
1782+{
1783+
1784+class RuntimeImpl : public std::enable_shared_from_this<RuntimeImpl>
1785+{
1786+public:
1787+ RuntimeImpl();
1788+ RuntimeImpl(QDBusConnection const& bus);
1789+ RuntimeImpl(RuntimeImpl const&) = delete;
1790+ RuntimeImpl(RuntimeImpl&&) = delete;
1791+ ~RuntimeImpl();
1792+ RuntimeImpl& operator=(RuntimeImpl const&) = delete;
1793+ RuntimeImpl& operator=(RuntimeImpl&&) = delete;
1794+
1795+ bool isValid() const;
1796+ StorageError error() const;
1797+ QDBusConnection connection() const;
1798+ AccountsJob* accounts() const;
1799+ StorageError shutdown();
1800+
1801+ std::shared_ptr<OnlineAccounts::Manager> accounts_manager() const;
1802+
1803+ Account make_test_account(QString const& bus_name,
1804+ QString const& object_path);
1805+
1806+ Account make_test_account(QString const& bus_name,
1807+ QString const& object_path,
1808+ QString const& owner_id,
1809+ QString const& owner,
1810+ QString const& description);
1811+
1812+private:
1813+ bool is_valid_;
1814+ StorageError error_;
1815+ QDBusConnection conn_;
1816+ std::shared_ptr<OnlineAccounts::Manager> accounts_manager_;
1817+
1818+ friend class unity::storage::qt::Runtime;
1819+};
1820+
1821+} // namespace internal
1822+} // namespace qt
1823+} // namespace storage
1824+} // namespace unity
1825
1826=== added file 'include/unity/storage/qt/internal/StorageErrorImpl.h'
1827--- include/unity/storage/qt/internal/StorageErrorImpl.h 1970-01-01 00:00:00 +0000
1828+++ include/unity/storage/qt/internal/StorageErrorImpl.h 2016-09-21 05:03:46 +0000
1829@@ -0,0 +1,85 @@
1830+/*
1831+ * Copyright (C) 2016 Canonical Ltd
1832+ *
1833+ * This program is free software: you can redistribute it and/or modify
1834+ * it under the terms of the GNU Lesser General Public License version 3 as
1835+ * published by the Free Software Foundation.
1836+ *
1837+ * This program is distributed in the hope that it will be useful,
1838+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
1839+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1840+ * GNU Lesser General Public License for more details.
1841+ *
1842+ * You should have received a copy of the GNU Lesser General Public License
1843+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1844+ *
1845+ * Authors: Michi Henning <michi.henning@canonical.com>
1846+ */
1847+
1848+#pragma once
1849+
1850+#include <unity/storage/qt/StorageError.h>
1851+
1852+namespace unity
1853+{
1854+namespace storage
1855+{
1856+namespace qt
1857+{
1858+namespace internal
1859+{
1860+
1861+class StorageErrorImpl
1862+{
1863+public:
1864+ StorageErrorImpl();
1865+ StorageErrorImpl(StorageError::Type type, QString const& msg);
1866+ StorageErrorImpl(StorageError::Type type, QString const& msg, QString const& item_id);
1867+ StorageErrorImpl(StorageError::Type type, QString const& msg, QString const& item_id, QString const& item_name);
1868+ StorageErrorImpl(StorageError::Type type, QString const& msg, int error_code);
1869+ StorageErrorImpl(StorageErrorImpl const&) = default;
1870+ StorageErrorImpl(StorageErrorImpl&&) = default;
1871+ ~StorageErrorImpl() = default;
1872+ StorageErrorImpl& operator=(StorageErrorImpl const&) = default;
1873+ StorageErrorImpl& operator=(StorageErrorImpl&&) = default;
1874+
1875+ StorageError::Type type() const;
1876+ QString name() const;
1877+ QString message() const;
1878+ QString errorString() const;
1879+
1880+ QString itemId() const;
1881+ QString itemName() const;
1882+ int errorCode() const;
1883+
1884+ // Generic factory for errors that don't require extra arguments.
1885+ static StorageError make_error(StorageError::Type, QString const& msg);
1886+
1887+ // Factories to make things more convenient and ensure consistency.
1888+ static StorageError local_comms_error(QString const& msg);
1889+ static StorageError remote_comms_error(QString const& msg);
1890+ static StorageError deleted_error(QString const& msg, QString const& item_id);
1891+ static StorageError runtime_destroyed_error(QString const& msg);
1892+ static StorageError not_exists_error(QString const& msg, QString const& key);
1893+ static StorageError exists_error(QString const& msg, QString const& item_id, QString const& item_name);
1894+ static StorageError conflict_error(QString const& msg);
1895+ static StorageError permission_error(QString const& msg);
1896+ static StorageError cancelled_error(QString const& msg);
1897+ static StorageError logic_error(QString const& msg);
1898+ static StorageError invalid_argument_error(QString const& msg);
1899+ static StorageError resource_error(QString const& msg, int error_code);
1900+
1901+private:
1902+ StorageError::Type type_;
1903+ QString name_;
1904+ QString message_;
1905+ QString item_id_;
1906+ QString item_name_;
1907+ int error_code_;
1908+};
1909+
1910+
1911+} // namespace internal
1912+} // namespace qt
1913+} // namespace storage
1914+} // namespace unity
1915
1916=== added file 'include/unity/storage/qt/internal/unmarshal_error.h'
1917--- include/unity/storage/qt/internal/unmarshal_error.h 1970-01-01 00:00:00 +0000
1918+++ include/unity/storage/qt/internal/unmarshal_error.h 2016-09-21 05:03:46 +0000
1919@@ -0,0 +1,39 @@
1920+/*
1921+ * Copyright (C) 2016 Canonical Ltd
1922+ *
1923+ * This program is free software: you can redistribute it and/or modify
1924+ * it under the terms of the GNU Lesser General Public License version 3 as
1925+ * published by the Free Software Foundation.
1926+ *
1927+ * This program is distributed in the hope that it will be useful,
1928+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
1929+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1930+ * GNU Lesser General Public License for more details.
1931+ *
1932+ * You should have received a copy of the GNU Lesser General Public License
1933+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1934+ *
1935+ * Authors: Michi Henning <michi.henning@canonical.com>
1936+ */
1937+
1938+#pragma once
1939+
1940+#include <unity/storage/qt/StorageError.h>
1941+
1942+class QDBusPendingCallWatcher;
1943+
1944+namespace unity
1945+{
1946+namespace storage
1947+{
1948+namespace qt
1949+{
1950+namespace internal
1951+{
1952+
1953+StorageError unmarshal_error(QDBusPendingCallWatcher const& call);
1954+
1955+} // namespace internal
1956+} // namespace qt
1957+} // storage
1958+} // unity
1959
1960=== added file 'include/unity/storage/qt/internal/validate.h'
1961--- include/unity/storage/qt/internal/validate.h 1970-01-01 00:00:00 +0000
1962+++ include/unity/storage/qt/internal/validate.h 2016-09-21 05:03:46 +0000
1963@@ -0,0 +1,44 @@
1964+/*
1965+ * Copyright (C) 2016 Canonical Ltd
1966+ *
1967+ * This program is free software: you can redistribute it and/or modify
1968+ * it under the terms of the GNU Lesser General Public License version 3 as
1969+ * published by the Free Software Foundation.
1970+ *
1971+ * This program is distributed in the hope that it will be useful,
1972+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
1973+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1974+ * GNU Lesser General Public License for more details.
1975+ *
1976+ * You should have received a copy of the GNU Lesser General Public License
1977+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1978+ *
1979+ * Authors: Michi Henning <michi.henning@canonical.com>
1980+ */
1981+
1982+#pragma once
1983+
1984+#include <QString>
1985+
1986+namespace unity
1987+{
1988+namespace storage
1989+{
1990+namespace internal
1991+{
1992+
1993+class ItemMetadata;
1994+
1995+} // namespace internal
1996+
1997+namespace qt
1998+{
1999+namespace internal
2000+{
2001+
2002+void validate(QString const& method, unity::storage::internal::ItemMetadata const& md);
2003+
2004+} // namespace internal
2005+} // namespace qt
2006+} // namespace storage
2007+} // namespace unity
2008
2009=== added file 'src/qt/Account.cpp'
2010--- src/qt/Account.cpp 1970-01-01 00:00:00 +0000
2011+++ src/qt/Account.cpp 2016-09-21 05:03:46 +0000
2012@@ -0,0 +1,148 @@
2013+/*
2014+ * Copyright (C) 2016 Canonical Ltd
2015+ *
2016+ * This program is free software: you can redistribute it and/or modify
2017+ * it under the terms of the GNU Lesser General Public License version 3 as
2018+ * published by the Free Software Foundation.
2019+ *
2020+ * This program is distributed in the hope that it will be useful,
2021+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
2022+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2023+ * GNU Lesser General Public License for more details.
2024+ *
2025+ * You should have received a copy of the GNU Lesser General Public License
2026+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
2027+ *
2028+ * Authors: Michi Henning <michi.henning@canonical.com>
2029+ */
2030+
2031+#include <unity/storage/qt/Account.h>
2032+
2033+#include <unity/storage/qt/internal/AccountImpl.h>
2034+
2035+#include <cassert>
2036+
2037+using namespace std;
2038+
2039+namespace unity
2040+{
2041+namespace storage
2042+{
2043+namespace qt
2044+{
2045+
2046+Account::Account()
2047+ : p_(make_shared<internal::AccountImpl>())
2048+{
2049+}
2050+
2051+Account::Account(shared_ptr<internal::AccountImpl> const& p)
2052+ : p_(p)
2053+{
2054+ assert(p);
2055+}
2056+
2057+Account::Account(Account const& other)
2058+ : p_(other.p_)
2059+{
2060+}
2061+
2062+Account::Account(Account&& other)
2063+ : p_(make_shared<internal::AccountImpl>())
2064+{
2065+ p_->is_valid_ = false;
2066+ swap(p_, other.p_);
2067+}
2068+
2069+Account::~Account() = default;
2070+
2071+Account& Account::operator=(Account const& other)
2072+{
2073+ if (this == &other)
2074+ {
2075+ return *this;
2076+ }
2077+ p_ = other.p_;
2078+ return *this;
2079+}
2080+
2081+Account& Account::operator=(Account&& other)
2082+{
2083+ p_->is_valid_ = false;
2084+ swap(p_, other.p_);
2085+ return *this;
2086+}
2087+
2088+bool Account::isValid() const
2089+{
2090+ return p_->is_valid_;
2091+}
2092+
2093+QString Account::owner() const
2094+{
2095+ return p_->owner();
2096+}
2097+
2098+QString Account::ownerId() const
2099+{
2100+ return p_->ownerId();
2101+}
2102+
2103+QString Account::description() const
2104+{
2105+ return p_->description();
2106+}
2107+
2108+ItemListJob* Account::roots() const
2109+{
2110+ return p_->roots();
2111+}
2112+
2113+ItemJob* Account::get(QString const& itemId) const
2114+{
2115+ return p_->get(itemId);
2116+}
2117+
2118+bool Account::operator==(Account const& other) const
2119+{
2120+ return p_->operator==(*other.p_);
2121+}
2122+
2123+bool Account::operator!=(Account const& other) const
2124+{
2125+ return p_->operator!=(*other.p_);
2126+}
2127+
2128+bool Account::operator<(Account const& other) const
2129+{
2130+ return p_->operator<(*other.p_);
2131+}
2132+
2133+bool Account::operator<=(Account const& other) const
2134+{
2135+ return p_->operator<=(*other.p_);
2136+}
2137+
2138+bool Account::operator>(Account const& other) const
2139+{
2140+ return p_->operator>(*other.p_);
2141+}
2142+
2143+bool Account::operator>=(Account const& other) const
2144+{
2145+ return p_->operator>=(*other.p_);
2146+}
2147+
2148+size_t Account::hash() const
2149+{
2150+ return p_->hash();
2151+}
2152+
2153+} // namespace qt
2154+} // namespace storage
2155+} // namespace unity
2156+
2157+uint qHash(unity::storage::qt::Account const& acc)
2158+{
2159+ return acc.hash();
2160+}
2161
2162=== added file 'src/qt/AccountsJob.cpp'
2163--- src/qt/AccountsJob.cpp 1970-01-01 00:00:00 +0000
2164+++ src/qt/AccountsJob.cpp 2016-09-21 05:03:46 +0000
2165@@ -0,0 +1,68 @@
2166+/*
2167+ * Copyright (C) 2016 Canonical Ltd
2168+ *
2169+ * This program is free software: you can redistribute it and/or modify
2170+ * it under the terms of the GNU Lesser General Public License version 3 as
2171+ * published by the Free Software Foundation.
2172+ *
2173+ * This program is distributed in the hope that it will be useful,
2174+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
2175+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2176+ * GNU Lesser General Public License for more details.
2177+ *
2178+ * You should have received a copy of the GNU Lesser General Public License
2179+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
2180+ *
2181+ * Authors: Michi Henning <michi.henning@canonical.com>
2182+ */
2183+
2184+#include <unity/storage/qt/AccountsJob.h>
2185+
2186+#include <unity/storage/qt/Account.h>
2187+#include <unity/storage/qt/internal/AccountsJobImpl.h>
2188+
2189+using namespace unity::storage::qt;
2190+using namespace std;
2191+
2192+namespace unity
2193+{
2194+namespace storage
2195+{
2196+namespace qt
2197+{
2198+
2199+AccountsJob::AccountsJob(shared_ptr<internal::RuntimeImpl> const& runtime)
2200+ : p_(new internal::AccountsJobImpl(this, runtime))
2201+{
2202+}
2203+
2204+AccountsJob::AccountsJob(StorageError const& error)
2205+ : p_(new internal::AccountsJobImpl(this, error))
2206+{
2207+}
2208+
2209+AccountsJob::~AccountsJob() = default;
2210+
2211+bool AccountsJob::isValid() const
2212+{
2213+ return p_->isValid();
2214+}
2215+
2216+AccountsJob::Status AccountsJob::status() const
2217+{
2218+ return p_->status();
2219+}
2220+
2221+StorageError AccountsJob::error() const
2222+{
2223+ return p_->error();
2224+}
2225+
2226+QList<Account> AccountsJob::accounts() const
2227+{
2228+ return p_->accounts();
2229+}
2230+
2231+} // namespace qt
2232+} // namespace storage
2233+} // namespace unity
2234
2235=== modified file 'src/qt/CMakeLists.txt'
2236--- src/qt/CMakeLists.txt 2016-06-08 03:57:50 +0000
2237+++ src/qt/CMakeLists.txt 2016-09-21 05:03:46 +0000
2238@@ -1,1 +1,83 @@
2239 add_subdirectory(client)
2240+
2241+set_source_files_properties(${CMAKE_SOURCE_DIR}/data/provider.xml PROPERTIES
2242+ CLASSNAME ProviderInterface
2243+ INCLUDE unity/storage/internal/dbusmarshal.h
2244+)
2245+
2246+qt5_add_dbus_interface(generated_files
2247+ ${CMAKE_SOURCE_DIR}/data/provider.xml
2248+ ProviderInterface
2249+)
2250+set_source_files_properties(${generated_files} PROPERTIES
2251+ COMPILE_FLAGS "-Wno-ctor-dtor-privacy -Wmissing-field-initializers"
2252+ GENERATED TRUE
2253+)
2254+
2255+# Sources for remote client V2 library.
2256+set(QT_CLIENT_LIB_V2_SRC
2257+ Account.cpp
2258+ AccountsJob.cpp
2259+ Item.cpp
2260+ ItemJob.cpp
2261+ ItemListJob.cpp
2262+ Runtime.cpp
2263+ StorageError.cpp
2264+ internal/AccountImpl.cpp
2265+ internal/AccountsJobImpl.cpp
2266+ internal/HandlerBase.cpp
2267+ internal/ItemImpl.cpp
2268+ internal/ItemJobImpl.cpp
2269+ internal/ItemListJobImpl.cpp
2270+ internal/RuntimeImpl.cpp
2271+ internal/StorageErrorImpl.cpp
2272+ internal/unmarshal_error.cpp
2273+ internal/validate.cpp
2274+ ${generated_files}
2275+ ${CMAKE_SOURCE_DIR}/include/unity/storage/qt/AccountsJob.h
2276+ ${CMAKE_SOURCE_DIR}/include/unity/storage/qt/Item.h
2277+ ${CMAKE_SOURCE_DIR}/include/unity/storage/qt/ItemJob.h
2278+ ${CMAKE_SOURCE_DIR}/include/unity/storage/qt/ItemListJob.h
2279+ ${CMAKE_SOURCE_DIR}/include/unity/storage/qt/Runtime.h
2280+ ${CMAKE_SOURCE_DIR}/include/unity/storage/qt/internal/AccountsJobImpl.h
2281+ ${CMAKE_SOURCE_DIR}/include/unity/storage/qt/internal/HandlerBase.h
2282+ ${CMAKE_SOURCE_DIR}/include/unity/storage/qt/internal/ItemJobImpl.h
2283+ ${CMAKE_SOURCE_DIR}/include/unity/storage/qt/internal/ItemListJobImpl.h
2284+)
2285+
2286+add_library(storage-framework-qt-client-v2 SHARED
2287+ ${QT_CLIENT_LIB_V2_SRC}
2288+ ${generated_files}
2289+)
2290+target_include_directories(storage-framework-qt-client-v2 PRIVATE
2291+ ${Qt5DBus_INCLUDE_DIRS}
2292+ ${Qt5Network_INCLUDE_DIRS}
2293+ ${ONLINEACCOUNTS_DEPS_INCLUDE_DIRS}
2294+)
2295+set_target_properties(storage-framework-qt-client-v2 PROPERTIES
2296+ AUTOMOC TRUE
2297+ LINK_FLAGS "-Wl,--no-undefined"
2298+ OUTPUT_NAME "storage-framework-qt-client-${SF_CLIENT_API_VERSION}"
2299+ SOVERSION ${SF_CLIENT_SOVERSION}
2300+ VERSION ${SF_CLIENT_LIBVERSION}
2301+)
2302+target_link_libraries(storage-framework-qt-client-v2
2303+ storage-framework-common-internal
2304+ Qt5::Core
2305+ Qt5::DBus
2306+ Qt5::Network
2307+ ${ONLINEACCOUNTS_DEPS_LDFLAGS}
2308+)
2309+install(
2310+ TARGETS storage-framework-qt-client-v2
2311+ LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
2312+)
2313+
2314+configure_file(
2315+ storage-framework-qt-client.pc.in
2316+ storage-framework-qt-client-${SF_CLIENT_API_VERSION}.pc
2317+)
2318+install(
2319+ FILES ${CMAKE_CURRENT_BINARY_DIR}/storage-framework-qt-client-${SF_CLIENT_API_VERSION}.pc
2320+ DESTINATION ${CMAKE_INSTALL_LIBDIR}/pkgconfig
2321+)
2322
2323=== added file 'src/qt/Item.cpp'
2324--- src/qt/Item.cpp 1970-01-01 00:00:00 +0000
2325+++ src/qt/Item.cpp 2016-09-21 05:03:46 +0000
2326@@ -0,0 +1,230 @@
2327+/*
2328+ * Copyright (C) 2016 Canonical Ltd
2329+ *
2330+ * This program is free software: you can redistribute it and/or modify
2331+ * it under the terms of the GNU Lesser General Public License version 3 as
2332+ * published by the Free Software Foundation.
2333+ *
2334+ * This program is distributed in the hope that it will be useful,
2335+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
2336+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2337+ * GNU Lesser General Public License for more details.
2338+ *
2339+ * You should have received a copy of the GNU Lesser General Public License
2340+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
2341+ *
2342+ * Authors: Michi Henning <michi.henning@canonical.com>
2343+ */
2344+
2345+#include <unity/storage/qt/Item.h>
2346+#include <unity/storage/qt/internal/ItemImpl.h>
2347+
2348+#include <cassert>
2349+#include <QDebug> // TODO: remove this
2350+
2351+using namespace std;
2352+
2353+namespace unity
2354+{
2355+namespace storage
2356+{
2357+namespace qt
2358+{
2359+
2360+Item::Item()
2361+ : p_(make_shared<internal::ItemImpl>())
2362+{
2363+}
2364+
2365+Item::Item(shared_ptr<internal::ItemImpl> const& p)
2366+ : p_(p)
2367+{
2368+ assert(p);
2369+}
2370+
2371+Item::Item(Item const& other)
2372+ : p_(other.p_)
2373+{
2374+}
2375+
2376+Item::Item(Item&& other)
2377+{
2378+ p_->is_valid_ = false;
2379+ swap(p_, other.p_);
2380+}
2381+
2382+Item::~Item() = default;
2383+
2384+Item& Item::operator=(Item const& other)
2385+{
2386+ if (this == &other)
2387+ {
2388+ return *this;
2389+ }
2390+ p_ = other.p_;
2391+ return *this;
2392+}
2393+
2394+Item& Item::operator=(Item&& other)
2395+{
2396+ p_->is_valid_ = false;
2397+ swap(p_, other.p_);
2398+ return *this;
2399+}
2400+
2401+bool Item::isValid() const
2402+{
2403+ return p_->is_valid_;
2404+}
2405+
2406+QString Item::itemId() const
2407+{
2408+ return p_->itemId();
2409+}
2410+
2411+QString Item::name() const
2412+{
2413+ return p_->name();
2414+}
2415+
2416+Account Item::account() const
2417+{
2418+ return p_->account();
2419+}
2420+
2421+#if 0
2422+Item Item::root() const
2423+{
2424+
2425+ return p_->root();
2426+}
2427+#endif
2428+
2429+QString Item::etag() const
2430+{
2431+ return p_->etag();
2432+}
2433+
2434+Item::Type Item::type() const
2435+{
2436+ return p_->type();
2437+}
2438+
2439+QVariantMap Item::metadata() const
2440+{
2441+ return p_->metadata();
2442+}
2443+
2444+QDateTime Item::lastModifiedTime() const
2445+{
2446+ return p_->lastModifiedTime();
2447+}
2448+
2449+QVector<QString> Item::parentIds() const
2450+{
2451+ return p_->parentIds();
2452+}
2453+
2454+ItemListJob* Item::parents() const
2455+{
2456+ return p_->parents();
2457+}
2458+
2459+ItemJob* Item::copy(Item const& newParent, QString const& newName) const
2460+{
2461+ return p_->copy(newParent, newName);
2462+}
2463+
2464+ItemJob* Item::move(Item const& newParent, QString const& newName) const
2465+{
2466+ return p_->move(newParent, newName);
2467+}
2468+
2469+VoidJob* Item::deleteItem() const
2470+{
2471+ return p_->deleteItem();
2472+}
2473+
2474+Uploader* Item::createUploader(ConflictPolicy policy, qint64 sizeInBytes) const
2475+{
2476+ return p_->createUploader(policy, sizeInBytes);
2477+}
2478+
2479+Downloader* Item::createDownloader() const
2480+{
2481+ return p_->createDownloader();
2482+}
2483+
2484+ItemListJob* Item::list() const
2485+{
2486+ return p_->list();
2487+}
2488+
2489+ItemListJob* Item::lookup(QString const& name) const
2490+{
2491+ return p_->lookup(name);
2492+}
2493+
2494+ItemJob* Item::createFolder(QString const& name) const
2495+{
2496+ return p_->createFolder(name);
2497+}
2498+
2499+Uploader* Item::createFile(QString const& name) const
2500+{
2501+ return p_->createFile(name);
2502+}
2503+
2504+IntJob* Item::freeSpaceBytes() const
2505+{
2506+ return p_->freeSpaceBytes();
2507+}
2508+
2509+IntJob* Item::usedSpaceBytes() const
2510+{
2511+ return p_->usedSpaceBytes();
2512+}
2513+
2514+bool Item::operator==(Item const& other) const
2515+{
2516+ return p_->operator==(*other.p_);
2517+}
2518+
2519+bool Item::operator!=(Item const& other) const
2520+{
2521+ return p_->operator!=(*other.p_);
2522+}
2523+
2524+bool Item::operator<(Item const& other) const
2525+{
2526+ return p_->operator<(*other.p_);
2527+}
2528+
2529+bool Item::operator<=(Item const& other) const
2530+{
2531+ return p_->operator<=(*other.p_);
2532+}
2533+
2534+bool Item::operator>(Item const& other) const
2535+{
2536+ return p_->operator>(*other.p_);
2537+}
2538+
2539+bool Item::operator>=(Item const& other) const
2540+{
2541+ return p_->operator>=(*other.p_);
2542+}
2543+
2544+size_t Item::hash() const
2545+{
2546+ return p_->hash();
2547+}
2548+
2549+} // namespace qt
2550+} // namespace storage
2551+} // namespace unity
2552+
2553+uint qHash(unity::storage::qt::Item const& i)
2554+{
2555+ return i.hash();
2556+}
2557
2558=== added file 'src/qt/ItemJob.cpp'
2559--- src/qt/ItemJob.cpp 1970-01-01 00:00:00 +0000
2560+++ src/qt/ItemJob.cpp 2016-09-21 05:03:46 +0000
2561@@ -0,0 +1,62 @@
2562+/*
2563+ * Copyright (C) 2016 Canonical Ltd
2564+ *
2565+ * This program is free software: you can redistribute it and/or modify
2566+ * it under the terms of the GNU Lesser General Public License version 3 as
2567+ * published by the Free Software Foundation.
2568+ *
2569+ * This program is distributed in the hope that it will be useful,
2570+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
2571+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2572+ * GNU Lesser General Public License for more details.
2573+ *
2574+ * You should have received a copy of the GNU Lesser General Public License
2575+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
2576+ *
2577+ * Authors: Michi Henning <michi.henning@canonical.com>
2578+ */
2579+
2580+#include <unity/storage/qt/ItemJob.h>
2581+
2582+#include <unity/storage/qt/internal/ItemJobImpl.h>
2583+
2584+using namespace unity::storage::qt;
2585+using namespace std;
2586+
2587+namespace unity
2588+{
2589+namespace storage
2590+{
2591+namespace qt
2592+{
2593+
2594+ItemJob::ItemJob(unique_ptr<internal::ItemJobImpl> p)
2595+ : p_(move(p))
2596+{
2597+}
2598+
2599+ItemJob::~ItemJob() = default;
2600+
2601+bool ItemJob::isValid() const
2602+{
2603+ return p_->isValid();
2604+}
2605+
2606+ItemJob::Status ItemJob::status() const
2607+{
2608+ return p_->status();
2609+}
2610+
2611+StorageError ItemJob::error() const
2612+{
2613+ return p_->error();
2614+}
2615+
2616+Item ItemJob::item() const
2617+{
2618+ return p_->item();
2619+}
2620+
2621+} // namespace qt
2622+} // namespace storage
2623+} // namespace unity
2624
2625=== added file 'src/qt/ItemListJob.cpp'
2626--- src/qt/ItemListJob.cpp 1970-01-01 00:00:00 +0000
2627+++ src/qt/ItemListJob.cpp 2016-09-21 05:03:46 +0000
2628@@ -0,0 +1,57 @@
2629+/*
2630+ * Copyright (C) 2016 Canonical Ltd
2631+ *
2632+ * This program is free software: you can redistribute it and/or modify
2633+ * it under the terms of the GNU Lesser General Public License version 3 as
2634+ * published by the Free Software Foundation.
2635+ *
2636+ * This program is distributed in the hope that it will be useful,
2637+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
2638+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2639+ * GNU Lesser General Public License for more details.
2640+ *
2641+ * You should have received a copy of the GNU Lesser General Public License
2642+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
2643+ *
2644+ * Authors: Michi Henning <michi.henning@canonical.com>
2645+ */
2646+
2647+#include <unity/storage/qt/ItemListJob.h>
2648+
2649+#include <unity/storage/qt/internal/ItemListJobImpl.h>
2650+
2651+using namespace unity::storage::qt;
2652+using namespace std;
2653+
2654+namespace unity
2655+{
2656+namespace storage
2657+{
2658+namespace qt
2659+{
2660+
2661+ItemListJob::ItemListJob(unique_ptr<internal::ItemListJobImpl> p)
2662+ : p_(move(p))
2663+{
2664+}
2665+
2666+ItemListJob::~ItemListJob() = default;
2667+
2668+bool ItemListJob::isValid() const
2669+{
2670+ return p_->isValid();
2671+}
2672+
2673+ItemListJob::Status ItemListJob::status() const
2674+{
2675+ return p_->status();
2676+}
2677+
2678+StorageError ItemListJob::error() const
2679+{
2680+ return p_->error();
2681+}
2682+
2683+} // namespace qt
2684+} // namespace storage
2685+} // namespace unity
2686
2687=== added file 'src/qt/Runtime.cpp'
2688--- src/qt/Runtime.cpp 1970-01-01 00:00:00 +0000
2689+++ src/qt/Runtime.cpp 2016-09-21 05:03:46 +0000
2690@@ -0,0 +1,87 @@
2691+/*
2692+ * Copyright (C) 2016 Canonical Ltd
2693+ *
2694+ * This program is free software: you can redistribute it and/or modify
2695+ * it under the terms of the GNU Lesser General Public License version 3 as
2696+ * published by the Free Software Foundation.
2697+ *
2698+ * This program is distributed in the hope that it will be useful,
2699+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
2700+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2701+ * GNU Lesser General Public License for more details.
2702+ *
2703+ * You should have received a copy of the GNU Lesser General Public License
2704+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
2705+ *
2706+ * Authors: Michi Henning <michi.henning@canonical.com>
2707+ */
2708+
2709+#include <unity/storage/qt/Runtime.h>
2710+
2711+#include <unity/storage/qt/internal/RuntimeImpl.h>
2712+
2713+using namespace std;
2714+
2715+namespace unity
2716+{
2717+namespace storage
2718+{
2719+namespace qt
2720+{
2721+
2722+Runtime::Runtime(QObject* parent)
2723+ : QObject(parent)
2724+ , p_(new internal::RuntimeImpl)
2725+{
2726+}
2727+
2728+Runtime::Runtime(QDBusConnection const& bus, QObject* parent)
2729+ : QObject(parent)
2730+ , p_(new internal::RuntimeImpl(bus))
2731+{
2732+}
2733+
2734+Runtime::~Runtime() = default;
2735+
2736+bool Runtime::isValid() const
2737+{
2738+ return p_->isValid();
2739+}
2740+
2741+StorageError Runtime::error() const
2742+{
2743+ return p_->error();
2744+}
2745+
2746+QDBusConnection Runtime::connection() const
2747+{
2748+ return p_->connection();
2749+}
2750+
2751+StorageError Runtime::shutdown()
2752+{
2753+ return p_->shutdown();
2754+}
2755+
2756+AccountsJob* Runtime::accounts() const
2757+{
2758+ return p_->accounts();
2759+}
2760+
2761+Account Runtime::make_test_account(QString const& bus_name, QString const& object_path)
2762+{
2763+ return p_->make_test_account(bus_name, object_path);
2764+}
2765+
2766+Account Runtime::make_test_account(QString const& bus_name,
2767+ QString const& object_path,
2768+ QString const& owner_id,
2769+ QString const& owner,
2770+ QString const& description)
2771+{
2772+ return p_->make_test_account(bus_name, object_path, owner_id, owner, description);
2773+}
2774+
2775+} // namespace qt
2776+} // namespace storage
2777+} // namespace unity
2778
2779=== added file 'src/qt/StorageError.cpp'
2780--- src/qt/StorageError.cpp 1970-01-01 00:00:00 +0000
2781+++ src/qt/StorageError.cpp 2016-09-21 05:03:46 +0000
2782@@ -0,0 +1,98 @@
2783+/*
2784+ * Copyright (C) 2016 Canonical Ltd
2785+ *
2786+ * This program is free software: you can redistribute it and/or modify
2787+ * it under the terms of the GNU Lesser General Public License version 3 as
2788+ * published by the Free Software Foundation.
2789+ *
2790+ * This program is distributed in the hope that it will be useful,
2791+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
2792+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2793+ * GNU Lesser General Public License for more details.
2794+ *
2795+ * You should have received a copy of the GNU Lesser General Public License
2796+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
2797+ *
2798+ * Authors: Michi Henning <michi.henning@canonical.com>
2799+ */
2800+
2801+#include <unity/storage/qt/StorageError.h>
2802+#include <unity/storage/qt/internal/StorageErrorImpl.h>
2803+
2804+#include <cassert>
2805+#include <memory>
2806+
2807+using namespace std;
2808+
2809+namespace unity
2810+{
2811+namespace storage
2812+{
2813+namespace qt
2814+{
2815+
2816+StorageError::StorageError()
2817+ : p_(new internal::StorageErrorImpl)
2818+{
2819+}
2820+
2821+StorageError::StorageError(StorageError const& other)
2822+ : p_(new internal::StorageErrorImpl(*other.p_))
2823+{
2824+}
2825+
2826+StorageError::StorageError(StorageError&&) = default;
2827+
2828+StorageError::StorageError(unique_ptr<internal::StorageErrorImpl> p)
2829+ : p_(move(p))
2830+{
2831+}
2832+
2833+StorageError::~StorageError() = default;
2834+
2835+StorageError& StorageError::operator=(StorageError const& other)
2836+{
2837+ *p_ = *other.p_;
2838+ return *this;
2839+}
2840+
2841+StorageError& StorageError::operator=(StorageError&&) = default;
2842+
2843+StorageError::Type StorageError::type() const
2844+{
2845+ return p_->type();
2846+}
2847+
2848+QString StorageError::name() const
2849+{
2850+ return p_->name();
2851+}
2852+
2853+QString StorageError::message() const
2854+{
2855+ return p_->message();
2856+}
2857+
2858+QString StorageError::errorString() const
2859+{
2860+ return p_->errorString();
2861+}
2862+
2863+QString StorageError::itemId() const
2864+{
2865+ return p_->itemId();
2866+}
2867+
2868+QString StorageError::itemName() const
2869+{
2870+ return p_->itemName();
2871+}
2872+
2873+int StorageError::errorCode() const
2874+{
2875+ return p_->errorCode();
2876+}
2877+
2878+} // namespace qt
2879+} // namespace storage
2880+} // namespace unity
2881
2882=== modified file 'src/qt/client/CMakeLists.txt'
2883--- src/qt/client/CMakeLists.txt 2016-08-11 06:53:25 +0000
2884+++ src/qt/client/CMakeLists.txt 2016-09-21 05:03:46 +0000
2885@@ -50,9 +50,9 @@
2886 set_target_properties(storage-framework-qt-local-client PROPERTIES
2887 AUTOMOC TRUE
2888 LINK_FLAGS "-Wl,--no-undefined"
2889- OUTPUT_NAME "storage-framework-qt-local-client-${SF_CLIENT_API_VERSION}"
2890- SOVERSION ${SF_CLIENT_SOVERSION}
2891- VERSION ${SF_CLIENT_LIBVERSION}
2892+ OUTPUT_NAME "storage-framework-qt-local-client-1"
2893+ SOVERSION 0
2894+ VERSION 0.0.1
2895 )
2896 target_link_libraries(storage-framework-qt-local-client
2897 storage-framework-common-internal
2898@@ -70,10 +70,10 @@
2899
2900 configure_file(
2901 storage-framework-qt-local-client.pc.in
2902- storage-framework-qt-local-client-${SF_CLIENT_API_VERSION}.pc
2903+ storage-framework-qt-local-client-1.pc
2904 )
2905 install(
2906- FILES ${CMAKE_CURRENT_BINARY_DIR}/storage-framework-qt-local-client-${SF_CLIENT_API_VERSION}.pc
2907+ FILES ${CMAKE_CURRENT_BINARY_DIR}/storage-framework-qt-local-client-1.pc
2908 DESTINATION ${CMAKE_INSTALL_LIBDIR}/pkgconfig
2909 )
2910
2911@@ -104,9 +104,9 @@
2912 set_target_properties(storage-framework-qt-client PROPERTIES
2913 AUTOMOC TRUE
2914 LINK_FLAGS "-Wl,--no-undefined"
2915- OUTPUT_NAME "storage-framework-qt-client-${SF_CLIENT_API_VERSION}"
2916- SOVERSION ${SF_CLIENT_SOVERSION}
2917- VERSION ${SF_CLIENT_LIBVERSION}
2918+ OUTPUT_NAME "storage-framework-qt-client-1"
2919+ SOVERSION 0
2920+ VERSION 0.0.1
2921 )
2922 target_link_libraries(storage-framework-qt-client
2923 storage-framework-common-internal
2924@@ -122,10 +122,10 @@
2925 )
2926
2927 configure_file(
2928- storage-framework-qt-client.pc.in
2929- storage-framework-qt-client-${SF_CLIENT_API_VERSION}.pc
2930+ storage-framework-qt-client-1.pc.in
2931+ storage-framework-qt-client-1.pc
2932 )
2933 install(
2934- FILES ${CMAKE_CURRENT_BINARY_DIR}/storage-framework-qt-client-${SF_CLIENT_API_VERSION}.pc
2935+ FILES ${CMAKE_CURRENT_BINARY_DIR}/storage-framework-qt-client-1.pc
2936 DESTINATION ${CMAKE_INSTALL_LIBDIR}/pkgconfig
2937 )
2938
2939=== added file 'src/qt/client/storage-framework-qt-client-1.pc.in'
2940--- src/qt/client/storage-framework-qt-client-1.pc.in 1970-01-01 00:00:00 +0000
2941+++ src/qt/client/storage-framework-qt-client-1.pc.in 2016-09-21 05:03:46 +0000
2942@@ -0,0 +1,6 @@
2943+Name: storage-framework-qt-client-1
2944+Description: A Qt client library for the storage framework (soon to be deprecated)
2945+Version: 0.1
2946+Requires.private: Qt5Core Qt5Network
2947+Cflags: -I@CMAKE_INSTALL_FULL_INCLUDEDIR@/storage-framework-client-1
2948+Libs: -L@CMAKE_INSTALL_FULL_LIBDIR@ -lstorage-framework-qt-client-1
2949
2950=== added file 'src/qt/client/storage-framework-qt-local-client.pc.in'
2951--- src/qt/client/storage-framework-qt-local-client.pc.in 1970-01-01 00:00:00 +0000
2952+++ src/qt/client/storage-framework-qt-local-client.pc.in 2016-09-21 05:03:46 +0000
2953@@ -0,0 +1,6 @@
2954+Name: storage-framework-qt-local-client-1
2955+Description: A Qt client library for the storage framework (soon to be deprecated)
2956+Version: @PROJECT_VERSION@
2957+Requires.private: Qt5Core Qt5Network
2958+Cflags: -I@CMAKE_INSTALL_FULL_INCLUDEDIR@/storage-framework-client-1
2959+Libs: -L@CMAKE_INSTALL_FULL_LIBDIR@ -lstorage-framework-qt-local-client-1
2960
2961=== removed file 'src/qt/client/storage-framework-qt-local-client.pc.in'
2962--- src/qt/client/storage-framework-qt-local-client.pc.in 2016-07-11 03:28:40 +0000
2963+++ src/qt/client/storage-framework-qt-local-client.pc.in 1970-01-01 00:00:00 +0000
2964@@ -1,6 +0,0 @@
2965-Name: storage-framework-qt-local-client-@SF_CLIENT_API_VERSION@
2966-Description: A Qt client library for the storage framework
2967-Version: @PROJECT_VERSION@
2968-Requires.private: Qt5Core Qt5Network
2969-Cflags: -I@CMAKE_INSTALL_FULL_INCLUDEDIR@/storage-framework-client-@SF_CLIENT_API_VERSION@
2970-Libs: -L@CMAKE_INSTALL_FULL_LIBDIR@ -lstorage-framework-qt-local-client-@SF_CLIENT_API_VERSION@
2971
2972=== added directory 'src/qt/internal'
2973=== added file 'src/qt/internal/AccountImpl.cpp'
2974--- src/qt/internal/AccountImpl.cpp 1970-01-01 00:00:00 +0000
2975+++ src/qt/internal/AccountImpl.cpp 2016-09-21 05:03:46 +0000
2976@@ -0,0 +1,226 @@
2977+/*
2978+ * Copyright (C) 2016 Canonical Ltd
2979+ *
2980+ * This program is free software: you can redistribute it and/or modify
2981+ * it under the terms of the GNU Lesser General Public License version 3 as
2982+ * published by the Free Software Foundation.
2983+ *
2984+ * This program is distributed in the hope that it will be useful,
2985+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
2986+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2987+ * GNU Lesser General Public License for more details.
2988+ *
2989+ * You should have received a copy of the GNU Lesser General Public License
2990+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
2991+ *
2992+ * Authors: Michi Henning <michi.henning@canonical.com>
2993+ */
2994+
2995+#include <unity/storage/qt/internal/AccountImpl.h>
2996+
2997+#include "ProviderInterface.h"
2998+#include <unity/storage/qt/Account.h>
2999+#include <unity/storage/qt/internal/ItemImpl.h>
3000+#include <unity/storage/qt/internal/ItemJobImpl.h>
3001+#include <unity/storage/qt/internal/ItemListJobImpl.h>
3002+#include <unity/storage/qt/internal/RuntimeImpl.h>
3003+#include <unity/storage/qt/Runtime.h>
3004+
3005+#include <boost/functional/hash.hpp>
3006+
3007+#include <cassert>
3008+
3009+using namespace std;
3010+
3011+namespace unity
3012+{
3013+namespace storage
3014+{
3015+namespace qt
3016+{
3017+namespace internal
3018+{
3019+
3020+AccountImpl::AccountImpl()
3021+ : is_valid_(false)
3022+{
3023+}
3024+
3025+AccountImpl::AccountImpl(shared_ptr<RuntimeImpl> const& runtime,
3026+ QString const& bus_name,
3027+ QString const& object_path,
3028+ QString const& owner_id,
3029+ QString const& owner,
3030+ QString const& description)
3031+ : is_valid_(true)
3032+ , bus_name_(bus_name)
3033+ , object_path_(object_path)
3034+ , owner_id_(owner_id)
3035+ , owner_(owner)
3036+ , description_(description)
3037+ , runtime_(runtime)
3038+ , provider_(new ProviderInterface(bus_name, object_path, runtime->connection()))
3039+{
3040+ assert(!bus_name.isEmpty());
3041+ assert(!object_path.isEmpty());
3042+}
3043+
3044+QString AccountImpl::owner() const
3045+{
3046+ return is_valid_ ? owner_ : "";
3047+}
3048+
3049+QString AccountImpl::ownerId() const
3050+{
3051+ return is_valid_ ? owner_id_ : "";
3052+}
3053+
3054+QString AccountImpl::description() const
3055+{
3056+ return is_valid_ ? description_ : "";
3057+}
3058+
3059+ItemListJob* AccountImpl::roots() const
3060+{
3061+ auto runtime = runtime_.lock();
3062+ if (!runtime || !runtime->isValid())
3063+ {
3064+ auto e = StorageErrorImpl::runtime_destroyed_error("Account::roots(): Runtime was destroyed previously");
3065+ return ItemListJobImpl::make_item_list_job(e);
3066+ }
3067+
3068+ auto validate = [](storage::internal::ItemMetadata const& md)
3069+ {
3070+ if (md.type != ItemType::root)
3071+ {
3072+ QString msg = "provider returned non-root item type: " + QString::number(int(md.type));
3073+ qCritical() << msg;
3074+ throw StorageErrorImpl::local_comms_error(msg);
3075+ }
3076+ };
3077+
3078+ QString method = "Account::roots()";
3079+ auto reply = provider_->Roots();
3080+ auto This = const_pointer_cast<AccountImpl>(shared_from_this());
3081+ return ItemListJobImpl::make_item_list_job(This, method, reply, validate);
3082+}
3083+
3084+ItemJob* AccountImpl::get(QString const& itemId) const
3085+{
3086+ auto runtime = runtime_.lock();
3087+ if (!runtime || !runtime->isValid())
3088+ {
3089+ auto e = StorageErrorImpl::runtime_destroyed_error("Account::get(): Runtime was destroyed previously");
3090+ return ItemJobImpl::make_item_job(e);
3091+ }
3092+
3093+ // TODO: use defaulted param?
3094+ auto validate = [](storage::internal::ItemMetadata const&)
3095+ {
3096+ };
3097+
3098+ QString method = "Item::get()";
3099+ auto reply = provider_->Metadata(itemId);
3100+ auto This = const_pointer_cast<AccountImpl>(shared_from_this());
3101+ return ItemJobImpl::make_item_job(This, method, reply, validate);
3102+}
3103+
3104+bool AccountImpl::operator==(AccountImpl const& other) const
3105+{
3106+ if (is_valid_)
3107+ {
3108+ return other.is_valid_
3109+ && owner_ == other.owner_
3110+ && owner_id_ == other.owner_id_
3111+ && description_ == other.description_;
3112+ }
3113+ return !other.is_valid_;
3114+}
3115+
3116+bool AccountImpl::operator!=(AccountImpl const& other) const
3117+{
3118+ return !operator==(other);
3119+}
3120+
3121+bool AccountImpl::operator<(AccountImpl const& other) const
3122+{
3123+ if (!is_valid_)
3124+ {
3125+ return other.is_valid_;
3126+ }
3127+ if (is_valid_ && !other.is_valid_)
3128+ {
3129+ return false;
3130+ }
3131+ assert(is_valid_ && other.is_valid_);
3132+ if (owner_id_ < other.owner_id_)
3133+ {
3134+ return true;
3135+ }
3136+ if (owner_id_ > other.owner_id_)
3137+ {
3138+ return false;
3139+ }
3140+ if (owner_ < other.owner_)
3141+ {
3142+ return true;
3143+ }
3144+ if (owner_ > other.owner_)
3145+ {
3146+ return false;
3147+ }
3148+ if (description_ < other.description_)
3149+ {
3150+ return true;
3151+ }
3152+ return false;
3153+}
3154+
3155+bool AccountImpl::operator<=(AccountImpl const& other) const
3156+{
3157+ return operator<(other) || operator==(other);
3158+}
3159+
3160+bool AccountImpl::operator>(AccountImpl const& other) const
3161+{
3162+ return !operator<=(other);
3163+}
3164+
3165+bool AccountImpl::operator>=(AccountImpl const& other) const
3166+{
3167+ return !operator<(other);
3168+}
3169+
3170+shared_ptr<ProviderInterface> AccountImpl::provider() const
3171+{
3172+ return provider_;
3173+}
3174+
3175+size_t AccountImpl::hash() const
3176+{
3177+ if (!is_valid_)
3178+ {
3179+ return 0;
3180+ }
3181+ size_t hash = 0;
3182+ boost::hash_combine(hash, qHash(owner_));
3183+ boost::hash_combine(hash, qHash(owner_id_));
3184+ boost::hash_combine(hash, qHash(description_));
3185+ return hash;
3186+}
3187+
3188+Account AccountImpl::make_account(shared_ptr<RuntimeImpl> const& runtime,
3189+ QString const& bus_name,
3190+ QString const& object_path,
3191+ QString const& owner_id,
3192+ QString const& owner,
3193+ QString const& description)
3194+{
3195+ shared_ptr<AccountImpl> p(new AccountImpl(runtime, bus_name, object_path, owner_id, owner, description));
3196+ return Account(p);
3197+}
3198+
3199+} // namespace internal
3200+} // namespace qt
3201+} // namespace storage
3202+} // namespace unity
3203
3204=== added file 'src/qt/internal/AccountsJobImpl.cpp'
3205--- src/qt/internal/AccountsJobImpl.cpp 1970-01-01 00:00:00 +0000
3206+++ src/qt/internal/AccountsJobImpl.cpp 2016-09-21 05:03:46 +0000
3207@@ -0,0 +1,183 @@
3208+/*
3209+ * Copyright (C) 2016 Canonical Ltd
3210+ *
3211+ * This program is free software: you can redistribute it and/or modify
3212+ * it under the terms of the GNU Lesser General Public License version 3 as
3213+ * published by the Free Software Foundation.
3214+ *
3215+ * This program is distributed in the hope that it will be useful,
3216+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
3217+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
3218+ * GNU Lesser General Public License for more details.
3219+ *
3220+ * You should have received a copy of the GNU Lesser General Public License
3221+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
3222+ *
3223+ * Authors: Michi Henning <michi.henning@canonical.com>
3224+ */
3225+
3226+#include <unity/storage/qt/internal/AccountsJobImpl.h>
3227+
3228+#include <unity/storage/qt/internal/AccountImpl.h>
3229+#include <unity/storage/qt/internal/RuntimeImpl.h>
3230+#include <unity/storage/qt/internal/StorageErrorImpl.h>
3231+
3232+#include <OnlineAccounts/Account>
3233+
3234+#include <cassert>
3235+
3236+using namespace std;
3237+
3238+namespace unity
3239+{
3240+namespace storage
3241+{
3242+namespace qt
3243+{
3244+namespace internal
3245+{
3246+
3247+namespace
3248+{
3249+
3250+// TODO: We retrieve the accounts directly from online accounts until we have a working registry.
3251+
3252+static map<QString, QString> const BUS_NAMES =
3253+{
3254+ { "google-drive-scope", "com.canonical.StorageFramework.Provider.ProviderTest" },
3255+ { "com.canonical.scopes.mcloud_mcloud_mcloud", "com.canonical.StorageFramework.Provider.McloudProvider" }
3256+};
3257+
3258+} // namespace
3259+
3260+AccountsJobImpl::AccountsJobImpl(AccountsJob* public_instance, shared_ptr<RuntimeImpl> const& runtime)
3261+ : public_instance_(public_instance)
3262+ , status_(AccountsJob::Loading)
3263+ , runtime_(runtime)
3264+{
3265+ assert(public_instance);
3266+ assert(runtime);
3267+
3268+ initialize_accounts();
3269+}
3270+
3271+AccountsJobImpl::AccountsJobImpl(AccountsJob* public_instance, StorageError const& error)
3272+ : public_instance_(public_instance)
3273+ , status_(AccountsJob::Loading)
3274+ , error_(error)
3275+{
3276+ assert(public_instance);
3277+ assert(error.type() != StorageError::NoError);
3278+
3279+ status_ = emit_status_changed(AccountsJob::Error);
3280+}
3281+
3282+bool AccountsJobImpl::isValid() const
3283+{
3284+ return status_ != AccountsJob::Status::Error;
3285+}
3286+
3287+AccountsJob::Status AccountsJobImpl::status() const
3288+{
3289+ return status_;
3290+}
3291+
3292+StorageError AccountsJobImpl::error() const
3293+{
3294+ return error_;
3295+}
3296+
3297+QList<Account> AccountsJobImpl::accounts() const
3298+{
3299+ auto runtime = get_runtime("AccountsJob::accounts()");
3300+ if (!runtime)
3301+ {
3302+ return QList<Account>();
3303+ }
3304+ if (status_ != AccountsJob::Finished)
3305+ {
3306+ return QList<Account>();
3307+ }
3308+ return accounts_;
3309+}
3310+
3311+void AccountsJobImpl::manager_ready()
3312+{
3313+ timer_.stop();
3314+ disconnect(this);
3315+ initialize_accounts();
3316+}
3317+
3318+// LCOV_EXCL_START
3319+void AccountsJobImpl::timeout()
3320+{
3321+ disconnect(this);
3322+ error_ = StorageErrorImpl::local_comms_error("AccountsJob(): timeout retrieving Online accounts");
3323+ status_ = emit_status_changed(AccountsJob::Error);
3324+}
3325+// LCOV_EXCL_STOP
3326+
3327+AccountsJob::Status AccountsJobImpl::emit_status_changed(AccountsJob::Status new_status) const
3328+{
3329+ if (status_ == AccountsJob::Loading) // Once in a final state, we don't emit the signal again.
3330+ {
3331+ // We defer emission of the signal so the client gets a chance to connect to the signal
3332+ // in case we emit the signal from the constructor.
3333+ QMetaObject::invokeMethod(public_instance_,
3334+ "statusChanged",
3335+ Qt::QueuedConnection,
3336+ Q_ARG(unity::storage::qt::AccountsJob::Status, new_status));
3337+ }
3338+ return new_status;
3339+}
3340+
3341+shared_ptr<RuntimeImpl> AccountsJobImpl::get_runtime(QString const& method) const
3342+{
3343+ auto runtime = runtime_.lock();
3344+ if (!runtime || !runtime->isValid())
3345+ {
3346+ QString msg = method + ": Runtime was destroyed previously";
3347+ auto This = const_cast<AccountsJobImpl*>(this);
3348+ This->error_ = StorageErrorImpl::runtime_destroyed_error(msg);
3349+ This->status_ = emit_status_changed(AccountsJob::Error);
3350+ }
3351+ return runtime;
3352+}
3353+
3354+void AccountsJobImpl::initialize_accounts()
3355+{
3356+ auto runtime = get_runtime("AccountsJob()");
3357+ assert(runtime);
3358+
3359+ auto manager = runtime->accounts_manager();
3360+ if (!manager->isReady())
3361+ {
3362+ connect(manager.get(), &OnlineAccounts::Manager::ready, this, &AccountsJobImpl::manager_ready);
3363+ connect(&timer_, &QTimer::timeout, this, &AccountsJobImpl::timeout);
3364+ timer_.setSingleShot(true);
3365+ timer_.start(30000); // TODO: Need config for this eventually.
3366+ return;
3367+ }
3368+
3369+ for (auto const map_entry : BUS_NAMES)
3370+ {
3371+ auto service_id = map_entry.first;
3372+ for (auto const& a : manager->availableAccounts(service_id))
3373+ {
3374+ auto object_path = QStringLiteral("/provider/%1").arg(a->id());
3375+ auto bus_name = map_entry.second;
3376+ accounts_.append(AccountImpl::make_account(runtime,
3377+ bus_name,
3378+ object_path,
3379+ a->serviceId(),
3380+ "",
3381+ a->displayName()));
3382+ }
3383+ }
3384+ status_ = emit_status_changed(AccountsJob::Finished);
3385+}
3386+
3387+} // namespace internal
3388+} // namespace qt
3389+} // namespace storage
3390+} // namespace unity
3391
3392=== added file 'src/qt/internal/HandlerBase.cpp'
3393--- src/qt/internal/HandlerBase.cpp 1970-01-01 00:00:00 +0000
3394+++ src/qt/internal/HandlerBase.cpp 2016-09-21 05:03:46 +0000
3395@@ -0,0 +1,59 @@
3396+/*
3397+ * Copyright (C) 2016 Canonical Ltd
3398+ *
3399+ * This program is free software: you can redistribute it and/or modify
3400+ * it under the terms of the GNU Lesser General Public License version 3 as
3401+ * published by the Free Software Foundation.
3402+ *
3403+ * This program is distributed in the hope that it will be useful,
3404+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
3405+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
3406+ * GNU Lesser General Public License for more details.
3407+ *
3408+ * You should have received a copy of the GNU Lesser General Public License
3409+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
3410+ *
3411+ * Authors: Michi Henning <michi.henning@canonical.com>
3412+ */
3413+
3414+#include <unity/storage/qt/internal/HandlerBase.h>
3415+
3416+#pragma GCC diagnostic push
3417+#pragma GCC diagnostic ignored "-Wctor-dtor-privacy"
3418+#include <QFuture>
3419+#pragma GCC diagnostic pop
3420+
3421+#include <cassert>
3422+
3423+using namespace std;
3424+
3425+namespace unity
3426+{
3427+namespace storage
3428+{
3429+namespace qt
3430+{
3431+namespace internal
3432+{
3433+
3434+HandlerBase::HandlerBase(QObject* parent,
3435+ QDBusPendingCall const& call,
3436+ function<void(QDBusPendingCallWatcher&)> const& closure)
3437+ : QObject(parent)
3438+ , watcher_(call)
3439+ , closure_(closure)
3440+{
3441+ assert(closure);
3442+ connect(&watcher_, &QDBusPendingCallWatcher::finished, this, &HandlerBase::finished);
3443+}
3444+
3445+void HandlerBase::finished(QDBusPendingCallWatcher* call)
3446+{
3447+ deleteLater();
3448+ closure_(*call);
3449+}
3450+
3451+} // namespace internal
3452+} // namespace qt
3453+} // namespace storage
3454+} // namespace unity
3455
3456=== added file 'src/qt/internal/ItemImpl.cpp'
3457--- src/qt/internal/ItemImpl.cpp 1970-01-01 00:00:00 +0000
3458+++ src/qt/internal/ItemImpl.cpp 2016-09-21 05:03:46 +0000
3459@@ -0,0 +1,248 @@
3460+/*
3461+ * Copyright (C) 2016 Canonical Ltd
3462+ *
3463+ * This program is free software: you can redistribute it and/or modify
3464+ * it under the terms of the GNU Lesser General Public License version 3 as
3465+ * published by the Free Software Foundation.
3466+ *
3467+ * This program is distributed in the hope that it will be useful,
3468+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
3469+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
3470+ * GNU Lesser General Public License for more details.
3471+ *
3472+ * You should have received a copy of the GNU Lesser General Public License
3473+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
3474+ *
3475+ * Authors: Michi Henning <michi.henning@canonical.com>
3476+ */
3477+
3478+#include <unity/storage/qt/internal/ItemImpl.h>
3479+
3480+#include "ProviderInterface.h"
3481+#include <unity/storage/provider/metadata_keys.h>
3482+#include <unity/storage/qt/internal/AccountImpl.h>
3483+#include <unity/storage/qt/internal/ItemJobImpl.h>
3484+#include <unity/storage/qt/internal/RuntimeImpl.h>
3485+#include <unity/storage/qt/internal/validate.h>
3486+
3487+#include <cassert>
3488+
3489+using namespace std;
3490+
3491+namespace unity
3492+{
3493+namespace storage
3494+{
3495+namespace qt
3496+{
3497+namespace internal
3498+{
3499+
3500+ItemImpl::ItemImpl()
3501+ : is_valid_(false)
3502+{
3503+ md_.type = storage::ItemType::file;
3504+}
3505+
3506+ItemImpl::ItemImpl(storage::internal::ItemMetadata const& md,
3507+ std::shared_ptr<AccountImpl> const& account)
3508+ : is_valid_(true)
3509+ , md_(md)
3510+ , account_(account)
3511+{
3512+ assert(account);
3513+}
3514+
3515+QString ItemImpl::itemId() const
3516+{
3517+ return is_valid_ ? md_.item_id : "";
3518+}
3519+
3520+QString ItemImpl::name() const
3521+{
3522+ return is_valid_ ? md_.name : "";
3523+}
3524+
3525+Account ItemImpl::account() const
3526+{
3527+ return is_valid_ ? account_ : Account();
3528+}
3529+
3530+#if 0
3531+Item ItemImpl::root() const
3532+{
3533+ return is_valid_ ? root_ : Item();
3534+}
3535+#endif
3536+
3537+QString ItemImpl::etag() const
3538+{
3539+ return is_valid_ ? md_.etag : "";
3540+}
3541+
3542+Item::Type ItemImpl::type() const
3543+{
3544+ switch (md_.type)
3545+ {
3546+ case storage::ItemType::file:
3547+ return Item::File;
3548+ case storage::ItemType::folder:
3549+ return Item::Folder;
3550+ case storage::ItemType::root:
3551+ return Item::Root;
3552+ default:
3553+ abort(); // LCOV_EXCL_LINE // Impossible
3554+ }
3555+}
3556+
3557+QVariantMap ItemImpl::metadata() const
3558+{
3559+ // TODO: Need to agree on metadata representation.
3560+ return is_valid_ ? QVariantMap() : QVariantMap();
3561+}
3562+
3563+QDateTime ItemImpl::lastModifiedTime() const
3564+{
3565+ return is_valid_ ? QDateTime::fromString(md_.metadata.value(provider::LAST_MODIFIED_TIME).toString(), Qt::ISODate)
3566+ : QDateTime();
3567+}
3568+
3569+QVector<QString> ItemImpl::parentIds() const
3570+{
3571+ return is_valid_ ? md_.parent_ids : QVector<QString>();
3572+}
3573+
3574+ItemListJob* ItemImpl::parents() const
3575+{
3576+ return nullptr; // TODO
3577+}
3578+
3579+ItemJob* ItemImpl::copy(Item const& newParent, QString const& newName) const
3580+{
3581+ return nullptr; // TODO
3582+}
3583+
3584+ItemJob* ItemImpl::move(Item const& newParent, QString const& newName) const
3585+{
3586+ return nullptr; // TODO
3587+}
3588+
3589+VoidJob* ItemImpl::deleteItem() const
3590+{
3591+ return nullptr; // TODO
3592+}
3593+
3594+Uploader* ItemImpl::createUploader(ConflictPolicy policy, qint64 sizeInBytes) const
3595+{
3596+ return nullptr; // TODO
3597+}
3598+
3599+Downloader* ItemImpl::createDownloader() const
3600+{
3601+ return nullptr; // TODO
3602+}
3603+
3604+ItemListJob* ItemImpl::list() const
3605+{
3606+ return nullptr; // TODO
3607+}
3608+
3609+ItemListJob* ItemImpl::lookup(QString const& name) const
3610+{
3611+ return nullptr; // TODO
3612+}
3613+
3614+ItemJob* ItemImpl::createFolder(QString const& name) const
3615+{
3616+ return nullptr; // TODO
3617+}
3618+
3619+Uploader* ItemImpl::createFile(QString const& name) const
3620+{
3621+ return nullptr; // TODO
3622+}
3623+
3624+IntJob* ItemImpl::freeSpaceBytes() const
3625+{
3626+ return nullptr; // TODO
3627+}
3628+
3629+IntJob* ItemImpl::usedSpaceBytes() const
3630+{
3631+ return nullptr; // TODO
3632+}
3633+
3634+bool ItemImpl::operator==(ItemImpl const& other) const
3635+{
3636+ if (is_valid_)
3637+ {
3638+ return other.is_valid_ && md_.item_id == other.md_.item_id;
3639+ }
3640+ return !other.is_valid_;
3641+}
3642+
3643+bool ItemImpl::operator!=(ItemImpl const& other) const
3644+{
3645+ return !operator==(other);
3646+}
3647+
3648+bool ItemImpl::operator<(ItemImpl const& other) const
3649+{
3650+ if (is_valid_)
3651+ {
3652+ return other.is_valid_ && md_.item_id < other.md_.item_id;
3653+ }
3654+ return other.is_valid_;
3655+}
3656+
3657+bool ItemImpl::operator<=(ItemImpl const& other) const
3658+{
3659+ return operator<(other) or operator==(other);
3660+}
3661+
3662+bool ItemImpl::operator>(ItemImpl const& other) const
3663+{
3664+ return !operator<=(other);
3665+}
3666+
3667+bool ItemImpl::operator>=(ItemImpl const& other) const
3668+{
3669+ return !operator<(other);
3670+}
3671+
3672+size_t ItemImpl::hash() const
3673+{
3674+ if (!is_valid_)
3675+ {
3676+ return 0;
3677+ }
3678+ return qHash(md_.item_id);
3679+}
3680+
3681+Item ItemImpl::make_item(QString const& method,
3682+ storage::internal::ItemMetadata const& md,
3683+ std::shared_ptr<AccountImpl> const& account)
3684+{
3685+ validate(method, md); // Throws if no good.
3686+ auto p = make_shared<ItemImpl>(md, account);
3687+ return Item(p);
3688+}
3689+
3690+#if 0
3691+shared_ptr<RuntimeImpl> ItemImpl::get_runtime(QString const& method) const
3692+{
3693+ auto runtime = account_->runtime_.lock();
3694+ if (!runtime || !runtime->isValid())
3695+ {
3696+ QString msg = method + ": Runtime was destroyed previously";
3697+ auto This = const_cast<ItemImpl*>(this);
3698+ This->error_ = StorageErrorImpl::runtime_destroyed_error(msg);
3699+ }
3700+ return runtime;
3701+}
3702+#endif
3703+
3704+} // namespace internal
3705+} // namespace qt
3706+} // namespace storage
3707+} // namespace unity
3708
3709=== added file 'src/qt/internal/ItemJobImpl.cpp'
3710--- src/qt/internal/ItemJobImpl.cpp 1970-01-01 00:00:00 +0000
3711+++ src/qt/internal/ItemJobImpl.cpp 2016-09-21 05:03:46 +0000
3712@@ -0,0 +1,138 @@
3713+/*
3714+ * Copyright (C) 2016 Canonical Ltd
3715+ *
3716+ * This program is free software: you can redistribute it and/or modify
3717+ * it under the terms of the GNU Lesser General Public License version 3 as
3718+ * published by the Free Software Foundation.
3719+ *
3720+ * This program is distributed in the hope that it will be useful,
3721+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
3722+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
3723+ * GNU Lesser General Public License for more details.
3724+ *
3725+ * You should have received a copy of the GNU Lesser General Public License
3726+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
3727+ *
3728+ * Authors: Michi Henning <michi.henning@canonical.com>
3729+ */
3730+
3731+#include <unity/storage/qt/internal/ItemJobImpl.h>
3732+
3733+#include <unity/storage/internal/dbusmarshal.h>
3734+#include <unity/storage/internal/ItemMetadata.h>
3735+#include <unity/storage/qt/internal/Handler.h>
3736+#include <unity/storage/qt/internal/ItemImpl.h>
3737+
3738+using namespace std;
3739+
3740+namespace unity
3741+{
3742+namespace storage
3743+{
3744+namespace qt
3745+{
3746+namespace internal
3747+{
3748+
3749+ItemJobImpl::ItemJobImpl(shared_ptr<AccountImpl> const& account,
3750+ QString const& method,
3751+ QDBusPendingReply<storage::internal::ItemMetadata> const& reply,
3752+ std::function<void(storage::internal::ItemMetadata const&)> const& validate)
3753+ : status_(ItemJob::Loading)
3754+ , method_(method)
3755+ , account_(account)
3756+ , validate_(validate)
3757+{
3758+ assert(!method.isEmpty());
3759+ assert(account);
3760+ assert(validate);
3761+
3762+ auto process_reply = [this](decltype(reply)& r)
3763+ {
3764+ auto metadata = r.value();
3765+ try
3766+ {
3767+ validate_(metadata);
3768+ item_ = ItemImpl::make_item(method_, metadata, account_);
3769+ status_ = emit_status_changed(ItemJob::Finished);
3770+ }
3771+ catch (StorageError const& e)
3772+ {
3773+ // Bad metadata received from provider, validate_() or make_item() have logged it.
3774+ error_ = e;
3775+ status_ = emit_status_changed(ItemJob::Error);
3776+ }
3777+ };
3778+
3779+ auto process_error = [this](StorageError const& error)
3780+ {
3781+ error_ = error;
3782+ status_ = emit_status_changed(ItemJob::Error);
3783+ };
3784+
3785+ new Handler<storage::internal::ItemMetadata>(this, reply, process_reply, process_error);
3786+}
3787+
3788+ItemJobImpl::ItemJobImpl(StorageError const& error)
3789+ : status_(ItemJob::Loading)
3790+ , error_(error)
3791+{
3792+}
3793+
3794+bool ItemJobImpl::isValid() const
3795+{
3796+ return status_ != ItemJob::Status::Error;
3797+}
3798+
3799+ItemJob::Status ItemJobImpl::status() const
3800+{
3801+ return status_;
3802+}
3803+
3804+StorageError ItemJobImpl::error() const
3805+{
3806+ return error_;
3807+}
3808+
3809+Item ItemJobImpl::item() const
3810+{
3811+ return Item(); // TODO
3812+}
3813+
3814+ItemJob* ItemJobImpl::make_item_job(shared_ptr<AccountImpl> const& account,
3815+ QString const& method,
3816+ QDBusPendingReply<storage::internal::ItemMetadata> const& reply,
3817+ std::function<void(storage::internal::ItemMetadata const&)> const& validate)
3818+{
3819+ unique_ptr<ItemJobImpl> impl(new ItemJobImpl(account, method, reply, validate));
3820+ auto job = new ItemJob(move(impl));
3821+ job->p_->public_instance_ = job;
3822+ return job;
3823+}
3824+
3825+ItemJob* ItemJobImpl::make_item_job(StorageError const& error)
3826+{
3827+ unique_ptr<ItemJobImpl> impl(new ItemJobImpl(error));
3828+ auto job = new ItemJob(move(impl));
3829+ job->p_->public_instance_ = job;
3830+ job->p_->status_ = job->p_->emit_status_changed(ItemJob::Error);
3831+ return job;
3832+}
3833+
3834+ItemJob::Status ItemJobImpl::emit_status_changed(ItemJob::Status new_status) const
3835+{
3836+ // TODO: should be an assert!
3837+ if (status_ == ItemJob::Loading) // Once in a final state, we don't emit the signal again.
3838+ {
3839+ QMetaObject::invokeMethod(public_instance_,
3840+ "statusChanged",
3841+ Qt::QueuedConnection,
3842+ Q_ARG(unity::storage::qt::ItemJob::Status, new_status));
3843+ }
3844+ return new_status;
3845+}
3846+
3847+} // namespace internal
3848+} // namespace qt
3849+} // namespace storage
3850+} // namespace unity
3851
3852=== added file 'src/qt/internal/ItemListJobImpl.cpp'
3853--- src/qt/internal/ItemListJobImpl.cpp 1970-01-01 00:00:00 +0000
3854+++ src/qt/internal/ItemListJobImpl.cpp 2016-09-21 05:03:46 +0000
3855@@ -0,0 +1,148 @@
3856+/*
3857+ * Copyright (C) 2016 Canonical Ltd
3858+ *
3859+ * This program is free software: you can redistribute it and/or modify
3860+ * it under the terms of the GNU Lesser General Public License version 3 as
3861+ * published by the Free Software Foundation.
3862+ *
3863+ * This program is distributed in the hope that it will be useful,
3864+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
3865+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
3866+ * GNU Lesser General Public License for more details.
3867+ *
3868+ * You should have received a copy of the GNU Lesser General Public License
3869+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
3870+ *
3871+ * Authors: Michi Henning <michi.henning@canonical.com>
3872+ */
3873+
3874+#include <unity/storage/qt/internal/ItemListJobImpl.h>
3875+
3876+#include <unity/storage/internal/dbusmarshal.h>
3877+#include <unity/storage/internal/ItemMetadata.h>
3878+#include <unity/storage/qt/internal/Handler.h>
3879+#include <unity/storage/qt/internal/ItemImpl.h>
3880+
3881+using namespace std;
3882+
3883+namespace unity
3884+{
3885+namespace storage
3886+{
3887+namespace qt
3888+{
3889+namespace internal
3890+{
3891+
3892+ItemListJobImpl::ItemListJobImpl(shared_ptr<AccountImpl> const& account,
3893+ QString const& method,
3894+ QDBusPendingReply<QList<storage::internal::ItemMetadata>> const& reply,
3895+ std::function<void(storage::internal::ItemMetadata const&)> const& validate)
3896+ : status_(ItemListJob::Loading)
3897+ , method_(method)
3898+ , account_(account)
3899+ , validate_(validate)
3900+{
3901+ assert(!method.isEmpty());
3902+ assert(account);
3903+ assert(validate);
3904+
3905+ auto process_reply = [this](decltype(reply)& r)
3906+ {
3907+ QList<Item> items;
3908+ auto metadata = r.value();
3909+ for (auto const& md : metadata)
3910+ {
3911+ try
3912+ {
3913+ validate_(md);
3914+ auto item = ItemImpl::make_item(method_, md, account_);
3915+ items.append(item);
3916+ }
3917+ catch (StorageError const&)
3918+ {
3919+ // Bad metadata received from provider, validate_() or make_item() have logged it.
3920+ }
3921+ }
3922+ emit_items_ready(items);
3923+ status_ = emit_status_changed(ItemListJob::Finished);
3924+ };
3925+
3926+ auto process_error = [this](StorageError const& error)
3927+ {
3928+ error_ = error;
3929+ status_ = emit_status_changed(ItemListJob::Error);
3930+ };
3931+
3932+ new Handler<QList<storage::internal::ItemMetadata>>(this, reply, process_reply, process_error);
3933+}
3934+
3935+ItemListJobImpl::ItemListJobImpl(StorageError const& error)
3936+ : status_(ItemListJob::Loading)
3937+ , error_(error)
3938+{
3939+}
3940+
3941+bool ItemListJobImpl::isValid() const
3942+{
3943+ return status_ != ItemListJob::Status::Error;
3944+}
3945+
3946+ItemListJob::Status ItemListJobImpl::status() const
3947+{
3948+ return status_;
3949+}
3950+
3951+StorageError ItemListJobImpl::error() const
3952+{
3953+ return error_;
3954+}
3955+
3956+ItemListJob* ItemListJobImpl::make_item_list_job(
3957+ shared_ptr<AccountImpl> const& account,
3958+ QString const& method,
3959+ QDBusPendingReply<QList<storage::internal::ItemMetadata>> const& reply,
3960+ std::function<void(storage::internal::ItemMetadata const&)> const& validate)
3961+{
3962+ unique_ptr<ItemListJobImpl> impl(new ItemListJobImpl(account, method, reply, validate));
3963+ auto job = new ItemListJob(move(impl));
3964+ job->p_->public_instance_ = job;
3965+ return job;
3966+}
3967+
3968+ItemListJob* ItemListJobImpl::make_item_list_job(StorageError const& error)
3969+{
3970+ unique_ptr<ItemListJobImpl> impl(new ItemListJobImpl(error));
3971+ auto job = new ItemListJob(move(impl));
3972+ job->p_->public_instance_ = job;
3973+ job->p_->status_ = job->p_->emit_status_changed(ItemListJob::Error);
3974+ return job;
3975+}
3976+
3977+ItemListJob::Status ItemListJobImpl::emit_status_changed(ItemListJob::Status new_status) const
3978+{
3979+ // TODO: use assert
3980+ if (status_ == ItemListJob::Loading) // Once in a final state, we don't emit the signal again.
3981+ {
3982+ // We defer emission of the signal so the client gets a chance to connect to the signal
3983+ // in case we emit the signal from the constructor.
3984+ QMetaObject::invokeMethod(public_instance_,
3985+ "statusChanged",
3986+ Qt::QueuedConnection,
3987+ Q_ARG(unity::storage::qt::ItemListJob::Status, new_status));
3988+ }
3989+ return new_status;
3990+}
3991+
3992+void ItemListJobImpl::emit_items_ready(QList<Item> const& items) const
3993+{
3994+ QMetaObject::invokeMethod(public_instance_,
3995+ "itemsReady",
3996+ Qt::QueuedConnection,
3997+ Q_ARG(QList<unity::storage::qt::Item>, items));
3998+}
3999+
4000+} // namespace internal
4001+} // namespace qt
4002+} // namespace storage
4003+} // namespace unity
4004
4005=== added file 'src/qt/internal/RuntimeImpl.cpp'
4006--- src/qt/internal/RuntimeImpl.cpp 1970-01-01 00:00:00 +0000
4007+++ src/qt/internal/RuntimeImpl.cpp 2016-09-21 05:03:46 +0000
4008@@ -0,0 +1,168 @@
4009+/*
4010+ * Copyright (C) 2016 Canonical Ltd
4011+ *
4012+ * This program is free software: you can redistribute it and/or modify
4013+ * it under the terms of the GNU Lesser General Public License version 3 as
4014+ * published by the Free Software Foundation.
4015+ *
4016+ * This program is distributed in the hope that it will be useful,
4017+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
4018+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
4019+ * GNU Lesser General Public License for more details.
4020+ *
4021+ * You should have received a copy of the GNU Lesser General Public License
4022+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
4023+ *
4024+ * Authors: Michi Henning <michi.henning@canonical.com>
4025+ */
4026+
4027+#include <unity/storage/qt/internal/RuntimeImpl.h>
4028+
4029+#include <unity/storage/internal/dbusmarshal.h>
4030+#include <unity/storage/qt/AccountsJob.h>
4031+#include <unity/storage/qt/internal/AccountImpl.h>
4032+#include <unity/storage/qt/internal/StorageErrorImpl.h>
4033+#include <unity/storage/qt/Item.h>
4034+#include <unity/storage/qt/ItemJob.h>
4035+#include <unity/storage/qt/ItemListJob.h>
4036+#include <unity/storage/qt/Runtime.h>
4037+
4038+#include <QDBusError>
4039+#include <QDBusMetaType>
4040+
4041+using namespace std;
4042+
4043+namespace unity
4044+{
4045+namespace storage
4046+{
4047+namespace qt
4048+{
4049+namespace internal
4050+{
4051+namespace
4052+{
4053+
4054+void register_meta_types()
4055+{
4056+ qRegisterMetaType<unity::storage::qt::AccountsJob::Status>();
4057+ qRegisterMetaType<unity::storage::qt::Item>();
4058+ qRegisterMetaType<QList<unity::storage::qt::Item>>();
4059+ qRegisterMetaType<unity::storage::qt::ItemJob::Status>();
4060+ qRegisterMetaType<unity::storage::qt::ItemListJob::Status>();
4061+
4062+ qDBusRegisterMetaType<unity::storage::internal::ItemMetadata>();
4063+ qDBusRegisterMetaType<QList<unity::storage::internal::ItemMetadata>>();
4064+}
4065+
4066+}
4067+
4068+// TODO: chain the two constructors.
4069+RuntimeImpl::RuntimeImpl()
4070+ : is_valid_(true)
4071+ , conn_(QDBusConnection::sessionBus())
4072+ , accounts_manager_(new OnlineAccounts::Manager("", conn_))
4073+{
4074+ register_meta_types();
4075+
4076+#if 0
4077+ if (!conn_.isConnected())
4078+ {
4079+ // LCOV_EXCL_START
4080+ is_valid_ = false;
4081+ QString msg = "Runtime(): cannot connect to session bus: " + conn_.lastError().message();
4082+ error_ = StorageErrorImpl::local_comms_error(msg);
4083+ // LCOV_EXCL_STOP
4084+ }
4085+#endif
4086+}
4087+
4088+RuntimeImpl::RuntimeImpl(QDBusConnection const& bus)
4089+ : is_valid_(true)
4090+ , conn_(bus)
4091+ , accounts_manager_(new OnlineAccounts::Manager("", conn_))
4092+{
4093+ register_meta_types();
4094+
4095+#if 0
4096+ if (!conn_.isConnected())
4097+ {
4098+ is_valid_ = false;
4099+ QString msg = "Runtime(): DBus connection is not connected";
4100+ error_ = StorageErrorImpl::local_comms_error(msg);
4101+ }
4102+#endif
4103+}
4104+
4105+RuntimeImpl::~RuntimeImpl()
4106+{
4107+ shutdown();
4108+}
4109+
4110+bool RuntimeImpl::isValid() const
4111+{
4112+ return is_valid_;
4113+}
4114+
4115+StorageError RuntimeImpl::error() const
4116+{
4117+ return error_;
4118+}
4119+
4120+QDBusConnection RuntimeImpl::connection() const
4121+{
4122+ return conn_;
4123+}
4124+
4125+AccountsJob* RuntimeImpl::accounts() const
4126+{
4127+ if (!is_valid_)
4128+ {
4129+ QString msg = "Runtime::accounts(): Runtime was destroyed previously";
4130+ return new AccountsJob(StorageErrorImpl::runtime_destroyed_error(msg));
4131+ }
4132+ auto This = const_cast<RuntimeImpl*>(this);
4133+ return new AccountsJob(This->shared_from_this());
4134+}
4135+
4136+StorageError RuntimeImpl::shutdown()
4137+{
4138+ if (is_valid_)
4139+ {
4140+ conn_.disconnectFromBus(conn_.name());
4141+ is_valid_ = false;
4142+ return StorageError();
4143+ }
4144+ error_ = StorageErrorImpl::runtime_destroyed_error("Runtime::shutdown(): Runtime was destroyed previously");
4145+ return error_;
4146+}
4147+
4148+shared_ptr<OnlineAccounts::Manager> RuntimeImpl::accounts_manager() const
4149+{
4150+ return accounts_manager_;
4151+}
4152+
4153+Account RuntimeImpl::make_test_account(QString const& bus_name,
4154+ QString const& object_path)
4155+{
4156+ return make_test_account(bus_name, object_path, "", "", "");
4157+}
4158+
4159+Account RuntimeImpl::make_test_account(QString const& bus_name,
4160+ QString const& object_path,
4161+ QString const& owner_id,
4162+ QString const& owner,
4163+ QString const& description)
4164+{
4165+ return AccountImpl::make_account(shared_from_this(),
4166+ bus_name,
4167+ object_path,
4168+ owner_id,
4169+ owner,
4170+ description);
4171+}
4172+
4173+} // namespace internal
4174+} // namespace qt
4175+} // namespace storage
4176+} // namespace unity
4177
4178=== added file 'src/qt/internal/StorageErrorImpl.cpp'
4179--- src/qt/internal/StorageErrorImpl.cpp 1970-01-01 00:00:00 +0000
4180+++ src/qt/internal/StorageErrorImpl.cpp 2016-09-21 05:03:46 +0000
4181@@ -0,0 +1,230 @@
4182+/*
4183+ * Copyright (C) 2016 Canonical Ltd
4184+ *
4185+ * This program is free software: you can redistribute it and/or modify
4186+ * it under the terms of the GNU Lesser General Public License version 3 as
4187+ * published by the Free Software Foundation.
4188+ *
4189+ * This program is distributed in the hope that it will be useful,
4190+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
4191+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
4192+ * GNU Lesser General Public License for more details.
4193+ *
4194+ * You should have received a copy of the GNU Lesser General Public License
4195+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
4196+ *
4197+ * Authors: Michi Henning <michi.henning@canonical.com>
4198+ */
4199+
4200+#include <unity/storage/qt/internal/StorageErrorImpl.h>
4201+
4202+#include <cassert>
4203+#include <memory>
4204+
4205+using namespace std;
4206+
4207+namespace unity
4208+{
4209+namespace storage
4210+{
4211+namespace qt
4212+{
4213+namespace internal
4214+{
4215+
4216+namespace
4217+{
4218+
4219+static char const * const ERROR_NAMES[StorageError::__LAST_STORAGE_ERROR] =
4220+{
4221+ "NoError", "LocalCommsError", "RemoteCommsError", "Deleted", "RuntimeDestroyed", "NotExists",
4222+ "Exists", "Conflict", "PermissionDenied", "Cancelled", "LogicError", "InvalidArgument", "ResourceError"
4223+};
4224+
4225+} // namespace
4226+
4227+StorageErrorImpl::StorageErrorImpl()
4228+ : type_(StorageError::Type::NoError)
4229+ , name_(ERROR_NAMES[type_])
4230+ , message_("No error")
4231+ , error_code_(0)
4232+{
4233+}
4234+
4235+StorageErrorImpl::StorageErrorImpl(StorageError::Type type, QString const& msg)
4236+ : type_(type)
4237+ , name_(ERROR_NAMES[type_])
4238+ , message_(msg)
4239+ , error_code_(0)
4240+{
4241+ assert( type == StorageError::Type::LocalCommsError
4242+ || type == StorageError::Type::RemoteCommsError
4243+ || type == StorageError::Type::RuntimeDestroyed
4244+ || type == StorageError::Type::Conflict
4245+ || type == StorageError::Type::PermissionDenied
4246+ || type == StorageError::Type::Cancelled
4247+ || type == StorageError::Type::LogicError
4248+ || type == StorageError::Type::InvalidArgument);
4249+ assert(!msg.isEmpty());
4250+}
4251+
4252+StorageErrorImpl::StorageErrorImpl(StorageError::Type type, QString const& msg, QString const& key)
4253+ : type_(type)
4254+ , name_(ERROR_NAMES[type_])
4255+ , message_(msg)
4256+ , error_code_(0)
4257+{
4258+ assert( type == StorageError::Type::Deleted
4259+ || type == StorageError::Type::NotExists);
4260+ assert(!msg.isEmpty());
4261+
4262+ item_id_ = key;
4263+ if (type == StorageError::Type::NotExists)
4264+ {
4265+ item_name_ = key;
4266+ }
4267+}
4268+
4269+StorageErrorImpl::StorageErrorImpl(StorageError::Type type,
4270+ QString const& msg,
4271+ QString const& item_id,
4272+ QString const& item_name)
4273+ : type_(type)
4274+ , name_(ERROR_NAMES[type_])
4275+ , message_(msg)
4276+ , item_id_(item_id)
4277+ , item_name_(item_name)
4278+ , error_code_(0)
4279+{
4280+ assert(type == StorageError::Type::Exists);
4281+ assert(!msg.isEmpty());
4282+ assert(!item_id.isEmpty());
4283+ assert(!item_name.isEmpty());
4284+}
4285+
4286+StorageErrorImpl::StorageErrorImpl(StorageError::Type type, QString const& msg, int error_code)
4287+ : type_(type)
4288+ , message_(msg)
4289+ , error_code_(error_code)
4290+{
4291+ assert(type == StorageError::Type::ResourceError);
4292+ assert(!msg.isEmpty());
4293+}
4294+
4295+StorageError::Type StorageErrorImpl::type() const
4296+{
4297+ return type_;
4298+}
4299+
4300+QString StorageErrorImpl::name() const
4301+{
4302+ return name_;
4303+}
4304+
4305+QString StorageErrorImpl::message() const
4306+{
4307+ return message_;
4308+}
4309+
4310+QString StorageErrorImpl::errorString() const
4311+{
4312+ return name_ + ": " + message_;
4313+}
4314+
4315+QString StorageErrorImpl::itemId() const
4316+{
4317+ return item_id_;
4318+}
4319+
4320+QString StorageErrorImpl::itemName() const
4321+{
4322+ return item_name_;
4323+}
4324+
4325+int StorageErrorImpl::errorCode() const
4326+{
4327+ return error_code_;
4328+}
4329+
4330+StorageError StorageErrorImpl::make_error(StorageError::Type type, QString const& msg)
4331+{
4332+ unique_ptr<StorageErrorImpl> p(new StorageErrorImpl(type, msg));
4333+ return StorageError(move(p));
4334+}
4335+
4336+StorageError StorageErrorImpl::local_comms_error(QString const& msg)
4337+{
4338+ unique_ptr<StorageErrorImpl> p(new StorageErrorImpl(StorageError::Type::LocalCommsError, msg));
4339+ return StorageError(move(p));
4340+}
4341+
4342+StorageError StorageErrorImpl::remote_comms_error(QString const& msg)
4343+{
4344+ unique_ptr<StorageErrorImpl> p(new StorageErrorImpl(StorageError::Type::RemoteCommsError, msg));
4345+ return StorageError(move(p));
4346+}
4347+
4348+StorageError StorageErrorImpl::deleted_error(QString const& msg, QString const& item_id)
4349+{
4350+ unique_ptr<StorageErrorImpl> p(new StorageErrorImpl(StorageError::Type::Deleted, msg, item_id));
4351+ return StorageError(move(p));
4352+}
4353+
4354+StorageError StorageErrorImpl::runtime_destroyed_error(QString const& msg)
4355+{
4356+ unique_ptr<StorageErrorImpl> p(new StorageErrorImpl(StorageError::Type::RuntimeDestroyed, msg));
4357+ return StorageError(move(p));
4358+}
4359+
4360+StorageError StorageErrorImpl::not_exists_error(QString const& msg, QString const& key)
4361+{
4362+ unique_ptr<StorageErrorImpl> p(new StorageErrorImpl(StorageError::Type::NotExists, msg, key));
4363+ return StorageError(move(p));
4364+}
4365+
4366+StorageError StorageErrorImpl::exists_error(QString const& msg, QString const& item_id, QString const& item_name)
4367+{
4368+ unique_ptr<StorageErrorImpl> p(new StorageErrorImpl(StorageError::Type::Exists, msg, item_id, item_name));
4369+ return StorageError(move(p));
4370+}
4371+
4372+StorageError StorageErrorImpl::conflict_error(QString const& msg)
4373+{
4374+ unique_ptr<StorageErrorImpl> p(new StorageErrorImpl(StorageError::Type::Conflict, msg));
4375+ return StorageError(move(p));
4376+}
4377+
4378+StorageError StorageErrorImpl::permission_error(QString const& msg)
4379+{
4380+ unique_ptr<StorageErrorImpl> p(new StorageErrorImpl(StorageError::Type::PermissionDenied, msg));
4381+ return StorageError(move(p));
4382+}
4383+
4384+StorageError StorageErrorImpl::cancelled_error(QString const& msg)
4385+{
4386+ unique_ptr<StorageErrorImpl> p(new StorageErrorImpl(StorageError::Type::Cancelled, msg));
4387+ return StorageError(move(p));
4388+}
4389+
4390+StorageError StorageErrorImpl::logic_error(QString const& msg)
4391+{
4392+ unique_ptr<StorageErrorImpl> p(new StorageErrorImpl(StorageError::Type::LogicError, msg));
4393+ return StorageError(move(p));
4394+}
4395+
4396+StorageError StorageErrorImpl::invalid_argument_error(QString const& msg)
4397+{
4398+ unique_ptr<StorageErrorImpl> p(new StorageErrorImpl(StorageError::Type::InvalidArgument, msg));
4399+ return StorageError(move(p));
4400+}
4401+
4402+StorageError StorageErrorImpl::resource_error(QString const& msg, int error_code)
4403+{
4404+ unique_ptr<StorageErrorImpl> p(new StorageErrorImpl(StorageError::Type::ResourceError, msg, error_code));
4405+ return StorageError(move(p));
4406+}
4407+
4408+} // namespace internal
4409+} // namespace qt
4410+} // namespace storage
4411+} // namespace unity
4412
4413=== added file 'src/qt/internal/unmarshal_error.cpp'
4414--- src/qt/internal/unmarshal_error.cpp 1970-01-01 00:00:00 +0000
4415+++ src/qt/internal/unmarshal_error.cpp 2016-09-21 05:03:46 +0000
4416@@ -0,0 +1,131 @@
4417+/*
4418+ * Copyright (C) 2016 Canonical Ltd
4419+ *
4420+ * This program is free software: you can redistribute it and/or modify
4421+ * it under the terms of the GNU Lesser General Public License version 3 as
4422+ * published by the Free Software Foundation.
4423+ *
4424+ * This program is distributed in the hope that it will be useful,
4425+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
4426+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
4427+ * GNU Lesser General Public License for more details.
4428+ *
4429+ * You should have received a copy of the GNU Lesser General Public License
4430+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
4431+ *
4432+ * Authors: Michi Henning <michi.henning@canonical.com>
4433+ */
4434+
4435+#include <unity/storage/qt/internal/unmarshal_error.h>
4436+
4437+#include <unity/storage/internal/dbus_error.h>
4438+#include <unity/storage/qt/internal/StorageErrorImpl.h>
4439+
4440+#include <QDBusPendingReply>
4441+
4442+#include <cassert>
4443+#include <map>
4444+
4445+using namespace unity::storage::internal;
4446+using namespace std;
4447+
4448+namespace unity
4449+{
4450+namespace storage
4451+{
4452+namespace qt
4453+{
4454+namespace internal
4455+{
4456+namespace
4457+{
4458+
4459+template<StorageError::Type T>
4460+StorageError make_error(QDBusPendingCallWatcher const& call)
4461+{
4462+ QDBusPendingReply<QString> reply = call;
4463+ auto msg = reply.argumentAt<0>();
4464+ return StorageErrorImpl::make_error(T, msg);
4465+}
4466+
4467+template<>
4468+StorageError make_error<StorageError::NotExists>(QDBusPendingCallWatcher const& call)
4469+{
4470+ QDBusPendingReply<QString, QString> reply = call;
4471+ auto msg = reply.argumentAt<0>();
4472+ auto key = reply.argumentAt<1>();
4473+ return StorageErrorImpl::not_exists_error(msg, key);
4474+}
4475+
4476+template<>
4477+StorageError make_error<StorageError::Exists>(QDBusPendingCallWatcher const& call)
4478+{
4479+ QDBusPendingReply<QString, QString, QString> reply = call;
4480+ auto msg = reply.argumentAt<0>();
4481+ auto id = reply.argumentAt<1>();
4482+ auto name = reply.argumentAt<2>();
4483+ return StorageErrorImpl::exists_error(msg, id, name);
4484+}
4485+
4486+template<>
4487+StorageError make_error<StorageError::ResourceError>(QDBusPendingCallWatcher const& call)
4488+{
4489+ QDBusPendingReply<QString, int> reply = call;
4490+ auto msg = reply.argumentAt<0>();
4491+ auto error_code = reply.argumentAt<1>();
4492+ return StorageErrorImpl::resource_error(msg, error_code);
4493+}
4494+
4495+static const map<QString, function<StorageError(QDBusPendingCallWatcher const& call)>> exception_factories =
4496+{
4497+ { "RemoteCommsException", make_error<StorageError::RemoteCommsError> },
4498+ { "NotExistsException", make_error<StorageError::NotExists> },
4499+ { "ExistsException", make_error<StorageError::Exists> },
4500+ { "ConflictException", make_error<StorageError::Conflict> },
4501+ { "PermissionException", make_error<StorageError::PermissionDenied> },
4502+ { "CancelledException", make_error<StorageError::Cancelled> },
4503+ { "LogicException", make_error<StorageError::LogicError> },
4504+ { "InvalidArgumentException", make_error<StorageError::InvalidArgument> },
4505+ { "ResourceException", make_error<StorageError::ResourceError> },
4506+ { "QuotaException", make_error<StorageError::QuotaExceeded> },
4507+ { "UnknownException", make_error<StorageError::LocalCommsError> } // Yes, LocalCommsError is intentional
4508+};
4509+
4510+} // namespace
4511+
4512+StorageError unmarshal_error(QDBusPendingCallWatcher const& call)
4513+{
4514+ assert(call.isError());
4515+
4516+ int err = call.error().type();
4517+ if (err != QDBusError::Other)
4518+ {
4519+ // Some DBus error that doesn't represent a StorageError.
4520+ return StorageErrorImpl::local_comms_error(call.error().message());
4521+ }
4522+
4523+ auto exception_type = call.error().name();
4524+ if (!exception_type.startsWith(DBUS_ERROR_PREFIX))
4525+ {
4526+ // Some error with the wrong prefix (should never happen unless the server is broken).
4527+ QString msg = "unmarshal_exception(): unknown exception type received from server: " + exception_type
4528+ + ": " + call.error().message();
4529+ return StorageErrorImpl::local_comms_error(msg);
4530+ }
4531+ exception_type = exception_type.remove(0, strlen(DBUS_ERROR_PREFIX));
4532+
4533+ auto factory_it = exception_factories.find(exception_type);
4534+ if (factory_it == exception_factories.end())
4535+ {
4536+ // Some StorageError that we don't recognize.
4537+ QString msg = "unmarshal_exception(): unknown exception type received from server: " + exception_type
4538+ + ": " + call.error().message();
4539+ return StorageErrorImpl::local_comms_error(msg);
4540+ }
4541+ return factory_it->second(call);
4542+}
4543+
4544+} // namespace internal
4545+} // namespace qt
4546+} // namespace storage
4547+} // namespace unity
4548
4549=== added file 'src/qt/internal/validate.cpp'
4550--- src/qt/internal/validate.cpp 1970-01-01 00:00:00 +0000
4551+++ src/qt/internal/validate.cpp 2016-09-21 05:03:46 +0000
4552@@ -0,0 +1,170 @@
4553+/*
4554+ * Copyright (C) 2016 Canonical Ltd
4555+ *
4556+ * This program is free software: you can redistribute it and/or modify
4557+ * it under the terms of the GNU Lesser General Public License version 3 as
4558+ * published by the Free Software Foundation.
4559+ *
4560+ * This program is distributed in the hope that it will be useful,
4561+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
4562+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
4563+ * GNU Lesser General Public License for more details.
4564+ *
4565+ * You should have received a copy of the GNU Lesser General Public License
4566+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
4567+ *
4568+ * Authors: Michi Henning <michi.henning@canonical.com>
4569+ */
4570+
4571+#include <unity/storage/qt/internal/validate.h>
4572+
4573+#include <unity/storage/internal/ItemMetadata.h>
4574+#include <unity/storage/provider/metadata_keys.h>
4575+#include <unity/storage/qt/internal/StorageErrorImpl.h>
4576+
4577+#include <QDateTime>
4578+#include <QDebug>
4579+#include <QString>
4580+
4581+using namespace unity::storage::internal;
4582+using namespace std;
4583+
4584+namespace unity
4585+{
4586+namespace storage
4587+{
4588+namespace qt
4589+{
4590+namespace internal
4591+{
4592+
4593+namespace
4594+{
4595+
4596+// Check that actual type and value match the expect type and value for a particular metadata entry.
4597+
4598+void validate_type_and_value(QString const& prefix,
4599+ QMapIterator<QString, QVariant> actual,
4600+ unordered_map<string, provider::MetadataType>::const_iterator known)
4601+{
4602+ using namespace unity::storage::provider;
4603+
4604+ switch (known->second)
4605+ {
4606+ case MetadataType::iso_8601_date_time:
4607+ {
4608+ if (actual.value().type() != QVariant::String)
4609+ {
4610+ QString msg = prefix + actual.key() + ": expected value of type String, but received value of type "
4611+ + actual.value().typeName();
4612+ throw StorageErrorImpl::local_comms_error(msg);
4613+ }
4614+ QDateTime dt = QDateTime::fromString(actual.value().toString(), Qt::ISODate);
4615+ if (!dt.isValid())
4616+ {
4617+ QString msg = prefix + actual.key() + ": value \"" + actual.value().toString()
4618+ + "\" does not parse as ISO-8601 date";
4619+ throw StorageErrorImpl::local_comms_error(msg);
4620+ }
4621+ auto timespec = dt.timeSpec();
4622+ if (timespec == Qt::LocalTime)
4623+ {
4624+ QString msg = prefix + actual.key() + ": value \"" + actual.value().toString()
4625+ + "\" lacks a time zone specification";
4626+ throw StorageErrorImpl::local_comms_error(msg);
4627+ }
4628+ break;
4629+ }
4630+ case MetadataType::int64:
4631+ {
4632+ if (actual.value().type() != QVariant::LongLong)
4633+ {
4634+ QString msg = prefix + actual.key() + ": expected value of type LongLong, but received value of type "
4635+ + actual.value().typeName();
4636+ throw StorageErrorImpl::local_comms_error(msg);
4637+ }
4638+ break;
4639+ }
4640+ default:
4641+ {
4642+ abort(); // Impossible. // LCOV_EXCL_LINE
4643+ }
4644+ }
4645+}
4646+
4647+} // namespace
4648+
4649+void validate(QString const& method, ItemMetadata const& md)
4650+{
4651+ using namespace unity::storage::provider;
4652+
4653+ QString prefix = method + ": received invalid metadata from provider: ";
4654+
4655+ // Basic sanity checks for mandatory fields.
4656+ if (md.item_id.isEmpty())
4657+ {
4658+ throw StorageErrorImpl::local_comms_error(prefix + "item_id cannot be empty");
4659+ }
4660+ if (md.type != ItemType::root)
4661+ {
4662+ if (md.parent_ids.isEmpty())
4663+ {
4664+ throw StorageErrorImpl::local_comms_error(prefix + "file or folder must have at least one parent ID");
4665+ }
4666+ for (int i = 0; i < md.parent_ids.size(); ++i)
4667+ {
4668+ if (md.parent_ids.at(i).isEmpty())
4669+ {
4670+ throw StorageErrorImpl::local_comms_error(prefix + "parent_id of file or folder cannot be empty");
4671+ }
4672+ }
4673+ }
4674+ if (md.type == ItemType::root && !md.parent_ids.isEmpty())
4675+ {
4676+ throw StorageErrorImpl::local_comms_error(prefix + "metadata: parent_ids of root must be empty");
4677+ }
4678+ if (md.name.isEmpty())
4679+ {
4680+ throw StorageErrorImpl::local_comms_error(prefix + "name cannot be empty");
4681+ }
4682+ if (md.etag.isEmpty())
4683+ {
4684+ throw StorageErrorImpl::local_comms_error(prefix + "etag cannot be empty");
4685+ }
4686+
4687+ // Sanity check metadata to make sure only known metadata keys appear.
4688+ QMapIterator<QString, QVariant> actual(md.metadata);
4689+ while (actual.hasNext())
4690+ {
4691+ actual.next();
4692+ auto known = known_metadata.find(actual.key().toStdString());
4693+ if (known == known_metadata.end())
4694+ {
4695+ qWarning() << prefix << "unknown metadata key:" << actual.key();
4696+ }
4697+ else
4698+ {
4699+ validate_type_and_value(prefix, actual, known);
4700+ }
4701+ }
4702+
4703+ // Sanity check metadata to make sure that mandatory fields are present.
4704+ if (md.type == ItemType::file)
4705+ {
4706+ if (!md.metadata.contains(SIZE_IN_BYTES))
4707+ {
4708+ QString msg = prefix + "missing key " + SIZE_IN_BYTES + " in metadata for " + md.item_id;
4709+ throw StorageErrorImpl::local_comms_error(msg);
4710+ }
4711+ if (!md.metadata.contains(LAST_MODIFIED_TIME))
4712+ {
4713+ QString msg = prefix + "missing key " + LAST_MODIFIED_TIME + " in metadata for " + md.item_id;
4714+ throw StorageErrorImpl::local_comms_error(msg);
4715+ }
4716+ }
4717+}
4718+
4719+} // namespace internal
4720+} // namespace qt
4721+} // namespace storage
4722+} // namespace unity
4723
4724=== renamed file 'src/qt/client/storage-framework-qt-client.pc.in' => 'src/qt/storage-framework-qt-client.pc.in'
4725=== modified file 'tests/CMakeLists.txt'
4726--- tests/CMakeLists.txt 2016-08-11 04:20:06 +0000
4727+++ tests/CMakeLists.txt 2016-09-21 05:03:46 +0000
4728@@ -14,6 +14,7 @@
4729 set(unit_test_dirs
4730 local-client
4731 remote-client
4732+ remote-client-v1
4733 provider-AccountData
4734 provider-DBusPeerCache
4735 provider-ProviderInterface
4736
4737=== modified file 'tests/headers/CMakeLists.txt'
4738--- tests/headers/CMakeLists.txt 2016-08-22 04:35:33 +0000
4739+++ tests/headers/CMakeLists.txt 2016-09-21 05:03:46 +0000
4740@@ -7,6 +7,7 @@
4741 set(subdirs
4742 unity/storage
4743 unity/storage/provider
4744+ unity/storage/qt
4745 unity/storage/qt/client
4746 unity/storage/qt/client/internal/local_client
4747 unity/storage/qt/client/internal/remote_client
4748
4749=== added directory 'tests/remote-client'
4750=== renamed directory 'tests/remote-client' => 'tests/remote-client-v1'
4751=== modified file 'tests/remote-client-v1/CMakeLists.txt'
4752--- tests/remote-client/CMakeLists.txt 2016-08-18 04:54:24 +0000
4753+++ tests/remote-client-v1/CMakeLists.txt 2016-09-21 05:03:46 +0000
4754@@ -1,10 +1,10 @@
4755-add_executable(remote-client_test remote-client_test.cpp MockProvider.cpp)
4756-set_target_properties(remote-client_test PROPERTIES AUTOMOC TRUE)
4757+add_executable(remote-client-v1_test remote-client-v1_test.cpp MockProvider.cpp)
4758+set_target_properties(remote-client-v1_test PROPERTIES AUTOMOC TRUE)
4759
4760 add_definitions(-DTEST_DIR="${CMAKE_CURRENT_BINARY_DIR}" -DBOOST_THREAD_VERSION=4)
4761 include_directories(${GLIB_DEPS_INCLUDE_DIRS})
4762
4763-target_link_libraries(remote-client_test
4764+target_link_libraries(remote-client-v1_test
4765 storage-framework-provider
4766 storage-framework-qt-client
4767 Qt5::Network
4768@@ -14,7 +14,7 @@
4769 testutils
4770 gtest
4771 )
4772-add_test(remote-client remote-client_test)
4773-add_dependencies(remote-client_test qt-client-all-headers provider-test)
4774+add_test(remote-client-v1 remote-client-v1_test)
4775+add_dependencies(remote-client-v1_test qt-client-all-headers provider-test)
4776
4777 set(UNIT_TEST_TARGETS ${UNIT_TEST_TARGETS} PARENT_SCOPE)
4778
4779=== renamed file 'tests/remote-client/remote-client_test.cpp' => 'tests/remote-client-v1/remote-client-v1_test.cpp'
4780--- tests/remote-client/remote-client_test.cpp 2016-09-02 02:56:52 +0000
4781+++ tests/remote-client-v1/remote-client-v1_test.cpp 2016-09-21 05:03:46 +0000
4782@@ -81,6 +81,7 @@
4783 void SetUp() override
4784 {
4785 runtime_ = Runtime::create(connection());
4786+ //acc_ = runtime_->make_test_account(service_connection_->baseService(), impossible_name());
4787 acc_ = runtime_->make_test_account(bus_name(), object_path());
4788 }
4789
4790
4791=== added file 'tests/remote-client/CMakeLists.txt'
4792--- tests/remote-client/CMakeLists.txt 1970-01-01 00:00:00 +0000
4793+++ tests/remote-client/CMakeLists.txt 2016-09-21 05:03:46 +0000
4794@@ -0,0 +1,20 @@
4795+add_executable(remote-client_test remote-client_test.cpp MockProvider.cpp)
4796+set_target_properties(remote-client_test PROPERTIES AUTOMOC TRUE)
4797+
4798+add_definitions(-DTEST_DIR="${CMAKE_CURRENT_BINARY_DIR}" -DBOOST_THREAD_VERSION=4)
4799+include_directories(${GLIB_DEPS_INCLUDE_DIRS})
4800+
4801+target_link_libraries(remote-client_test
4802+ storage-framework-provider
4803+ storage-framework-qt-client-v2
4804+ Qt5::Network
4805+ Qt5::Test
4806+ ${Boost_LIBRARIES}
4807+ ${GLIB_DEPS_LIBRARIES}
4808+ testutils
4809+ gtest
4810+)
4811+add_test(remote-client remote-client_test)
4812+add_dependencies(remote-client_test qt-client-all-headers provider-test)
4813+
4814+set(UNIT_TEST_TARGETS ${UNIT_TEST_TARGETS} PARENT_SCOPE)
4815
4816=== added file 'tests/remote-client/MockProvider.cpp'
4817--- tests/remote-client/MockProvider.cpp 1970-01-01 00:00:00 +0000
4818+++ tests/remote-client/MockProvider.cpp 2016-09-21 05:03:46 +0000
4819@@ -0,0 +1,237 @@
4820+/*
4821+ * Copyright (C) 2016 Canonical Ltd
4822+ *
4823+ * This program is free software: you can redistribute it and/or modify
4824+ * it under the terms of the GNU Lesser General Public License version 3 as
4825+ * published by the Free Software Foundation.
4826+ *
4827+ * This program is distributed in the hope that it will be useful,
4828+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
4829+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
4830+ * GNU Lesser General Public License for more details.
4831+ *
4832+ * You should have received a copy of the GNU Lesser General Public License
4833+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
4834+ *
4835+ * Authors: Michi Henning <michi.henning@canonical.com>
4836+ */
4837+
4838+#include "MockProvider.h"
4839+
4840+#include <unity/storage/provider/Exceptions.h>
4841+#include <unity/storage/provider/metadata_keys.h>
4842+
4843+#include <boost/thread.hpp>
4844+#include <boost/thread/future.hpp>
4845+
4846+#include <chrono>
4847+#include <thread>
4848+#include <inttypes.h>
4849+
4850+using namespace unity::storage;
4851+using namespace unity::storage::provider;
4852+using namespace std;
4853+
4854+using boost::make_exceptional_future;
4855+using boost::make_ready_future;
4856+
4857+MockProvider::MockProvider()
4858+{
4859+}
4860+
4861+MockProvider::MockProvider(string const& cmd)
4862+ : cmd_(cmd)
4863+{
4864+}
4865+
4866+boost::future<ItemList> MockProvider::roots(Context const&)
4867+{
4868+ cerr << "roots CALLED" << endl;
4869+ ItemList roots =
4870+ {
4871+ {"root_id", {}, "Root", "etag", ItemType::root, {}}
4872+ };
4873+ return make_ready_future<ItemList>(roots);
4874+}
4875+
4876+boost::future<tuple<ItemList,string>> MockProvider::list(
4877+ string const& item_id, string const& page_token,
4878+ Context const&)
4879+{
4880+ if (item_id != "root_id")
4881+ {
4882+ string msg = string("Item::list(): no such item: \"") + item_id + "\"";
4883+ return make_exceptional_future<tuple<ItemList,string>>(NotExistsException(msg, item_id));
4884+ }
4885+ if (page_token != "")
4886+ {
4887+ string msg = string("Item::list(): invalid page token: \"") + page_token + "\"";
4888+ return make_exceptional_future<tuple<ItemList,string>>(LogicException("invalid page token"));
4889+ }
4890+ ItemList children =
4891+ {
4892+ {
4893+ "child_id", { "root_id" }, "Child", "etag", ItemType::file,
4894+ { { SIZE_IN_BYTES, 0 }, { LAST_MODIFIED_TIME, "2007-04-05T14:30Z" } }
4895+ }
4896+ };
4897+ boost::promise<tuple<ItemList,string>> p;
4898+ p.set_value(make_tuple(children, string()));
4899+ return p.get_future();
4900+}
4901+
4902+boost::future<ItemList> MockProvider::lookup(
4903+ string const& parent_id, string const& name, Context const&)
4904+{
4905+ if (parent_id != "root_id")
4906+ {
4907+ string msg = string("Folder::lookup(): no such item: \"") + parent_id + "\"";
4908+ return make_exceptional_future<ItemList>(NotExistsException(msg, parent_id));
4909+ }
4910+ if (name != "Child")
4911+ {
4912+ string msg = string("Folder::lookup(): no such item: \"") + name + "\"";
4913+ return make_exceptional_future<ItemList>(NotExistsException(msg, name));
4914+ }
4915+ ItemList children =
4916+ {
4917+ { "child_id", { "root_id" }, "Child", "etag", ItemType::file,
4918+ { { SIZE_IN_BYTES, 0 }, { LAST_MODIFIED_TIME, "2007-04-05T14:30Z" } } }
4919+ };
4920+ return make_ready_future<ItemList>(children);
4921+}
4922+
4923+boost::future<Item> MockProvider::metadata(string const& item_id, Context const&)
4924+{
4925+ if (item_id == "root_id")
4926+ {
4927+ Item metadata{"root_id", {}, "Root", "etag", ItemType::root, {}};
4928+ return make_ready_future<Item>(metadata);
4929+ }
4930+ else if (item_id == "child_id")
4931+ {
4932+ Item metadata
4933+ {
4934+ "child_id", { "root_id" }, "Child", "etag", ItemType::file,
4935+ { { SIZE_IN_BYTES, 0 }, { LAST_MODIFIED_TIME, "2007-04-05T14:30Z" } }
4936+ };
4937+ return make_ready_future<Item>(metadata);
4938+ }
4939+ else if (item_id == "child_folder_id")
4940+ {
4941+ Item metadata{"child_folder_id", { "root_id" }, "Child_Folder", "etag", ItemType::folder, {}};
4942+ return make_ready_future<Item>(metadata);
4943+ }
4944+ return make_exceptional_future<Item>(NotExistsException("metadata(): no such item: " + item_id, item_id));
4945+}
4946+
4947+boost::future<Item> MockProvider::create_folder(
4948+ string const& parent_id, string const& name,
4949+ Context const&)
4950+{
4951+ Item metadata{"new_folder_id", { parent_id }, name, "etag", ItemType::folder, {}};
4952+ return make_ready_future<Item>(metadata);
4953+}
4954+
4955+string make_job_id()
4956+{
4957+ static int last_job_id = 0;
4958+ return to_string(++last_job_id);
4959+}
4960+
4961+boost::future<unique_ptr<UploadJob>> MockProvider::create_file(
4962+ string const&, string const&,
4963+ int64_t, string const&, bool, Context const&)
4964+{
4965+ return make_ready_future<unique_ptr<UploadJob>>(new MockUploadJob(make_job_id()));
4966+}
4967+
4968+boost::future<unique_ptr<UploadJob>> MockProvider::update(
4969+ string const&, int64_t, string const&, Context const&)
4970+{
4971+ return make_ready_future<unique_ptr<UploadJob>>(new MockUploadJob(make_job_id()));
4972+}
4973+
4974+boost::future<unique_ptr<DownloadJob>> MockProvider::download(
4975+ string const&, Context const&)
4976+{
4977+ unique_ptr<DownloadJob> job(new MockDownloadJob(make_job_id()));
4978+ const char contents[] = "Hello world";
4979+ if (write(job->write_socket(), contents, sizeof(contents)) != sizeof(contents))
4980+ {
4981+ ResourceException e("download(): write failed", errno);
4982+ job->report_error(make_exception_ptr(e));
4983+ return make_exceptional_future<unique_ptr<DownloadJob>>(e);
4984+ }
4985+ job->report_complete();
4986+ return make_ready_future(std::move(job));
4987+}
4988+
4989+boost::future<void> MockProvider::delete_item(
4990+ string const&, Context const&)
4991+{
4992+ return make_ready_future();
4993+}
4994+
4995+boost::future<Item> MockProvider::move(
4996+ string const& item_id, string const& new_parent_id,
4997+ string const& new_name, Context const&)
4998+{
4999+ Item metadata{item_id, { new_parent_id }, new_name, "etag", ItemType::file, {}};
5000+ return make_ready_future(metadata);
The diff has been truncated for viewing.

Subscribers

People subscribed via source and target branches

to all changes: