From c8c4f82080c1fd95c54c4fc28d64b9eed2255f92 Mon Sep 17 00:00:00 2001 From: Piotr Tanski Date: Mon, 30 Nov 2020 13:48:05 +0100 Subject: [PATCH] [EGD-4487] Application notes implemented. (#1094) * [EGD-4487] Implementation of notes application. --- changelog.md | 1 + image/assets/lang/English.json | 10 +- image/user/db/notes_001.sql | 3 +- image/user/db/notes_002.sql | 52 ++--- module-apps/BasePresenter.hpp | 29 +++ .../application-notes/ApplicationNotes.cpp | 95 ++++++---- .../application-notes/ApplicationNotes.hpp | 30 +-- module-apps/application-notes/CMakeLists.txt | 37 ++-- module-apps/application-notes/NotesModel.cpp | 57 ------ module-apps/application-notes/NotesModel.hpp | 33 ---- .../application-notes/data/NoteSwitchData.cpp | 16 ++ .../application-notes/data/NoteSwitchData.hpp | 22 +++ .../model/NotesListModel.cpp | 81 ++++++++ .../model/NotesListModel.hpp | 43 +++++ .../model/NotesRepository.cpp | 64 +++++++ .../model/NotesRepository.hpp | 39 ++++ .../presenter/NoteEditWindowPresenter.cpp | 16 ++ .../presenter/NoteEditWindowPresenter.hpp | 39 ++++ .../presenter/NotePreviewWindowPresenter.cpp | 16 ++ .../presenter/NotePreviewWindowPresenter.hpp | 39 ++++ .../presenter/NotesMainWindowPresenter.cpp | 26 +++ .../presenter/NotesMainWindowPresenter.hpp | 43 +++++ .../application-notes/style/NoteEditStyle.hpp | 25 +++ .../style/NotePreviewStyle.hpp | 24 +++ .../style/NotesListStyle.hpp | 45 +++++ .../style/NotesMainWindowStyle.hpp | 37 ++++ .../application-notes/widgets/NotesItem.cpp | 105 +++++----- .../application-notes/widgets/NotesItem.hpp | 52 ++--- .../windows/NoteEditWindow.cpp | 152 +++++++++++++++ .../windows/NoteEditWindow.hpp | 43 +++++ .../windows/NoteMainWindow.cpp | 179 ++++++++++++++++++ .../windows/NoteMainWindow.hpp | 46 +++++ .../windows/NotePreviewWindow.cpp | 129 +++++++++++++ .../windows/NotePreviewWindow.hpp | 39 ++++ .../windows/NotesEditWindow.cpp | 88 --------- .../windows/NotesEditWindow.hpp | 41 ---- .../windows/NotesMainWindow.cpp | 86 --------- .../windows/NotesMainWindow.hpp | 44 ----- .../windows/NotesOptions.cpp | 108 +++++++++++ .../windows/NotesOptions.hpp | 25 +++ module-db/CMakeLists.txt | 3 + module-db/Interface/NotesRecord.cpp | 155 ++++++++++----- module-db/Interface/NotesRecord.hpp | 58 +++--- module-db/Interface/Record.hpp | 5 + module-db/Tables/NotesTable.cpp | 86 +++------ module-db/Tables/NotesTable.hpp | 43 ++--- module-db/Tables/Table.hpp | 8 +- module-db/queries/notes/QueryNoteRemove.cpp | 33 ++++ module-db/queries/notes/QueryNoteRemove.hpp | 35 ++++ module-db/queries/notes/QueryNoteStore.cpp | 33 ++++ module-db/queries/notes/QueryNoteStore.hpp | 36 ++++ module-db/queries/notes/QueryNotesGet.cpp | 45 +++++ module-db/queries/notes/QueryNotesGet.hpp | 40 ++++ module-db/tests/CMakeLists.txt | 3 +- module-db/tests/NotesRecord_tests.cpp | 67 +++++++ module-db/tests/NotesTable_tests.cpp | 65 +++++++ 56 files changed, 2094 insertions(+), 680 deletions(-) create mode 100644 module-apps/BasePresenter.hpp delete mode 100644 module-apps/application-notes/NotesModel.cpp delete mode 100644 module-apps/application-notes/NotesModel.hpp create mode 100644 module-apps/application-notes/data/NoteSwitchData.cpp create mode 100644 module-apps/application-notes/data/NoteSwitchData.hpp create mode 100644 module-apps/application-notes/model/NotesListModel.cpp create mode 100644 module-apps/application-notes/model/NotesListModel.hpp create mode 100644 module-apps/application-notes/model/NotesRepository.cpp create mode 100644 module-apps/application-notes/model/NotesRepository.hpp create mode 100644 module-apps/application-notes/presenter/NoteEditWindowPresenter.cpp create mode 100644 module-apps/application-notes/presenter/NoteEditWindowPresenter.hpp create mode 100644 module-apps/application-notes/presenter/NotePreviewWindowPresenter.cpp create mode 100644 module-apps/application-notes/presenter/NotePreviewWindowPresenter.hpp create mode 100644 module-apps/application-notes/presenter/NotesMainWindowPresenter.cpp create mode 100644 module-apps/application-notes/presenter/NotesMainWindowPresenter.hpp create mode 100644 module-apps/application-notes/style/NoteEditStyle.hpp create mode 100644 module-apps/application-notes/style/NotePreviewStyle.hpp create mode 100644 module-apps/application-notes/style/NotesListStyle.hpp create mode 100644 module-apps/application-notes/style/NotesMainWindowStyle.hpp create mode 100644 module-apps/application-notes/windows/NoteEditWindow.cpp create mode 100644 module-apps/application-notes/windows/NoteEditWindow.hpp create mode 100644 module-apps/application-notes/windows/NoteMainWindow.cpp create mode 100644 module-apps/application-notes/windows/NoteMainWindow.hpp create mode 100644 module-apps/application-notes/windows/NotePreviewWindow.cpp create mode 100644 module-apps/application-notes/windows/NotePreviewWindow.hpp delete mode 100644 module-apps/application-notes/windows/NotesEditWindow.cpp delete mode 100644 module-apps/application-notes/windows/NotesEditWindow.hpp delete mode 100644 module-apps/application-notes/windows/NotesMainWindow.cpp delete mode 100644 module-apps/application-notes/windows/NotesMainWindow.hpp create mode 100644 module-apps/application-notes/windows/NotesOptions.cpp create mode 100644 module-apps/application-notes/windows/NotesOptions.hpp create mode 100644 module-db/queries/notes/QueryNoteRemove.cpp create mode 100644 module-db/queries/notes/QueryNoteRemove.hpp create mode 100644 module-db/queries/notes/QueryNoteStore.cpp create mode 100644 module-db/queries/notes/QueryNoteStore.hpp create mode 100644 module-db/queries/notes/QueryNotesGet.cpp create mode 100644 module-db/queries/notes/QueryNotesGet.hpp create mode 100644 module-db/tests/NotesRecord_tests.cpp create mode 100644 module-db/tests/NotesTable_tests.cpp diff --git a/changelog.md b/changelog.md index feb913a44c95bc3b973cf2a364920fc1c3eacd83..89ed363380bd8037ae1f4eae47adbbeaaf21d86e 100644 --- a/changelog.md +++ b/changelog.md @@ -3,6 +3,7 @@ [Current release] ### Added +* `[notes]` Notes application implemented. ### Changed diff --git a/image/assets/lang/English.json b/image/assets/lang/English.json index a3cc90a3f272ad3886f245bbf273e46d84fdffa9..0b5cbd434c47ac04b7957dbf71eb4f77d7d5af2a 100644 --- a/image/assets/lang/English.json +++ b/image/assets/lang/English.json @@ -122,10 +122,14 @@ "app_options_contact_edit": "Edit Contact", "app_notes_title_main": "Notes", - "app_notes_new_note": "New Note", - "app_notes_save": "SAVE", + "app_notes_edit_new_note": "Edit/New Note", + "app_notes_copy_text": "Copy text", + "app_notes_copy_paste": "Paste text", "app_notes_edit": "EDIT", - "app_notes_back": "BACK", + "app_notes_edited": "Edited", + "app_notes_delete_note": "Delete", + "app_notes_note_delete_confirmation": "Do you really want to delete this note?", + "app_notes_no_notes": "There are no notes yet.\nPress Left arrow to add new.", "app_calllog_title_main": "Calls", "app_calllog_new_note": "New Note", diff --git a/image/user/db/notes_001.sql b/image/user/db/notes_001.sql index 1404dd81aab8d1d3dc010b9e7aca2fc46a0263dd..1f6affaa960e2d7ff50c1950fa66466e5ade30d1 100644 --- a/image/user/db/notes_001.sql +++ b/image/user/db/notes_001.sql @@ -1,6 +1,5 @@ CREATE TABLE IF NOT EXISTS notes( _id INTEGER PRIMARY KEY, date INTEGER, - snippet TEXT DEFAULT '', - path TEXT DEFAULT '' + snippet TEXT DEFAULT '' ); diff --git a/image/user/db/notes_002.sql b/image/user/db/notes_002.sql index 3ca8d803646d45b0ce1b2b524bb447d34fc1f413..31edc61a3406cc1b94a1e3dbbf9cbae3f7c6343a 100644 --- a/image/user/db/notes_002.sql +++ b/image/user/db/notes_002.sql @@ -1,36 +1,36 @@ BEGIN; -INSERT OR IGNORE INTO notes ("_id","date","snippet","path") VALUES (1,1565586181,'snippet 1','/data/applications/notes/1565586181.txt'); -INSERT OR IGNORE INTO notes ("_id","date","snippet","path") VALUES (2,1565586381,'snippet 2 +INSERT OR IGNORE INTO notes ("_id","date","snippet") VALUES (1,1565586181,'snippet 1'); +INSERT OR IGNORE INTO notes ("_id","date","snippet") VALUES (2,1565586381,'snippet 2 222 222 -222','/data/applications/notes/1565586381.txt'); -INSERT OR IGNORE INTO notes ("_id","date","snippet","path") VALUES (3,1565588181,'snippet 3 -333333333333333333333333333333333333333333333333333','/data/applications/notes/1565588181.txt'); -INSERT OR IGNORE INTO notes ("_id","date","snippet","path") VALUES (4,1565596181,'snippet 4 4444444444444444444444444444444444444444444444444444444444444444444444444444','/data/applications/notes/1565596181.txt'); -INSERT OR IGNORE INTO notes ("_id","date","snippet","path") VALUES (5,1565606181,'snippet 5 555555 +222'); +INSERT OR IGNORE INTO notes ("_id","date","snippet") VALUES (3,1565588181,'snippet 3 +333333333333333333333333333333333333333333333333333'); +INSERT OR IGNORE INTO notes ("_id","date","snippet") VALUES (4,1565596181,'snippet 4 4444444444444444444444444444444444444444444444444444444444444444444444444444'); +INSERT OR IGNORE INTO notes ("_id","date","snippet") VALUES (5,1565606181,'snippet 5 555555 555555555 -55555','/data/applications/notes/1565606181.txt'); -INSERT OR IGNORE INTO notes ("_id","date","snippet","path") VALUES (6,1565616181,'snippet 66666 66666 66666 66666 66666','/data/applications/notes/1565616181.txt'); -INSERT OR IGNORE INTO notes ("_id","date","snippet","path") VALUES (7,1565626181,'snippet 7 -','/data/applications/notes/1565626181.txt'); -INSERT OR IGNORE INTO notes ("_id","date","snippet","path") VALUES (8,1565646181,'snippet 8 +55555'); +INSERT OR IGNORE INTO notes ("_id","date","snippet") VALUES (6,1565616181,'snippet 66666 66666 66666 66666 66666'); +INSERT OR IGNORE INTO notes ("_id","date","snippet") VALUES (7,1565626181,'snippet 7 +'); +INSERT OR IGNORE INTO notes ("_id","date","snippet") VALUES (8,1565646181,'snippet 8 -8','/data/applications/notes/1565646181.txt'); -INSERT OR IGNORE INTO notes ("_id","date","snippet","path") VALUES (9,1565666181,'snippet 9 +8'); +INSERT OR IGNORE INTO notes ("_id","date","snippet") VALUES (9,1565666181,'snippet 9 -9','/data/applications/notes/1565666181.txt'); -INSERT OR IGNORE INTO notes ("_id","date","snippet","path") VALUES (10,1565686181,'snippet 10 +9'); +INSERT OR IGNORE INTO notes ("_id","date","snippet") VALUES (10,1565686181,'snippet 10 10 -10','/data/applications/notes/1565686181.txt'); -INSERT OR IGNORE INTO notes ("_id","date","snippet","path") VALUES (11,1565706181,'snippet 11','/data/applications/notes/1565706181.txt'); -INSERT OR IGNORE INTO notes ("_id","date","snippet","path") VALUES (12,1565726181,'snippet 12','/data/applications/notes/1565726181.txt'); -INSERT OR IGNORE INTO notes ("_id","date","snippet","path") VALUES (13,1565746181,'snippet 13','/data/applications/notes/1565746181.txt'); -INSERT OR IGNORE INTO notes ("_id","date","snippet","path") VALUES (14,1565766181,'snippet 14','/data/applications/notes/1565766181.txt'); -INSERT OR IGNORE INTO notes ("_id","date","snippet","path") VALUES (15,1565786181,'snippet 15','/data/applications/notes/1565786181.txt'); -INSERT OR IGNORE INTO notes ("_id","date","snippet","path") VALUES (16,1565806181,'snippet 16 -','/data/applications/notes/1565806181.txt'); -INSERT OR IGNORE INTO notes ("_id","date","snippet","path") VALUES (17,1565826181,'snippet 17 +10'); +INSERT OR IGNORE INTO notes ("_id","date","snippet") VALUES (11,1565706181,'snippet 11'); +INSERT OR IGNORE INTO notes ("_id","date","snippet") VALUES (12,1565726181,'snippet 12'); +INSERT OR IGNORE INTO notes ("_id","date","snippet") VALUES (13,1565746181,'snippet 13'); +INSERT OR IGNORE INTO notes ("_id","date","snippet") VALUES (14,1565766181,'snippet 14'); +INSERT OR IGNORE INTO notes ("_id","date","snippet") VALUES (15,1565786181,'snippet 15'); +INSERT OR IGNORE INTO notes ("_id","date","snippet") VALUES (16,1565806181,'snippet 16 +'); +INSERT OR IGNORE INTO notes ("_id","date","snippet") VALUES (17,1565826181,'snippet 17 17 -17','/data/applications/notes/1565826181.txt'); +17'); COMMIT; diff --git a/module-apps/BasePresenter.hpp b/module-apps/BasePresenter.hpp new file mode 100644 index 0000000000000000000000000000000000000000..f64851cb4062c3ebe14adadac8e16725f1ca1e67 --- /dev/null +++ b/module-apps/BasePresenter.hpp @@ -0,0 +1,29 @@ +// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved. +// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md + +#pragma once + +#include + +namespace app +{ + template class BasePresenter + { + public: + virtual ~BasePresenter() noexcept = default; + + void attach(VIEW *oth) noexcept + { + view = oth; + } + + VIEW *getView() const noexcept + { + assert(view != nullptr); + return view; + } + + private: + VIEW *view = nullptr; + }; +} // namespace app diff --git a/module-apps/application-notes/ApplicationNotes.cpp b/module-apps/application-notes/ApplicationNotes.cpp index ad4fe99545bc859a8b4ce22942eb735089b420a7..9da802e578a2eab9a4455ea543e0c18f6f225785 100644 --- a/module-apps/application-notes/ApplicationNotes.cpp +++ b/module-apps/application-notes/ApplicationNotes.cpp @@ -1,67 +1,70 @@ // Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved. // For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md +#include "ApplicationNotes.hpp" + #include "MessageType.hpp" -#include "windows/NotesMainWindow.hpp" -#include "windows/NotesEditWindow.hpp" +#include "windows/NoteMainWindow.hpp" +#include "windows/NotePreviewWindow.hpp" +#include "windows/NoteEditWindow.hpp" + #include +#include -#include "ApplicationNotes.hpp" +#include +#include +#include +#include +#include namespace app { + namespace + { + constexpr auto NotesStackSize = 4096U; + } // namespace + ApplicationNotes::ApplicationNotes(std::string name, std::string parent, StartInBackground startInBackground) - : Application(name, parent, startInBackground, 4096) + : Application(name, parent, startInBackground, NotesStackSize) {} - ApplicationNotes::~ApplicationNotes() - { - LOG_INFO("deleting"); - } - // Invoked upon receiving data message sys::MessagePointer ApplicationNotes::DataReceivedHandler(sys::DataMessage *msgl, sys::ResponseMessage *resp) { - auto retMsg = Application::DataReceivedHandler(msgl); // if message was handled by application's template there is no need to process further. - if ((reinterpret_cast(retMsg.get())->retCode == sys::ReturnCodes::Success)) { + if (static_cast(retMsg.get())->retCode == sys::ReturnCodes::Success) { return retMsg; } - bool handled = false; - - // handle database response if (resp != nullptr) { - handled = true; switch (resp->responseTo) { - case MessageType::DBNotesGetLimitOffset: { - if (getCurrentWindow()->onDatabaseMessage(resp)) - refreshWindow(gui::RefreshModes::GUI_REFRESH_FAST); - } break; + case MessageType::DBQuery: + if (auto queryResponse = dynamic_cast(resp); queryResponse != nullptr) { + if (auto result = queryResponse->getResult(); result && result->hasListener()) { + if (result->handle()) { + refreshWindow(gui::RefreshModes::GUI_REFRESH_FAST); + } + } + } + break; default: break; } + return msgHandled(); } - - if (handled) - return std::make_shared(); - else - return std::make_shared(sys::ReturnCodes::Unresolved); + return msgNotHandled(); } - // Invoked during initialization sys::ReturnCodes ApplicationNotes::InitHandler() { - - auto ret = Application::InitHandler(); - if (ret != sys::ReturnCodes::Success) + const auto ret = Application::InitHandler(); + if (ret != sys::ReturnCodes::Success) { return ret; + } createUserInterface(); - setActiveWindow(gui::name::window::main_window); - return ret; } @@ -70,17 +73,37 @@ namespace app return sys::ReturnCodes::Success; } + sys::ReturnCodes ApplicationNotes::SwitchPowerModeHandler(const sys::ServicePowerMode mode) + { + return sys::ReturnCodes::Success; + } + void ApplicationNotes::createUserInterface() { - windowsFactory.attach(gui::name::window::main_window, [](Application *app, const std::string &name) { - return std::make_unique(app); + windowsFactory.attach(gui::name::window::main_window, [this](Application *app, const std::string &name) { + auto notesRepository = std::make_unique(this); + auto notesProvider = std::make_shared(this, std::move(notesRepository)); + auto presenter = std::make_unique(notesProvider); + return std::make_unique(app, std::move(presenter)); }); - windowsFactory.attach(gui::name::window::main_window, [](Application *app, const std::string &name) { - return std::make_unique(app); + windowsFactory.attach(gui::name::window::note_preview, [this](Application *app, const std::string &name) { + auto notesRepository = std::make_unique(this); + auto presenter = std::make_unique(std::move(notesRepository)); + return std::make_unique(app, std::move(presenter)); }); + windowsFactory.attach(gui::name::window::note_edit, [this](Application *app, const std::string &name) { + auto notesRepository = std::make_unique(this); + auto presenter = std::make_unique(std::move(notesRepository)); + return std::make_unique(app, std::move(presenter)); + }); + windowsFactory.attach(gui::name::window::note_confirm_dialog, [](Application *app, const std::string &name) { + return std::make_unique(app, name); + }); + windowsFactory.attach( + utils::localize.get("app_phonebook_options_title"), + [](Application *app, const std::string &name) { return std::make_unique(app, name); }); } void ApplicationNotes::destroyUserInterface() {} - -} /* namespace app */ +} // namespace app diff --git a/module-apps/application-notes/ApplicationNotes.hpp b/module-apps/application-notes/ApplicationNotes.hpp index 0411a8284680d65578fd1dee9c26afc6b8158459..b6d5c33649d2c70b13711798f48c9682299d3279 100644 --- a/module-apps/application-notes/ApplicationNotes.hpp +++ b/module-apps/application-notes/ApplicationNotes.hpp @@ -1,12 +1,18 @@ // Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved. // For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md -#ifndef MODULE_APPS_APPLICATION_NOTES_APPLICATIONNOTES_HPP_ -#define MODULE_APPS_APPLICATION_NOTES_APPLICATIONNOTES_HPP_ +#pragma once -#include "NotesModel.hpp" +#include "module-apps/application-notes/model/NotesListModel.hpp" #include "Application.hpp" +namespace gui::name::window +{ + inline constexpr auto note_preview = "NotePreview"; + inline constexpr auto note_edit = "NoteEdit"; + inline constexpr auto note_confirm_dialog = "ConfirmDialog"; +} // namespace gui::name::window + namespace app { inline constexpr auto name_notes = "ApplicationNotes"; @@ -14,18 +20,14 @@ namespace app class ApplicationNotes : public Application { public: - ApplicationNotes(std::string name = name_notes, - std::string parent = {}, - StartInBackground startInBackground = {false}); - virtual ~ApplicationNotes(); + explicit ApplicationNotes(std::string name = name_notes, + std::string parent = {}, + StartInBackground startInBackground = {false}); + sys::MessagePointer DataReceivedHandler(sys::DataMessage *msgl, sys::ResponseMessage *resp) override; sys::ReturnCodes InitHandler() override; sys::ReturnCodes DeinitHandler() override; - - sys::ReturnCodes SwitchPowerModeHandler(const sys::ServicePowerMode mode) override final - { - return sys::ReturnCodes::Success; - } + sys::ReturnCodes SwitchPowerModeHandler(const sys::ServicePowerMode mode) override; void createUserInterface() override; void destroyUserInterface() override; @@ -38,6 +40,4 @@ namespace app return {{manager::actions::Launch}}; } }; -} /* namespace app */ - -#endif /* MODULE_APPS_APPLICATION_NOTES_APPLICATIONNOTES_HPP_ */ +} // namespace app diff --git a/module-apps/application-notes/CMakeLists.txt b/module-apps/application-notes/CMakeLists.txt index be9d5cbdbf4b6257446cf3df32478d36df1d8166..f34ccd6c7587022a6100f656a85549827258a461 100644 --- a/module-apps/application-notes/CMakeLists.txt +++ b/module-apps/application-notes/CMakeLists.txt @@ -1,12 +1,9 @@ - -include_directories( ${CMAKE_PROJECT_NAME} - +include_directories( ${CMAKE_PROJECT_NAME} PUBLIC "${CMAKE_CURRENT_LIST_DIR}" ) include_directories( ${PROJECT_NAME} - PUBLIC "${CMAKE_CURRENT_LIST_DIR}" ) @@ -15,19 +12,33 @@ target_sources( ${PROJECT_NAME} PRIVATE "${CMAKE_CURRENT_LIST_DIR}/ApplicationNotes.cpp" - "${CMAKE_CURRENT_LIST_DIR}/NotesModel.cpp" + "${CMAKE_CURRENT_LIST_DIR}/model/NotesListModel.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}/widgets/NotesItem.cpp" - "${CMAKE_CURRENT_LIST_DIR}/windows/NotesMainWindow.cpp" - "${CMAKE_CURRENT_LIST_DIR}/windows/NotesEditWindow.cpp" - + "${CMAKE_CURRENT_LIST_DIR}/windows/NoteMainWindow.cpp" + "${CMAKE_CURRENT_LIST_DIR}/windows/NotePreviewWindow.cpp" + "${CMAKE_CURRENT_LIST_DIR}/windows/NoteEditWindow.cpp" + "${CMAKE_CURRENT_LIST_DIR}/windows/NotesOptions.cpp" + "${CMAKE_CURRENT_LIST_DIR}/data/NoteSwitchData.cpp" PUBLIC "${CMAKE_CURRENT_LIST_DIR}/ApplicationNotes.hpp" - "${CMAKE_CURRENT_LIST_DIR}/NotesModel.hpp" - "${CMAKE_CURRENT_LIST_DIR}/windows/NotesMainWindow.hpp" - "${CMAKE_CURRENT_LIST_DIR}/windows/NotesEditWindow.hpp" + "${CMAKE_CURRENT_LIST_DIR}/model/NotesListModel.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}/widgets/NotesItem.hpp" + "${CMAKE_CURRENT_LIST_DIR}/windows/NoteMainWindow.hpp" + "${CMAKE_CURRENT_LIST_DIR}/windows/NotePreviewWindow.hpp" + "${CMAKE_CURRENT_LIST_DIR}/windows/NoteEditWindow.hpp" + "${CMAKE_CURRENT_LIST_DIR}/windows/NotesOptions.hpp" + "${CMAKE_CURRENT_LIST_DIR}/data/NoteSwitchData.hpp" ) -target_include_directories( ${PROJECT_NAME} +target_include_directories(${PROJECT_NAME} PRIVATE service-db - ) +) diff --git a/module-apps/application-notes/NotesModel.cpp b/module-apps/application-notes/NotesModel.cpp deleted file mode 100644 index 64d7a6363ad80cadad89edc1b064fdda1e753266..0000000000000000000000000000000000000000 --- a/module-apps/application-notes/NotesModel.cpp +++ /dev/null @@ -1,57 +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 -#include "widgets/NotesItem.hpp" - -#include "NotesModel.hpp" -#include "ListView.hpp" - -#include -#include - -NotesModel::NotesModel(app::Application *app) : DatabaseModel(app) -{} - -unsigned int NotesModel::requestRecordsCount() -{ - recordsCount = DBServiceAPI::NotesGetCount(application); - return recordsCount; -} - -void NotesModel::requestRecords(const uint32_t offset, const uint32_t limit) -{ - DBServiceAPI::NotesGetLimitOffset(application, offset, limit); -} - -bool NotesModel::updateRecords(std::vector records) -{ -#if DEBUG_DB_MODEL_DATA == 1 - LOG_DEBUG("Offset: %" PRIu32 ", Limit: %" PRIu32 " Count: %" PRIu32 "", offset, limit, count); - for (uint32_t i = 0; i < records.get()->size(); ++i) { - LOG_DEBUG("id: %" PRIu32 ", filename: %s", - records.get()->operator[](i).ID, - records.get()->operator[](i).path.c_str()); - } -#endif - - DatabaseModel::updateRecords(std::move(records)); - list->onProviderDataUpdate(); - - return true; -} - -unsigned int NotesModel::getMinimalItemHeight() const -{ - return 146; -} - -gui::ListItem *NotesModel::getItem(gui::Order order) -{ - std::shared_ptr note = getRecord(order); - - auto *item = new gui::NotesItem(this, !(application->isTimeFormat12())); - - item->setNote(note); - return item; -} diff --git a/module-apps/application-notes/NotesModel.hpp b/module-apps/application-notes/NotesModel.hpp deleted file mode 100644 index 0f47b685fe3abd6747b36f2f8daf0e641a774367..0000000000000000000000000000000000000000 --- a/module-apps/application-notes/NotesModel.hpp +++ /dev/null @@ -1,33 +0,0 @@ -// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved. -// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md - -#ifndef MODULE_APPS_APPLICATION_NOTES_NOTESMODEL_HPP_ -#define MODULE_APPS_APPLICATION_NOTES_NOTESMODEL_HPP_ - -#include - -#include "Interface/NotesRecord.hpp" -#include "DatabaseModel.hpp" -#include "NotesRecord.hpp" -#include "Application.hpp" -#include "ListItemProvider.hpp" - -/* - * - */ -class NotesModel : public app::DatabaseModel, public gui::ListItemProvider -{ - public: - NotesModel(app::Application *app); - - // virtual methods - bool updateRecords(std::vector records) override; - void requestRecords(const uint32_t offset, const uint32_t limit) override; - - // virtual methods for ListViewProvider - unsigned int getMinimalItemHeight() const override; - gui::ListItem *getItem(gui::Order order) override; - [[nodiscard]] unsigned int requestRecordsCount() override; -}; - -#endif /* MODULE_APPS_APPLICATION_NOTES_NOTESMODEL_HPP_ */ diff --git a/module-apps/application-notes/data/NoteSwitchData.cpp b/module-apps/application-notes/data/NoteSwitchData.cpp new file mode 100644 index 0000000000000000000000000000000000000000..70b944adc7ec69c96812aafec79901077b9e0f64 --- /dev/null +++ b/module-apps/application-notes/data/NoteSwitchData.cpp @@ -0,0 +1,16 @@ +// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved. +// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md + +#include "NoteSwitchData.hpp" + +namespace app::notes +{ + NoteSwitchData::NoteSwitchData(NotesRecord record) + : gui::SwitchData(std::string{"NotePreview"}), record{std::move(record)} + {} + + const NotesRecord &NoteSwitchData::getRecord() const noexcept + { + return record; + } +} // namespace app::notes diff --git a/module-apps/application-notes/data/NoteSwitchData.hpp b/module-apps/application-notes/data/NoteSwitchData.hpp new file mode 100644 index 0000000000000000000000000000000000000000..16ba077981b8bf132540ebce88b34dcd753f44ed --- /dev/null +++ b/module-apps/application-notes/data/NoteSwitchData.hpp @@ -0,0 +1,22 @@ +// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved. +// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md + +#pragma once + +#include + +#include + +namespace app::notes +{ + class NoteSwitchData : public gui::SwitchData + { + public: + explicit NoteSwitchData(NotesRecord record); + + const NotesRecord &getRecord() const noexcept; + + private: + NotesRecord record; + }; +} // namespace app::notes diff --git a/module-apps/application-notes/model/NotesListModel.cpp b/module-apps/application-notes/model/NotesListModel.cpp new file mode 100644 index 0000000000000000000000000000000000000000..8d8092f2b77e15c06bb31f8c85579acdde8db7c2 --- /dev/null +++ b/module-apps/application-notes/model/NotesListModel.cpp @@ -0,0 +1,81 @@ +// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved. +// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md + +#include "NotesListModel.hpp" + +#include "module-apps/application-notes/widgets/NotesItem.hpp" +#include "module-apps/application-notes/style/NotesListStyle.hpp" +#include "module-apps/application-notes/windows/NotesOptions.hpp" +#include "module-apps/application-notes/data/NoteSwitchData.hpp" +#include + +#include +#include + +namespace app::notes +{ + NotesListItemProvider::NotesListItemProvider(Application *app) : DatabaseModel(app) + {} + + NotesListModel::NotesListModel(app::Application *app, std::shared_ptr notesRepository) + : NotesListItemProvider(app), notesRepository{std::move(notesRepository)} + {} + + unsigned int NotesListModel::requestRecordsCount() + { + return recordsCount; + } + + bool NotesListModel::updateRecords(std::vector records) + { + DatabaseModel::updateRecords(std::move(records)); + list->onProviderDataUpdate(); + return true; + } + + unsigned int NotesListModel::getMinimalItemHeight() const + { + return style::list::item::Height; + } + + gui::ListItem *NotesListModel::getItem(gui::Order order) + { + std::shared_ptr note = getRecord(order); + if (!note) { + return nullptr; + } + + auto item = new gui::NotesItem(note); + item->activatedCallback = [this, note = note.get()](gui::Item &) { + application->switchWindow(gui::name::window::note_preview, std::make_unique(*note)); + return true; + }; + item->inputCallback = [this, note = note.get()](gui::Item &, const gui::InputEvent &event) { + if (event.isShortPress() && event.is(gui::KeyCode::KEY_LF)) { + application->switchWindow( + utils::localize.get("app_phonebook_options_title"), + std::make_unique(noteListOptions(application, *note, *notesRepository))); + } + return false; + }; + return item; + } + + void NotesListModel::requestRecords(uint32_t offset, uint32_t limit) + { + notesRepository->get( + offset, limit, [this](const std::vector &records, unsigned int notesRepoCount) { + return onNotesRetrieved(records, notesRepoCount); + }); + } + + bool NotesListModel::onNotesRetrieved(const std::vector &records, unsigned int notesRepoCount) + { + if (recordsCount != notesRepoCount) { + recordsCount = notesRepoCount; + list->rebuildList(::style::listview::RebuildType::Full, 0, true); + return false; + } + return updateRecords(records); + } +} // namespace app::notes diff --git a/module-apps/application-notes/model/NotesListModel.hpp b/module-apps/application-notes/model/NotesListModel.hpp new file mode 100644 index 0000000000000000000000000000000000000000..7e157a326b03ad64cf6d2b814604717cecf6f925 --- /dev/null +++ b/module-apps/application-notes/model/NotesListModel.hpp @@ -0,0 +1,43 @@ +// Copyright (c) 2017-2020, 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 + +#include + +#include "NotesRepository.hpp" + +namespace app::notes +{ + class NotesListItemProvider : public app::DatabaseModel, public gui::ListItemProvider + { + public: + explicit NotesListItemProvider(app::Application *app); + }; + + class NotesListModel : public NotesListItemProvider + { + public: + NotesListModel(app::Application *app, std::shared_ptr notesRepository); + + [[nodiscard]] unsigned int requestRecordsCount() override; + [[nodiscard]] bool updateRecords(std::vector records) override; + void requestRecords(std::uint32_t offset, std::uint32_t limit) override; + + [[nodiscard]] gui::ListItem *getItem(gui::Order order) override; + [[nodiscard]] unsigned int getMinimalItemHeight() const override; + + private: + bool onNotesRetrieved(const std::vector &records, unsigned int notesRepoCount); + + std::shared_ptr notesRepository; + }; +} // namespace app::notes diff --git a/module-apps/application-notes/model/NotesRepository.cpp b/module-apps/application-notes/model/NotesRepository.cpp new file mode 100644 index 0000000000000000000000000000000000000000..fa844084736878766dc7d30c2401d68213817a6a --- /dev/null +++ b/module-apps/application-notes/model/NotesRepository.cpp @@ -0,0 +1,64 @@ +// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved. +// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md + +#include "NotesRepository.hpp" + +#include +#include +#include + +#include + +namespace app::notes +{ + NotesDBRepository::NotesDBRepository(Application *application) : application{application} + {} + + void NotesDBRepository::get(std::uint32_t offset, std::uint32_t limit, const OnGetCallback &callback) + { + auto query = std::make_unique(offset, limit); + query->setQueryListener(db::QueryCallback::fromFunction([callback](auto response) { + auto result = dynamic_cast(response); + if (result == nullptr) { + return false; + } + if (callback) { + callback(result->getRecords(), result->getCount()); + } + return true; + })); + DBServiceAPI::GetQuery(application, db::Interface::Name::Notes, std::move(query)); + } + + void NotesDBRepository::save(const NotesRecord ¬e, const OnResultCallback &callback) + { + auto query = std::make_unique(note); + query->setQueryListener(db::QueryCallback::fromFunction([callback](auto response) { + auto result = dynamic_cast(response); + if (result == nullptr) { + return false; + } + if (callback) { + callback(result->succeed()); + } + return true; + })); + DBServiceAPI::GetQuery(application, db::Interface::Name::Notes, std::move(query)); + } + + void NotesDBRepository::remove(const NotesRecord ¬e, const OnResultCallback &callback) + { + auto query = std::make_unique(note.ID); + query->setQueryListener(db::QueryCallback::fromFunction([callback](auto response) { + auto result = dynamic_cast(response); + if (result == nullptr) { + return false; + } + if (callback) { + callback(result->succeed()); + } + return true; + })); + DBServiceAPI::GetQuery(application, db::Interface::Name::Notes, std::move(query)); + } +} // namespace app::notes diff --git a/module-apps/application-notes/model/NotesRepository.hpp b/module-apps/application-notes/model/NotesRepository.hpp new file mode 100644 index 0000000000000000000000000000000000000000..d4a0e09bad7acf3c5ae9cb569f38b3e630443fff --- /dev/null +++ b/module-apps/application-notes/model/NotesRepository.hpp @@ -0,0 +1,39 @@ +// Copyright (c) 2017-2020, 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 AbstractNotesRepository + { + public: + using OnGetCallback = std::function &, unsigned int)>; + 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 save(const NotesRecord ¬e, const OnResultCallback &callback) = 0; + virtual void remove(const NotesRecord ¬e, const OnResultCallback &callback) = 0; + }; + + class NotesDBRepository : public AbstractNotesRepository + { + public: + explicit NotesDBRepository(Application *application); + + void get(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; + + private: + Application *application; + }; +} // namespace app::notes diff --git a/module-apps/application-notes/presenter/NoteEditWindowPresenter.cpp b/module-apps/application-notes/presenter/NoteEditWindowPresenter.cpp new file mode 100644 index 0000000000000000000000000000000000000000..4597c3c150669c4c3ae996f86584ba4341f622e9 --- /dev/null +++ b/module-apps/application-notes/presenter/NoteEditWindowPresenter.cpp @@ -0,0 +1,16 @@ +// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved. +// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md + +#include "NoteEditWindowPresenter.hpp" + +namespace app::notes +{ + NoteEditWindowPresenter::NoteEditWindowPresenter(std::unique_ptr &¬esRepository) + : notesRepository{std::move(notesRepository)} + {} + + void NoteEditWindowPresenter::save(const NotesRecord ¬e) + { + notesRepository->save(note, nullptr); + } +} // namespace app::notes diff --git a/module-apps/application-notes/presenter/NoteEditWindowPresenter.hpp b/module-apps/application-notes/presenter/NoteEditWindowPresenter.hpp new file mode 100644 index 0000000000000000000000000000000000000000..bcfbffc11e1a7da150659d5e8318653bcda9e8b5 --- /dev/null +++ b/module-apps/application-notes/presenter/NoteEditWindowPresenter.hpp @@ -0,0 +1,39 @@ +// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved. +// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md + +#pragma once + +#include + +#include + +namespace app::notes +{ + class NoteEditWindowContract + { + public: + class View + { + public: + virtual ~View() noexcept = default; + }; + class Presenter : public BasePresenter + { + public: + virtual ~Presenter() noexcept = default; + + virtual void save(const NotesRecord ¬e) = 0; + }; + }; + + class NoteEditWindowPresenter : public NoteEditWindowContract::Presenter + { + public: + explicit NoteEditWindowPresenter(std::unique_ptr &¬esRepository); + + void save(const NotesRecord ¬e) override; + + private: + std::unique_ptr notesRepository; + }; +} // namespace app::notes diff --git a/module-apps/application-notes/presenter/NotePreviewWindowPresenter.cpp b/module-apps/application-notes/presenter/NotePreviewWindowPresenter.cpp new file mode 100644 index 0000000000000000000000000000000000000000..2fd1a2d5d1b2780c712a6134a1e349bdb74d73cc --- /dev/null +++ b/module-apps/application-notes/presenter/NotePreviewWindowPresenter.cpp @@ -0,0 +1,16 @@ +// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved. +// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md + +#include "NotePreviewWindowPresenter.hpp" + +namespace app::notes +{ + NotePreviewWindowPresenter::NotePreviewWindowPresenter(std::unique_ptr notesRepository) + : notesRepository{std::move(notesRepository)} + {} + + AbstractNotesRepository &NotePreviewWindowPresenter::getRepository() + { + return *notesRepository; + } +} // namespace app::notes diff --git a/module-apps/application-notes/presenter/NotePreviewWindowPresenter.hpp b/module-apps/application-notes/presenter/NotePreviewWindowPresenter.hpp new file mode 100644 index 0000000000000000000000000000000000000000..90aeafd2efc1d26776fd1ae3576f3f692c970670 --- /dev/null +++ b/module-apps/application-notes/presenter/NotePreviewWindowPresenter.hpp @@ -0,0 +1,39 @@ +// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved. +// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md + +#pragma once + +#include + +#include + +namespace app::notes +{ + class NotePreviewWindowContract + { + public: + class View + { + public: + virtual ~View() noexcept = default; + }; + class Presenter : public BasePresenter + { + public: + virtual ~Presenter() noexcept = default; + + virtual AbstractNotesRepository &getRepository() = 0; + }; + }; + + class NotePreviewWindowPresenter : public NotePreviewWindowContract::Presenter + { + public: + explicit NotePreviewWindowPresenter(std::unique_ptr notesRepository); + + AbstractNotesRepository &getRepository() override; + + private: + std::unique_ptr notesRepository; + }; +} // namespace app::notes diff --git a/module-apps/application-notes/presenter/NotesMainWindowPresenter.cpp b/module-apps/application-notes/presenter/NotesMainWindowPresenter.cpp new file mode 100644 index 0000000000000000000000000000000000000000..b863ba49b0c2ebb6c9fbef78e4f266bd84f94696 --- /dev/null +++ b/module-apps/application-notes/presenter/NotesMainWindowPresenter.cpp @@ -0,0 +1,26 @@ +// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved. +// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md + +#include "NotesMainWindowPresenter.hpp" + +namespace app::notes +{ + NotesMainWindowPresenter::NotesMainWindowPresenter(std::shared_ptr notesProvider) + : notesProvider{std::move(notesProvider)} + {} + + std::shared_ptr NotesMainWindowPresenter::getNotesItemProvider() const + { + 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 new file mode 100644 index 0000000000000000000000000000000000000000..5a68701b674c97de86488ad856ff1f830a151b66 --- /dev/null +++ b/module-apps/application-notes/presenter/NotesMainWindowPresenter.hpp @@ -0,0 +1,43 @@ +// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved. +// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md + +#pragma once + +#include + +#include + +namespace app::notes +{ + class NotesMainWindowContract + { + public: + class View + { + public: + virtual ~View() noexcept = default; + }; + class Presenter : public BasePresenter + { + public: + virtual ~Presenter() noexcept = default; + + virtual std::shared_ptr getNotesItemProvider() const = 0; + virtual bool isNoteListEmpty() = 0; + virtual bool updateNotes(std::vector &&records) = 0; + }; + }; + + class NotesMainWindowPresenter : public NotesMainWindowContract::Presenter + { + public: + 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; + }; +} // namespace app::notes diff --git a/module-apps/application-notes/style/NoteEditStyle.hpp b/module-apps/application-notes/style/NoteEditStyle.hpp new file mode 100644 index 0000000000000000000000000000000000000000..79cdfd8324111dddccef8cac404d9317ad2e08ee --- /dev/null +++ b/module-apps/application-notes/style/NoteEditStyle.hpp @@ -0,0 +1,25 @@ +// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved. +// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md + +#pragma once + +#include + +namespace app::notes::style::edit +{ + constexpr inline auto LeftMargin = ::style::window::default_left_margin; + constexpr inline auto TopMargin = ::style::header::height + ::style::margins::very_big - 1; + constexpr inline auto Width = ::style::window::default_body_width; + constexpr inline auto Height = ::style::window::default_body_height - ::style::margins::very_big; + + namespace counter + { + constexpr inline auto Height = 30; + } // namespace counter + + namespace text + { + constexpr inline auto TopMargin = 6; + constexpr inline auto Height = ::app::notes::style::edit::Height - counter::Height - TopMargin; + } // namespace text +} // namespace app::notes::style::edit diff --git a/module-apps/application-notes/style/NotePreviewStyle.hpp b/module-apps/application-notes/style/NotePreviewStyle.hpp new file mode 100644 index 0000000000000000000000000000000000000000..cf8a565c50201b2a0f028f51a3bbe5c472c1834b --- /dev/null +++ b/module-apps/application-notes/style/NotePreviewStyle.hpp @@ -0,0 +1,24 @@ +// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved. +// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md + +#pragma once + +#include + +namespace app::notes::style::preview +{ + constexpr inline auto LeftMargin = ::style::window::default_left_margin; + constexpr inline auto TopMargin = ::style::header::height + ::style::margins::very_big - 1; + constexpr inline auto Width = ::style::window::default_body_width; + constexpr inline auto Height = ::style::window::default_body_height - ::style::margins::very_big; + + namespace date + { + constexpr inline auto Height = 30; + } // namespace date + namespace text + { + constexpr inline auto TopMargin = 7; + constexpr inline auto Height = ::app::notes::style::preview::Height - date::Height - TopMargin; + } // namespace text +} // namespace app::notes::style::preview diff --git a/module-apps/application-notes/style/NotesListStyle.hpp b/module-apps/application-notes/style/NotesListStyle.hpp new file mode 100644 index 0000000000000000000000000000000000000000..bf48891a0114a6c6500530e8c46c2bbcc161266b --- /dev/null +++ b/module-apps/application-notes/style/NotesListStyle.hpp @@ -0,0 +1,45 @@ +// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved. +// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md + +#pragma once + +#include + +namespace app::notes::style::list +{ + constexpr inline auto X = ::style::window::default_left_margin; + constexpr inline auto Y = ::style::header::height + ::style::margins::small - 1; + constexpr inline auto Width = ::style::window::default_body_width; + constexpr inline auto Height = ::style::window::default_body_height - ::style::margins::small; + + constexpr inline auto PenWidth = 0; + constexpr inline auto FocusedPenWidth = 0; + + namespace item + { + constexpr inline auto Height = 136; + constexpr inline auto Radius = 0; + + constexpr inline auto VerticalPadding = 16; + constexpr inline auto LeftPadding = 10; + constexpr inline auto RightPadding = 4; + namespace title + { + constexpr inline auto Width = 310; + constexpr inline auto Height = 33; + } // namespace title + + namespace date + { + constexpr inline auto Width = 90; + constexpr inline auto Height = 20; + } // namespace date + + namespace snippet + { + constexpr inline auto Width = 417; + constexpr inline auto Height = 66; + constexpr inline auto TopMargin = 5; + } // namespace snippet + } // namespace item +} // namespace app::notes::style::list diff --git a/module-apps/application-notes/style/NotesMainWindowStyle.hpp b/module-apps/application-notes/style/NotesMainWindowStyle.hpp new file mode 100644 index 0000000000000000000000000000000000000000..6bfbb94ea32dd4000a91b03d0f55a091ecee485c --- /dev/null +++ b/module-apps/application-notes/style/NotesMainWindowStyle.hpp @@ -0,0 +1,37 @@ +// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved. +// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md + +#pragma once + +#include + +namespace app::notes::style::main_window +{ + namespace new_note_arrow + { + constexpr inline auto X = 30; + constexpr inline auto Y = 62; + constexpr inline auto ImageSource = "arrow_left"; + } // namespace new_note_arrow + + namespace new_note_image + { + constexpr inline auto X = 48; + constexpr inline auto Y = 55; + constexpr inline auto ImageSource = "cross"; + } // namespace new_note_image + + namespace search_arrow + { + constexpr inline auto X = 480 - 30 - 13; + constexpr inline auto Y = 62; + constexpr inline auto ImageSource = "arrow_right"; + } // namespace search_arrow + + namespace search_image + { + constexpr inline auto X = 480 - 48 - 26; + constexpr inline auto Y = 55; + constexpr inline auto ImageSource = "search"; + } // namespace search_image +} // namespace app::notes::style::main_window diff --git a/module-apps/application-notes/widgets/NotesItem.cpp b/module-apps/application-notes/widgets/NotesItem.cpp index 23055eeb979385495abba2c78e57bd6025be6a0e..5bde5fb64cebd2aceb58fa6451dbe52433b5fcdf 100644 --- a/module-apps/application-notes/widgets/NotesItem.cpp +++ b/module-apps/application-notes/widgets/NotesItem.cpp @@ -2,71 +2,90 @@ // For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md #include "NotesItem.hpp" + #include +#include + +#include namespace gui { - - NotesItem::NotesItem(NotesModel *model, bool mode24H) : model{model}, mode24H{mode24H} + NotesItem::NotesItem(std::shared_ptr record) : note{std::move(record)} { - setMinimumSize(style::window::default_body_width, 146); - setMaximumSize(style::window::default_body_width, 146); - - setRadius(8); - - setPenFocusWidth(3); - setPenWidth(1); + buildInterface(); + } - hour = new gui::Label(this, 0, 0, 0, 0); - hour->setPenFocusWidth(0); - hour->setPenWidth(0); - hour->setFont(style::window::font::medium); - hour->setAlignment(gui::Alignment{gui::Alignment::Horizontal::Right, gui::Alignment::Vertical::Top}); + void NotesItem::buildInterface() + { + namespace notesItemStyle = app::notes::style::list::item; + setMinimumSize(style::window::default_body_width, notesItemStyle::Height); + setMaximumSize(style::window::default_body_width, notesItemStyle::Height); + setRadius(notesItemStyle::Radius); + setEdges(RectangleEdge::Bottom | RectangleEdge::Top); + setPenFocusWidth(style::window::default_border_focus_w); + setPenWidth(style::window::default_border_no_focus_w); - title = new gui::Label(this, 0, 0, 0, 0); - title->setPenFocusWidth(0); - title->setPenWidth(0); + title = createEmptyLabel(this); title->setFont(style::window::font::bigbold); title->setAlignment(gui::Alignment{gui::Alignment::Horizontal::Left, gui::Alignment::Vertical::Top}); - snippet = new gui::Label(this, 0, 0, 0, 0); - snippet->setPenFocusWidth(0); - snippet->setPenWidth(0); + date = createEmptyLabel(this); + date->setFont(style::window::font::medium); + date->setAlignment(gui::Alignment{gui::Alignment::Horizontal::Right, gui::Alignment::Vertical::Top}); + + snippet = new gui::TextFixedSize(this, 0, 0, 0, 0); snippet->setFont(style::window::font::small); - snippet->setAlignment(gui::Alignment{gui::Alignment::Horizontal::Left, gui::Alignment::Vertical::Center}); + snippet->setAlignment(gui::Alignment{gui::Alignment::Horizontal::Left}); + snippet->setEdges(gui::RectangleEdge::None); + snippet->setPenFocusWidth(::style::window::default_border_focus_w); + snippet->setPenWidth(::style::window::default_border_rect_no_focus); + snippet->setEditMode(gui::EditMode::BROWSE); + snippet->setUnderline(false); + + setSnippet(note->snippet); + setDateText(note->date); } - NotesItem::~NotesItem() + gui::Label *NotesItem::createEmptyLabel(Item *parent) { - note = nullptr; + auto label = new gui::Label(parent, 0, 0, 0, 0); + label->setPenFocusWidth(0); + label->setPenWidth(0); + return label; } - bool NotesItem::onDimensionChanged(const BoundingBox &oldDim, const BoundingBox &newDim) + void NotesItem::setSnippet(const UTF8 ¬eText) { - hour->setPosition(11, 0); - hour->setSize(newDim.w - 22, 40); - - title->setPosition(11, 0); - title->setSize(68, 40); - - snippet->setPosition(11, 40); - snippet->setSize(newDim.w - 22, newDim.h - 40); - return true; + title->setText(noteText); + snippet->setText(noteText); } - // sets copy of alarm's - void NotesItem::setNote(std::shared_ptr ¬e) + void NotesItem::setDateText(std::uint32_t timestamp) { - this->note = note; - // set values of the labels - title->setText(std::to_string(note->ID)); - snippet->setText(note->path); + if (auto dt = utils::time::DateTime(timestamp); dt.isYesterday()) { + date->setText(utils::localize.get("common_yesterday")); + } + else { + date->setText(dt); + } } - bool NotesItem::onActivated(void *data) + bool NotesItem::onDimensionChanged(const BoundingBox &oldDim, const BoundingBox &newDim) { - LOG_INFO("ITEM WAS PRESSED"); + namespace notesItemStyle = app::notes::style::list::item; + title->setPosition(notesItemStyle::LeftPadding, notesItemStyle::VerticalPadding); + title->setSize(notesItemStyle::title::Width, notesItemStyle::title::Height); + + date->setPosition(notesItemStyle::LeftPadding, notesItemStyle::VerticalPadding); + date->setSize(newDim.w - (notesItemStyle::LeftPadding + notesItemStyle::RightPadding), + notesItemStyle::date::Height); + + snippet->setPosition(notesItemStyle::LeftPadding, + notesItemStyle::VerticalPadding + notesItemStyle::title::Height + + notesItemStyle::snippet::TopMargin); + snippet->setSize(newDim.w - (notesItemStyle::LeftPadding + notesItemStyle::RightPadding), + newDim.h - (2 * notesItemStyle::VerticalPadding) - notesItemStyle::title::Height - + notesItemStyle::snippet::TopMargin); return true; } - -} /* namespace gui */ +} // namespace gui diff --git a/module-apps/application-notes/widgets/NotesItem.hpp b/module-apps/application-notes/widgets/NotesItem.hpp index ff137b3ab7ec894dd61e7e7e4beacac6683e6047..3d4586e64a46f5bd428c16cb65ba5092f20d8024 100644 --- a/module-apps/application-notes/widgets/NotesItem.hpp +++ b/module-apps/application-notes/widgets/NotesItem.hpp @@ -1,45 +1,33 @@ // Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved. // For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md -#ifndef MODULE_APPS_APPLICATION_NOTES_WIDGETS_NOTESITEM_HPP_ -#define MODULE_APPS_APPLICATION_NOTES_WIDGETS_NOTESITEM_HPP_ +#pragma once -#include "Label.hpp" -#include "ListItem.hpp" -#include "../NotesModel.hpp" +#include +#include +#include + +#include namespace gui { - - /* - * @brief Widget used to display information about note in the notes list view. - */ class NotesItem : public ListItem { - - NotesModel *model = nullptr; - // pointer to the notes record - std::shared_ptr note = nullptr; - // this is hour in the mode defined in settings - gui::Label *hour = nullptr; - gui::Label *title = nullptr; - gui::Label *snippet = nullptr; - // flag that defines if time should be displayed in 24h mode - bool mode24H = false; - public: - NotesItem(NotesModel *model, bool mode24H); - virtual ~NotesItem(); - // sets copy of alarm's - void setNote(std::shared_ptr ¬e); - - // returns alarm structure - std::shared_ptr getAlarm(); - // virtual methods from Item + explicit NotesItem(std::shared_ptr record); + bool onDimensionChanged(const BoundingBox &oldDim, const BoundingBox &newDim) override; - bool onActivated(void *data) override; - }; -} /* namespace gui */ + private: + static gui::Label *createEmptyLabel(Item *parent); -#endif /* MODULE_APPS_APPLICATION_NOTES_WIDGETS_NOTESITEM_HPP_ */ + void buildInterface(); + void setSnippet(const UTF8 ¬eText); + void setDateText(std::uint32_t timestamp); + + std::shared_ptr note; + gui::Label *date = nullptr; + gui::Label *title = nullptr; + gui::TextFixedSize *snippet = nullptr; + }; +} // namespace gui diff --git a/module-apps/application-notes/windows/NoteEditWindow.cpp b/module-apps/application-notes/windows/NoteEditWindow.cpp new file mode 100644 index 0000000000000000000000000000000000000000..229f9b3443620cec454d78f1915432538bb5b9e4 --- /dev/null +++ b/module-apps/application-notes/windows/NoteEditWindow.cpp @@ -0,0 +1,152 @@ +// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved. +// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md + +#include "NoteEditWindow.hpp" + +#include + +#include + +#include +#include +#include +#include +#include + +#include +#include + +#include +#include + +namespace app::notes +{ + namespace + { + constexpr auto MaxCharactersCount = 4000U; + } // namespace + + NoteEditWindow::NoteEditWindow(app::Application *app, + std::unique_ptr &&windowPresenter) + : gui::AppWindow(app, gui::name::window::note_edit), presenter{std::move(windowPresenter)} + { + presenter->attach(this); + buildInterface(); + } + + NoteEditWindow::~NoteEditWindow() noexcept + { + destroyInterface(); + } + + void NoteEditWindow::rebuild() + { + destroyInterface(); + buildInterface(); + } + + void NoteEditWindow::buildInterface() + { + AppWindow::buildInterface(); + + setTitle(utils::localize.get("app_notes_edit_new_note")); + + namespace editStyle = app::notes::style::edit; + charactersCounter = new gui::Label( + this, editStyle::LeftMargin, editStyle::TopMargin, editStyle::Width, editStyle::counter::Height); + charactersCounter->setEdges(gui::RectangleEdge::None); + charactersCounter->setFont(::style::window::font::verysmall); + charactersCounter->setAlignment(gui::Alignment{gui::Alignment::Horizontal::Right}); + + edit = new gui::Text(this, + editStyle::LeftMargin, + editStyle::TopMargin + editStyle::counter::Height + editStyle::text::TopMargin, + editStyle::Width, + editStyle::text::Height); + edit->setAlignment(gui::Alignment{gui::Alignment::Vertical::Top}); + edit->setPenFocusWidth(::style::window::default_border_focus_w); + edit->setPenWidth(::style::window::default_border_rect_no_focus); + edit->setEdges(gui::RectangleEdge::None); + edit->setFont(::style::window::font::medium); + edit->setInputMode(new InputMode( + {InputMode::ABC, InputMode::abc, InputMode::digit}, + [=](const UTF8 &text) { bottomBarTemporaryMode(text); }, + [=]() { bottomBarRestoreFromTemporaryMode(); }, + [=]() { selectSpecialCharacter(); })); + edit->setTextChangedCallback([this](Item &, const UTF8 &text) { setCharactersCount(text.length()); }); + + bottomBar->setActive(gui::BottomBar::Side::LEFT, true); + bottomBar->setText(gui::BottomBar::Side::LEFT, utils::localize.get(::style::strings::common::options)); + + bottomBar->setActive(gui::BottomBar::Side::CENTER, true); + bottomBar->setText(gui::BottomBar::Side::CENTER, utils::localize.get(::style::strings::common::save)); + + bottomBar->setActive(gui::BottomBar::Side::RIGHT, true); + bottomBar->setText(gui::BottomBar::Side::RIGHT, utils::localize.get(::style::strings::common::back)); + + topBar->setActive(gui::TopBar::Elements::TIME, true); + + setFocusItem(edit); + } + + void NoteEditWindow::setCharactersCount(std::uint32_t count) + { + std::ostringstream counterText; + counterText << count << '/' << MaxCharactersCount; + charactersCounter->setText(counterText.str()); + } + + void NoteEditWindow::destroyInterface() + { + erase(); + charactersCounter = nullptr; + edit = nullptr; + } + + void NoteEditWindow::onBeforeShow(gui::ShowMode mode, gui::SwitchData *data) + { + auto editData = dynamic_cast(data); + if (editData == nullptr) { + return; + } + + notesRecord = std::make_unique(editData->getRecord()); + setNoteText(notesRecord->snippet); + } + + void NoteEditWindow::setNoteText(const UTF8 &text) + { + edit->setText(text); + } + + bool NoteEditWindow::onInput(const gui::InputEvent &inputEvent) + { + if (inputEvent.isShortPress()) { + if (inputEvent.is(gui::KeyCode::KEY_ENTER)) { + saveNote(); + auto switchData = std::make_unique(*notesRecord); + switchData->ignoreCurrentWindowOnStack = true; + application->switchWindow(gui::name::window::note_preview, std::move(switchData)); + } + if (inputEvent.is(gui::KeyCode::KEY_LF)) { + application->switchWindow( + utils::localize.get("app_phonebook_options_title"), + std::make_unique(noteEditOptions(application, *notesRecord, edit))); + } + } + return AppWindow::onInput(inputEvent); + } + + void NoteEditWindow::saveNote() + { + const auto &newSnippetText = edit->getText(); + if (newSnippetText.length() > MaxCharactersCount) { + LOG_ERROR("Unable to save the note: text is too long."); + return; + } + + notesRecord->date = utils::time::getCurrentTimestamp().getTime(); + notesRecord->snippet = newSnippetText; + presenter->save(*notesRecord); + } +} // namespace app::notes diff --git a/module-apps/application-notes/windows/NoteEditWindow.hpp b/module-apps/application-notes/windows/NoteEditWindow.hpp new file mode 100644 index 0000000000000000000000000000000000000000..aeab480504188509aa02db718091236d4d5bb2ec --- /dev/null +++ b/module-apps/application-notes/windows/NoteEditWindow.hpp @@ -0,0 +1,43 @@ +// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved. +// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md + +#pragma once + +#include + +#include "AppWindow.hpp" + +#include + +#include "gui/widgets/Label.hpp" +#include "gui/widgets/Text.hpp" +#include "gui/input/InputEvent.hpp" + +#include + +namespace app::notes +{ + class NoteEditWindow : public gui::AppWindow, public NoteEditWindowContract::View + { + public: + NoteEditWindow(app::Application *app, std::unique_ptr &&windowPresenter); + ~NoteEditWindow() noexcept override; + + void onBeforeShow(gui::ShowMode mode, gui::SwitchData *data) override; + bool onInput(const gui::InputEvent &inputEvent) override; + + void rebuild() override; + void buildInterface() override; + void destroyInterface() override; + + private: + void setCharactersCount(std::uint32_t count); + void setNoteText(const UTF8 &text); + void saveNote(); + + std::unique_ptr presenter; + std::unique_ptr notesRecord; + gui::Label *charactersCounter; + gui::Text *edit; + }; +} // namespace app::notes diff --git a/module-apps/application-notes/windows/NoteMainWindow.cpp b/module-apps/application-notes/windows/NoteMainWindow.cpp new file mode 100644 index 0000000000000000000000000000000000000000..ee608380680ec77ebd89d4f8dfafb01e77557b90 --- /dev/null +++ b/module-apps/application-notes/windows/NoteMainWindow.cpp @@ -0,0 +1,179 @@ +// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved. +// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md + +#include "NoteMainWindow.hpp" + +#include +#include + +#include +#include + +#include + +#include +#include +#include + +#include +#include +#include + +namespace app::notes +{ + NoteMainWindow::NoteMainWindow(app::Application *app, + std::unique_ptr &&windowPresenter) + : AppWindow(app, gui::name::window::main_window), presenter{std::move(windowPresenter)} + { + presenter->attach(this); + buildInterface(); + } + + NoteMainWindow::~NoteMainWindow() noexcept + { + destroyInterface(); + } + + void NoteMainWindow::rebuild() + { + destroyInterface(); + buildInterface(); + } + + void NoteMainWindow::buildInterface() + { + AppWindow::buildInterface(); + + setTitle(utils::localize.get("app_notes_title_main")); + + bottomBar->setActive(gui::BottomBar::Side::LEFT, true); + bottomBar->setText(gui::BottomBar::Side::LEFT, utils::localize.get(::style::strings::common::options)); + bottomBar->setActive(gui::BottomBar::Side::CENTER, true); + bottomBar->setText(gui::BottomBar::Side::CENTER, utils::localize.get(::style::strings::common::open)); + bottomBar->setActive(gui::BottomBar::Side::RIGHT, true); + bottomBar->setText(gui::BottomBar::Side::RIGHT, utils::localize.get(::style::strings::common::back)); + topBar->setActive(gui::TopBar::Elements::TIME, true); + + namespace windowStyle = app::notes::style::main_window; + leftArrowImage = new gui::Image(this, + windowStyle::new_note_arrow::X, + windowStyle::new_note_arrow::Y, + 0, + 0, + windowStyle::new_note_arrow::ImageSource); + rightArrowImage = new gui::Image(this, + windowStyle::search_arrow::X, + windowStyle::search_arrow::Y, + 0, + 0, + windowStyle::search_arrow::ImageSource); + newNoteImage = new gui::Image(this, + windowStyle::new_note_image::X, + windowStyle::new_note_image::Y, + 0, + 0, + windowStyle::new_note_image::ImageSource); + searchImage = new gui::Image(this, + windowStyle::search_image::X, + windowStyle::search_image::Y, + 0, + 0, + windowStyle::search_image::ImageSource); + + namespace listStyle = app::notes::style::list; + list = new gui::ListView( + this, listStyle::X, listStyle::Y, listStyle::Width, listStyle::Height, presenter->getNotesItemProvider()); + list->setPenWidth(listStyle::PenWidth); + list->setPenFocusWidth(listStyle::FocusedPenWidth); + list->focusChangedCallback = [this]([[maybe_unused]] gui::Item &item) { + onListFilled(); + return true; + }; + list->setVisible(true); + list->rebuildList(); + + emptyListIcon = new gui::Icon(this, + 0, + ::style::header::height, + ::style::window_width, + ::style::window_height - ::style::header::height - ::style::footer::height, + "phonebook_empty_grey_circle_W_G", + utils::localize.get("app_notes_no_notes")); + emptyListIcon->focusChangedCallback = [this]([[maybe_unused]] gui::Item &item) { + onEmptyList(); + return true; + }; + emptyListIcon->setVisible(false); + + setFocusItem(list); + } + + void NoteMainWindow::destroyInterface() + { + erase(); + list = nullptr; + leftArrowImage = nullptr; + rightArrowImage = nullptr; + newNoteImage = nullptr; + searchImage = nullptr; + emptyListIcon = nullptr; + } + + void NoteMainWindow::onBeforeShow(gui::ShowMode mode, gui::SwitchData *data) + { + if (presenter->isNoteListEmpty()) { + showEmptyIcon(); + } + else { + showList(); + } + } + + void NoteMainWindow::showEmptyIcon() + { + list->setVisible(false); + emptyListIcon->setVisible(true); + setFocusItem(emptyListIcon); + } + + void NoteMainWindow::showList() + { + list->rebuildList(); + list->setVisible(true); + emptyListIcon->setVisible(false); + setFocusItem(list); + } + + void NoteMainWindow::onEmptyList() + { + bottomBar->setActive(gui::BottomBar::Side::LEFT, false); + bottomBar->setActive(gui::BottomBar::Side::CENTER, false); + rightArrowImage->setVisible(false); + searchImage->setVisible(false); + } + + void NoteMainWindow::onListFilled() + { + bottomBar->setActive(gui::BottomBar::Side::LEFT, true); + bottomBar->setActive(gui::BottomBar::Side::CENTER, true); + rightArrowImage->setVisible(true); + searchImage->setVisible(true); + } + + bool NoteMainWindow::onInput(const gui::InputEvent &inputEvent) + { + if (inputEvent.isShortPress()) { + if (inputEvent.is(gui::KeyCode::KEY_LEFT)) { + application->switchWindow(gui::name::window::note_edit, + std::make_unique(NotesRecord{})); + } + } + return AppWindow::onInput(inputEvent); + } + + bool NoteMainWindow::onDatabaseMessage(sys::Message *msgl) + { + auto *msg = static_cast(msgl); + return presenter->updateNotes(std::move(*msg->records)); + } +} // namespace app::notes diff --git a/module-apps/application-notes/windows/NoteMainWindow.hpp b/module-apps/application-notes/windows/NoteMainWindow.hpp new file mode 100644 index 0000000000000000000000000000000000000000..3ff14858d539bb340f8d90d8147a890e95ef1dbd --- /dev/null +++ b/module-apps/application-notes/windows/NoteMainWindow.hpp @@ -0,0 +1,46 @@ +// Copyright (c) 2017-2020, 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 + +#include + +namespace app::notes +{ + class NoteMainWindow : public gui::AppWindow, public NotesMainWindowContract::View + { + public: + NoteMainWindow(app::Application *app, std::unique_ptr &&windowPresenter); + ~NoteMainWindow() noexcept override; + + // virtual methods + bool onInput(const gui::InputEvent &inputEvent) override; + void onBeforeShow(gui::ShowMode mode, gui::SwitchData *data) override; + + void rebuild() override; + void buildInterface() override; + void destroyInterface() override; + bool onDatabaseMessage(sys::Message *msg) override; + + private: + void showEmptyIcon(); + void showList(); + void onEmptyList(); + void onListFilled(); + + std::unique_ptr presenter; + gui::ListView *list = nullptr; + gui::Image *leftArrowImage = nullptr; + gui::Image *rightArrowImage = nullptr; + gui::Image *newNoteImage = nullptr; + gui::Image *searchImage = nullptr; + gui::Icon *emptyListIcon = nullptr; + }; +} // namespace app::notes diff --git a/module-apps/application-notes/windows/NotePreviewWindow.cpp b/module-apps/application-notes/windows/NotePreviewWindow.cpp new file mode 100644 index 0000000000000000000000000000000000000000..b15bfe27f5b59a901d1af1f2775a9cecebee4c1f --- /dev/null +++ b/module-apps/application-notes/windows/NotePreviewWindow.cpp @@ -0,0 +1,129 @@ +// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved. +// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md + +#include "NotePreviewWindow.hpp" + +#include +#include +#include +#include +#include + +#include +#include + +#include + +#include +#include + +namespace app::notes +{ + NotePreviewWindow::NotePreviewWindow(app::Application *app, + std::unique_ptr &&windowPresenter) + : AppWindow(app, gui::name::window::note_preview), presenter(std::move(windowPresenter)) + { + presenter->attach(this); + buildInterface(); + } + + NotePreviewWindow::~NotePreviewWindow() noexcept + { + destroyInterface(); + } + + void NotePreviewWindow::rebuild() + { + destroyInterface(); + buildInterface(); + } + + void NotePreviewWindow::destroyInterface() + { + erase(); + date = nullptr; + note = nullptr; + } + + void NotePreviewWindow::buildInterface() + { + AppWindow::buildInterface(); + + setTitle(utils::localize.get("app_notes_title_main")); + + namespace previewStyle = app::notes::style::preview; + date = new gui::Label( + this, previewStyle::LeftMargin, previewStyle::TopMargin, previewStyle::Width, previewStyle::date::Height); + date->setEdges(gui::RectangleEdge::None); + date->setFont(::style::window::font::small); + + note = + new gui::TextFixedSize(this, + previewStyle::LeftMargin, + previewStyle::TopMargin + previewStyle::date::Height + previewStyle::text::TopMargin, + previewStyle::Width, + previewStyle::text::Height); + note->setEdges(gui::RectangleEdge::None); + note->setFont(::style::window::font::medium); + note->setAlignment(gui::Alignment{gui::Alignment::Vertical::Top}); + note->setPenFocusWidth(::style::window::default_border_focus_w); + note->setPenWidth(::style::window::default_border_rect_no_focus); + note->setEditMode(gui::EditMode::BROWSE); + note->setUnderline(false); + + bottomBar->setActive(gui::BottomBar::Side::LEFT, true); + bottomBar->setText(gui::BottomBar::Side::LEFT, utils::localize.get(::style::strings::common::options)); + + bottomBar->setActive(gui::BottomBar::Side::CENTER, true); + bottomBar->setText(gui::BottomBar::Side::CENTER, utils::localize.get("app_notes_edit")); + + bottomBar->setActive(gui::BottomBar::Side::RIGHT, true); + bottomBar->setText(gui::BottomBar::Side::RIGHT, utils::localize.get(::style::strings::common::back)); + + topBar->setActive(gui::TopBar::Elements::TIME, true); + + setFocusItem(note); + } + + void NotePreviewWindow::onBeforeShow(gui::ShowMode mode, gui::SwitchData *data) + { + auto previewData = dynamic_cast(data); + if (previewData == nullptr) { + return; + } + + notesRecord = std::make_unique(previewData->getRecord()); + setEditDateText(notesRecord->date); + note->setText(notesRecord->snippet); + } + + void NotePreviewWindow::setEditDateText(std::uint32_t timestamp) + { + utils::time::DateTime dt{timestamp}; + std::ostringstream dateText; + dateText << utils::localize.get("app_notes_edited") << ": "; + if (dt.isToday()) { + dateText << utils::localize.get("common_today") << ", "; + } + else if (dt.isYesterday()) { + dateText << utils::localize.get("common_yesterday") << ", "; + } + dateText << dt; + date->setText(dateText.str()); + } + + bool NotePreviewWindow::onInput(const gui::InputEvent &inputEvent) + { + if (inputEvent.isShortPress()) { + if (inputEvent.is(gui::KeyCode::KEY_ENTER)) { + application->switchWindow(gui::name::window::note_edit, std::make_unique(*notesRecord)); + } + else if (inputEvent.is(gui::KeyCode::KEY_LF)) { + application->switchWindow(utils::localize.get("app_phonebook_options_title"), + std::make_unique(notePreviewOptions( + application, *notesRecord, presenter->getRepository(), note))); + } + } + return AppWindow::onInput(inputEvent); + } +} // namespace app::notes diff --git a/module-apps/application-notes/windows/NotePreviewWindow.hpp b/module-apps/application-notes/windows/NotePreviewWindow.hpp new file mode 100644 index 0000000000000000000000000000000000000000..1c00b8397ed2bd8544e938a0eb4aeebf3441c672 --- /dev/null +++ b/module-apps/application-notes/windows/NotePreviewWindow.hpp @@ -0,0 +1,39 @@ +// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved. +// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md + +#pragma once + +#include "AppWindow.hpp" + +#include +#include + +#include +#include +#include + +namespace app::notes +{ + class NotePreviewWindow : public gui::AppWindow, public NotePreviewWindowContract::View + { + public: + NotePreviewWindow(app::Application *app, + std::unique_ptr &&windowPresenter); + ~NotePreviewWindow() noexcept override; + + void onBeforeShow(gui::ShowMode mode, gui::SwitchData *data) override; + bool onInput(const gui::InputEvent &inputEvent) override; + + void rebuild() override; + void buildInterface() override; + void destroyInterface() override; + + private: + void setEditDateText(std::uint32_t editTimestamp); + + std::unique_ptr presenter; + std::unique_ptr notesRecord; + gui::TextFixedSize *note = nullptr; + gui::Label *date = nullptr; + }; +} // namespace app::notes diff --git a/module-apps/application-notes/windows/NotesEditWindow.cpp b/module-apps/application-notes/windows/NotesEditWindow.cpp deleted file mode 100644 index cb8c08ecc34127f23f3d2da701ed56912c89d525..0000000000000000000000000000000000000000 --- a/module-apps/application-notes/windows/NotesEditWindow.cpp +++ /dev/null @@ -1,88 +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 -#include - -#include - -#include "bsp/rtc/rtc.hpp" - -#include "../ApplicationNotes.hpp" - -#include -#include "module-utils/i18n/i18n.hpp" - -#include "Label.hpp" -#include "Margins.hpp" -#include "Text.hpp" -#include "NotesEditWindow.hpp" -#include - -UTF8 textString = "Very long test line ABCDEFGHIJKLMNOPQRST123456789\n" - "abcdefghijklmnopqrs 123456789 ABCDEFGHIJKLMONPQRSTUW 12345\n test\nnew line\n\n\n12345"; - -namespace gui -{ - - NotesEditWindow::NotesEditWindow(app::Application *app) : AppWindow(app, "EditWindow") - { - buildInterface(); - } - - void NotesEditWindow::rebuild() - { - destroyInterface(); - buildInterface(); - } - void NotesEditWindow::buildInterface() - { - AppWindow::buildInterface(); - - bottomBar->setActive(BottomBar::Side::CENTER, true); - bottomBar->setActive(BottomBar::Side::RIGHT, true); - bottomBar->setText(BottomBar::Side::CENTER, utils::localize.get("app_notes_save")); - bottomBar->setText(BottomBar::Side::RIGHT, utils::localize.get("app_notes_back")); - - setTitle(utils::localize.get("app_notes_new_note")); - - text = new gui::Text(this, 11, 105, 480 - 22, 600 - 105 - 50); - text->setFont(style::window::font::medium); - text->setRadius(5); - text->setMargins(gui::Margins(10, 5, 10, 5)); - text->activatedCallback = [=](gui::Item &item) { - UTF8 getstr = text->getText(); - time_t timestamp; - bsp::rtc_GetCurrentTimestamp(×tamp); - - UTF8 filename = "sys/data/applications/notes/" + std::to_string(timestamp) + ".txt"; - - auto file = vfs.fopen(filename.c_str(), "wb"); - vfs.fwrite(getstr.c_str(), getstr.used() - 1, 1, file); - vfs.fclose(file); - return true; - }; - text->setTextType(TextType::MULTI_LINE); - text->setEditMode(EditMode::BROWSE); - text->setInputMode(new InputMode({InputMode::ABC, InputMode::abc})); - - topBar->setActive(TopBar::Elements::TIME, true); - } - - void NotesEditWindow::destroyInterface() - { - erase(); - } - - NotesEditWindow::~NotesEditWindow() - { - destroyInterface(); - } - - void NotesEditWindow::onBeforeShow(ShowMode mode, SwitchData *data) - { - text->setText(textString); - setFocusItem(text); - } - -} /* namespace gui */ diff --git a/module-apps/application-notes/windows/NotesEditWindow.hpp b/module-apps/application-notes/windows/NotesEditWindow.hpp deleted file mode 100644 index ab9de1a4069a1eb70689ab1b05397fcd247ee629..0000000000000000000000000000000000000000 --- a/module-apps/application-notes/windows/NotesEditWindow.hpp +++ /dev/null @@ -1,41 +0,0 @@ -// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved. -// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md - -#ifndef MODULE_APPS_APPLICATION_NOTES_WINDOWS_NOTESEDITWINDOW_HPP_ -#define MODULE_APPS_APPLICATION_NOTES_WINDOWS_NOTESEDITWINDOW_HPP_ - -#include -#include - -#include "AppWindow.hpp" -#include "gui/widgets/Text.hpp" -#include "gui/widgets/Label.hpp" -#include "gui/widgets/Image.hpp" -#include "gui/widgets/Window.hpp" -#include "gui/widgets/BottomBar.hpp" -#include "gui/widgets/TopBar.hpp" -#include "gui/widgets/ListView.hpp" - -namespace gui -{ - - class NotesEditWindow : public AppWindow - { - Text *text = nullptr; - Label *title = nullptr; - - public: - NotesEditWindow(app::Application *app); - virtual ~NotesEditWindow(); - - // virtual methods - void onBeforeShow(ShowMode mode, SwitchData *data) override; - - void rebuild() override; - void buildInterface() override; - void destroyInterface() override; - }; - -} /* namespace gui */ - -#endif /* MODULE_APPS_APPLICATION_NOTES_WINDOWS_NOTESEDITWINDOW_HPP_ */ diff --git a/module-apps/application-notes/windows/NotesMainWindow.cpp b/module-apps/application-notes/windows/NotesMainWindow.cpp deleted file mode 100644 index 56f9847bf3dfa4beb0839826aa1aeb2c980bd6e7..0000000000000000000000000000000000000000 --- a/module-apps/application-notes/windows/NotesMainWindow.cpp +++ /dev/null @@ -1,86 +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 -#include - -#include "InputEvent.hpp" -#include - -#include "../ApplicationNotes.hpp" - -#include -#include "module-utils/i18n/i18n.hpp" - -#include "Label.hpp" -#include "Margins.hpp" -#include "NotesMainWindow.hpp" -#include - -namespace gui -{ - - NotesMainWindow::NotesMainWindow(app::Application *app) - : AppWindow(app, gui::name::window::main_window), notesModel{std::make_shared(app)} - { - buildInterface(); - } - - void NotesMainWindow::rebuild() - { - destroyInterface(); - buildInterface(); - } - - void NotesMainWindow::buildInterface() - { - AppWindow::buildInterface(); - - list = new gui::ListView(this, 16, 105, 480 - 32, 440, notesModel); - list->setPenFocusWidth(0); - list->setPenWidth(0); - - setFocusItem(list); - - setTitle(utils::localize.get("app_notes_title_main")); - - bottomBar->setActive(BottomBar::Side::CENTER, true); - bottomBar->setActive(BottomBar::Side::RIGHT, true); - bottomBar->setText(BottomBar::Side::CENTER, utils::localize.get(style::strings::common::open)); - bottomBar->setText(BottomBar::Side::RIGHT, utils::localize.get(style::strings::common::back)); - - topBar->setActive(TopBar::Elements::TIME, true); - } - - void NotesMainWindow::destroyInterface() - { - erase(); - } - - void NotesMainWindow::onBeforeShow(ShowMode mode, SwitchData *data) - { - list->rebuildList(); - } - - bool NotesMainWindow::onInput(const InputEvent &inputEvent) - { - - // process only if key is released - if ((inputEvent.state != InputEvent::State::keyReleasedShort) || - (inputEvent.state != InputEvent::State::keyReleasedLong)) { - if (inputEvent.keyCode == KeyCode::KEY_LEFT) { - application->switchWindow("EditWindow"); - return true; - } - } - - return AppWindow::onInput(inputEvent); - } - - bool NotesMainWindow::onDatabaseMessage(sys::Message *msgl) - { - DBNotesResponseMessage *msg = reinterpret_cast(msgl); - return notesModel->updateRecords(std::move(*msg->records)); - } - -} /* namespace gui */ diff --git a/module-apps/application-notes/windows/NotesMainWindow.hpp b/module-apps/application-notes/windows/NotesMainWindow.hpp deleted file mode 100644 index 5a62170281c88564fa9a7f727203c1288ea8e887..0000000000000000000000000000000000000000 --- a/module-apps/application-notes/windows/NotesMainWindow.hpp +++ /dev/null @@ -1,44 +0,0 @@ -// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved. -// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md - -#ifndef MODULE_APPS_APPLICATION_NOTES_WINDOWS_NOTESMAINWINDOW_HPP_ -#define MODULE_APPS_APPLICATION_NOTES_WINDOWS_NOTESMAINWINDOW_HPP_ - -#include -#include - -#include "AppWindow.hpp" -#include "gui/widgets/Label.hpp" -#include "gui/widgets/Image.hpp" -#include "gui/widgets/Window.hpp" -#include "gui/widgets/BottomBar.hpp" -#include "gui/widgets/TopBar.hpp" -#include "gui/widgets/ListView.hpp" - -#include "../NotesModel.hpp" - -namespace gui -{ - - class NotesMainWindow : public AppWindow - { - std::shared_ptr notesModel = nullptr; - gui::ListView *list = nullptr; - Label *title = nullptr; - - public: - NotesMainWindow(app::Application *app); - - // virtual methods - bool onInput(const InputEvent &inputEvent) override; - void onBeforeShow(ShowMode mode, SwitchData *data) override; - - void rebuild() override; - void buildInterface() override; - void destroyInterface() override; - bool onDatabaseMessage(sys::Message *msg) override; - }; - -} /* namespace gui */ - -#endif /* MODULE_APPS_APPLICATION_NOTES_WINDOWS_NOTESMAINWINDOW_HPP_ */ diff --git a/module-apps/application-notes/windows/NotesOptions.cpp b/module-apps/application-notes/windows/NotesOptions.cpp new file mode 100644 index 0000000000000000000000000000000000000000..6d3e639c25c7bcfccfe5cbcb622be5a0f2f99a4d --- /dev/null +++ b/module-apps/application-notes/windows/NotesOptions.cpp @@ -0,0 +1,108 @@ +// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved. +// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md + +#include "NotesOptions.hpp" + +#include +#include + +#include +#include + +#include + +#include + +namespace app::notes +{ + namespace + { + void addOption(const std::string &translationId, + std::function onClickCallback, + std::list &options) + { + options.emplace_back(utils::localize.get(translationId), onClickCallback); + } + + void removeNote(const NotesRecord &record, Application *application, AbstractNotesRepository ¬esRepository) + { + gui::DialogMetadata meta; + meta.action = [record, application, ¬esRepository] { + notesRepository.remove( + record, [application](bool) { application->switchWindow(gui::name::window::main_window); }); + return true; + }; + meta.text = utils::localize.get("app_notes_note_delete_confirmation"); + meta.icon = "phonebook_contact_delete_trashcan"; + application->switchWindow(gui::name::window::note_confirm_dialog, + std::make_unique(meta)); + } + } // namespace + + std::list noteListOptions(Application *application, + const NotesRecord &record, + AbstractNotesRepository ¬esRepository) + { + std::list options; + addOption( + {"app_notes_delete_note"}, + [application, record, ¬esRepository](gui::Item &item) { + removeNote(record, application, notesRepository); + return true; + }, + options); + return options; + } + + std::list notePreviewOptions(Application *application, + const NotesRecord &record, + AbstractNotesRepository ¬esRepository, + gui::Text *textWidget) + { + std::list options; + addOption( + {"app_notes_copy_text"}, + [application, textWidget](gui::Item &item) { + if (textWidget != nullptr) { + Clipboard::getInstance().copy(textWidget->getText()); + } + application->returnToPreviousWindow(); + return true; + }, + options); + addOption( + {"app_notes_delete_note"}, + [application, record, ¬esRepository](gui::Item &item) { + removeNote(record, application, notesRepository); + return true; + }, + options); + return options; + } + + std::list noteEditOptions(Application *application, const NotesRecord &record, gui::Text *textWidget) + { + std::list options; + addOption( + {"app_notes_copy_text"}, + [application, textWidget](gui::Item &item) { + if (textWidget != nullptr) { + Clipboard::getInstance().copy(textWidget->getText()); + } + application->returnToPreviousWindow(); + return true; + }, + options); + addOption( + {"app_notes_copy_paste"}, + [application, textWidget](gui::Item &item) { + if (textWidget != nullptr) { + textWidget->addText(Clipboard::getInstance().paste()); + } + application->returnToPreviousWindow(); + return true; + }, + options); + return options; + } +} // namespace app::notes diff --git a/module-apps/application-notes/windows/NotesOptions.hpp b/module-apps/application-notes/windows/NotesOptions.hpp new file mode 100644 index 0000000000000000000000000000000000000000..c5b7f7ea05da7a4d6c91fb4127398ce9c289ede6 --- /dev/null +++ b/module-apps/application-notes/windows/NotesOptions.hpp @@ -0,0 +1,25 @@ +// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved. +// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md + +#pragma once + +#include +#include + +namespace gui +{ + class Option; // Forward declaration. + class Text; // Forward declaration. +} // namespace gui + +namespace app::notes +{ + std::list noteListOptions(Application *application, + const NotesRecord &record, + AbstractNotesRepository ¬esRepository); + std::list notePreviewOptions(Application *application, + const NotesRecord &record, + AbstractNotesRepository ¬esRepository, + gui::Text *textWidget); + std::list noteEditOptions(Application *application, const NotesRecord &record, gui::Text *textWidget); +} // namespace app::notes diff --git a/module-db/CMakeLists.txt b/module-db/CMakeLists.txt index f7d7ee12041e31f227062aa73d5c1f6d1773a19d..8e41145c3e03d32de3e34762b593645e9cbd3069 100644 --- a/module-db/CMakeLists.txt +++ b/module-db/CMakeLists.txt @@ -87,6 +87,9 @@ set(SOURCES queries/messages/threads/QueryThreadGetByContactID.cpp queries/messages/threads/QueryThreadRemove.cpp queries/messages/threads/QueryThreadMarkAsRead.cpp + queries/notes/QueryNotesGet.cpp + queries/notes/QueryNoteStore.cpp + queries/notes/QueryNoteRemove.cpp queries/calllog/QueryCalllogSetAllRead.cpp queries/calllog/QueryCalllogGet.cpp queries/calllog/QueryCalllogGetCount.cpp diff --git a/module-db/Interface/NotesRecord.cpp b/module-db/Interface/NotesRecord.cpp index cbdff05537abd51c1104505ee2835e23d06eb19f..1a16b8aa472a45516934a967ef4c6b125345bd1b 100644 --- a/module-db/Interface/NotesRecord.cpp +++ b/module-db/Interface/NotesRecord.cpp @@ -2,100 +2,153 @@ // For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md #include "NotesRecord.hpp" -#include "../Tables/NotesTable.hpp" -NotesRecordInterface::NotesRecordInterface(NotesDB *notesDb) : notesDB(notesDb) -{} +#include "queries/notes/QueryNotesGet.hpp" +#include "queries/notes/QueryNoteStore.hpp" +#include "queries/notes/QueryNoteRemove.hpp" -NotesRecordInterface::~NotesRecordInterface() -{} +#include -bool NotesRecordInterface::Add(const NotesRecord &rec) +namespace { - // Create SMS - notesDB->notes.add(NotesTableRow{.date = rec.date, .snippet = rec.snippet, .path = rec.path}); + NotesTableFields toNotesTableFields(NotesRecordField field) + { + switch (field) { + case NotesRecordField::Date: + return NotesTableFields::Date; + case NotesRecordField::Snippet: + return NotesTableFields::Snippet; + } + throw std::invalid_argument{"Invalid notes record field passed."}; + } +} // namespace - // TODO: error check +NotesRecordInterface::NotesRecordInterface(NotesDB *notesDb) : notesDB(notesDb) +{} - return true; +bool NotesRecordInterface::Add(const NotesRecord &rec) +{ + return notesDB->notes.add(NotesTableRow{.date = rec.date, .snippet = rec.snippet}); } -uint32_t NotesRecordInterface::GetCount() +std::uint32_t NotesRecordInterface::GetCount() { return notesDB->notes.count(); } -std::unique_ptr> NotesRecordInterface::GetLimitOffsetByField(uint32_t offset, - uint32_t limit, +std::unique_ptr> NotesRecordInterface::GetLimitOffsetByField(std::uint32_t offset, + std::uint32_t limit, NotesRecordField field, const char *str) { - return GetLimitOffset(offset, limit); -} - -std::unique_ptr> NotesRecordInterface::GetLimitOffset(uint32_t offset, uint32_t limit) -{ - auto notes = notesDB->notes.getLimitOffset(offset, limit); - - auto records = std::make_unique>(); - // - NotesRecordInterface notesInterface(notesDB); + auto records = std::make_unique>(); + const auto notes = notesDB->notes.getLimitOffsetByField(offset, limit, toNotesTableFields(field), str); for (const auto &w : notes) { - - records->push_back({ - .ID = w.ID, - .date = w.date, - .snippet = w.snippet, - .path = w.path, - }); + NotesRecord record{w.ID, w.date, w.snippet}; + records->push_back(std::move(record)); } - return records; } -bool NotesRecordInterface::Update(const NotesRecord &rec) +std::unique_ptr> NotesRecordInterface::GetLimitOffset(std::uint32_t offset, + std::uint32_t limit) { + return std::make_unique>(getNotes(offset, limit)); +} +bool NotesRecordInterface::Update(const NotesRecord &rec) +{ auto note = notesDB->notes.getById(rec.ID); - if (note.ID == 0) { + if (note.ID == DB_ID_NONE) { return false; } - notesDB->notes.update(NotesTableRow{.ID = rec.ID, .date = rec.date, .snippet = rec.snippet, .path = rec.path}); - + notesDB->notes.update(NotesTableRow{.ID = rec.ID, .date = rec.date, .snippet = rec.snippet}); return true; } -bool NotesRecordInterface::RemoveByID(uint32_t id) +bool NotesRecordInterface::RemoveAll() { + return notesDB->notes.removeAll(); +} - auto note = notesDB->notes.getById(id); - if (note.ID == 0) { - return false; - } - - // Remove SMS - if (notesDB->notes.removeById(id) == false) { - return false; - } - - return true; +bool NotesRecordInterface::RemoveByID(std::uint32_t id) +{ + return notesDB->notes.removeById(id); } bool NotesRecordInterface::RemoveByField(NotesRecordField field, const char *str) { - switch (field) { - case NotesRecordField::Data: + case NotesRecordField::Date: return notesDB->notes.removeByField(NotesTableFields::Date, str); default: return false; } } -NotesRecord NotesRecordInterface::GetByID(uint32_t id) +NotesRecord NotesRecordInterface::GetByID(std::uint32_t id) { auto note = notesDB->notes.getById(id); + return NotesRecord{note.ID, note.date, note.snippet}; +} + +std::vector NotesRecordInterface::getNotes(std::uint32_t offset, std::uint32_t limit) const +{ + std::vector records; + const auto notes = notesDB->notes.getLimitOffset(offset, limit); + for (const auto &w : notes) { + NotesRecord record{w.ID, w.date, w.snippet}; + records.push_back(std::move(record)); + } + return records; +} - return NotesRecord{.ID = note.ID, .date = note.date, .snippet = note.snippet, .path = note.path}; +std::unique_ptr NotesRecordInterface::runQuery(std::shared_ptr query) +{ + if (typeid(*query) == typeid(db::query::QueryNotesGet)) { + return getQuery(query); + } + if (typeid(*query) == typeid(db::query::QueryNoteStore)) { + return storeQuery(query); + } + if (typeid(*query) == typeid(db::query::QueryNoteRemove)) { + return removeQuery(query); + } + return nullptr; +} + +std::unique_ptr NotesRecordInterface::getQuery(const std::shared_ptr &query) +{ + const auto localQuery = static_cast(query.get()); + const auto &records = getNotes(localQuery->getOffset(), localQuery->getLimit()); + auto response = std::make_unique(records, GetCount()); + response->setRequestQuery(query); + return response; +} + +std::unique_ptr NotesRecordInterface::storeQuery(const std::shared_ptr &query) +{ + const auto localQuery = static_cast(query.get()); + const auto &record = localQuery->getRecord(); + bool isSuccess = false; + if (const auto exists = notesDB->notes.getById(record.ID).ID != DB_ID_NONE; exists) { + isSuccess = Update(record); + } + else { + isSuccess = Add(record); + } + + auto response = std::make_unique(isSuccess); + response->setRequestQuery(query); + return response; +} + +std::unique_ptr NotesRecordInterface::removeQuery(const std::shared_ptr &query) +{ + const auto localQuery = static_cast(query.get()); + const auto isSuccess = RemoveByID(localQuery->getRecordId()); + auto response = std::make_unique(isSuccess); + response->setRequestQuery(query); + return response; } diff --git a/module-db/Interface/NotesRecord.hpp b/module-db/Interface/NotesRecord.hpp index 4f4890bf6db292a8ce834d77cc4adec4ffb46178..e83f2707427ac8b1bfee485053abb606a8b701f3 100644 --- a/module-db/Interface/NotesRecord.hpp +++ b/module-db/Interface/NotesRecord.hpp @@ -4,51 +4,53 @@ #pragma once #include "Record.hpp" -#include -#include "../Databases/NotesDB.hpp" -#include "utf8/UTF8.hpp" + +#include +#include + +#include + +#include "module-db/Databases/NotesDB.hpp" #include "../Common/Common.hpp" -struct NotesRecord +struct NotesRecord : public Record { - uint32_t ID; - uint32_t date; + std::uint32_t date; UTF8 snippet; - UTF8 path; }; enum class NotesRecordField { - Data, + Date, Snippet, - Path }; -/* - * - */ class NotesRecordInterface : public RecordInterface { public: - NotesRecordInterface(NotesDB *notesDb); - virtual ~NotesRecordInterface(); - - bool Add(const NotesRecord &rec) override final; - bool RemoveByID(uint32_t id) override final; - bool RemoveByField(NotesRecordField field, const char *str) override final; - bool Update(const NotesRecord &rec) override final; - NotesRecord GetByID(uint32_t id) override final; + explicit NotesRecordInterface(NotesDB *notesDb); + + bool Add(const NotesRecord &rec) override; + bool RemoveAll() override; + bool RemoveByID(std::uint32_t id) override; + bool RemoveByField(NotesRecordField field, const char *str) override; + bool Update(const NotesRecord &rec) override; + NotesRecord GetByID(std::uint32_t id) override; + std::uint32_t GetCount() override; + std::unique_ptr> GetLimitOffset(std::uint32_t offset, std::uint32_t limit) override; + std::unique_ptr> GetLimitOffsetByField(std::uint32_t offset, + std::uint32_t limit, + NotesRecordField field, + const char *str) override; - uint32_t GetCount() override final; + std::unique_ptr runQuery(std::shared_ptr query) override; - std::unique_ptr> GetLimitOffset(uint32_t offset, uint32_t limit) override final; + private: + std::vector getNotes(std::uint32_t offset, std::uint32_t limit) const; - std::unique_ptr> GetLimitOffsetByField(uint32_t offset, - uint32_t limit, - NotesRecordField field, - const char *str) override final; + std::unique_ptr getQuery(const std::shared_ptr &query); + std::unique_ptr storeQuery(const std::shared_ptr &query); + std::unique_ptr removeQuery(const std::shared_ptr &query); - private: - const uint32_t snippetLength = 60; NotesDB *notesDB; }; diff --git a/module-db/Interface/Record.hpp b/module-db/Interface/Record.hpp index 5ca7c535485d78895531c8b979b19cfa3f668cac..c6428f46d02e3efa8a92fd2439c9f9acb82b4c0f 100644 --- a/module-db/Interface/Record.hpp +++ b/module-db/Interface/Record.hpp @@ -23,6 +23,11 @@ template class RecordInterface : public db::Interface return true; }; + virtual bool RemoveAll() + { + return true; + } + virtual bool RemoveByID(uint32_t id) { return true; diff --git a/module-db/Tables/NotesTable.cpp b/module-db/Tables/NotesTable.cpp index b00db6ee7d57d6832e020eec2c5a332d48b429d2..62045d9cb83e6df6ddf79e8d6610b3bd39e4b593 100644 --- a/module-db/Tables/NotesTable.cpp +++ b/module-db/Tables/NotesTable.cpp @@ -6,9 +6,6 @@ NotesTable::NotesTable(Database *db) : Table(db) {} -NotesTable::~NotesTable() -{} - bool NotesTable::create() { return true; @@ -16,13 +13,16 @@ bool NotesTable::create() bool NotesTable::add(NotesTableRow entry) { - return db->execute("INSERT or ignore INTO notes ( date, snippet, path ) VALUES (%lu,'%q','%q');", - entry.date, - entry.snippet.c_str(), - entry.path.c_str()); + return db->execute( + "INSERT or ignore INTO notes ( date, snippet ) VALUES ( %lu, '%q' );", entry.date, entry.snippet.c_str()); +} + +bool NotesTable::removeAll() +{ + return db->execute("DELETE FROM notes;"); } -bool NotesTable::removeById(uint32_t id) +bool NotesTable::removeById(std::uint32_t id) { return db->execute("DELETE FROM notes where _id = %lu;", id); } @@ -30,79 +30,61 @@ bool NotesTable::removeById(uint32_t id) bool NotesTable::removeByField(NotesTableFields field, const char *str) { std::string fieldName; - switch (field) { case NotesTableFields::Date: fieldName = "date"; break; - - case NotesTableFields::Path: - fieldName = "path"; - break; - case NotesTableFields::Snippet: fieldName = "snippet"; break; default: return false; } - return db->execute("DELETE FROM note where %q = '%q';", fieldName.c_str(), str); } bool NotesTable::update(NotesTableRow entry) { - return db->execute("UPDATE notes SET date = %lu, snippet = '%q', , snippet = '%q' WHERE _id=%lu;", - entry.date, - entry.snippet.c_str(), - entry.path.c_str(), - entry.ID); + return db->execute( + "UPDATE notes SET date = %lu, snippet = '%q' WHERE _id = %lu;", entry.date, entry.snippet.c_str(), entry.ID); } -NotesTableRow NotesTable::getById(uint32_t id) +NotesTableRow NotesTable::getById(std::uint32_t id) { - auto retQuery = db->query("SELECT * FROM notes WHERE _id= %u;", id); - + auto retQuery = db->query("SELECT * FROM notes WHERE _id = %lu;", id); if ((retQuery == nullptr) || (retQuery->getRowCount() == 0)) { return NotesTableRow(); } - return NotesTableRow{ (*retQuery)[0].getUInt32(), // ID (*retQuery)[1].getUInt32(), // date - (*retQuery)[2].getString(), // snippet - (*retQuery)[3].getString(), // path + (*retQuery)[2].getString() // snippet }; } -std::vector NotesTable::getLimitOffset(uint32_t offset, uint32_t limit) +std::vector NotesTable::getLimitOffset(std::uint32_t offset, std::uint32_t limit) { - auto retQuery = db->query("SELECT * from notes ORDER BY date LIMIT %lu OFFSET %lu;", limit, offset); - + auto retQuery = db->query("SELECT * FROM notes ORDER BY date DESC LIMIT %lu OFFSET %lu;", limit, offset); if ((retQuery == nullptr) || (retQuery->getRowCount() == 0)) { return std::vector(); } std::vector ret; - do { ret.push_back(NotesTableRow{ (*retQuery)[0].getUInt32(), // ID (*retQuery)[1].getUInt32(), // date - (*retQuery)[2].getString(), // snippet - (*retQuery)[3].getString(), // path + (*retQuery)[2].getString() // snippet }); } while (retQuery->nextRow()); - return ret; } -std::vector NotesTable::getLimitOffsetByField(uint32_t offset, - uint32_t limit, +std::vector NotesTable::getLimitOffsetByField(std::uint32_t offset, + std::uint32_t limit, NotesTableFields field, const char *str) { - std::string fieldName; switch (field) { case NotesTableFields::Date: @@ -111,52 +93,44 @@ std::vector NotesTable::getLimitOffsetByField(uint32_t offset, case NotesTableFields ::Snippet: fieldName = "snippet"; break; - case NotesTableFields ::Path: - fieldName = "path"; - break; default: return std::vector(); } - auto retQuery = db->query( - "SELECT * from notes WHERE %q='%q' ORDER BY date LIMIT %lu OFFSET %lu;", fieldName.c_str(), str, limit, offset); - + auto retQuery = db->query("SELECT * FROM notes WHERE %q='%q' ORDER BY date DESC LIMIT %lu OFFSET %lu;", + fieldName.c_str(), + str, + limit, + offset); if ((retQuery == nullptr) || (retQuery->getRowCount() == 0)) { return std::vector(); } std::vector ret; - do { ret.push_back(NotesTableRow{ (*retQuery)[0].getUInt32(), // ID (*retQuery)[1].getUInt32(), // date - (*retQuery)[2].getString(), // snippet - (*retQuery)[3].getString(), // path + (*retQuery)[2].getString() // snippet }); } while (retQuery->nextRow()); - return ret; } -uint32_t NotesTable::count() +std::uint32_t NotesTable::count() { - auto queryRet = db->query("SELECT COUNT(*) FROM NOTES;"); - + auto queryRet = db->query("SELECT COUNT(*) FROM notes;"); if (queryRet->getRowCount() == 0) { return 0; } - - return uint32_t{(*queryRet)[0].getUInt32()}; + return (*queryRet)[0].getUInt32(); } -uint32_t NotesTable::countByFieldId(const char *field, uint32_t id) +std::uint32_t NotesTable::countByFieldId(const char *field, std::uint32_t id) { - auto queryRet = db->query("SELECT COUNT(*) FROM notes WHERE %q=%lu;", field, id); - + auto queryRet = db->query("SELECT COUNT(*) FROM notes WHERE %q = %lu;", field, id); if ((queryRet == nullptr) || (queryRet->getRowCount() == 0)) { return 0; } - - return uint32_t{(*queryRet)[0].getUInt32()}; + return (*queryRet)[0].getUInt32(); } diff --git a/module-db/Tables/NotesTable.hpp b/module-db/Tables/NotesTable.hpp index 50407115a54afe939b3fcfd96a796724bea415a2..db001927c5ad56aa03402f4b5531cc5daf8d89dc 100644 --- a/module-db/Tables/NotesTable.hpp +++ b/module-db/Tables/NotesTable.hpp @@ -3,6 +3,8 @@ #pragma once +#include + #include "Table.hpp" #include "Record.hpp" #include "Database/Database.hpp" @@ -11,40 +13,35 @@ struct NotesTableRow { - uint32_t ID = DB_ID_NONE; - uint32_t date; - UTF8 snippet; // up to 60 characters - UTF8 path; + std::uint32_t ID = DB_ID_NONE; + std::uint32_t date; + UTF8 snippet; }; enum class NotesTableFields { Date, Snippet, - Path }; -/* - * - */ class NotesTable : public Table { public: - NotesTable(Database *db); - virtual ~NotesTable(); - - bool create() override final; - bool add(NotesTableRow entry) override final; - bool removeById(uint32_t id) override final; - bool removeByField(NotesTableFields field, const char *str) override final; - bool update(NotesTableRow entry) override final; - NotesTableRow getById(uint32_t id) override final; - std::vector getLimitOffset(uint32_t offset, uint32_t limit) override final; - std::vector getLimitOffsetByField(uint32_t offset, - uint32_t limit, + explicit NotesTable(Database *db); + + bool create() override; + bool add(NotesTableRow entry) override; + bool removeAll() override; + bool removeById(std::uint32_t id) override; + bool removeByField(NotesTableFields field, const char *str) override; + bool update(NotesTableRow entry) override; + NotesTableRow getById(std::uint32_t id) override; + std::vector getLimitOffset(std::uint32_t offset, std::uint32_t limit) override; + std::vector getLimitOffsetByField(std::uint32_t offset, + std::uint32_t limit, NotesTableFields field, - const char *str) override final; + const char *str) override; - uint32_t count() override final; - uint32_t countByFieldId(const char *field, uint32_t id) override final; + std::uint32_t count() override; + std::uint32_t countByFieldId(const char *field, std::uint32_t id) override; }; diff --git a/module-db/Tables/Table.hpp b/module-db/Tables/Table.hpp index 08e7a15510e218af98e5993999a2fdc2498259b9..5fbbe4b8fd1924c380fae93a4f6dc92c9bc9adca 100644 --- a/module-db/Tables/Table.hpp +++ b/module-db/Tables/Table.hpp @@ -17,8 +17,12 @@ template class Table virtual ~Table() {} - virtual bool create() = 0; - virtual bool add(T entry) = 0; + virtual bool create() = 0; + virtual bool add(T entry) = 0; + virtual bool removeAll() + { + return false; + } virtual bool removeById(uint32_t id) = 0; virtual bool removeByField(F field, const char *str) { diff --git a/module-db/queries/notes/QueryNoteRemove.cpp b/module-db/queries/notes/QueryNoteRemove.cpp new file mode 100644 index 0000000000000000000000000000000000000000..7fd0511f08740674c0c308bd941dae1cf49935dd --- /dev/null +++ b/module-db/queries/notes/QueryNoteRemove.cpp @@ -0,0 +1,33 @@ +// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved. +// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md + +#include "QueryNoteRemove.hpp" + +namespace db::query +{ + QueryNoteRemove::QueryNoteRemove(unsigned int recordId) : Query(Query::Type::Delete), recordId{recordId} + {} + + unsigned int QueryNoteRemove::getRecordId() const noexcept + { + return recordId; + } + + std::string QueryNoteRemove::debugInfo() const + { + return {"QueryNoteRemove"}; + } + + NoteRemoveResult::NoteRemoveResult(bool isSuccess) : isSuccess{isSuccess} + {} + + bool NoteRemoveResult::succeed() const noexcept + { + return isSuccess; + } + + auto NoteRemoveResult::debugInfo() const -> std::string + { + return {"NoteRemoveResult"}; + } +} // namespace db::query diff --git a/module-db/queries/notes/QueryNoteRemove.hpp b/module-db/queries/notes/QueryNoteRemove.hpp new file mode 100644 index 0000000000000000000000000000000000000000..86c45d73339347a655005c8d1c795cb4e8e000ad --- /dev/null +++ b/module-db/queries/notes/QueryNoteRemove.hpp @@ -0,0 +1,35 @@ +// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved. +// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md + +#pragma once + +#include + +#include +#include "Interface/NotesRecord.hpp" + +namespace db::query +{ + class QueryNoteRemove : public Query + { + public: + explicit QueryNoteRemove(unsigned int recordId); + [[nodiscard]] unsigned int getRecordId() const noexcept; + [[nodiscard]] std::string debugInfo() const override; + + private: + unsigned int recordId; + }; + + class NoteRemoveResult : public QueryResult + { + public: + explicit NoteRemoveResult(bool isSuccess); + + [[nodiscard]] bool succeed() const noexcept; + [[nodiscard]] std::string debugInfo() const override; + + private: + bool isSuccess; + }; +} // namespace db::query diff --git a/module-db/queries/notes/QueryNoteStore.cpp b/module-db/queries/notes/QueryNoteStore.cpp new file mode 100644 index 0000000000000000000000000000000000000000..769ec94d4b6513fc11190a527f5d14af0e8633d7 --- /dev/null +++ b/module-db/queries/notes/QueryNoteStore.cpp @@ -0,0 +1,33 @@ +// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved. +// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md + +#include "QueryNoteStore.hpp" + +namespace db::query +{ + QueryNoteStore::QueryNoteStore(NotesRecord record) : Query(Query::Type::Create), record{std::move(record)} + {} + + const NotesRecord &QueryNoteStore::getRecord() const noexcept + { + return record; + } + + std::string QueryNoteStore::debugInfo() const + { + return {"QueryNoteStore"}; + } + + NoteStoreResult::NoteStoreResult(bool isSuccess) : isSuccess{isSuccess} + {} + + bool NoteStoreResult::succeed() const noexcept + { + return isSuccess; + } + + auto NoteStoreResult::debugInfo() const -> std::string + { + return {"NoteStoreResult"}; + } +} // namespace db::query diff --git a/module-db/queries/notes/QueryNoteStore.hpp b/module-db/queries/notes/QueryNoteStore.hpp new file mode 100644 index 0000000000000000000000000000000000000000..7516bb09c3120b084ba4a58a1c36eb997099908b --- /dev/null +++ b/module-db/queries/notes/QueryNoteStore.hpp @@ -0,0 +1,36 @@ +// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved. +// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md + +#pragma once + +#include + +#include +#include "Interface/NotesRecord.hpp" + +namespace db::query +{ + class QueryNoteStore : public Query + { + public: + explicit QueryNoteStore(NotesRecord record); + + [[nodiscard]] const NotesRecord &getRecord() const noexcept; + [[nodiscard]] std::string debugInfo() const override; + + private: + NotesRecord record; + }; + + class NoteStoreResult : public QueryResult + { + public: + explicit NoteStoreResult(bool isSuccess); + + [[nodiscard]] bool succeed() const noexcept; + [[nodiscard]] std::string debugInfo() const override; + + private: + bool isSuccess; + }; +} // namespace db::query diff --git a/module-db/queries/notes/QueryNotesGet.cpp b/module-db/queries/notes/QueryNotesGet.cpp new file mode 100644 index 0000000000000000000000000000000000000000..47f1e6601b0875a0610ac167e5fd582decac8517 --- /dev/null +++ b/module-db/queries/notes/QueryNotesGet.cpp @@ -0,0 +1,45 @@ +// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved. +// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md + +#include "QueryNotesGet.hpp" + +namespace db::query +{ + QueryNotesGet::QueryNotesGet(unsigned int offset, unsigned int limit) + : Query(Query::Type::Read), offset{offset}, limit{limit} + {} + + unsigned int QueryNotesGet::getOffset() const noexcept + { + return offset; + } + + unsigned int QueryNotesGet::getLimit() const noexcept + { + return limit; + } + + std::string QueryNotesGet::debugInfo() const + { + return {"QueryNotesGet"}; + } + + NotesGetResult::NotesGetResult(std::vector notes, unsigned int dbRecordsCount) + : records{std::move(notes)}, dbRecordsCount{dbRecordsCount} + {} + + const std::vector &NotesGetResult::getRecords() const noexcept + { + return records; + } + + unsigned int NotesGetResult::getCount() const noexcept + { + return dbRecordsCount; + } + + auto NotesGetResult::debugInfo() const -> std::string + { + return {"NotesGetResult"}; + } +} // namespace db::query diff --git a/module-db/queries/notes/QueryNotesGet.hpp b/module-db/queries/notes/QueryNotesGet.hpp new file mode 100644 index 0000000000000000000000000000000000000000..67310458e2355e3d4ac5b3874ea25992defd85ba --- /dev/null +++ b/module-db/queries/notes/QueryNotesGet.hpp @@ -0,0 +1,40 @@ +// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved. +// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md + +#pragma once + +#include + +#include +#include "Interface/NotesRecord.hpp" + +namespace db::query +{ + class QueryNotesGet : public Query + { + public: + explicit QueryNotesGet(unsigned int offset = 0U, unsigned int limit = 0U); + + [[nodiscard]] unsigned int getOffset() const noexcept; + [[nodiscard]] unsigned int getLimit() const noexcept; + [[nodiscard]] std::string debugInfo() const override; + + private: + unsigned int offset; + unsigned int limit; + }; + + class NotesGetResult : public QueryResult + { + public: + NotesGetResult(std::vector notes, unsigned int dbRecordsCount); + + [[nodiscard]] const std::vector &getRecords() const noexcept; + [[nodiscard]] unsigned int getCount() const noexcept; + [[nodiscard]] std::string debugInfo() const override; + + private: + std::vector records; + unsigned int dbRecordsCount; + }; +} // namespace db::query diff --git a/module-db/tests/CMakeLists.txt b/module-db/tests/CMakeLists.txt index 456b1830eda6c99302e9595e0de832de38e586f2..2bfc87ed1dc104ce301e06b49e7107165ae7ea1a 100644 --- a/module-db/tests/CMakeLists.txt +++ b/module-db/tests/CMakeLists.txt @@ -22,7 +22,8 @@ add_catch2_executable( "${CMAKE_CURRENT_SOURCE_DIR}/CalllogTable_tests.cpp" "${CMAKE_CURRENT_SOURCE_DIR}/NotificationsTable_tests.cpp" "${CMAKE_CURRENT_SOURCE_DIR}/EventsTable_tests.cpp" - + "${CMAKE_CURRENT_SOURCE_DIR}/NotesRecord_tests.cpp" + "${CMAKE_CURRENT_SOURCE_DIR}/NotesTable_tests.cpp" "${CMAKE_CURRENT_SOURCE_DIR}/CalllogRecord_tests.cpp" "${CMAKE_CURRENT_SOURCE_DIR}/ContactsRecord_tests.cpp" "${CMAKE_CURRENT_SOURCE_DIR}/SMSRecord_tests.cpp" diff --git a/module-db/tests/NotesRecord_tests.cpp b/module-db/tests/NotesRecord_tests.cpp new file mode 100644 index 0000000000000000000000000000000000000000..f2d07f8eaac2ab6c93f3d5d19520fcbca899f95a --- /dev/null +++ b/module-db/tests/NotesRecord_tests.cpp @@ -0,0 +1,67 @@ +// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved. +// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md + +#include + +#include +#include +#include +#include + +#include "Database/Database.hpp" +#include "Databases/NotesDB.hpp" + +TEST_CASE("Notes Record tests") +{ + Database::initialize(); + + auto notesDb = std::make_unique(); + REQUIRE(notesDb->isInitialized()); + + NotesRecordInterface notesRecordInterface{notesDb.get()}; + notesRecordInterface.RemoveAll(); // Empty the notes database. + + constexpr auto testSnippet = "TEST SNIPPET"; + + NotesRecord recordIn; + recordIn.snippet = testSnippet; + + notesRecordInterface.Add(recordIn); + REQUIRE(notesRecordInterface.GetCount() == 1); + + SECTION("Get notes query") + { + auto query = std::make_unique(0, notesRecordInterface.GetCount()); + auto response = notesRecordInterface.runQuery(std::move(query)); + auto getResult = static_cast(response.get()); + + REQUIRE(getResult->getRecords().size() == notesRecordInterface.GetCount()); + REQUIRE(getResult->getCount() == notesRecordInterface.GetCount()); + REQUIRE(getResult->getRecords()[0].snippet == testSnippet); + } + + SECTION("Add a note") + { + NotesRecord record; + record.snippet = testSnippet; + + auto query = std::make_unique(record); + auto response = notesRecordInterface.runQuery(std::move(query)); + auto addResult = static_cast(response.get()); + + REQUIRE(addResult->succeed()); + REQUIRE(notesRecordInterface.GetCount() == 2); + } + + SECTION("Remove a note") + { + auto query = std::make_unique(1); + auto response = notesRecordInterface.runQuery(std::move(query)); + auto removeResult = static_cast(response.get()); + + REQUIRE(removeResult->succeed()); + REQUIRE(notesRecordInterface.GetCount() == 0); + } + + Database::deinitialize(); +}; diff --git a/module-db/tests/NotesTable_tests.cpp b/module-db/tests/NotesTable_tests.cpp new file mode 100644 index 0000000000000000000000000000000000000000..60a746d4a180d3f771a6cd1b87f71da588862b74 --- /dev/null +++ b/module-db/tests/NotesTable_tests.cpp @@ -0,0 +1,65 @@ +// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved. +// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md + +#include + +#include +#include "Database/Database.hpp" +#include "Databases/NotesDB.hpp" + +TEST_CASE("Notes Table tests") +{ + Database::initialize(); + + auto notesDb = std::make_unique(); + REQUIRE(notesDb->isInitialized()); + + NotesTable table{notesDb.get()}; + table.removeAll(); + REQUIRE(table.count() == 0); + + constexpr auto testSnippet = "TEST SNIPPET"; + + NotesTableRow rowIn; + rowIn.snippet = testSnippet; + + table.add(rowIn); + REQUIRE(table.count() == 1); + + SECTION("Get notes") + { + const auto &records = table.getLimitOffset(0, table.count()); + REQUIRE(records.size() == table.count()); + REQUIRE(records[0].snippet == testSnippet); + } + + SECTION("Add a note") + { + NotesTableRow row; + row.snippet = testSnippet; + table.add(row); + REQUIRE(table.count() == 2); + } + + SECTION("Update a note") + { + constexpr auto testId = 1; + constexpr auto testSnippetUpdated = "UPDATED TEST SNIPPET"; + NotesTableRow row; + row.ID = testId; + row.snippet = testSnippetUpdated; + table.update(row); + REQUIRE(table.count() == 1); + + const auto &record = table.getById(testId); + REQUIRE(record.snippet == testSnippetUpdated); + } + + SECTION("Remove a note") + { + table.removeById(1); + REQUIRE(table.count() == 0); + } + + Database::deinitialize(); +} \ No newline at end of file