void update();
/**
+ * @brief Destroy dynamically allocated provider safely.
+ * @details If provider is currently busy the destruction is postponed.
+ * @remark No callbacks will be called after this method is called.
+ */
+ void destroy();
+
+ /**
* @brief Set whether to start update immediately when update() is called.
* @param[in] isEnabled Whether data update is enabled
*/
void finishUpdate();
private:
+ bool m_IsBusy;
bool m_IsInitialized;
bool m_IsUpdateEnabled;
bool m_IsUpdatePending;
- bool m_IsUpdating;
+ bool m_IsDestroyPending;
InitializeCallback m_OnInitialized;
InsertCallback m_OnInserted;
using namespace Model2;
DataProvider::DataProvider()
- : m_IsInitialized(false),
- m_IsUpdateEnabled(true), m_IsUpdatePending(false), m_IsUpdating(false)
+ : m_IsBusy(false), m_IsInitialized(false),
+ m_IsUpdateEnabled(true), m_IsUpdatePending(false),
+ m_IsDestroyPending(false)
{
}
void DataProvider::initialize(InitializeCallback callback)
{
- if (m_IsInitialized) {
+ if (m_IsInitialized || m_IsBusy) {
return;
}
+ m_IsBusy = true;
m_OnInitialized = std::move(callback);
+
startInit();
}
return;
}
- if (!m_IsUpdateEnabled || m_IsUpdating) {
+ if (!m_IsUpdateEnabled || m_IsBusy) {
m_IsUpdatePending = true;
return;
}
+ m_IsBusy = true;
m_IsUpdatePending = false;
- m_IsUpdating = true;
if (m_OnUpdateStarted) {
m_OnUpdateStarted();
}
+
startUpdate();
}
+void DataProvider::destroy()
+{
+ if (m_IsBusy) {
+ m_IsDestroyPending = true;
+ } else {
+ delete this;
+ }
+}
+
void DataProvider::setUpdateEnabled(bool isEnabled)
{
m_IsUpdateEnabled = isEnabled;
void DataProvider::finishInit(DataList dataList)
{
+ if (m_IsDestroyPending) {
+ delete this;
+ return;
+ }
+
m_DataList = std::move(dataList);
m_IsInitialized = true;
if (m_OnInitialized) {
m_OnInitialized();
+ m_OnInitialized = nullptr;
}
+
+ m_IsBusy = false;
}
void DataProvider::finishUpdate()
{
+ if (m_IsDestroyPending) {
+ delete this;
+ return;
+ }
+
for (auto it = m_DataList.begin(); it != m_DataList.end(); ) {
auto changeType = (*it)->m_ChangeType;
(*it)->onUpdated();
m_OnUpdateFinished();
}
- m_IsUpdating = false;
+ m_IsBusy = false;
if (m_IsUpdatePending) {
update();
}
* @param[in] provider Person provider
*/
explicit ListView(Model::PersonProvider *provider);
+ virtual ~ListView() override;
/**
* @brief Create person list view
void setUpdateEnabled(bool isEnabled);
protected:
- Model::PersonProvider *getProvider() const;
+ Model2::DataProvider *getProvider() const;
/**
* @brief Called when provider initialization is finished.
Section m_Sections[SectionMax];
std::map<Utils::UniString, PersonGroupItem *> m_PersonGroups;
- std::unique_ptr<Model::PersonProvider> m_PersonProvider;
- Model2::SearchProvider m_SearchProvider;
+ Model2::DataProvider *m_PersonProvider;
+ Model2::SearchProvider *m_SearchProvider;
FillFinishCallback m_OnFillFinished;
};
ListSection::~ListSection()
{
- delete m_Provider;
removeIndexItem();
+ m_Provider->destroy();
}
void ListSection::setUpdateEnabled(bool isEnabled)
m_Index(nullptr), m_AddButton(nullptr),
m_NoContentHelpText("IDS_PB_BODY_AFTER_YOU_CREATE_CONTACTS_THEY_WILL_BE_SHOWN_HERE"),
m_IsSearching(false), m_IsEmpty(true),
- m_HasAddButton(true), m_SearchField(nullptr), m_PersonProvider(provider),
- m_SearchProvider(*m_PersonProvider, PersonComparator())
+ m_HasAddButton(true), m_SearchField(nullptr),
+ m_PersonProvider(provider),
+ m_SearchProvider(new SearchProvider(*m_PersonProvider, PersonComparator()))
{
auto strings = Common::getSelectViewStrings();
strings.titleDefault = "IDS_PB_TAB_CONTACTS";
{
}
+ListView::~ListView()
+{
+ delete m_SearchProvider;
+ m_PersonProvider->destroy();
+}
+
void ListView::setSectionVisibility(SectionId section, bool isVisible)
{
m_Sections[section].m_IsVisible = isVisible;
}
}
-PersonProvider *ListView::getProvider() const
+DataProvider *ListView::getProvider() const
{
- return m_PersonProvider.get();
+ return m_PersonProvider;
}
void ListView::onInitialized()
fillLayout();
updateSection(SectionMyProfile);
- m_SearchProvider.initialize(std::bind(&ListView::onInitialized, this));
- m_SearchProvider.setInsertCallback(std::bind(&ListView::onPersonInserted, this, _1));
- m_SearchProvider.setUpdateFinishCallback(std::bind(&ListView::onUpdateFinished, this));
+ m_SearchProvider->initialize(std::bind(&ListView::onInitialized, this));
+ m_SearchProvider->setInsertCallback(std::bind(&ListView::onPersonInserted, this, _1));
+ m_SearchProvider->setUpdateFinishCallback(std::bind(&ListView::onUpdateFinished, this));
}
void ListView::setFillFinishCallback(FillFinishCallback callback)
switch (sectionId) {
case SectionFavorites:
title = "IDS_PB_HEADER_FAVOURITES";
- provider = new FavoritesProvider(FavoritesProvider::ModeDefault, m_PersonProvider->getFilterType());
+ provider = new FavoritesProvider(FavoritesProvider::ModeDefault,
+ static_cast<PersonProvider &>(*m_PersonProvider).getFilterType());
break;
case SectionMfc:
title = "IDS_PB_HEADER_MOST_FREQUENT_CONTACTS_ABB2";
if (m_PersonGroups.empty()) {
PersonGroupItem *group = nullptr;
- for (auto &&dataItem: m_SearchProvider.getDataList()) {
+ for (auto &&dataItem: m_SearchProvider->getDataList()) {
SearchData &searchData = static_cast<SearchData &>(*dataItem);
Person &person = static_cast<Person &>(searchData.getDataItem());
void ListView::updateEmptyState()
{
- bool isEmpty = m_IsSearching ? m_SearchProvider.empty() : m_PersonGroups.empty();
+ bool isEmpty = m_IsSearching ? m_SearchProvider->empty() : m_PersonGroups.empty();
updateIndex();
updateSearchField();
updateAddButton();
}
- m_SearchProvider.search(str);
+ m_SearchProvider->search(str);
elm_genlist_filter_set(m_Genlist->getEvasObject(), (void *) str);
updateEmptyState();
}
int updateType = m_UpdateType;
m_UpdateType = UpdateNone;
- if (updateType & UpdateRecords) {
- updateRecords();
- }
- if (updateType & UpdateList) {
- updateList();
- }
- finishUpdate();
+ new Thread([this, updateType] {
+ contacts_connect_on_thread();
+ if (updateType & UpdateRecords) {
+ updateRecords();
+ }
+ if (updateType & UpdateList) {
+ updateList();
+ }
+ contacts_disconnect_on_thread();
+ }, std::bind(&PersonProvider::finishUpdate, this));
}
void PersonProvider::updateList()