[Gallery] Implemented "Save to Gear" feature in ViewerPage 89/128789/2
authorIgor Nazarov <i.nazarov@samsung.com>
Thu, 11 May 2017 10:22:53 +0000 (13:22 +0300)
committerIgor Nazarov <i.nazarov@samsung.com>
Mon, 15 May 2017 14:07:10 +0000 (17:07 +0300)
- Implemented UI logic in ViewerPage for "Save to Gear" feature;
- Implemented MediaItem::Saver job to save media in thread.

Change-Id: I33ead34e0a9a79e1667ea36c621436bd2054bac1

inc/model/MediaItem.h
inc/presenters/ViewerPage.h
inc/resources.h
src/model/MediaItem.cpp
src/presenters/ThumbnailPage.cpp
src/presenters/ViewerPage.cpp
src/resources.cpp

index d72f8a4d100671ea95bc630c69ab550686b73e5f..5f62b9ece0a3d7eff5588937f36e65282a551567 100644 (file)
@@ -35,6 +35,15 @@ namespace gallery {
                        ucl::SharedRef<MediaItems> m_items;
                };
 
+               class Saver;
+               class SaverBuilder final {
+               public:
+                       SaverBuilder &setItem(const MediaItemSRef &item);
+                       IJobSRef build(const NotiHandler &onComplete) const;
+               private:
+                       MediaItemSRef m_item;
+               };
+
                enum {
                        FLAG_THUMBNAIL = 1,
                        FLAG_REMOVE = 2,
index 8fa80e2317c8a355268d9d43a42f2e02afb51913..bef8407234848d709036a028b0ff0962e4d00a9a 100644 (file)
 
 #include "Page.h"
 
+#include "IMoreOptionsListener.h"
+
 namespace gallery {
 
-       class ViewerPage final : public Page {
+       class ViewerPage final : public Page,
+                       private IMoreOptionsListener {
        public:
                class Builder {
                public:
@@ -58,15 +61,31 @@ namespace gallery {
                void onZoomEnd(ucl::Widget &widget, void *eventInfo);
                void onDoubleTap(int x, int y);
 
+               void onJobComplete();
+
+               // Presenter //
+
+               virtual void onActivateBy(const DeactivatorInfo &info) final override;
+               virtual void onDeactivateBy(const DeactivatorInfo &info) final override;
+
                // Page //
 
                virtual void onBackKey() final override;
 
+               // IMoreOptionsListener //
+
+               virtual void onMoreOptionClicked(MoreOptionsPresenter &sender,
+                               const MoreOption &option) final override;
+
        private:
                const MediaItemSRef m_media;
                const bool m_exitOnZoomOut;
                ImageViewerSRef m_imageViewer;
                TouchParserSRef m_touchParser;
+               IJobSRef m_job;
+               PageContentSRef m_content;
+               MoreOptionsPresenterSRef m_more;
+               ProcessingPresenterSRef m_processing;
        };
 }
 
index b1ffda45c527f4c02f7cd9d1d044101a8913de02..9403a67ad77b3032b0123bd32dd35d15fb9efb18 100644 (file)
@@ -45,6 +45,9 @@ namespace gallery {
        extern const ucl::TString STR_DELETING;
        extern const ucl::TString STR_DELETED;
        extern const ucl::TString STR_FAILED;
+       extern const ucl::TString STR_SAVE_TO_GEAR;
+       extern const ucl::TString STR_SAVING;
+       extern const ucl::TString STR_SAVED;
 }
 
 #endif // __GALLERY_RESOURCES_H__
index 2586354da063a465fdf846b57c125f6b4e203fc2..b87ba318a8b19b069b1a1f4dc3a22852b469c063 100644 (file)
@@ -87,6 +87,57 @@ namespace gallery {
                return result;
        }
 
+       // MediaItem::Saver //
+
+       class MediaItem::Saver final : public BaseJob {
+       public:
+               friend class MediaItem::SaverBuilder;
+               Saver(const NotiHandler &onComplete,
+                               const MediaItemSRef &item) :
+                       BaseJob(onComplete, false),
+                       m_item(item)
+               {
+               }
+
+       protected:
+               // BaseJob //
+               virtual Result execute() final override
+               {
+                       FAIL_RETURN(m_item->saveToDevice(),
+                                       "m_item->saveToDevice() failed!");
+                       return RES_OK;
+               }
+
+       private:
+               const MediaItemSRef m_item;
+       };
+
+       // MediaItem::SaverBuilder //
+
+       MediaItem::SaverBuilder &MediaItem::SaverBuilder::
+                       setItem(const MediaItemSRef &item)
+       {
+               m_item = item;
+               return *this;
+       }
+
+       IJobSRef MediaItem::SaverBuilder::build(
+                       const NotiHandler &onComplete) const
+       {
+               if (!onComplete) {
+                       LOG_RETURN_VALUE(RES_INVALID_ARGUMENTS, {}, "onComplete is NULL!");
+               }
+               if (!m_item) {
+                       LOG_RETURN_VALUE(RES_INVALID_ARGUMENTS, {}, "m_item is NULL!");
+               }
+
+               auto result = makeShared<Saver>(onComplete, m_item);
+
+               FAIL_RETURN_VALUE(result->prepare(), {}, "result->prepare() failed!");
+
+               return result;
+       }
+
        // MediaItem //
 
        MediaItem::MediaItem(const int flags, const MediaType type) :
index 76d5c0e54fe30f7c7503c26b12dd79d8de176699..a3b308f4e7d319b1bee6fab26d1170315a7757a3 100644 (file)
@@ -140,6 +140,9 @@ namespace gallery {
 
        ThumbnailPage::~ThumbnailPage()
        {
+               if (m_more) {
+                       m_more->setOpened(false);
+               }
                if (m_page) {
                        m_page->exitNoTransition();
                }
index 2ae6c6f0b0fb2a41f8eaa17a3aa3a752ba6f2d8f..c736755b90862a07048b0e6e1dfb21225d0ad863 100644 (file)
 #include "presenters/ViewerPage.h"
 
 #include "model/MediaItem.h"
+#include "model/IJob.h"
 
+#include "view/PageContent.h"
 #include "view/ImageViewer.h"
 #include "view/TouchParser.h"
 
+#include "presenters/MoreOptionsPresenter.h"
+#include "presenters/ProcessingPresenter.h"
+
+#include "resources.h"
 #include "common.h"
 
+namespace gallery { namespace { namespace impl {
+
+       enum {
+               MORE_OPTION_ID_SAVE
+       };
+}}}
+
 namespace gallery {
 
        using namespace ucl;
@@ -109,11 +122,16 @@ namespace gallery {
 
        ViewerPage::~ViewerPage()
        {
+               if (m_more) {
+                       m_more->setOpened(false);
+               }
        }
 
        Result ViewerPage::prepare()
        {
-               const bool hasThumb = (m_media->getFlags() & MediaItem::FLAG_THUMBNAIL);
+               const int mediaFlags = m_media->getFlags();
+               const bool canSave = (mediaFlags & MediaItem::FLAG_SAVE);
+               const bool hasThumb = (mediaFlags & MediaItem::FLAG_THUMBNAIL);
 
                m_imageViewer = ImageViewer::Builder().
                                setHighResImagePath(m_media->getFilePath()).
@@ -123,6 +141,35 @@ namespace gallery {
                        LOG_RETURN(RES_FAIL, "ImageViewer::build() failed!");
                }
 
+               ElmWidget *rootWidget = m_imageViewer.get();
+
+               if (canSave) {
+                       m_content = PageContent::Builder().
+                                       setFlags(PageContent::FLAG_MORE_OPTIONS).
+                                       build(getNaviframe());
+                       if (!m_content) {
+                               LOG_RETURN(RES_FAIL, "PageContent::build() failed!");
+                       }
+
+                       rootWidget = m_content.get();
+                       m_content->set(*m_imageViewer);
+
+                       m_more = MoreOptionsPresenter::Builder().
+                                       addOption({impl::MORE_OPTION_ID_SAVE,
+                                               STR_SAVE_TO_GEAR, nullptr,
+                                               getImageTheme(ICON_MORE_OPT_SAVE)}).
+                                       build(*m_content);
+                       if (!m_more) {
+                               LOG_RETURN(RES_FAIL, "MoreOptionsPresenter::build() failed!");
+                       }
+
+                       m_content->set(m_more->getWidget(),
+                                       PageContent::Part::MORE_OPTIONS);
+                       addDeactivatorSource(m_more->getWidget());
+
+                       m_more->setListener(asWeakThis<IMoreOptionsListener>(this));
+               }
+
                if (hasThumb) {
                        FAIL_RETURN(m_media->getThumbnailPath(DELEGATE(
                                        ViewerPage::onThumbnail, this)),
@@ -133,14 +180,14 @@ namespace gallery {
                                WEAK_DELEGATE(ViewerPage::onZoomEnd, asWeak(*this)));
 
                FAIL_RETURN(Page::prepare(
-                       [this]()
+                       [this, rootWidget]()
                        {
                                const auto topItem = getNaviframe().getTopItem();
                                if (topItem) {
                                        return getNaviframe().insertAfter(topItem,
-                                                       *m_imageViewer, NAVIFRAME_EMPTY);
+                                                       *rootWidget, NAVIFRAME_EMPTY);
                                }
-                               return getNaviframe().push(*m_imageViewer, NAVIFRAME_EMPTY);
+                               return getNaviframe().push(*rootWidget, NAVIFRAME_EMPTY);
                        }),
                        "Page::prepare() failed!");
 
@@ -187,6 +234,20 @@ namespace gallery {
                }
        }
 
+       void ViewerPage::onActivateBy(const DeactivatorInfo &info)
+       {
+               if (m_more && (info.deactivator == &getNaviframe())) {
+                       m_more->activateBy(info.deactivator);
+               }
+       }
+
+       void ViewerPage::onDeactivateBy(const DeactivatorInfo &info)
+       {
+               if (m_more && (info.deactivator == &getNaviframe())) {
+                       m_more->deactivateBy(info.deactivator);
+               }
+       }
+
        void ViewerPage::onBackKey()
        {
                if (m_imageViewer->isZoomedOut()) {
@@ -195,4 +256,41 @@ namespace gallery {
                        m_imageViewer->zoomOut();
                }
        }
+
+       void ViewerPage::onMoreOptionClicked(MoreOptionsPresenter &sender,
+                       const MoreOption &option)
+       {
+               sender.setOpened(false);
+
+               if (m_job) {
+                       LOG_RETURN_VOID(RES_ILLEGAL_STATE, "m_job is not NULL");
+               }
+
+               m_job = MediaItem::SaverBuilder().
+                               setItem(m_media).
+                               build(WEAK_DELEGATE(ViewerPage::onJobComplete, asWeak(*this)));
+               if (!m_job) {
+                       LOG_RETURN_VOID(RES_FAIL,
+                                       "MediaItem::SaverBuilder::build() failed!");
+               }
+
+               m_processing = ProcessingPresenter::Builder().
+                               setProcessingText(STR_SAVING).
+                               build(*m_content);
+       }
+
+       void ViewerPage::onJobComplete()
+       {
+               if (m_processing) {
+                       if (isGood(m_job->getResult())) {
+                               m_processing->complete(STR_SAVED,
+                                               ProcessingPresenter::IconType::CHECK);
+                       } else {
+                               m_processing->complete(STR_FAILED);
+                       }
+                       m_processing.reset();
+               }
+
+               m_job.reset();
+       }
 }
index bfd9ff61128def23e4ac0e3281bb3c24b1a5f2d7..d3af53b8fd965009d44ed76d8510beb88df93779 100644 (file)
@@ -31,4 +31,7 @@ namespace gallery {
        const ucl::TString STR_DELETING {"Deleting..."};
        const ucl::TString STR_DELETED {"Deleted."};
        const ucl::TString STR_FAILED {"Failed."};
+       const ucl::TString STR_SAVE_TO_GEAR {"Save to Gear"};
+       const ucl::TString STR_SAVING {"Saving..."};
+       const ucl::TString STR_SAVED {"Saved."};
 }