#define MODEL_DATA_ITEM_H
#include <functional>
-#include <memory>
#include <tizen.h>
namespace Model
typedef std::function<void()> DeleteCallback;
DataItem();
+ DataItem(const DataItem &);
virtual ~DataItem() { }
/**
*/
void update(void *data);
+ /**
+ * @return Whether is standalone (not managed by DataProvider).
+ */
+ bool isStandalone() const;
+
+ /**
+ * @brief Set whether item is standalone or managed by DataProvider.
+ * @param[in] isStandalone Whether item is standalone
+ */
+ void setStandalone(bool isStandalone);
+
/**
* @brief Set update callback.
* @param[in] callback Update callback
void setDeleteCallback(DeleteCallback callback);
protected:
+ /**
+ * @brief Mark item as changed with specified change type.
+ * @param[in] changeType Item change type
+ * @param[in] changes Which item data was updated if type is ChangeUpdate
+ */
+ void setChanged(ChangeType changeType, int changes = 0);
+
+ /**
+ * @brief Called after setStandalone() to change item standalone state.
+ * @param[in] isStandalone Whether item is standalone
+ */
+ virtual void onStandalone(bool isStandalone) { }
+
/**
* @brief Called after update() to update item data.
* @param[in] data New item data
friend class DataProvider;
void onUpdated();
+ bool m_IsStandalone;
int m_Changes;
ChangeType m_ChangeType;
#include <list>
+
namespace Model
{
- /**
- * @brief Unique pointer to data item
- */
- typedef std::unique_ptr<DataItem> DataItemPtr;
-
- /**
- * @brief List of data items
- */
- typedef std::list<DataItemPtr> DataList;
-
class EXPORT_API DataProvider
{
public:
+ typedef std::list<DataItem *> DataList;
/**
* @brief Called once initialization is finished.
typedef std::function<void()> InitializeCallback;
/**
- * @brief Called after item was inserted.
- * @param[in] Inserted item
+ * @brief Called when provider has started or finished updating its items.
*/
- typedef std::function<void(DataItem &)> InsertCallback;
+ typedef std::function<void()> UpdateCallback;
/**
- * @brief Called when provider has started or finished updating its items.
+ * @brief Called after item was inserted.
+ * @param[in] Inserted item
*/
- typedef std::function<void()> UpdateCallback;
+ typedef std::function<void(DataItem &)> InsertCallback;
DataProvider();
- virtual ~DataProvider() { }
+ virtual ~DataProvider();
/**
* @return Provider data list.
void update();
/**
- * @brief Set provider update mode.
- * @param[in] isEnabled Whether data update is enabled.
+ * @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 setUpdateMode(bool isEnabled);
+ void destroy();
+
+ /**
+ * @brief Set whether to start update immediately when update() is called.
+ * @param[in] isEnabled Whether data update is enabled
+ */
+ void setUpdateEnabled(bool isEnabled);
/**
* @brief Set insert callback.
protected:
/**
* @brief Called after initialize() to initialize provider data.
- * @post onInitialized() should be called when initialization is finished.
+ * @post finishInit() should be called when initialization is finished.
*/
- virtual void onInitialize();
+ virtual void startInit() = 0;
/**
* @brief Called after update() to update provider data.
- * @post onUpdateStarted() should be called when update has started.
- * @post onUpdateFinished() should be called when update is finished.
+ * @post finishUpdate() should be called when update is finished.
*/
- virtual void onUpdate();
+ virtual void startUpdate() = 0;
/**
* @brief Insert new DataItem into the list.
* @param[in] dataItem New data item
*/
- void insertDataItem(DataItemPtr dataItem);
+ void insertDataItem(DataItem *dataItem);
/**
* @brief Delete DataItem from the list.
void deleteDataItem(DataItem &dataItem);
/**
- * @brief Should be called to notify that initialization is finished.
+ * @brief Should be called when initialization is finished.
* @param[in] dataList Initialized data list
*/
- void onInitialized(DataList dataList);
-
- /**
- * @brief Should be called to notify that update has started.
- */
- void onUpdateStarted();
+ void finishInit(DataList dataList);
/**
- * @brief Should be called to notify that update is finished.
+ * @brief Should be called when update is finished.
* @details Notifies clients about changes and removes deleted items from the list.
*/
- void onUpdateFinished();
+ 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;
{
public:
/**
- * @brief Callback to be called when SearchResult is set
+ * @brief Called when SearchResult is changed.
* @param[in] Search result
*/
typedef std::function<void(const SearchResult *)> ChangeCallback;
/**
- * @brief Create SearchData object
+ * @brief Create SearchData object.
* @param[in] dataItem Data item reference
*/
- SearchData(DataItem &dataItem);
+ explicit SearchData(DataItem &dataItem);
/**
- * @return DataItem reference
+ * @return DataItem reference.
*/
DataItem &getDataItem();
/**
- * @return DataItem reference
+ * @return DataItem reference.
*/
const DataItem &getDataItem() const;
/**
- * @return Search result
+ * @return Search result.
*/
const SearchResult *getSearchResult() const;
/**
- * @brief Set search result
+ * @brief Set search result.
* @param[in] searchResult Search result
*/
void setSearchResult(SearchResult *searchResult);
/**
- * @brief Set change callback
- * @param[in] callback @see ChangedCallback
+ * @brief Set change callback.
+ * @param[in] callback @see ChangeCallback
*/
void setChangeCallback(ChangeCallback callback);
class EXPORT_API SearchEngine
{
public:
+ typedef DataProvider::DataList DataList;
/**
* @brief Create search engine
template <typename List>
void incrementalSearch(const List &list, const std::string &query);
- SearchData *getSearchData(const DataItemPtr &data);
+ SearchData *getSearchData(DataItem *data);
SearchData *getSearchData(const SearchResultItem &searchItem);
void updateSearchResult(ResultList &list);
class EXPORT_API SearchProvider : public DataProvider
{
public:
-
/**
* @brief Create SearchProvider
* @param[in] provider DataProvider
bool empty() const;
private:
- virtual void onInitialize() override;
+ virtual void startInit() override;
+ virtual void startUpdate() override { }
SearchData *createSearchData(DataItem &dataItem);
void onInserted(DataItem &dataItem);
namespace Model
{
- class SearchResult;
-
- typedef std::unique_ptr<SearchResult> SearchResultPtr;
-
class EXPORT_API SearchResult
{
public:
/**
- * @brief Determines range of chars, which are as substring
+ * @brief Represents substring of matched string.
*/
typedef Utils::Range<const char *> Substring;
SearchResult();
/**
- * @brief Create SearchResult object
+ * @brief Create SearchResult object.
* @param[in] fieldId Field ID matched with query
* @param[in] str Matched string
* @param[in] substr Matched substring
SearchResult(int fieldId, const char *str, Substring substr);
/**
- * @return Field ID matched with query
+ * @return Field ID matched with query.
*/
int getMatchedField() const;
/**
- * @return Matched string
+ * @return Matched string.
*/
const char *getMatchedString() const;
/**
- * @return Matched substring
+ * @return Matched substring.
*/
const Substring &getMatchedSubstring() const;
const char *m_MatchedString;
Substring m_MatchedSubstring;
};
+
+ typedef std::unique_ptr<SearchResult> SearchResultPtr;
}
#endif /* MODEL_SEARCH_RESULT_H */
using namespace Model;
DataItem::DataItem()
- : m_Changes(0), m_ChangeType(ChangeNone)
+ : m_IsStandalone(false), m_Changes(0), m_ChangeType(ChangeNone)
+{
+}
+
+DataItem::DataItem(const DataItem &that)
+ : DataItem()
{
}
void DataItem::update(void *data)
{
- m_Changes = onUpdate(data);
+ m_Changes |= onUpdate(data);
m_ChangeType = ChangeUpdate;
+
+ if (m_IsStandalone) {
+ onUpdated();
+ }
+}
+
+bool DataItem::isStandalone() const
+{
+ return m_IsStandalone;
+}
+
+void DataItem::setStandalone(bool isStandalone)
+{
+ if (m_IsStandalone != isStandalone) {
+ m_IsStandalone = isStandalone;
+ onStandalone(m_IsStandalone);
+ }
}
void DataItem::setUpdateCallback(UpdateCallback callback)
m_OnDeleted = std::move(callback);
}
+void DataItem::setChanged(ChangeType changeType, int changes)
+{
+ if (m_ChangeType == ChangeNone) {
+ m_ChangeType = changeType;
+ }
+ if (changeType == ChangeUpdate) {
+ m_Changes |= changes;
+ }
+
+ if (m_IsStandalone) {
+ onUpdated();
+ }
+}
+
void DataItem::onUpdated()
{
switch (m_ChangeType) {
using namespace Model;
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)
{
}
-const DataList &DataProvider::getDataList()
+DataProvider::~DataProvider()
+{
+ for (auto &&dataItem : m_DataList) {
+ delete dataItem;
+ }
+}
+
+const DataProvider::DataList &DataProvider::getDataList()
{
return m_DataList;
}
void DataProvider::initialize(InitializeCallback callback)
{
- if (m_IsInitialized) {
+ if (m_IsInitialized || m_IsBusy) {
return;
}
+ m_IsBusy = true;
m_OnInitialized = std::move(callback);
- onInitialize();
+
+ startInit();
}
void DataProvider::update()
return;
}
- if (!m_IsUpdateEnabled || m_IsUpdating) {
+ if (!m_IsUpdateEnabled || m_IsBusy) {
m_IsUpdatePending = true;
return;
}
+ m_IsBusy = true;
m_IsUpdatePending = false;
- onUpdate();
+ if (m_OnUpdateStarted) {
+ m_OnUpdateStarted();
+ }
+
+ startUpdate();
}
-void DataProvider::setUpdateMode(bool isEnabled)
+void DataProvider::destroy()
+{
+ if (m_IsBusy) {
+ m_IsDestroyPending = true;
+ } else {
+ delete this;
+ }
+}
+
+void DataProvider::setUpdateEnabled(bool isEnabled)
{
m_IsUpdateEnabled = isEnabled;
if (m_IsUpdateEnabled && m_IsUpdatePending) {
m_OnUpdateFinished = std::move(callback);
}
-void DataProvider::onInitialize()
-{
- onInitialized({ });
-}
-
-void DataProvider::onUpdate()
-{
- onUpdateStarted();
- onUpdateFinished();
-}
-
-void DataProvider::insertDataItem(DataItemPtr dataItem)
+void DataProvider::insertDataItem(DataItem *dataItem)
{
dataItem->m_ChangeType = ChangeInsert;
- m_DataList.push_back(std::move(dataItem));
+ m_DataList.push_back(dataItem);
}
void DataProvider::deleteDataItem(DataItem &dataItem)
dataItem.m_ChangeType = ChangeDelete;
}
-void DataProvider::onInitialized(DataList dataList)
+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::onUpdateStarted()
+void DataProvider::finishUpdate()
{
- m_IsUpdating = true;
- if (m_OnUpdateStarted) {
- m_OnUpdateStarted();
+ if (m_IsDestroyPending) {
+ delete this;
+ return;
}
-}
-void DataProvider::onUpdateFinished()
-{
for (auto it = m_DataList.begin(); it != m_DataList.end(); ) {
auto changeType = (*it)->m_ChangeType;
(*it)->onUpdated();
m_OnInserted(**it);
}
} else if (changeType == ChangeDelete) {
+ delete *it;
it = m_DataList.erase(it);
continue;
}
m_OnUpdateFinished();
}
- m_IsUpdating = false;
+ m_IsBusy = false;
if (m_IsUpdatePending) {
update();
}
}
}
-SearchData *SearchEngine::getSearchData(const DataItemPtr &data)
+SearchData *SearchEngine::getSearchData(DataItem *data)
{
- return static_cast<SearchData *>(data.get());
+ return static_cast<SearchData *>(data);
}
SearchData *SearchEngine::getSearchData(const SearchResultItem &resultItem)
void SearchEngine::resetSearchResult()
{
for (auto &&data : m_DataList) {
- SearchData *searchData = static_cast<SearchData *>(data.get());
+ SearchData *searchData = static_cast<SearchData *>(data);
searchData->setSearchResult(nullptr);
}
}
: m_Provider(provider), m_SearchEngine(getDataList(), std::move(comparator))
{
m_Provider.setInsertCallback(std::bind(&SearchProvider::onInserted, this, _1));
- m_Provider.setUpdateStartCallback(std::bind(&SearchProvider::onUpdateStarted, this));
- m_Provider.setUpdateFinishCallback(std::bind(&SearchProvider::onUpdateFinished, this));
+ m_Provider.setUpdateStartCallback(std::bind(&SearchProvider::update, this));
+ m_Provider.setUpdateFinishCallback(std::bind(&SearchProvider::finishUpdate, this));
}
SearchProvider::~SearchProvider()
return m_SearchEngine.empty();
}
-void SearchProvider::onInitialize()
+void SearchProvider::startInit()
{
m_Provider.initialize([this] {
DataList dataList;
for (auto &&dataItem : m_Provider.getDataList()) {
- dataList.push_back(DataItemPtr(createSearchData(*dataItem)));
+ dataList.push_back(createSearchData(*dataItem));
}
- onInitialized(std::move(dataList));
+ finishInit(std::move(dataList));
});
}
void SearchProvider::onInserted(DataItem &dataItem)
{
SearchData *searchData = createSearchData(dataItem);
- insertDataItem(DataItemPtr(searchData));
+ insertDataItem(searchData);
m_SearchEngine.insertSearchData(searchData);
}
* @brief Get list of memo
* @param[in] list list of memos
*/
- typedef std::function<void(::Model::DataList list)> MemoListReceivedCallback;
+ typedef std::function<void(::Model::DataProvider::DataList list)> MemoListReceivedCallback;
/**
* @brief Get memo
* @param[in] memo Memo
*/
- typedef std::function<void(::Model::DataItemPtr memo)> MemoReceivedCallback;
+ typedef std::function<void(::Model::DataItem *memo)> MemoReceivedCallback;
/**
* @brief Called when memo data has been changed.
result_set_cursor cursor, bool providerResult, const char *error);
void initialize();
- ::Model::DataItemPtr createMemo(result_set_cursor cursor, int columnCount);
+ Memo *createMemo(result_set_cursor cursor, int columnCount);
void setMemoContent(Memo *memo, result_set_cursor cursor, int column);
void setMemoImages(Memo *memo, char *image);
bundle *prepareBundle(Memo *memo);
protected:
/**
- * @see DataProvider::onInitialize().
+ * @see DataProvider::startInit().
*/
- virtual void onInitialize() override;
+ virtual void startInit() override;
/**
- * @see DataProvider::onUpdate().
+ * @see DataProvider::startUpdate().
*/
- virtual void onUpdate() override;
-
+ virtual void startUpdate() override;
private:
struct UpdateInfo
data_control_data_change_type_e type;
};
- void onMemoReceived(::Model::DataItemPtr newItem, long long id, data_control_data_change_type_e type);
+ void onMemoReceived(::Model::DataItem *newItem, long long id, data_control_data_change_type_e type);
void onMemoDataChanged(long long id, data_control_data_change_type_e type);
void getMemoFromDB(long long id, data_control_data_change_type_e type);
{
RETM_IF(!providerResult, "onSelectResponse() failed.");
- DataList list;
+ DataProvider::DataList list;
int res = data_control_sql_step_first(cursor);
while (res == DATA_CONTROL_ERROR_NONE) {
- list.push_back(DataItemPtr(MemoBuilder::createMemo(cursor)));
+ list.push_back(MemoBuilder::createMemo(cursor));
res = data_control_sql_step_next(cursor);
}
Memo *MemoProvider::getMemo(long long id)
{
for (auto &&dataItem : getDataList()) {
- auto memo = (Memo *)dataItem.get();
+ auto memo = static_cast<Memo *>(dataItem);
if (memo->getId() == id) {
return memo;
}
m_Consumer.removeMemo(memo);
}
-void MemoProvider::onInitialize()
+void MemoProvider::startInit()
{
- m_Consumer.getMemoList(std::bind(&MemoProvider::onInitialized, this, _1));
+ m_Consumer.getMemoList(std::bind(&MemoProvider::finishInit, this, _1));
}
-void MemoProvider::onUpdate()
+void MemoProvider::startUpdate()
{
- onUpdateStarted();
-
for (auto it = m_Updates.begin(); it != m_Updates.end();) {
if (it->type == DATA_CONTROL_DATA_CHANGE_SQL_DELETE) {
if (Memo *memo = getMemo(it->id)) {
}
if (m_Updates.empty()) {
- onUpdateFinished();
+ finishUpdate();
}
}
update();
}
-void MemoProvider::onMemoReceived(DataItemPtr newItem, long long id, data_control_data_change_type_e type)
+void MemoProvider::onMemoReceived(::Model::DataItem *newItem, long long id, data_control_data_change_type_e type)
{
if (type == DATA_CONTROL_DATA_CHANGE_SQL_INSERT) {
- insertDataItem(std::move(newItem));
+ insertDataItem(newItem);
} else if (type == DATA_CONTROL_DATA_CHANGE_SQL_UPDATE) {
if (Memo *memo = getMemo(id)) {
- memo->update(newItem.get());
+ memo->update(newItem);
}
}
}
if (m_Updates.empty()) {
- onUpdateFinished();
+ finishUpdate();
}
}