From 56344b0579c474262880a6d50f666a3d553e4dcd Mon Sep 17 00:00:00 2001 From: Adam Dobrowolski Date: Wed, 5 May 2021 08:00:25 +0200 Subject: [PATCH] [EGD-6680] Notes crash fix on search Changed query for all matches to query with limit --- .../application-notes/ApplicationNotes.cpp | 12 ++-- module-apps/application-notes/CMakeLists.txt | 6 +- .../application-notes/data/NotesFoundData.cpp | 12 +--- .../application-notes/data/NotesFoundData.hpp | 6 +- .../model/NotesListModel.hpp | 16 +---- .../model/NotesListProvider.hpp | 17 ++++++ .../model/NotesRepository.cpp | 11 ++-- .../model/NotesRepository.hpp | 13 ++-- .../model/NotesSearchListModel.cpp | 16 +++++ .../model/NotesSearchListModel.hpp | 32 ++++++++++ .../model/SearchResultsListModel.cpp | 59 ------------------- .../model/SearchResultsListModel.hpp | 31 ---------- .../presenter/NotesMainWindowPresenter.cpp | 12 +--- .../presenter/NotesMainWindowPresenter.hpp | 6 +- .../presenter/NotesSearchResultPresenter.cpp | 34 +++++++++++ .../presenter/NotesSearchResultPresenter.hpp | 48 +++++++++++++++ .../presenter/SearchEngineWindowPresenter.cpp | 12 ++-- .../presenter/SearchEngineWindowPresenter.hpp | 15 ++--- .../windows/SearchEngineWindow.cpp | 10 +++- .../windows/SearchEngineWindow.hpp | 5 +- .../windows/SearchResultsWindow.cpp | 38 ++++++------ .../windows/SearchResultsWindow.hpp | 18 +++--- module-db/Interface/NotesRecord.cpp | 14 +++-- module-db/Interface/NotesRecord.hpp | 6 +- module-db/Tables/NotesTable.cpp | 25 ++++++-- module-db/Tables/NotesTable.hpp | 7 ++- .../queries/notes/QueryNotesGetByText.cpp | 10 +++- .../queries/notes/QueryNotesGetByText.hpp | 22 ++++++- module-db/tests/NotesRecord_tests.cpp | 2 +- module-db/tests/NotesTable_tests.cpp | 2 +- 30 files changed, 299 insertions(+), 218 deletions(-) create mode 100644 module-apps/application-notes/model/NotesListProvider.hpp create mode 100644 module-apps/application-notes/model/NotesSearchListModel.cpp create mode 100644 module-apps/application-notes/model/NotesSearchListModel.hpp delete mode 100644 module-apps/application-notes/model/SearchResultsListModel.cpp delete mode 100644 module-apps/application-notes/model/SearchResultsListModel.hpp create mode 100644 module-apps/application-notes/presenter/NotesSearchResultPresenter.cpp create mode 100644 module-apps/application-notes/presenter/NotesSearchResultPresenter.hpp diff --git a/module-apps/application-notes/ApplicationNotes.cpp b/module-apps/application-notes/ApplicationNotes.cpp index baca84f1dd7349d4533f3ecf070d36a37e952d9a..8d9d66b85ccb5e5958395d8f98f796325c3f083b 100644 --- a/module-apps/application-notes/ApplicationNotes.cpp +++ b/module-apps/application-notes/ApplicationNotes.cpp @@ -107,12 +107,14 @@ namespace app return std::make_unique(app, std::move(presenter)); }); windowsFactory.attach(gui::name::window::notes_search, [](Application *app, const std::string &name) { - auto notesRepository = std::make_unique(app); - auto presenter = std::make_unique(std::move(notesRepository)); - return std::make_unique(app, std::move(presenter)); + return std::make_unique(app, + std::make_unique()); }); - windowsFactory.attach(gui::name::window::notes_search_result, [](Application *app, const std::string &name) { - return std::make_unique(app); + windowsFactory.attach(gui::name::window::notes_search_result, [](Application *app, const std::string &) { + auto notesRepository = std::make_unique(app); + auto notesProvider = std::make_shared(app, std::move(notesRepository)); + auto presenter = std::make_unique(notesProvider); + return std::make_unique(app, std::move(presenter)); }); windowsFactory.attach(gui::name::window::note_dialog, [](Application *app, const std::string &name) { return std::make_unique(app, name); diff --git a/module-apps/application-notes/CMakeLists.txt b/module-apps/application-notes/CMakeLists.txt index 513162c05948eca05859c8c3e5af213ffee6a355..d94048a683b2a3550383b483dcd5e90594d2e714 100644 --- a/module-apps/application-notes/CMakeLists.txt +++ b/module-apps/application-notes/CMakeLists.txt @@ -13,12 +13,13 @@ target_sources( ${PROJECT_NAME} PRIVATE "${CMAKE_CURRENT_LIST_DIR}/ApplicationNotes.cpp" "${CMAKE_CURRENT_LIST_DIR}/model/NotesListModel.cpp" - "${CMAKE_CURRENT_LIST_DIR}/model/SearchResultsListModel.cpp" + "${CMAKE_CURRENT_LIST_DIR}/model/NotesSearchListModel.cpp" "${CMAKE_CURRENT_LIST_DIR}/model/NotesRepository.cpp" "${CMAKE_CURRENT_LIST_DIR}/presenter/NotesMainWindowPresenter.cpp" "${CMAKE_CURRENT_LIST_DIR}/presenter/NotePreviewWindowPresenter.cpp" "${CMAKE_CURRENT_LIST_DIR}/presenter/NoteEditWindowPresenter.cpp" "${CMAKE_CURRENT_LIST_DIR}/presenter/SearchEngineWindowPresenter.cpp" + "${CMAKE_CURRENT_LIST_DIR}/presenter/NotesSearchResultPresenter.cpp" "${CMAKE_CURRENT_LIST_DIR}/widgets/NotesItem.cpp" "${CMAKE_CURRENT_LIST_DIR}/windows/NoteMainWindow.cpp" "${CMAKE_CURRENT_LIST_DIR}/windows/NotePreviewWindow.cpp" @@ -31,12 +32,13 @@ target_sources( ${PROJECT_NAME} PUBLIC "${CMAKE_CURRENT_LIST_DIR}/ApplicationNotes.hpp" "${CMAKE_CURRENT_LIST_DIR}/model/NotesListModel.hpp" - "${CMAKE_CURRENT_LIST_DIR}/model/SearchResultsListModel.hpp" + "${CMAKE_CURRENT_LIST_DIR}/model/NotesSearchListModel.hpp" "${CMAKE_CURRENT_LIST_DIR}/model/NotesRepository.hpp" "${CMAKE_CURRENT_LIST_DIR}/presenter/NotesMainWindowPresenter.hpp" "${CMAKE_CURRENT_LIST_DIR}/presenter/NotePreviewWindowPresenter.hpp" "${CMAKE_CURRENT_LIST_DIR}/presenter/NoteEditWindowPresenter.hpp" "${CMAKE_CURRENT_LIST_DIR}/presenter/SearchEngineWindowPresenter.hpp" + "${CMAKE_CURRENT_LIST_DIR}/presenter/NotesSearchResultPresenter.hpp" "${CMAKE_CURRENT_LIST_DIR}/widgets/NotesItem.hpp" "${CMAKE_CURRENT_LIST_DIR}/windows/NoteMainWindow.hpp" "${CMAKE_CURRENT_LIST_DIR}/windows/NotePreviewWindow.hpp" diff --git a/module-apps/application-notes/data/NotesFoundData.cpp b/module-apps/application-notes/data/NotesFoundData.cpp index f46105a215a5f5a63415b1b5c7216f27c33b8e78..d9e3a282b4b0d4e319a48b56a479daeb49ae15aa 100644 --- a/module-apps/application-notes/data/NotesFoundData.cpp +++ b/module-apps/application-notes/data/NotesFoundData.cpp @@ -1,22 +1,16 @@ -// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved. +// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved. // For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md #include "NotesFoundData.hpp" namespace app::notes { - NotesFoundData::NotesFoundData(std::string searchText, std::vector notes) - : gui::SwitchData(std::string{"NotesFoundData"}), searchText{std::move(searchText)}, recordsFound{ - std::move(notes)} + NotesFoundData::NotesFoundData(std::string searchText) + : gui::SwitchData(std::string{"NotesFoundData"}), searchText{std::move(searchText)} {} const std::string &NotesFoundData::getSearchText() const noexcept { return searchText; } - - const std::vector &NotesFoundData::getFoundRecords() const noexcept - { - return recordsFound; - } } // namespace app::notes diff --git a/module-apps/application-notes/data/NotesFoundData.hpp b/module-apps/application-notes/data/NotesFoundData.hpp index 2035bbd32526f021c9fe717d981d784b45a2f9d1..53c43d05cac65a47249e577858dca2ae1d2274d7 100644 --- a/module-apps/application-notes/data/NotesFoundData.hpp +++ b/module-apps/application-notes/data/NotesFoundData.hpp @@ -1,4 +1,4 @@ -// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved. +// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved. // For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md #pragma once @@ -13,13 +13,11 @@ namespace app::notes class NotesFoundData : public gui::SwitchData { public: - NotesFoundData(std::string searchText, std::vector notes); + explicit NotesFoundData(std::string searchText); const std::string &getSearchText() const noexcept; - const std::vector &getFoundRecords() const noexcept; private: std::string searchText; - std::vector recordsFound; }; } // namespace app::notes diff --git a/module-apps/application-notes/model/NotesListModel.hpp b/module-apps/application-notes/model/NotesListModel.hpp index 7e157a326b03ad64cf6d2b814604717cecf6f925..fb96e3fb1d3efeb77d3e7398a14a88775e4f2fc2 100644 --- a/module-apps/application-notes/model/NotesListModel.hpp +++ b/module-apps/application-notes/model/NotesListModel.hpp @@ -1,4 +1,4 @@ -// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved. +// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved. // For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md #pragma once @@ -6,23 +6,14 @@ #include #include -#include -#include - -#include #include #include "NotesRepository.hpp" +#include "NotesListProvider.hpp" namespace app::notes { - class NotesListItemProvider : public app::DatabaseModel, public gui::ListItemProvider - { - public: - explicit NotesListItemProvider(app::Application *app); - }; - class NotesListModel : public NotesListItemProvider { public: @@ -35,9 +26,8 @@ namespace app::notes [[nodiscard]] gui::ListItem *getItem(gui::Order order) override; [[nodiscard]] unsigned int getMinimalItemHeight() const override; - private: + protected: bool onNotesRetrieved(const std::vector &records, unsigned int notesRepoCount); - std::shared_ptr notesRepository; }; } // namespace app::notes diff --git a/module-apps/application-notes/model/NotesListProvider.hpp b/module-apps/application-notes/model/NotesListProvider.hpp new file mode 100644 index 0000000000000000000000000000000000000000..c4daf7da31ffa54ea4fd4044b166806fb0fde903 --- /dev/null +++ b/module-apps/application-notes/model/NotesListProvider.hpp @@ -0,0 +1,17 @@ +// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved. +// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md + +#pragma once + +#include +#include +#include + +namespace app::notes +{ + class NotesListItemProvider : public app::DatabaseModel, public gui::ListItemProvider + { + public: + explicit NotesListItemProvider(app::Application *app); + }; +} // namespace app::notes diff --git a/module-apps/application-notes/model/NotesRepository.cpp b/module-apps/application-notes/model/NotesRepository.cpp index 77b44a09f76027395d9d2be8b9242e0037a214ed..b100de838eea0ccf5e9e17d291bd5bfd5109de5b 100644 --- a/module-apps/application-notes/model/NotesRepository.cpp +++ b/module-apps/application-notes/model/NotesRepository.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved. +// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved. // For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md #include "NotesRepository.hpp" @@ -33,9 +33,12 @@ namespace app::notes task->execute(application, this); } - void NotesDBRepository::getByText(const std::string &text, const OnFilteredCallback &callback) + void NotesDBRepository::getByText(const std::string &text, + std::uint32_t offset, + std::uint32_t limit, + const OnGetCallback &callback) { - auto query = std::make_unique(text); + auto query = std::make_unique(text, offset, limit); auto task = app::AsyncQuery::createFromQuery(std::move(query), db::Interface::Name::Notes); task->setCallback([callback](auto response) { auto result = dynamic_cast(response); @@ -43,7 +46,7 @@ namespace app::notes return false; } if (callback) { - callback(result->getRecords()); + callback(result->getRecords(), result->getCount()); } return true; }); diff --git a/module-apps/application-notes/model/NotesRepository.hpp b/module-apps/application-notes/model/NotesRepository.hpp index c882054b10b2b22ab8d829064f88c2867180092f..4ce3f8d7bc9cc803089c34f4733e0a746dd4979d 100644 --- a/module-apps/application-notes/model/NotesRepository.hpp +++ b/module-apps/application-notes/model/NotesRepository.hpp @@ -1,4 +1,4 @@ -// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved. +// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved. // For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md #pragma once @@ -15,13 +15,15 @@ namespace app::notes { public: using OnGetCallback = std::function &, unsigned int)>; - using OnFilteredCallback = std::function &)>; using OnResultCallback = std::function; virtual ~AbstractNotesRepository() noexcept = default; virtual void get(std::uint32_t offset, std::uint32_t limit, const OnGetCallback &callback) = 0; - virtual void getByText(const std::string &text, const OnFilteredCallback &callback) = 0; + virtual void getByText(const std::string &text, + std::uint32_t offset, + std::uint32_t limit, + const OnGetCallback &callback) = 0; virtual void save(const NotesRecord ¬e, const OnResultCallback &callback) = 0; virtual void remove(const NotesRecord ¬e, const OnResultCallback &callback) = 0; }; @@ -32,7 +34,10 @@ namespace app::notes explicit NotesDBRepository(Application *application); void get(std::uint32_t offset, std::uint32_t limit, const OnGetCallback &callback) override; - void getByText(const std::string &text, const OnFilteredCallback &callback) override; + void getByText(const std::string &text, + std::uint32_t offset, + std::uint32_t limit, + const OnGetCallback &callback) override; void save(const NotesRecord ¬e, const OnResultCallback &callback) override; void remove(const NotesRecord ¬e, const OnResultCallback &callback) override; diff --git a/module-apps/application-notes/model/NotesSearchListModel.cpp b/module-apps/application-notes/model/NotesSearchListModel.cpp new file mode 100644 index 0000000000000000000000000000000000000000..f38872d8f2bd4269b5452ce14c5a9ee915c3da9c --- /dev/null +++ b/module-apps/application-notes/model/NotesSearchListModel.cpp @@ -0,0 +1,16 @@ +// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved. +// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md + +#include "NotesSearchListModel.hpp" +#include "log/log.hpp" + +namespace app::notes +{ + void NotesSearchListModel::requestRecords(std::uint32_t offset, std::uint32_t limit) + { + notesRepository->getByText( + searchText, offset, limit, [this](const std::vector &records, unsigned int notesRepoCount) { + return onNotesRetrieved(records, notesRepoCount); + }); + } +} // namespace app::notes diff --git a/module-apps/application-notes/model/NotesSearchListModel.hpp b/module-apps/application-notes/model/NotesSearchListModel.hpp new file mode 100644 index 0000000000000000000000000000000000000000..1bade7c7dc318d63407566d503394e45d622f513 --- /dev/null +++ b/module-apps/application-notes/model/NotesSearchListModel.hpp @@ -0,0 +1,32 @@ +// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved. +// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md + +#pragma once + +#include + +#include "NotesListModel.hpp" + +namespace app::notes +{ + + class NotesSearchListModel : public NotesListModel + { + public: + NotesSearchListModel(app::Application *app, std::shared_ptr notesRepository) + : NotesListModel(app, std::move(notesRepository)) + {} + void setSearchText(const std::string &text) + { + searchText = text; + } + void requestRecords(std::uint32_t offset, std::uint32_t limit) override; + const std::string &getSearchText() const noexcept + { + return searchText; + } + + private: + std::string searchText; + }; +} // namespace app::notes diff --git a/module-apps/application-notes/model/SearchResultsListModel.cpp b/module-apps/application-notes/model/SearchResultsListModel.cpp deleted file mode 100644 index fd2dab58020ffabd3aa988c61651afa745003f72..0000000000000000000000000000000000000000 --- a/module-apps/application-notes/model/SearchResultsListModel.cpp +++ /dev/null @@ -1,59 +0,0 @@ -// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved. -// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md - -#include "SearchResultsListModel.hpp" - -#include "module-apps/application-notes/style/NotesListStyle.hpp" -#include "module-apps/application-notes/data/NoteSwitchData.hpp" - -#include -#include - -namespace app::notes -{ - SearchResultsListModel::SearchResultsListModel(Application *application) : application{application} - {} - - void SearchResultsListModel::setResults(const std::vector &results) - { - eraseInternalData(); - for (const auto ¬e : results) { - auto item = createItem(note); - internalData.push_back(std::move(item)); - } - } - - gui::NotesItem *SearchResultsListModel::createItem(const NotesRecord &record) const - { - auto item = new gui::NotesItem(std::make_shared(record)); - item->deleteByList = false; - item->activatedCallback = [this, record](gui::Item &) { - auto data = std::make_unique(record); - data->ignoreCurrentWindowOnStack = true; - application->switchWindow(gui::name::window::note_preview, std::move(data)); - return true; - }; - return item; - } - - void SearchResultsListModel::requestRecords(std::uint32_t offset, std::uint32_t limit) - { - setupModel(offset, limit); - list->onProviderDataUpdate(); - } - - unsigned int SearchResultsListModel::requestRecordsCount() - { - return internalData.size(); - } - - gui::ListItem *SearchResultsListModel::getItem(gui::Order order) - { - return getRecord(order); - } - - unsigned int SearchResultsListModel::getMinimalItemHeight() const - { - return style::list::item::Height; - } -} // namespace app::notes diff --git a/module-apps/application-notes/model/SearchResultsListModel.hpp b/module-apps/application-notes/model/SearchResultsListModel.hpp deleted file mode 100644 index 4df21e9cddbe41453a8c98998cfe5eed7b0024f7..0000000000000000000000000000000000000000 --- a/module-apps/application-notes/model/SearchResultsListModel.hpp +++ /dev/null @@ -1,31 +0,0 @@ -// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved. -// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md - -#pragma once - -#include -#include -#include -#include -#include - -namespace app::notes -{ - class SearchResultsListModel : public InternalModel, public gui::ListItemProvider - { - public: - explicit SearchResultsListModel(Application *application); - - void setResults(const std::vector &results); - - void requestRecords(std::uint32_t offset, std::uint32_t limit) override; - unsigned int requestRecordsCount() override; - unsigned int getMinimalItemHeight() const override; - gui::ListItem *getItem(gui::Order order) override; - - private: - gui::NotesItem *createItem(const NotesRecord &record) const; - - Application *application; - }; -} // namespace app::notes diff --git a/module-apps/application-notes/presenter/NotesMainWindowPresenter.cpp b/module-apps/application-notes/presenter/NotesMainWindowPresenter.cpp index b863ba49b0c2ebb6c9fbef78e4f266bd84f94696..df990a03652c82c4c22b2218ceac818ab0025959 100644 --- a/module-apps/application-notes/presenter/NotesMainWindowPresenter.cpp +++ b/module-apps/application-notes/presenter/NotesMainWindowPresenter.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved. +// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved. // For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md #include "NotesMainWindowPresenter.hpp" @@ -13,14 +13,4 @@ namespace app::notes { return notesProvider; } - - bool NotesMainWindowPresenter::isNoteListEmpty() - { - return notesProvider->requestRecordsCount() == 0U; - } - - bool NotesMainWindowPresenter::updateNotes(std::vector &&records) - { - return notesProvider->updateRecords(std::move(records)); - } } // namespace app::notes diff --git a/module-apps/application-notes/presenter/NotesMainWindowPresenter.hpp b/module-apps/application-notes/presenter/NotesMainWindowPresenter.hpp index 5a68701b674c97de86488ad856ff1f830a151b66..46247cff634458864f7025455f80965c48a27e09 100644 --- a/module-apps/application-notes/presenter/NotesMainWindowPresenter.hpp +++ b/module-apps/application-notes/presenter/NotesMainWindowPresenter.hpp @@ -1,4 +1,4 @@ -// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved. +// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved. // For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md #pragma once @@ -23,8 +23,6 @@ namespace app::notes virtual ~Presenter() noexcept = default; virtual std::shared_ptr getNotesItemProvider() const = 0; - virtual bool isNoteListEmpty() = 0; - virtual bool updateNotes(std::vector &&records) = 0; }; }; @@ -34,8 +32,6 @@ namespace app::notes explicit NotesMainWindowPresenter(std::shared_ptr notesListItemProvider); std::shared_ptr getNotesItemProvider() const override; - bool isNoteListEmpty() override; - bool updateNotes(std::vector &&records) override; private: std::shared_ptr notesProvider; diff --git a/module-apps/application-notes/presenter/NotesSearchResultPresenter.cpp b/module-apps/application-notes/presenter/NotesSearchResultPresenter.cpp new file mode 100644 index 0000000000000000000000000000000000000000..37b29155e7153df6fac4e92b6d3f3d1c743e0eca --- /dev/null +++ b/module-apps/application-notes/presenter/NotesSearchResultPresenter.cpp @@ -0,0 +1,34 @@ +// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved. +// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md + +#include "NotesSearchResultPresenter.hpp" + +namespace app::notes +{ + + NotesSearchWindowPresenter::NotesSearchWindowPresenter(std::shared_ptr notesListItemProvider) + : notesProvider(std::move(notesListItemProvider)) + {} + + std::shared_ptr NotesSearchWindowPresenter::getNotesItemProvider() const + { + return notesProvider; + } + + void NotesSearchWindowPresenter::handleSearchResults(db::NotificationMessage *msgNotification) + { + if (msgNotification->dataModified()) { + getView()->onResultsFilled(); + } + } + + void NotesSearchWindowPresenter::setSearchText(const std::string &text) + { + notesProvider->setSearchText(text); + } + + const std::string &NotesSearchWindowPresenter::getSearchText() const + { + return notesProvider->getSearchText(); + } +} // namespace app::notes diff --git a/module-apps/application-notes/presenter/NotesSearchResultPresenter.hpp b/module-apps/application-notes/presenter/NotesSearchResultPresenter.hpp new file mode 100644 index 0000000000000000000000000000000000000000..72faea96ab55daa371cc2721ef3da2a961a0cb12 --- /dev/null +++ b/module-apps/application-notes/presenter/NotesSearchResultPresenter.hpp @@ -0,0 +1,48 @@ +// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved. +// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md + +#pragma once + +#include + +#include +#include + +namespace app::notes +{ + class NotesSearchWindowContract + { + public: + class View + { + public: + virtual void onNothingFound(const std::string &searchText) = 0; + virtual void onResultsFilled() = 0; + virtual ~View() noexcept = default; + }; + + class Presenter : public BasePresenter + { + public: + virtual ~Presenter() noexcept = default; + virtual std::shared_ptr getNotesItemProvider() const = 0; + virtual void handleSearchResults(db::NotificationMessage *) = 0; + virtual void setSearchText(const std::string &str) = 0; + virtual const std::string &getSearchText() const = 0; + }; + }; + + class NotesSearchWindowPresenter : public NotesSearchWindowContract::Presenter + { + public: + explicit NotesSearchWindowPresenter(std::shared_ptr notesListItemProvider); + + std::shared_ptr getNotesItemProvider() const override; + void handleSearchResults(db::NotificationMessage *msg) override; + virtual void setSearchText(const std::string &text) override; + virtual const std::string &getSearchText() const override; + + private: + std::shared_ptr notesProvider; + }; +} // namespace app::notes diff --git a/module-apps/application-notes/presenter/SearchEngineWindowPresenter.cpp b/module-apps/application-notes/presenter/SearchEngineWindowPresenter.cpp index 9afbf1b91ea2be2b500d7629bd1be40875a5773d..e7cb8243f2f8756c74963e6804cb83872042bf9c 100644 --- a/module-apps/application-notes/presenter/SearchEngineWindowPresenter.cpp +++ b/module-apps/application-notes/presenter/SearchEngineWindowPresenter.cpp @@ -1,21 +1,17 @@ -// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved. +// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved. // For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md #include "SearchEngineWindowPresenter.hpp" +#include namespace app::notes { - SearchEngineWindowPresenter::SearchEngineWindowPresenter(std::unique_ptr &¬esRepository) - : notesRepository{std::move(notesRepository)} - {} - void SearchEngineWindowPresenter::searchFor(const std::string &searchText) { if (searchText.empty()) { - getView()->notesFound({}, searchText); + getView()->emptySearch(); return; } - notesRepository->getByText( - searchText, [searchText, this](const auto &records) { getView()->notesFound(records, searchText); }); + getView()->processValidSearch(searchText); } } // namespace app::notes diff --git a/module-apps/application-notes/presenter/SearchEngineWindowPresenter.hpp b/module-apps/application-notes/presenter/SearchEngineWindowPresenter.hpp index b39c006fbbe489b4b83b517017ba7dfe35ccbc9d..aca92ef17b1f08269ee8a3c9e64d585e3d9548a8 100644 --- a/module-apps/application-notes/presenter/SearchEngineWindowPresenter.hpp +++ b/module-apps/application-notes/presenter/SearchEngineWindowPresenter.hpp @@ -1,11 +1,11 @@ -// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved. +// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved. // For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md #pragma once #include "BasePresenter.hpp" -#include +#include namespace app::notes { @@ -16,14 +16,13 @@ namespace app::notes { public: virtual ~View() noexcept = default; - - virtual void notesFound(const std::vector ¬es, const std::string &searchText) = 0; + virtual void emptySearch() = 0; + virtual void processValidSearch(const std::string &searchText) = 0; }; class Presenter : public BasePresenter { public: virtual ~Presenter() noexcept = default; - virtual void searchFor(const std::string &searchText) = 0; }; }; @@ -31,11 +30,7 @@ namespace app::notes class SearchEngineWindowPresenter : public SearchEngineWindowContract::Presenter { public: - explicit SearchEngineWindowPresenter(std::unique_ptr &¬esRepository); - + SearchEngineWindowPresenter() = default; void searchFor(const std::string &searchText) override; - - private: - std::unique_ptr notesRepository; }; } // namespace app::notes diff --git a/module-apps/application-notes/windows/SearchEngineWindow.cpp b/module-apps/application-notes/windows/SearchEngineWindow.cpp index deda0830d28969805005d32d10a2a9774289fa29..ea1d4ead4263c4bcb04449318ec1443572bf8546 100644 --- a/module-apps/application-notes/windows/SearchEngineWindow.cpp +++ b/module-apps/application-notes/windows/SearchEngineWindow.cpp @@ -53,9 +53,13 @@ namespace app::notes return AppWindow::onInput(inputEvent); } - void SearchEngineWindow::notesFound(const std::vector ¬es, const std::string &searchText) + void SearchEngineWindow::emptySearch() { - application->switchWindow(gui::name::window::notes_search_result, - std::make_unique(searchText, notes)); + application->switchWindow(gui::name::window::notes_search_result, std::make_unique("")); + } + + void SearchEngineWindow::processValidSearch(const std::string &searchText) + { + application->switchWindow(gui::name::window::notes_search_result, std::make_unique(searchText)); } } // namespace app::notes diff --git a/module-apps/application-notes/windows/SearchEngineWindow.hpp b/module-apps/application-notes/windows/SearchEngineWindow.hpp index f844ebd8d30383b678defcc9952a927ea98b16da..02c94741cbd5e87f46812a0c68cac8fc05a172f2 100644 --- a/module-apps/application-notes/windows/SearchEngineWindow.hpp +++ b/module-apps/application-notes/windows/SearchEngineWindow.hpp @@ -1,4 +1,4 @@ -// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved. +// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved. // For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md #pragma once @@ -24,7 +24,8 @@ namespace app::notes void destroyInterface() override; bool onInput(const gui::InputEvent &inputEvent) override; - void notesFound(const std::vector ¬es, const std::string &searchText) override; + void emptySearch() override; + virtual void processValidSearch(const std::string &searchText) override; private: std::unique_ptr presenter; diff --git a/module-apps/application-notes/windows/SearchResultsWindow.cpp b/module-apps/application-notes/windows/SearchResultsWindow.cpp index 1c5a24d3f04515ea72b3b433ff9a6e99e067c05e..d379ba395091cece44b32a0102c7c1217b97c385 100644 --- a/module-apps/application-notes/windows/SearchResultsWindow.cpp +++ b/module-apps/application-notes/windows/SearchResultsWindow.cpp @@ -11,10 +11,9 @@ namespace app::notes { - SearchResultsWindow::SearchResultsWindow(Application *application) - : AppWindow(application, gui::name::window::notes_search_result), listModel{ - std::make_shared( - application)} + SearchResultsWindow::SearchResultsWindow(Application *application, + std::unique_ptr &&windowPresenter) + : AppWindow(application, gui::name::window::notes_search_result), presenter(std::move(windowPresenter)) { buildInterface(); } @@ -39,9 +38,10 @@ namespace app::notes style::list::Y, style::list::Width, style::list::Height, - listModel, + presenter->getNotesItemProvider(), gui::listview::ScrollBarType::Fixed); list->setScrollTopMargin(::style::margins::small); + list->emptyListCallback = [&]() { onNothingFound(presenter->getSearchText()); }; setFocusItem(list); } @@ -53,19 +53,9 @@ namespace app::notes void SearchResultsWindow::onBeforeShow(gui::ShowMode mode, gui::SwitchData *data) { - auto foundNotesData = dynamic_cast(data); - if (foundNotesData == nullptr) { - onNothingFound(); - return; - } - - if (const auto &records = foundNotesData->getFoundRecords(); !records.empty()) { - listModel->setResults(records); + if (auto foundNotesData = dynamic_cast(data); foundNotesData != nullptr) { + presenter->setSearchText(foundNotesData->getSearchText()); list->rebuildList(); - setFocusItem(list); - } - else { - onNothingFound(foundNotesData->getSearchText()); } } @@ -78,4 +68,18 @@ namespace app::notes data->ignoreCurrentWindowOnStack = true; application->switchWindow(gui::name::window::note_dialog, std::move(data)); } + + void SearchResultsWindow::onResultsFilled() + { + list->rebuildList(gui::listview::RebuildType::InPlace); + } + + bool SearchResultsWindow::onDatabaseMessage(sys::Message *msg) + { + if (auto *message = dynamic_cast(msg); + message != nullptr && message->interface == db::Interface::Name::Notes) { + presenter->handleSearchResults(message); + } + return false; + } } // namespace app::notes diff --git a/module-apps/application-notes/windows/SearchResultsWindow.hpp b/module-apps/application-notes/windows/SearchResultsWindow.hpp index 4b80ca5554e2bd96f3cba948dec6df1e8dade204..b75fdcf225549a9a201190e5b96d8b9365b315a2 100644 --- a/module-apps/application-notes/windows/SearchResultsWindow.hpp +++ b/module-apps/application-notes/windows/SearchResultsWindow.hpp @@ -1,4 +1,4 @@ -// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved. +// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved. // For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md #pragma once @@ -8,27 +8,29 @@ #include "AppWindow.hpp" #include -#include +#include #include namespace app::notes { - class SearchResultsWindow : public gui::AppWindow + class SearchResultsWindow : public gui::AppWindow, public NotesSearchWindowContract::View { public: - explicit SearchResultsWindow(Application *application); + explicit SearchResultsWindow(app::Application *app, + std::unique_ptr &&windowPresenter); ~SearchResultsWindow() noexcept override; void buildInterface() override; void destroyInterface() override; - + bool onDatabaseMessage(sys::Message *msg) override; void onBeforeShow(gui::ShowMode mode, gui::SwitchData *data) override; - private: - void onNothingFound(const std::string &searchText = {}); + std::unique_ptr presenter; - std::shared_ptr listModel; + private: + void onNothingFound(const std::string &searchText) override; + virtual void onResultsFilled() override; gui::ListView *list = nullptr; }; } // namespace app::notes diff --git a/module-db/Interface/NotesRecord.cpp b/module-db/Interface/NotesRecord.cpp index 130e4f35791662093de69a24a859377451a19ef0..bdacfa149812ffa95232ec485f19379b3ccba429 100644 --- a/module-db/Interface/NotesRecord.cpp +++ b/module-db/Interface/NotesRecord.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved. +// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved. // For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md #include "NotesRecord.hpp" @@ -105,15 +105,17 @@ std::vector NotesRecordInterface::getNotes(std::uint32_t offset, st return records; } -std::vector NotesRecordInterface::getNotesByText(const std::string &text) const +std::pair, unsigned int> NotesRecordInterface::getNotesByText(const std::string &text, + unsigned int offset, + unsigned int limit) const { std::vector records; - const auto ¬es = notesDB->notes.getByText(text); + auto [notes, count] = notesDB->notes.getByText(text, offset, limit); for (const auto ¬e : notes) { NotesRecord record{note.ID, note.date, note.snippet}; records.push_back(std::move(record)); } - return records; + return {records, count}; } std::unique_ptr NotesRecordInterface::runQuery(std::shared_ptr query) @@ -145,8 +147,8 @@ std::unique_ptr NotesRecordInterface::getQuery(const std::share std::unique_ptr NotesRecordInterface::getByTextQuery(const std::shared_ptr &query) { const auto localQuery = static_cast(query.get()); - const auto &records = getNotesByText(localQuery->getText()); - auto response = std::make_unique(records); + auto [records, count] = getNotesByText(localQuery->getText(), localQuery->getOffset(), localQuery->getLimit()); + auto response = std::make_unique(records, count); response->setRequestQuery(query); return response; } diff --git a/module-db/Interface/NotesRecord.hpp b/module-db/Interface/NotesRecord.hpp index 3dc295bf988b08c6de424dd43ba304e2652ed7ec..f84b6cc394700614a5170880acd8ec9bfaadd66d 100644 --- a/module-db/Interface/NotesRecord.hpp +++ b/module-db/Interface/NotesRecord.hpp @@ -1,4 +1,4 @@ -// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved. +// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved. // For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md #pragma once @@ -47,7 +47,9 @@ class NotesRecordInterface : public RecordInterface getNotes(std::uint32_t offset, std::uint32_t limit) const; - std::vector getNotesByText(const std::string &text) const; + std::pair, unsigned int> getNotesByText(const std::string &text, + unsigned int offset, + unsigned int limit) const; std::unique_ptr getQuery(const std::shared_ptr &query); std::unique_ptr getByTextQuery(const std::shared_ptr &query); diff --git a/module-db/Tables/NotesTable.cpp b/module-db/Tables/NotesTable.cpp index 541e1e229ebe8494b08cdae8403c7adf0c22af59..eb3c339c8ba47f30313881a2d380777bd45cc0f1 100644 --- a/module-db/Tables/NotesTable.cpp +++ b/module-db/Tables/NotesTable.cpp @@ -1,7 +1,9 @@ -// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved. +// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved. // For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md #include "NotesTable.hpp" +#include "log/log.hpp" +#include NotesTable::NotesTable(Database *db) : Table(db) {} @@ -117,11 +119,23 @@ std::vector NotesTable::getLimitOffsetByField(std::uint32_t offse return ret; } -std::vector NotesTable::getByText(const std::string &text) +std::pair, int> NotesTable::getByText(const std::string &text, + unsigned int offset, + unsigned int limit) { - auto retQuery = db->query("SELECT *, INSTR(snippet,'%s') pos FROM notes WHERE pos > 0;", text.c_str()); + + unsigned int count = 0; + auto queryRet = db->query("SELECT COUNT(*), INSTR(snippet,'%s') pos FROM notes WHERE pos > 0;", text.c_str()); + if (queryRet && queryRet->getRowCount() != 0) { + count = (*queryRet)[0].getUInt32(); + } + + std::string queryText = "SELECT *, INSTR(snippet,'" + text + "') pos FROM notes WHERE pos > 0 LIMIT " + + std::to_string(limit) + " offset " + std::to_string(offset) + " ;"; + auto retQuery = db->query(queryText.c_str()); + if (retQuery == nullptr || retQuery->getRowCount() == 0) { - return {}; + return {{}, count}; } std::vector records; @@ -133,7 +147,8 @@ std::vector NotesTable::getByText(const std::string &text) }; records.push_back(std::move(row)); } while (retQuery->nextRow()); - return records; + + return {records, count}; } std::uint32_t NotesTable::count() diff --git a/module-db/Tables/NotesTable.hpp b/module-db/Tables/NotesTable.hpp index 0172ae27b6f23791005df0bf25ce210b595f9b2c..537ff365538041f0629b3a3b1728a657979929d3 100644 --- a/module-db/Tables/NotesTable.hpp +++ b/module-db/Tables/NotesTable.hpp @@ -1,4 +1,4 @@ -// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved. +// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved. // For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md #pragma once @@ -41,8 +41,11 @@ class NotesTable : public Table std::uint32_t limit, NotesTableFields field, const char *str) override; - std::vector getByText(const std::string &text); + std::pair, int> getByText(const std::string &text, + unsigned int offset, + unsigned int limit); std::uint32_t count() override; + std::uint32_t countByText(); std::uint32_t countByFieldId(const char *field, std::uint32_t id) override; }; diff --git a/module-db/queries/notes/QueryNotesGetByText.cpp b/module-db/queries/notes/QueryNotesGetByText.cpp index c61e32f6766519d23bf4a07fe55e22b3bc3f2220..adecfff667aca0a921821297eb437b1c79a9deca 100644 --- a/module-db/queries/notes/QueryNotesGetByText.cpp +++ b/module-db/queries/notes/QueryNotesGetByText.cpp @@ -1,11 +1,14 @@ -// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved. +// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved. // For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md #include "QueryNotesGetByText.hpp" +#include + namespace db::query { - QueryNotesGetByText::QueryNotesGetByText(std::string text) : Query(Query::Type::Read), text{std::move(text)} + QueryNotesGetByText::QueryNotesGetByText(std::string text, unsigned int offset, unsigned int limit) + : Query(Query::Type::Read), offset(offset), limit(limit), text(std::move(text)) {} const std::string &QueryNotesGetByText::getText() const noexcept @@ -18,7 +21,8 @@ namespace db::query return {"QueryNotesGetByText"}; } - NotesGetByTextResult::NotesGetByTextResult(std::vector notes) : records{std::move(notes)} + NotesGetByTextResult::NotesGetByTextResult(std::vector notes, unsigned int count) + : records{std::move(notes)}, dbRecordsCount(count) {} const std::vector &NotesGetByTextResult::getRecords() const noexcept diff --git a/module-db/queries/notes/QueryNotesGetByText.hpp b/module-db/queries/notes/QueryNotesGetByText.hpp index 265f094a5630c86ef600a1379337fe238397ebc2..6689d4cdcfc76ce87fe08169c1da48b228e7f826 100644 --- a/module-db/queries/notes/QueryNotesGetByText.hpp +++ b/module-db/queries/notes/QueryNotesGetByText.hpp @@ -1,4 +1,4 @@ -// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved. +// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved. // For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md #pragma once @@ -13,24 +13,40 @@ namespace db::query class QueryNotesGetByText : public Query { public: - explicit QueryNotesGetByText(std::string text); + explicit QueryNotesGetByText(std::string text, unsigned int offset, unsigned int limit); [[nodiscard]] const std::string &getText() const noexcept; [[nodiscard]] std::string debugInfo() const override; + [[nodiscard]] unsigned int getOffset() const noexcept + { + return offset; + } + [[nodiscard]] unsigned int getLimit() const noexcept + { + return limit; + }; + private: + unsigned int offset; + unsigned int limit; std::string text; }; class NotesGetByTextResult : public QueryResult { public: - explicit NotesGetByTextResult(std::vector notes); + explicit NotesGetByTextResult(std::vector notes, unsigned int count); [[nodiscard]] const std::vector &getRecords() const noexcept; + [[nodiscard]] unsigned int getCount() const noexcept + { + return dbRecordsCount; + } [[nodiscard]] std::string debugInfo() const override; private: std::vector records; + unsigned int dbRecordsCount; }; } // namespace db::query diff --git a/module-db/tests/NotesRecord_tests.cpp b/module-db/tests/NotesRecord_tests.cpp index bf3df385870f06059c9bec1706b396a96073f900..1660169a490c25279213307b7c435dc49019ef70 100644 --- a/module-db/tests/NotesRecord_tests.cpp +++ b/module-db/tests/NotesRecord_tests.cpp @@ -46,7 +46,7 @@ TEST_CASE("Notes Record tests") SECTION("Get notes by text query") { constexpr auto testSearch = "TEST"; - auto query = std::make_unique(testSearch); + auto query = std::make_unique(testSearch, 0, 3); auto response = notesRecordInterface.runQuery(std::move(query)); auto getResult = static_cast(response.get()); diff --git a/module-db/tests/NotesTable_tests.cpp b/module-db/tests/NotesTable_tests.cpp index cbcb2534d9c3a1ca36fab4fe3129e64de7db8db4..04c1654c6db41d694f870aa7159cd48722f668dc 100644 --- a/module-db/tests/NotesTable_tests.cpp +++ b/module-db/tests/NotesTable_tests.cpp @@ -38,7 +38,7 @@ TEST_CASE("Notes Table tests") SECTION("Get notes by text query") { constexpr auto testSearch = "TEST"; - const auto &records = table.getByText(testSearch); + const auto [records, count] = table.getByText(testSearch, 0, 1); REQUIRE(records.size() == 1); REQUIRE(records[0].snippet == testSnippet); }