From 6762847302ab2ce05b7e9c4e69de62811cb1ab45 Mon Sep 17 00:00:00 2001 From: Denis Dolzhenko Date: Tue, 5 Apr 2016 18:49:52 +0300 Subject: [PATCH] TizenRefApp-5970 Selection mode in thread list resets after incoming meassage(or modifying some contact recipient from outside) Change-Id: If3f1a9cf3094c8edc93fb882c238a6f7935c1141 Signed-off-by: Denis Dolzhenko --- .gitignore | 1 + src/Common/MsgEngine/inc/MsgStorage.h | 1 + .../MsgEngine/src/private/MsgStoragePrivate.cpp | 15 ++ .../MsgEngine/src/private/MsgStoragePrivate.h | 1 + src/Common/View/inc/ListItem.h | 2 +- src/Common/View/inc/ListView.h | 6 + src/Common/View/src/ListItem.cpp | 10 +- src/Common/View/src/ListView.cpp | 37 +++++ src/MsgThread/Controller/inc/BaseThreadListItem.h | 1 + src/MsgThread/Controller/inc/ThreadList.h | 15 +- src/MsgThread/Controller/inc/ThreadListItem.h | 3 +- .../Controller/src/BaseThreadListItem.cpp | 5 + src/MsgThread/Controller/src/ThreadList.cpp | 171 +++++++++++++++++---- src/MsgThread/Controller/src/ThreadListItem.cpp | 12 +- 14 files changed, 238 insertions(+), 42 deletions(-) diff --git a/.gitignore b/.gitignore index 7583086..fc58abf 100644 --- a/.gitignore +++ b/.gitignore @@ -9,3 +9,4 @@ crash-info .sdk_delta.info .settings/ org.tizen.message-Test-result.xml +.package-stamp diff --git a/src/Common/MsgEngine/inc/MsgStorage.h b/src/Common/MsgEngine/inc/MsgStorage.h index 623d3fe..2a49c6b 100644 --- a/src/Common/MsgEngine/inc/MsgStorage.h +++ b/src/Common/MsgEngine/inc/MsgStorage.h @@ -48,6 +48,7 @@ namespace Msg virtual MsgThreadItemRef getThread(ThreadId id) = 0; virtual ThreadId getThreadId(const MsgAddressList &addressList) = 0; virtual ThreadId getThreadId(const std::list &addressList) = 0; + virtual ThreadId getThreadId(MsgId id) = 0; virtual bool deleteThread(ThreadId id) = 0; virtual MsgAddressListRef getAddressList(ThreadId id) = 0; virtual MsgThreadListRef searchThread(const std::string &word) = 0; diff --git a/src/Common/MsgEngine/src/private/MsgStoragePrivate.cpp b/src/Common/MsgEngine/src/private/MsgStoragePrivate.cpp index 7f6fbf4..3272984 100644 --- a/src/Common/MsgEngine/src/private/MsgStoragePrivate.cpp +++ b/src/Common/MsgEngine/src/private/MsgStoragePrivate.cpp @@ -403,3 +403,18 @@ bool MsgStoragePrivate::isReadReportChecked(MsgId msgId) msg_release_struct(&sendOpt); return readFlag; } + +ThreadId MsgStoragePrivate::getThreadId(MsgId id) +{ + int threadId = -1; + msg_struct_t msg = msg_create_struct(MSG_STRUCT_MESSAGE_INFO); + msg_struct_t sendOpt = msg_create_struct(MSG_STRUCT_SENDOPT); + + if(msg_get_message(m_ServiceHandle, id, msg, sendOpt) == 0) + msg_get_int_value(msg, MSG_MESSAGE_THREAD_ID_INT, &threadId); + + msg_release_struct(&msg); + msg_release_struct(&sendOpt); + + return threadId; +} diff --git a/src/Common/MsgEngine/src/private/MsgStoragePrivate.h b/src/Common/MsgEngine/src/private/MsgStoragePrivate.h index 235836d..a21cc13 100644 --- a/src/Common/MsgEngine/src/private/MsgStoragePrivate.h +++ b/src/Common/MsgEngine/src/private/MsgStoragePrivate.h @@ -39,6 +39,7 @@ namespace Msg virtual MsgThreadItemRef getThread(ThreadId id); virtual ThreadId getThreadId(const MsgAddressList &addressList); virtual ThreadId getThreadId(const std::list &addressList); + virtual ThreadId getThreadId(MsgId id); virtual bool deleteThread(ThreadId id); virtual MsgAddressListRef getAddressList(ThreadId id); virtual MsgThreadListRef searchThread(const std::string &word); diff --git a/src/Common/View/inc/ListItem.h b/src/Common/View/inc/ListItem.h index ab4aa7b..295830e 100644 --- a/src/Common/View/inc/ListItem.h +++ b/src/Common/View/inc/ListItem.h @@ -74,7 +74,7 @@ namespace Msg bool getSelected() const; void setExpanded(bool expand); void update(); - void updateFields(const char *parts, Elm_Genlist_Item_Field_Type type);; + void updateFields(const char *parts, Elm_Genlist_Item_Field_Type type); ListView *getOwner() const; Elm_Genlist_Item_Type getType() const; int getUserType() const; diff --git a/src/Common/View/inc/ListView.h b/src/Common/View/inc/ListView.h index e483543..de05503 100644 --- a/src/Common/View/inc/ListView.h +++ b/src/Common/View/inc/ListView.h @@ -31,12 +31,17 @@ namespace Msg : public View { public: + typedef int (*CmpFunc)(const ListItem &item1, const ListItem &item2); + + public: ListView(Evas_Object *parent); virtual ~ListView(); void setListener(IListViewListener *listener); bool appendItem(ListItem &listItem, ListItem *parent = nullptr); bool prependItem(ListItem &listItem, ListItem *parent = nullptr); + bool sortedInsertItem(ListItem &listItem, ListItem *parent = nullptr); + void setCmpFunc(CmpFunc fn); void deleteItem(ListItem &listItem); ListItemCollection getItems() const; ListItem *getFirstItem() const; @@ -76,6 +81,7 @@ namespace Msg private: IListViewListener *m_pListener; bool m_CheckMode; + CmpFunc m_CmpFunc; }; class IListViewListener diff --git a/src/Common/View/src/ListItem.cpp b/src/Common/View/src/ListItem.cpp index bef6dfd..6d20fd4 100644 --- a/src/Common/View/src/ListItem.cpp +++ b/src/Common/View/src/ListItem.cpp @@ -177,14 +177,8 @@ void ListItem::changeCheckedState(bool updateUi) void ListItem::setCheckedState(bool state, bool updateUi) { m_Checked = state; - const char *checkPart = getCheckPart(*this); - if(checkPart) - { - if(updateUi) - { - updateFields(checkPart, ELM_GENLIST_ITEM_FIELD_CONTENT); // FIXME: Blink during update part tizen_2.4 - } - } + if(updateUi) + elm_genlist_item_update(getElmObjItem()); } bool ListItem::getCheckedState() const diff --git a/src/Common/View/src/ListView.cpp b/src/Common/View/src/ListView.cpp index 428b4c7..39e7420 100644 --- a/src/Common/View/src/ListView.cpp +++ b/src/Common/View/src/ListView.cpp @@ -37,6 +37,7 @@ ListView::ListView(Evas_Object *parent) : View() , m_pListener(nullptr) , m_CheckMode(false) + , m_CmpFunc() { createListView(parent); } @@ -75,10 +76,46 @@ bool ListView::prependItem(ListItem &listItem, ListItem *parent) listItem.m_pOwner = this; Elm_Object_Item *elmItem = elm_genlist_item_prepend(getEo(), listItem.m_ItemStyle->m_pGenlistItemClass, &listItem, parentItem, listItem.getType(), on_item_selected_cb, this); + + listItem.setElmObjItem(elmItem); + return elmItem != nullptr; +} + +bool ListView::sortedInsertItem(ListItem &listItem, ListItem *parent) +{ + Elm_Object_Item *parentItem = parent ? parent->getElmObjItem() : nullptr; + + listItem.m_pOwner = this; + Elm_Object_Item *elmItem = elm_genlist_item_sorted_insert + ( + getEo(), + listItem.m_ItemStyle->m_pGenlistItemClass, + &listItem, + parentItem, + listItem.getType(), + [](const void *data1, const void *data2)->int + { + int res = 0; + ListItem *item1 = (ListItem*)elm_object_item_data_get((Elm_Object_Item*)data1); + ListItem *item2 = (ListItem*)elm_object_item_data_get((Elm_Object_Item*)data2); + if(item1->m_pOwner->m_CmpFunc) + res = item1->m_pOwner->m_CmpFunc(*item1, *item2); + + return res; + }, + on_item_selected_cb, + this + ); + listItem.setElmObjItem(elmItem); return elmItem != nullptr; } +void ListView::setCmpFunc(CmpFunc fn) +{ + m_CmpFunc = fn; +} + void ListView::deleteItem(ListItem &listItem) { elm_object_item_del(listItem.getElmObjItem()); diff --git a/src/MsgThread/Controller/inc/BaseThreadListItem.h b/src/MsgThread/Controller/inc/BaseThreadListItem.h index f7d23b0..fb1fa2c 100644 --- a/src/MsgThread/Controller/inc/BaseThreadListItem.h +++ b/src/MsgThread/Controller/inc/BaseThreadListItem.h @@ -45,6 +45,7 @@ namespace Msg void updateTime(); void updateMessage(const MsgThreadItem &threadItem); void updateMessage(const std::string &msg); + time_t getRawTime() const; protected: // ThreadListViewItem: diff --git a/src/MsgThread/Controller/inc/ThreadList.h b/src/MsgThread/Controller/inc/ThreadList.h index 4f3ca1f..a555170 100644 --- a/src/MsgThread/Controller/inc/ThreadList.h +++ b/src/MsgThread/Controller/inc/ThreadList.h @@ -22,6 +22,8 @@ #include "MsgStorage.h" #include "ContactManager.h" #include "SystemSettingsManager.h" +#include "MsgTypes.h" +#include namespace Msg { @@ -49,7 +51,9 @@ namespace Msg private: // IMsgStorageListener: - virtual void onMsgStorageChange(const MsgIdList &idList); + virtual void onMsgStorageUpdate(const MsgIdList &msgIdList); + virtual void onMsgStorageInsert(const MsgIdList &msgIdList); + virtual void onMsgStorageDelete(const MsgIdList &msgIdList); // IContactManagerListener: virtual void onContactChanged(); @@ -66,9 +70,16 @@ namespace Msg void checkAllItems(bool check); void checkHandler(SelectAllListItem &item); void checkHandler(ThreadListItem &item); - void updateList(); + void fillList(); + void deleteItems(); + void updateItems(const MsgIdList &idList); + void updateItems(); + void insertItem(const MsgThreadItem &msgThreadItem); + void insertItem(ThreadId id); bool isAllThreadListItemChecked() const; void updateSelectAllItem(); + std::set getThreadIdSet(const MsgIdList &idList); + static int cmpFunc(const ListItem &item1, const ListItem &item2); private: IThreadListListener *m_pListener; diff --git a/src/MsgThread/Controller/inc/ThreadListItem.h b/src/MsgThread/Controller/inc/ThreadListItem.h index 6118246..c9d07ca 100644 --- a/src/MsgThread/Controller/inc/ThreadListItem.h +++ b/src/MsgThread/Controller/inc/ThreadListItem.h @@ -35,7 +35,8 @@ namespace Msg virtual ~ThreadListItem(); ThreadId getThreadId() const; - void updateModel(const MsgThreadItem &threadItem); + void update(const MsgThreadItem &threadItem); + void update(); private: // ThreadListViewItem: diff --git a/src/MsgThread/Controller/src/BaseThreadListItem.cpp b/src/MsgThread/Controller/src/BaseThreadListItem.cpp index 8e433ad..a954bbd 100644 --- a/src/MsgThread/Controller/src/BaseThreadListItem.cpp +++ b/src/MsgThread/Controller/src/BaseThreadListItem.cpp @@ -131,3 +131,8 @@ Evas_Object *BaseThreadListItem::getThumbnail() { return m_App.getThumbnailMaker().getThumbById(*getOwner(), m_ThumbId); } + +time_t BaseThreadListItem::getRawTime() const +{ + return m_RawTime; +} diff --git a/src/MsgThread/Controller/src/ThreadList.cpp b/src/MsgThread/Controller/src/ThreadList.cpp index ced0557..0925169 100644 --- a/src/MsgThread/Controller/src/ThreadList.cpp +++ b/src/MsgThread/Controller/src/ThreadList.cpp @@ -26,9 +26,14 @@ using namespace Msg; namespace { - inline bool isSelectAll(ListItem *it) + inline SelectAllListItem *isSelectAll(ListItem *it) { - return dynamic_cast(it) != nullptr; + return dynamic_cast(it); + } + + inline const SelectAllListItem *isSelectAll(const ListItem *it) + { + return dynamic_cast(it); } } @@ -41,10 +46,12 @@ ThreadList::ThreadList(Evas_Object *parent, App &app) ListView::setListener(this); ListView::setMultiSelection(false); ListView::setMode(ELM_LIST_COMPRESS); + ListView::setCmpFunc(cmpFunc); + m_App.getMsgEngine().getStorage().addListener(*this); m_App.getContactManager().addListener(*this); m_App.getSysSettingsManager().addListener(*this); - updateList(); + fillList(); } ThreadList::~ThreadList() @@ -74,8 +81,8 @@ bool ThreadList::isDeleteModeEnabled() const void ThreadList::deleteSelectedItems() { - auto collection = getItems(); - for(ThreadListItem *it : collection) + auto items = getItems(); + for(ThreadListItem *it : items) { if(it->getCheckedState()) m_App.getMsgEngine().getStorage().deleteThread(it->getThreadId()); @@ -89,7 +96,7 @@ int ThreadList::getThreadsCheckedCount() const for(ThreadListItem *item : items) { if(item->isCheckable() && item->getCheckedState()) - count++; + ++count; } return count; } @@ -122,8 +129,10 @@ void ThreadList::checkAllItems(bool check) for(ListItem *it : items) { if(it->isCheckable() && !isSelectAll(it)) - it->setCheckedState(check, true); + it->setCheckedState(check, false); } + + updateRealizedItems(); } bool ThreadList::isAllThreadListItemChecked() const @@ -166,39 +175,111 @@ void ThreadList::checkHandler(ThreadListItem &item) m_pListener->onThreadListItemChecked(); } -void ThreadList::updateList() +int ThreadList::cmpFunc(const ListItem &item1, const ListItem &item2) +{ + if(isSelectAll(&item1)) + return 0; + + if(isSelectAll(&item2)) + return 1; + + auto &threadItem1 = static_cast(item1); + auto &threadItem2 = static_cast(item2); + return threadItem2.getRawTime() - threadItem1.getRawTime(); +} + +void ThreadList::insertItem(const MsgThreadItem &item) { - MsgThreadListRef list = m_App.getMsgEngine().getStorage().getThreadList(); - if(!list) + ListView::sortedInsertItem(*new ThreadListItem(item, m_App)); +} + +void ThreadList::insertItem(ThreadId id) +{ + MsgThreadItemRef threadItem = m_App.getMsgEngine().getStorage().getThread(id); + if(threadItem) + insertItem(*threadItem); +} + +void ThreadList::fillList() +{ + MsgThreadListRef msgThreadList = m_App.getMsgEngine().getStorage().getThreadList(); + if(!msgThreadList) return; - int length = list->getLength(); + int length = msgThreadList->getLength(); + for(int i = 0; i < length; ++i) { - ThreadListItem *item = new ThreadListItem(list->at(i), m_App); - ListView::appendItem(*item); + const MsgThreadItem &msgThreadItem = msgThreadList->at(i); + ListView::appendItem(*new ThreadListItem(msgThreadItem, m_App)); } } -void ThreadList::onMsgStorageChange(const MsgIdList &idList) +void ThreadList::deleteItems() { - ListView::clear(); // FIXME: temporary solution for demo - updateList(); - if(m_pListener) - m_pListener->onThreadListChanged(); + MsgThreadListRef msgThreadList = m_App.getMsgEngine().getStorage().getThreadList(); + if(!msgThreadList) + return; + + std::set threadIdSet; + int length = msgThreadList->getLength(); + for(int i = 0; i < length; ++i) + { + const MsgThreadItem &msgThreadItem = msgThreadList->at(i); + threadIdSet.insert(msgThreadItem.getId()); + } + + auto items = ListView::getItems(); + + for(ThreadListItem *item : items) + { + if(threadIdSet.count(item->getThreadId()) == 0) + ListView::deleteItem(*item); + } + + updateSelectAllItem(); } -void ThreadList::onContactChanged() +void ThreadList::updateItems(const MsgIdList &idList) { - MSG_LOG(""); - ListView::clear(); // FIXME: temporary solution for demo - updateList(); - if(m_pListener) - m_pListener->onThreadListChanged(); + auto threadIdSet = getThreadIdSet(idList); + auto threadItems = getItems(); + + for(ThreadListItem *threadListItem: threadItems) + { + if(threadIdSet.count(threadListItem->getThreadId())) + threadListItem->update(); + } + + updateRealizedItems(); +} + +void ThreadList::updateItems() +{ + auto items = getItems(); + for(ThreadListItem *item: items) + { + item->update(); + } + + updateRealizedItems(); +} + +std::set ThreadList::getThreadIdSet(const MsgIdList &idList) +{ + std::set res; + for(MsgId msgId : idList) + { + ThreadId threadId = m_App.getMsgEngine().getStorage().getThreadId(msgId); + if(threadId.isValid()) + res.insert(threadId); + } + return res; } void ThreadList::onListItemSelected(ListItem &listItem) { + MSG_LOG(""); ThreadListItem *it = dynamic_cast(&listItem); if(it && m_pListener) m_pListener->onListItemSelected(it->getThreadId()); @@ -206,17 +287,53 @@ void ThreadList::onListItemSelected(ListItem &listItem) void ThreadList::onListItemChecked(ListItem &listItem) { + MSG_LOG(""); if(ThreadListItem *it = dynamic_cast(&listItem)) checkHandler(*it); - else if(SelectAllListItem *it = dynamic_cast(&listItem)) + else if(SelectAllListItem *it = isSelectAll(&listItem)) checkHandler(*it); } +void ThreadList::onMsgStorageUpdate(const MsgIdList &msgIdList) +{ + MSG_LOG(""); + updateItems(msgIdList); +} + +void ThreadList::onMsgStorageInsert(const MsgIdList &msgIdList) +{ + MSG_LOG(""); + auto threadSet = getThreadIdSet(msgIdList); + for(ThreadId id : threadSet) + { + insertItem(id); + } + + updateSelectAllItem(); + + if(m_pListener) + m_pListener->onThreadListChanged(); +} + +void ThreadList::onMsgStorageDelete(const MsgIdList &msgIdList) +{ + MSG_LOG(""); + deleteItems(); + if(m_pListener) + m_pListener->onThreadListChanged(); +} + +void ThreadList::onContactChanged() +{ + MSG_LOG(""); + updateItems(); +} + void ThreadList::onTimeFormatChanged() { MSG_LOG(""); - auto items = ListView::getItems(); - for(BaseThreadListItem *item : items) + auto items = ListView::getItems(); + for(ThreadListItem *item : items) { item->updateTime(); } diff --git a/src/MsgThread/Controller/src/ThreadListItem.cpp b/src/MsgThread/Controller/src/ThreadListItem.cpp index 456b01b..15317ff 100644 --- a/src/MsgThread/Controller/src/ThreadListItem.cpp +++ b/src/MsgThread/Controller/src/ThreadListItem.cpp @@ -33,7 +33,7 @@ ThreadListItem::ThreadListItem(const MsgThreadItem &threadItem, App &app) : BaseThreadListItem(app) , m_ThreadId() { - updateModel(threadItem); + update(threadItem); } ThreadListItem::~ThreadListItem() @@ -55,7 +55,7 @@ Evas_Object *ThreadListItem::getIcon() return makeUnreadIcon(m_UnreadCount); } -void ThreadListItem::updateModel(const MsgThreadItem &threadItem) +void ThreadListItem::update(const MsgThreadItem &threadItem) { m_ThreadId = threadItem.getId(); @@ -82,10 +82,16 @@ void ThreadListItem::updateModel(const MsgThreadItem &threadItem) } setState(state, false); - setCheckedState(false, false); updateMessage(threadItem); updateThumbnailAndName(threadItem, true); updateTime(threadItem.getTime()); } +void ThreadListItem::update() +{ + MsgThreadItemRef msgThread = m_App.getMsgEngine().getStorage().getThread(m_ThreadId); + if(msgThread) + update(*msgThread); +} + -- 2.7.4