TizenRefApp-8457 [Gallery] Implement Delete one photo feature in 53/127753/2
authorIgor Nazarov <i.nazarov@samsung.com>
Fri, 28 Apr 2017 14:39:27 +0000 (17:39 +0300)
committerIgor Nazarov <i.nazarov@samsung.com>
Fri, 28 Apr 2017 14:47:46 +0000 (17:47 +0300)
PreviewPage

- implemented Delete one photo feature in PreviewPage;
- ProcessingPresenter updated;
- Refactoring to use MediaItems typedef;
- Fixed potential crash in ThumbnailPage destructor.

Change-Id: I144e38ac468a0c4573a41338122636a0bf79896b

12 files changed:
edc/layouts.edc
inc/presenters/IMoreOptionsListener.h
inc/presenters/PreviewPage.h
inc/presenters/ProcessingPresenter.h
inc/presenters/ThumbnailPage.h
inc/resources.h
src/model/GalleryAlbum.cpp
src/model/GalleryAlbum.h
src/presenters/PreviewPage.cpp
src/presenters/ProcessingPresenter.cpp
src/presenters/ThumbnailPage.cpp
src/resources.cpp

index b574fba18967529bd5dd85f847e9a46a46c7e92d..c322b259e7d71bc1b315b43d4be66b814b233ac3 100644 (file)
@@ -74,6 +74,12 @@ group { "elm/layout/gallery/proccessing";
          target: "gallery.swallow.progress";
          target: "elm.text";
       }
+      program { "gallery,show,bg";
+         signal: "gallery,show,bg";
+         source: "";
+         action: STATE_SET "visible";
+         target: "bg";
+      }
       program { "gallery,hide";
          signal: "gallery,hide";
          source: "";
index 9233c293ddf21374cb6ce44d31b233d605666e81..e8e61b6519fdaaa7cbafab77ce2bf10c7ed6082b 100644 (file)
@@ -23,12 +23,12 @@ namespace gallery {
 
        class IMoreOptionsListener : public ucl::Polymorphic {
        public:
-               virtual void onMoreOptionsOpened(MoreOptionsPresenter &sender) = 0;
-               virtual void onMoreOptionsClosed(MoreOptionsPresenter &sender) = 0;
                virtual void onMoreOptionClicked(MoreOptionsPresenter &sender,
                                const MoreOption &option) = 0;
                virtual void onMoreOptionSelected(MoreOptionsPresenter &sender,
                                const MoreOption &option) {};
+               virtual void onMoreOptionsOpened(MoreOptionsPresenter &sender) {};
+               virtual void onMoreOptionsClosed(MoreOptionsPresenter &sender) {};
        };
 }
 
index fe48a8dc2ace50c1af9f524827bca19615b95f2e..6743b56f9e2f05d6477e3eea890103b5c3205c06 100644 (file)
 
 #include "view/IImageGridListener.h"
 
+#include "IMoreOptionsListener.h"
+
 namespace gallery {
 
        class PreviewPage final : public Page,
-                       private IImageGridListener {
+                       private IImageGridListener,
+                       private IMoreOptionsListener {
        public:
                class Builder {
                public:
@@ -62,6 +65,7 @@ namespace gallery {
                void onAlbumChanged();
                bool onEachMedia(MediaItemSRef &&media);
 
+               void closeTempViews();
                void switchToSelectMode(int itemIndex);
                void switchToNormalMode();
                void toggleItemSelected(int itemIndex);
@@ -69,10 +73,16 @@ namespace gallery {
 
                void onPageExitRequest(Page &page);
 
+               bool onAlertEvent(AlertDialog &dialog, int event);
+               void onJobComplete();
+
+               // Presenter //
+
+               virtual void onActivateBy(const DeactivatorInfo &info) final override;
+               virtual void onDeactivateBy(const DeactivatorInfo &info) final override;
+
                // Page //
 
-               virtual void onActivate() final override;
-               virtual void onDeactivate() final override;
                virtual void onBackKey() final override;
 
                // IImageGridListener //
@@ -81,7 +91,11 @@ namespace gallery {
                virtual void onItemUnrealized(int itemIndex) final override;
                virtual void onItemEvent(int itemIndex,
                                int event, int x, int y) final override;
-               virtual void onTransitionFinished() final override;
+
+               // IMoreOptionsListener //
+
+               virtual void onMoreOptionClicked(MoreOptionsPresenter &sender,
+                               const MoreOption &option) final override;
 
        private:
                class Item;
@@ -91,6 +105,11 @@ namespace gallery {
                const IMediaAlbumSRef m_album;
                ImageGridSRef m_imageGrid;
                std::vector<ItemUPtr> m_items;
+               IJobSRef m_job;
+               PageContentSRef m_content;
+               MoreOptionsPresenterSRef m_more;
+               AlertDialogWRef m_alert;
+               ProcessingPresenterSRef m_processing;
                PageWRef m_page;
        };
 }
index 270c7ec1b8c98a6dfede4cae02658027de8ab307..4cb29997a32c3fc4dc5ee66334bf2b39de4cc796 100644 (file)
@@ -35,39 +35,35 @@ namespace gallery {
                public:
                        Builder();
                        Builder &setProcessingText(ucl::TString text);
-                       Builder &setCompleteText(ucl::TString text);
-                       Builder &setIconType(IconType value);
                        Builder &setForceProgress(bool value);
                        ProcessingPresenterSRef build(ucl::ElmWidget &parent) const;
                private:
                        ucl::TString m_processingText;
-                       ucl::TString m_completeText;
-                       IconType m_iconType;
                        bool m_forceProgress;
                };
 
                using DismissHandler = ucl::WeakDelegate<void()>;
 
        public:
-               void complete();
+               void complete(const ucl::TString &completeText,
+                               IconType iconType = IconType::NONE);
 
                void setDismissHandler(const DismissHandler &handler);
 
        private:
                friend class ucl::RefCountObj<ProcessingPresenter>;
-               ProcessingPresenter(ucl::RefCountObjBase &rc, IconType iconType);
+               ProcessingPresenter(ucl::RefCountObjBase &rc);
                virtual ~ProcessingPresenter();
 
                ucl::Result prepare(ucl::ElmWidget &parent,
                                const ucl::TString &processingText,
-                               const ucl::TString &completeText,
                                bool forceProgress);
 
                ucl::Result createWidget(ucl::ElmWidget &parent,
                                const ucl::TString &processingText);
                ucl::Result moveWidget();
                ucl::Result createProgress();
-               ucl::Result createPopup(const ucl::TString &completeText);
+               ucl::Result createPopup();
                ucl::Result createIcon();
 
                bool resetTimer(double timeout);
@@ -95,10 +91,10 @@ namespace gallery {
                };
 
        private:
-               const IconType m_iconType;
                ucl::LayoutSRef m_widget;
                ucl::StyledWidgetSRef m_popup;
                ucl::LayoutWRef m_icon;
+               IconType m_iconType;
                DismissHandler m_dismissHandler;
                Ecore_Timer *m_timer;
                State m_state;
index d2842296ab9c32ae6afe1ebfc4d61a63b09bcba5..925cc9e4f00a7ec84a603d25eab7e97d18bc0b75 100644 (file)
@@ -71,7 +71,7 @@ namespace gallery {
 
        private:
                const IMediaAlbumSRef m_album;
-               std::vector<MediaItemSRef> m_mediaItems;
+               MediaItems m_mediaItems;
 
                std::vector<RealizedItemUPtr> m_realizedItems;
 
index f230a1f7cab38f3e1924635fa9465a5a6d82f7d9..34b62076827031e79440a727040ad11b17c8f175 100644 (file)
@@ -38,6 +38,12 @@ namespace gallery {
        extern const ucl::TString STR_NO_PHOTOS;
        extern const ucl::TString STR_SELECT_ALL;
        extern const ucl::TString STR_DESELECT_ALL;
+       extern const ucl::TString STR_DELETE;
+       extern const ucl::TString STR_DELETE_CAPS;
+       extern const ucl::TString STR_DELETE_1_PHOTO;
+       extern const ucl::TString STR_DELETING;
+       extern const ucl::TString STR_DELETED;
+       extern const ucl::TString STR_FAILED;
 }
 
 #endif // __GALLERY_RESOURCES_H__
index 51be5db2262a799d245e454915f8c3f4ad1bdea5..5cdab127bea30954649518366f638b6b9a184467 100644 (file)
@@ -87,7 +87,7 @@ namespace gallery {
 
        Result GalleryAlbum::update()
        {
-               Items newItems;
+               MediaItems newItems;
 
                {
                        MutexLock lock(getMediaMutex());
@@ -95,7 +95,8 @@ namespace gallery {
                        const int ret = media_info_foreach_media_from_db(m_filter,
                                [](media_info_h media, void *user_data)
                                {
-                                       Items &newItems = (*static_cast<Items *>(user_data));
+                                       MediaItems &newItems =
+                                                       (*static_cast<MediaItems *>(user_data));
                                        auto item = MediaItem::newInstance(media);
                                        if (!item) {
                                                ELOG("MediaItem::newInstance() failed! Skipping");
index 027ce173bac40bb27056ee7e42916cfe99ca2367..de5bab2c730bb477c249cb85727b385542dd42f4 100644 (file)
@@ -52,13 +52,10 @@ namespace gallery {
 
                ucl::Result prepare();
 
-       private:
-               using Items = std::vector<MediaItemSRef>;
-
        private:
                filter_h m_filter;
                ucl::Event<NotiHandler> m_onChange;
-               Items m_items;
+               MediaItems m_items;
                bool m_isValid;
        };
 }
index 8cd7fd43d95b0405dba38bcd81d8c9deefd6ca29..b9d1fa241a1b64f8d3297eeafc4724af84af7e0b 100644 (file)
 
 #include "model/IMediaAlbum.h"
 #include "model/MediaItem.h"
+#include "model/IJob.h"
 
+#include "view/PageContent.h"
 #include "view/ImageGrid.h"
 
+#include "presenters/MoreOptionsPresenter.h"
+#include "presenters/AlertDialog.h"
+#include "presenters/ProcessingPresenter.h"
 #include "presenters/ViewerPage.h"
 
+#include "resources.h"
 #include "common.h"
 
 namespace gallery { namespace { namespace impl {
 
        constexpr auto BRING_IN_SCROLL_FRICTION = 0.25;
        constexpr auto PAGE_SCROLL_IN_FRICTION = 0.25;
+
+       enum {
+               MORE_OPTION_ID_DELETE
+       };
 }}}
 
 namespace gallery {
@@ -199,10 +209,13 @@ namespace gallery {
 
        PreviewPage::~PreviewPage()
        {
+               closeTempViews();
                if (m_page) {
                        m_page->exitNoTransition();
                }
-               m_imageGrid->setListener(nullptr);
+               if (m_imageGrid) {
+                       m_imageGrid->setListener(nullptr);
+               }
        }
 
        void PreviewPage::reload()
@@ -250,15 +263,36 @@ namespace gallery {
 
        Result PreviewPage::prepare(const bool enableSelectMode)
        {
+               m_content = PageContent::Builder().
+                               setFlags(PageContent::FLAG_MORE_OPTIONS).
+                               build(getNaviframe());
+               if (!m_content) {
+                       LOG_RETURN(RES_FAIL, "PageContent::build() failed!");
+               }
+
                m_imageGrid = ImageGrid::Builder().
                                setListener(this).
                                setType(ImageGrid::Type::LINEAR).
                                setSelectModeStartup(enableSelectMode).
-                               build(getNaviframe());
+                               build(*m_content);
                if (!m_imageGrid) {
                        LOG_RETURN(RES_FAIL, "ImageGrid::build() failed!");
                }
 
+               m_content->set(*m_imageGrid);
+
+               m_more = MoreOptionsPresenter::Builder().
+                               addOption({impl::MORE_OPTION_ID_DELETE,
+                                       STR_DELETE, nullptr,
+                                       getImageTheme(ICON_MORE_OPT_DELETE)}).
+                               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());
+
                FAIL_RETURN(m_album->forEachMedia(
                                DELEGATE(PreviewPage::onEachMedia, this)),
                                "m_album->forEachMedia() failed!");
@@ -266,7 +300,7 @@ namespace gallery {
                FAIL_RETURN(Page::prepare(
                        [this]()
                        {
-                               return getNaviframe().push(*m_imageGrid, NAVIFRAME_EMPTY);
+                               return getNaviframe().push(*m_content, NAVIFRAME_EMPTY);
                        }),
                        "Page::prepare() failed!");
 
@@ -275,6 +309,8 @@ namespace gallery {
                m_album->addChangeHandler(WEAK_DELEGATE(
                                PreviewPage::onAlbumChanged, asWeak(*this)));
 
+               m_more->setListener(asWeakThis<IMoreOptionsListener>(this));
+
                return RES_OK;
        }
 
@@ -316,18 +352,28 @@ namespace gallery {
                return true;
        }
 
-       void PreviewPage::onActivate()
+       void PreviewPage::onActivateBy(const DeactivatorInfo &info)
        {
-               elm_config_scroll_page_scroll_friction_set(
-                               impl::PAGE_SCROLL_IN_FRICTION);
-               elm_config_scroll_bring_in_scroll_friction_set(
-                               impl::BRING_IN_SCROLL_FRICTION);
+               if (info.deactivator == &getNaviframe()) {
+                       elm_config_scroll_page_scroll_friction_set(
+                                       impl::PAGE_SCROLL_IN_FRICTION);
+                       elm_config_scroll_bring_in_scroll_friction_set(
+                                       impl::BRING_IN_SCROLL_FRICTION);
 
-               m_imageGrid->activateRotary();
+                       m_more->activateBy(info.deactivator);
+               }
+
+               if (isActive()) {
+                       m_imageGrid->activateRotary();
+               }
        }
 
-       void PreviewPage::onDeactivate()
+       void PreviewPage::onDeactivateBy(const DeactivatorInfo &info)
        {
+               if (info.deactivator == &getNaviframe()) {
+                       m_more->deactivateBy(info.deactivator);
+               }
+
                m_imageGrid->deactivateRotary();
        }
 
@@ -356,7 +402,7 @@ namespace gallery {
        void PreviewPage::onItemEvent(const int itemIndex,
                        const int event, const int x, const int y)
        {
-               if (!isActive()) {
+               if (m_more->isOpened()) {
                        return;
                }
 
@@ -369,22 +415,91 @@ namespace gallery {
                }
 
                switch (event) {
-               case ImageGrid::ITEM_EVENT_TAP_AND_HOLD:
-                       switchToSelectMode(itemIndex);
-                       break;
                case ImageGrid::ITEM_EVENT_DOUBLE_TAP:
                        openViewer(itemIndex, x, y);
                        break;
                }
        }
 
-       void PreviewPage::onTransitionFinished()
+       void PreviewPage::onMoreOptionClicked(MoreOptionsPresenter &sender,
+                       const MoreOption &option)
+       {
+               sender.setOpened(false);
+
+               switch (option.id) {
+               case impl::MORE_OPTION_ID_DELETE:
+                       m_alert = AlertDialog::Builder().
+                                       setType(AlertDialog::Type::OK_CANCEL).
+                                       setText(STR_DELETE_1_PHOTO).
+                                       setHandler(WEAK_DELEGATE(
+                                               PreviewPage::onAlertEvent, asWeak(*this))).
+                                       build(getNaviframe());
+                       break;
+               default:
+                       WLOG("Unknown option id: %d;", option.id);
+                       break;
+               }
+       }
+
+       bool PreviewPage::onAlertEvent(AlertDialog &dialog, int event)
        {
-               m_imageGrid->update();
+               if (event != AlertDialog::EVENT_OK) {
+                       return true;
+               }
+
+               const int itemIndex = getCurrentItemIndex();
+               if (itemIndex < 0) {
+                       ELOG("Invalid item index!");
+                       return true;
+               }
+
+               m_job = MediaItem::RemoverBuilder().
+                               setItems({m_items[itemIndex]->getMedia()}).
+                               build(WEAK_DELEGATE(
+                                       PreviewPage::onJobComplete, asWeak(*this)));
+               if (!m_job) {
+                       ELOG("MediaItem::RemoverBuilder::build() failed!");
+                       return true;
+               }
+
+               m_processing = ProcessingPresenter::Builder().
+                       setProcessingText(STR_DELETING).
+                       build(*m_content);
+
+               return true;
+       }
+
+       void PreviewPage::onJobComplete()
+       {
+               if (m_processing) {
+                       if (isGood(m_job->getResult())) {
+                               m_processing->complete(STR_DELETED,
+                                               ProcessingPresenter::IconType::CHECK);
+                       } else {
+                               m_processing->complete(STR_FAILED);
+                       }
+                       m_processing.reset();
+               }
+
+               m_job.reset();
+
+               m_album->defragment();
+       }
+
+       void PreviewPage::closeTempViews()
+       {
+               if (m_alert) {
+                       m_alert->dismiss();
+               }
+               if (m_more) {
+                       m_more->setOpened(false);
+               }
        }
 
        void PreviewPage::switchToSelectMode(const int itemIndex)
        {
+               closeTempViews();
+
                for (auto &item: m_items) {
                        item->setSelected(false);
                }
@@ -396,6 +511,8 @@ namespace gallery {
 
        void PreviewPage::switchToNormalMode()
        {
+               closeTempViews();
+
                m_imageGrid->setSelectModeEnabled(false);
        }
 
index a6631a811a5c066465454eaa552dde04a5a2eee0..96596f73e3c898dd259be28c578504143706b5fc 100644 (file)
@@ -36,6 +36,7 @@ namespace gallery { namespace { namespace impl {
                        {"layout", "gallery", "proccessing"};
 
        constexpr EdjeSignal SIGNAL_SHOW {"gallery,show"};
+       constexpr EdjeSignal SIGNAL_SHOW_BG {"gallery,show,bg"};
        constexpr EdjeSignal SIGNAL_HIDE {"gallery,hide"};
        constexpr EdjeSignal SIGNAL_HIDE_PROGRESS {"gallery,hide,progress"};
 
@@ -55,7 +56,6 @@ namespace gallery {
        // ProcessingPresenter::Builder //
 
        ProcessingPresenter::Builder::Builder() :
-               m_iconType(IconType::NONE),
                m_forceProgress(false)
        {
        }
@@ -67,20 +67,6 @@ namespace gallery {
                return *this;
        }
 
-       ProcessingPresenter::Builder &ProcessingPresenter::Builder::
-                       setCompleteText(TString text)
-       {
-               m_completeText = std::move(text);
-               return *this;
-       }
-
-       ProcessingPresenter::Builder &ProcessingPresenter::Builder::
-                       setIconType(const IconType value)
-       {
-               m_iconType = value;
-               return *this;
-       }
-
        ProcessingPresenter::Builder &ProcessingPresenter::Builder::
                        setForceProgress(const bool value)
        {
@@ -91,10 +77,10 @@ namespace gallery {
        ProcessingPresenterSRef ProcessingPresenter::Builder::
                        build(ElmWidget &parent) const
        {
-               auto result = makeShared<ProcessingPresenter>(m_iconType);
+               auto result = makeShared<ProcessingPresenter>();
 
                FAIL_RETURN_VALUE(result->prepare(parent,
-                               m_processingText, m_completeText, m_forceProgress), {},
+                               m_processingText, m_forceProgress), {},
                                "result->prepare() failed!");
 
                return result;
@@ -102,10 +88,9 @@ namespace gallery {
 
        // ProcessingPresenter //
 
-       ProcessingPresenter::ProcessingPresenter(RefCountObjBase &rc,
-                       const IconType iconType) :
+       ProcessingPresenter::ProcessingPresenter(RefCountObjBase &rc) :
                Presenter(rc),
-               m_iconType(iconType),
+               m_iconType(IconType::NONE),
                m_timer(nullptr),
                m_state(State::WAITING),
                m_mayComplete(true),
@@ -122,7 +107,6 @@ namespace gallery {
 
        Result ProcessingPresenter::prepare(ElmWidget &parent,
                        const TString &processingText,
-                       const TString &completeText,
                        const bool forceProgress)
        {
                FAIL_RETURN(Presenter::prepare(parent),
@@ -134,16 +118,15 @@ namespace gallery {
 
                FAIL_RETURN(createProgress(), "createProgress() failed!");
 
-               FAIL_RETURN(createPopup(completeText), "createPopup() failed!");
-
-               if (m_iconType != IconType::NONE) {
-                       FAIL_RETURN(createIcon(), "createIcon() failed!");
-               }
+               FAIL_RETURN(createPopup(), "createPopup() failed!");
 
                if (forceProgress) {
                        showProgress();
-               } else if (!resetTimer(impl::IDLE_WAIT_TIME_SEC)) {
-                       LOG_RETURN(RES_FAIL, "resetTimer() failed!");
+               } else {
+                       m_widget->emit(impl::SIGNAL_SHOW_BG);
+                       if (!resetTimer(impl::IDLE_WAIT_TIME_SEC)) {
+                               LOG_RETURN(RES_FAIL, "resetTimer() failed!");
+                       }
                }
 
                addDeactivatorException(this);
@@ -200,7 +183,7 @@ namespace gallery {
                return RES_OK;
        }
 
-       Result ProcessingPresenter::createPopup(const TString &completeText)
+       Result ProcessingPresenter::createPopup()
        {
                Evas_Object *const popupEo = elm_popup_add(m_widget->getTopWidget());
                if (!popupEo) {
@@ -209,7 +192,6 @@ namespace gallery {
 
                m_popup = makeShared<StyledWidget>(popupEo, true);
                m_popup->setStyle(impl::POPUP_STYLE);
-               m_popup->setText(completeText, PART_TEXT);
 
                m_popup->addEventHandler(POPUP_DISMISSED, WEAK_DELEGATE(
                                ProcessingPresenter::onPopupDismissed, asWeak(*this)));
@@ -294,6 +276,7 @@ namespace gallery {
 
                        m_popup.reset();
 
+                       deactivateBy(m_popup.get());
                        broadcastActivateBy(this);
                        m_rc->unref();
                }
@@ -343,6 +326,7 @@ namespace gallery {
                if (m_dismissHandler) {
                        m_dismissHandler();
                }
+               m_widget.reset();
                deletePopup();
        }
 
@@ -356,13 +340,21 @@ namespace gallery {
                }
        }
 
-       void ProcessingPresenter::complete()
+       void ProcessingPresenter::complete(const TString &completeText,
+                       const IconType iconType)
        {
                if (m_isComplete) {
                        LOG_RETURN_VOID(RES_ILLEGAL_STATE, "Already in complete state!");
                }
                m_isComplete = true;
 
+               m_popup->setText(completeText, PART_TEXT);
+
+               if (iconType != IconType::NONE) {
+                       m_iconType = iconType;
+                       FAIL_LOG(createIcon(), "createIcon() failed!");
+               }
+
                m_rc->ref();
 
                tryShowPopup();
index 72c5334051a3e6592cc08fbc50e9df62fca9a6a0..2b4c456994888a156eef89ed1ff5232ffd2d6aa1 100644 (file)
@@ -136,7 +136,9 @@ namespace gallery {
                if (m_page) {
                        m_page->exitNoTransition();
                }
-               m_imageGrid->setListener(nullptr);
+               if (m_imageGrid) {
+                       m_imageGrid->setListener(nullptr);
+               }
        }
 
        void ThumbnailPage::reload()
index 5a4eb10ca4c1a004d048a3a06c4f7dcf74b455e3..45f5bd4f1ef2e4e9e8541de259357715072e1add 100644 (file)
@@ -24,4 +24,10 @@ namespace gallery {
        const ucl::TString STR_NO_PHOTOS {"No photos"};
        const ucl::TString STR_SELECT_ALL {"Select all"};
        const ucl::TString STR_DESELECT_ALL {"Deselect all"};
+       const ucl::TString STR_DELETE {"Delete"};
+       const ucl::TString STR_DELETE_CAPS {"DELETE"};
+       const ucl::TString STR_DELETE_1_PHOTO {"Delete 1 photo?"};
+       const ucl::TString STR_DELETING {"Deleting..."};
+       const ucl::TString STR_DELETED {"Deleted."};
+       const ucl::TString STR_FAILED {"Failed."};
 }