M changelog.md => changelog.md +1 -0
@@ 3,6 3,7 @@
[Current release]
### Added
+* `[notes]` Notes application implemented.
### Changed
M image/assets/lang/English.json => image/assets/lang/English.json +7 -3
@@ 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",
M image/user/db/notes_001.sql => image/user/db/notes_001.sql +1 -2
@@ 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 ''
);
M image/user/db/notes_002.sql => image/user/db/notes_002.sql +26 -26
@@ 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;
A module-apps/BasePresenter.hpp => module-apps/BasePresenter.hpp +29 -0
@@ 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 <cassert>
+
+namespace app
+{
+ template <typename VIEW> 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
M module-apps/application-notes/ApplicationNotes.cpp => module-apps/application-notes/ApplicationNotes.cpp +59 -36
@@ 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 <service-db/DBMessage.hpp>
+#include <service-db/QueryMessage.hpp>
-#include "ApplicationNotes.hpp"
+#include <module-apps/application-notes/presenter/NotesMainWindowPresenter.hpp>
+#include <module-apps/application-notes/presenter/NotePreviewWindowPresenter.hpp>
+#include <module-apps/application-notes/presenter/NoteEditWindowPresenter.hpp>
+#include <module-apps/windows/OptionWindow.hpp>
+#include <module-apps/windows/Dialog.hpp>
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<sys::ResponseMessage *>(retMsg.get())->retCode == sys::ReturnCodes::Success)) {
+ if (static_cast<sys::ResponseMessage *>(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<db::QueryResponse *>(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<sys::ResponseMessage>();
- else
- return std::make_shared<sys::ResponseMessage>(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<gui::NotesMainWindow>(app);
+ windowsFactory.attach(gui::name::window::main_window, [this](Application *app, const std::string &name) {
+ auto notesRepository = std::make_unique<notes::NotesDBRepository>(this);
+ auto notesProvider = std::make_shared<notes::NotesListModel>(this, std::move(notesRepository));
+ auto presenter = std::make_unique<notes::NotesMainWindowPresenter>(notesProvider);
+ return std::make_unique<notes::NoteMainWindow>(app, std::move(presenter));
});
- windowsFactory.attach(gui::name::window::main_window, [](Application *app, const std::string &name) {
- return std::make_unique<gui::NotesEditWindow>(app);
+ windowsFactory.attach(gui::name::window::note_preview, [this](Application *app, const std::string &name) {
+ auto notesRepository = std::make_unique<notes::NotesDBRepository>(this);
+ auto presenter = std::make_unique<notes::NotePreviewWindowPresenter>(std::move(notesRepository));
+ return std::make_unique<notes::NotePreviewWindow>(app, std::move(presenter));
});
+ windowsFactory.attach(gui::name::window::note_edit, [this](Application *app, const std::string &name) {
+ auto notesRepository = std::make_unique<notes::NotesDBRepository>(this);
+ auto presenter = std::make_unique<notes::NoteEditWindowPresenter>(std::move(notesRepository));
+ return std::make_unique<notes::NoteEditWindow>(app, std::move(presenter));
+ });
+ windowsFactory.attach(gui::name::window::note_confirm_dialog, [](Application *app, const std::string &name) {
+ return std::make_unique<gui::DialogYesNo>(app, name);
+ });
+ windowsFactory.attach(
+ utils::localize.get("app_phonebook_options_title"),
+ [](Application *app, const std::string &name) { return std::make_unique<gui::OptionWindow>(app, name); });
}
void ApplicationNotes::destroyUserInterface()
{}
-
-} /* namespace app */
+} // namespace app
M module-apps/application-notes/ApplicationNotes.hpp => module-apps/application-notes/ApplicationNotes.hpp +15 -15
@@ 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
M module-apps/application-notes/CMakeLists.txt => module-apps/application-notes/CMakeLists.txt +24 -13
@@ 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
- )
+)
D module-apps/application-notes/NotesModel.cpp => module-apps/application-notes/NotesModel.cpp +0 -57
@@ 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 <service-db/DBServiceAPI.hpp>
-#include "widgets/NotesItem.hpp"
-
-#include "NotesModel.hpp"
-#include "ListView.hpp"
-
-#include <module-utils/Utils.hpp>
-#include <module-services/service-db/agents/settings/SystemSettings.hpp>
-
-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<NotesRecord> 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<NotesRecord> note = getRecord(order);
-
- auto *item = new gui::NotesItem(this, !(application->isTimeFormat12()));
-
- item->setNote(note);
- return item;
-}
D module-apps/application-notes/NotesModel.hpp => module-apps/application-notes/NotesModel.hpp +0 -33
@@ 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 <vector>
-
-#include "Interface/NotesRecord.hpp"
-#include "DatabaseModel.hpp"
-#include "NotesRecord.hpp"
-#include "Application.hpp"
-#include "ListItemProvider.hpp"
-
-/*
- *
- */
-class NotesModel : public app::DatabaseModel<NotesRecord>, public gui::ListItemProvider
-{
- public:
- NotesModel(app::Application *app);
-
- // virtual methods
- bool updateRecords(std::vector<NotesRecord> 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_ */
A module-apps/application-notes/data/NoteSwitchData.cpp => module-apps/application-notes/data/NoteSwitchData.cpp +16 -0
@@ 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
A module-apps/application-notes/data/NoteSwitchData.hpp => module-apps/application-notes/data/NoteSwitchData.hpp +22 -0
@@ 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 <module-gui/gui/SwitchData.hpp>
+
+#include <module-db/Interface/NotesRecord.hpp>
+
+namespace app::notes
+{
+ class NoteSwitchData : public gui::SwitchData
+ {
+ public:
+ explicit NoteSwitchData(NotesRecord record);
+
+ const NotesRecord &getRecord() const noexcept;
+
+ private:
+ NotesRecord record;
+ };
+} // namespace app::notes
A module-apps/application-notes/model/NotesListModel.cpp => module-apps/application-notes/model/NotesListModel.cpp +81 -0
@@ 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 <module-apps/messages/OptionsWindow.hpp>
+
+#include <module-gui/gui/widgets/ListView.hpp>
+#include <module-gui/gui/input/InputEvent.hpp>
+
+namespace app::notes
+{
+ NotesListItemProvider::NotesListItemProvider(Application *app) : DatabaseModel(app)
+ {}
+
+ NotesListModel::NotesListModel(app::Application *app, std::shared_ptr<AbstractNotesRepository> notesRepository)
+ : NotesListItemProvider(app), notesRepository{std::move(notesRepository)}
+ {}
+
+ unsigned int NotesListModel::requestRecordsCount()
+ {
+ return recordsCount;
+ }
+
+ bool NotesListModel::updateRecords(std::vector<NotesRecord> 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<NotesRecord> 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<NoteSwitchData>(*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<gui::OptionsWindowOptions>(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<NotesRecord> &records, unsigned int notesRepoCount) {
+ return onNotesRetrieved(records, notesRepoCount);
+ });
+ }
+
+ bool NotesListModel::onNotesRetrieved(const std::vector<NotesRecord> &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
A module-apps/application-notes/model/NotesListModel.hpp => module-apps/application-notes/model/NotesListModel.hpp +43 -0
@@ 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 <cstdint>
+#include <vector>
+
+#include <module-apps/Application.hpp>
+#include <module-apps/DatabaseModel.hpp>
+
+#include <module-db/Interface/NotesRecord.hpp>
+
+#include <module-gui/gui/widgets/ListItemProvider.hpp>
+
+#include "NotesRepository.hpp"
+
+namespace app::notes
+{
+ class NotesListItemProvider : public app::DatabaseModel<NotesRecord>, public gui::ListItemProvider
+ {
+ public:
+ explicit NotesListItemProvider(app::Application *app);
+ };
+
+ class NotesListModel : public NotesListItemProvider
+ {
+ public:
+ NotesListModel(app::Application *app, std::shared_ptr<AbstractNotesRepository> notesRepository);
+
+ [[nodiscard]] unsigned int requestRecordsCount() override;
+ [[nodiscard]] bool updateRecords(std::vector<NotesRecord> 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<NotesRecord> &records, unsigned int notesRepoCount);
+
+ std::shared_ptr<AbstractNotesRepository> notesRepository;
+ };
+} // namespace app::notes
A module-apps/application-notes/model/NotesRepository.cpp => module-apps/application-notes/model/NotesRepository.cpp +64 -0
@@ 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 <module-db/queries/notes/QueryNotesGet.hpp>
+#include <module-db/queries/notes/QueryNoteStore.hpp>
+#include <module-db/queries/notes/QueryNoteRemove.hpp>
+
+#include <service-db/DBServiceAPI.hpp>
+
+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<db::query::QueryNotesGet>(offset, limit);
+ query->setQueryListener(db::QueryCallback::fromFunction([callback](auto response) {
+ auto result = dynamic_cast<db::query::NotesGetResult *>(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<db::query::QueryNoteStore>(note);
+ query->setQueryListener(db::QueryCallback::fromFunction([callback](auto response) {
+ auto result = dynamic_cast<db::query::NoteStoreResult *>(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<db::query::QueryNoteRemove>(note.ID);
+ query->setQueryListener(db::QueryCallback::fromFunction([callback](auto response) {
+ auto result = dynamic_cast<db::query::NoteRemoveResult *>(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
A module-apps/application-notes/model/NotesRepository.hpp => module-apps/application-notes/model/NotesRepository.hpp +39 -0
@@ 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 <functional>
+
+#include <module-apps/Application.hpp>
+
+#include <module-db/Interface/NotesRecord.hpp>
+
+namespace app::notes
+{
+ class AbstractNotesRepository
+ {
+ public:
+ using OnGetCallback = std::function<bool(const std::vector<NotesRecord> &, unsigned int)>;
+ using OnResultCallback = std::function<void(bool)>;
+
+ 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
A module-apps/application-notes/presenter/NoteEditWindowPresenter.cpp => module-apps/application-notes/presenter/NoteEditWindowPresenter.cpp +16 -0
@@ 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<AbstractNotesRepository> &¬esRepository)
+ : notesRepository{std::move(notesRepository)}
+ {}
+
+ void NoteEditWindowPresenter::save(const NotesRecord ¬e)
+ {
+ notesRepository->save(note, nullptr);
+ }
+} // namespace app::notes
A module-apps/application-notes/presenter/NoteEditWindowPresenter.hpp => module-apps/application-notes/presenter/NoteEditWindowPresenter.hpp +39 -0
@@ 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 <module-apps/BasePresenter.hpp>
+
+#include <module-apps/application-notes/model/NotesRepository.hpp>
+
+namespace app::notes
+{
+ class NoteEditWindowContract
+ {
+ public:
+ class View
+ {
+ public:
+ virtual ~View() noexcept = default;
+ };
+ class Presenter : public BasePresenter<NoteEditWindowContract::View>
+ {
+ public:
+ virtual ~Presenter() noexcept = default;
+
+ virtual void save(const NotesRecord ¬e) = 0;
+ };
+ };
+
+ class NoteEditWindowPresenter : public NoteEditWindowContract::Presenter
+ {
+ public:
+ explicit NoteEditWindowPresenter(std::unique_ptr<AbstractNotesRepository> &¬esRepository);
+
+ void save(const NotesRecord ¬e) override;
+
+ private:
+ std::unique_ptr<AbstractNotesRepository> notesRepository;
+ };
+} // namespace app::notes
A module-apps/application-notes/presenter/NotePreviewWindowPresenter.cpp => module-apps/application-notes/presenter/NotePreviewWindowPresenter.cpp +16 -0
@@ 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<AbstractNotesRepository> notesRepository)
+ : notesRepository{std::move(notesRepository)}
+ {}
+
+ AbstractNotesRepository &NotePreviewWindowPresenter::getRepository()
+ {
+ return *notesRepository;
+ }
+} // namespace app::notes
A module-apps/application-notes/presenter/NotePreviewWindowPresenter.hpp => module-apps/application-notes/presenter/NotePreviewWindowPresenter.hpp +39 -0
@@ 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 <module-apps/BasePresenter.hpp>
+
+#include <module-apps/application-notes/model/NotesRepository.hpp>
+
+namespace app::notes
+{
+ class NotePreviewWindowContract
+ {
+ public:
+ class View
+ {
+ public:
+ virtual ~View() noexcept = default;
+ };
+ class Presenter : public BasePresenter<NotePreviewWindowContract::View>
+ {
+ public:
+ virtual ~Presenter() noexcept = default;
+
+ virtual AbstractNotesRepository &getRepository() = 0;
+ };
+ };
+
+ class NotePreviewWindowPresenter : public NotePreviewWindowContract::Presenter
+ {
+ public:
+ explicit NotePreviewWindowPresenter(std::unique_ptr<AbstractNotesRepository> notesRepository);
+
+ AbstractNotesRepository &getRepository() override;
+
+ private:
+ std::unique_ptr<AbstractNotesRepository> notesRepository;
+ };
+} // namespace app::notes
A module-apps/application-notes/presenter/NotesMainWindowPresenter.cpp => module-apps/application-notes/presenter/NotesMainWindowPresenter.cpp +26 -0
@@ 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<NotesListItemProvider> notesProvider)
+ : notesProvider{std::move(notesProvider)}
+ {}
+
+ std::shared_ptr<gui::ListItemProvider> NotesMainWindowPresenter::getNotesItemProvider() const
+ {
+ return notesProvider;
+ }
+
+ bool NotesMainWindowPresenter::isNoteListEmpty()
+ {
+ return notesProvider->requestRecordsCount() == 0U;
+ }
+
+ bool NotesMainWindowPresenter::updateNotes(std::vector<NotesRecord> &&records)
+ {
+ return notesProvider->updateRecords(std::move(records));
+ }
+} // namespace app::notes
A module-apps/application-notes/presenter/NotesMainWindowPresenter.hpp => module-apps/application-notes/presenter/NotesMainWindowPresenter.hpp +43 -0
@@ 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 <module-apps/BasePresenter.hpp>
+
+#include <module-apps/application-notes/model/NotesListModel.hpp>
+
+namespace app::notes
+{
+ class NotesMainWindowContract
+ {
+ public:
+ class View
+ {
+ public:
+ virtual ~View() noexcept = default;
+ };
+ class Presenter : public BasePresenter<NotesMainWindowContract::View>
+ {
+ public:
+ virtual ~Presenter() noexcept = default;
+
+ virtual std::shared_ptr<gui::ListItemProvider> getNotesItemProvider() const = 0;
+ virtual bool isNoteListEmpty() = 0;
+ virtual bool updateNotes(std::vector<NotesRecord> &&records) = 0;
+ };
+ };
+
+ class NotesMainWindowPresenter : public NotesMainWindowContract::Presenter
+ {
+ public:
+ explicit NotesMainWindowPresenter(std::shared_ptr<NotesListItemProvider> notesListItemProvider);
+
+ std::shared_ptr<gui::ListItemProvider> getNotesItemProvider() const override;
+ bool isNoteListEmpty() override;
+ bool updateNotes(std::vector<NotesRecord> &&records) override;
+
+ private:
+ std::shared_ptr<NotesListItemProvider> notesProvider;
+ };
+} // namespace app::notes
A module-apps/application-notes/style/NoteEditStyle.hpp => module-apps/application-notes/style/NoteEditStyle.hpp +25 -0
@@ 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 <module-gui/gui/widgets/Style.hpp>
+
+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
A module-apps/application-notes/style/NotePreviewStyle.hpp => module-apps/application-notes/style/NotePreviewStyle.hpp +24 -0
@@ 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 <module-gui/gui/widgets/Style.hpp>
+
+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
A module-apps/application-notes/style/NotesListStyle.hpp => module-apps/application-notes/style/NotesListStyle.hpp +45 -0
@@ 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 <module-gui/gui/widgets/Style.hpp>
+
+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
A module-apps/application-notes/style/NotesMainWindowStyle.hpp => module-apps/application-notes/style/NotesMainWindowStyle.hpp +37 -0
@@ 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 <module-gui/gui/widgets/Style.hpp>
+
+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
M module-apps/application-notes/widgets/NotesItem.cpp => module-apps/application-notes/widgets/NotesItem.cpp +62 -43
@@ 2,71 2,90 @@
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
#include "NotesItem.hpp"
+
#include <Style.hpp>
+#include <module-apps/application-notes/style/NotesListStyle.hpp>
+
+#include <module-utils/time/time_conversion.hpp>
namespace gui
{
-
- NotesItem::NotesItem(NotesModel *model, bool mode24H) : model{model}, mode24H{mode24H}
+ NotesItem::NotesItem(std::shared_ptr<NotesRecord> 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<NotesRecord> ¬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
M module-apps/application-notes/widgets/NotesItem.hpp => module-apps/application-notes/widgets/NotesItem.hpp +20 -32
@@ 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 <module-gui/gui/widgets/Label.hpp>
+#include <module-gui/gui/widgets/ListItem.hpp>
+#include <module-gui/gui/widgets/TextFixedSize.hpp>
+
+#include <module-db/Interface/NotesRecord.hpp>
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<NotesRecord> 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<NotesRecord> ¬e);
-
- // returns alarm structure
- std::shared_ptr<NotesRecord> getAlarm();
- // virtual methods from Item
+ explicit NotesItem(std::shared_ptr<NotesRecord> 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<NotesRecord> note;
+ gui::Label *date = nullptr;
+ gui::Label *title = nullptr;
+ gui::TextFixedSize *snippet = nullptr;
+ };
+} // namespace gui
A module-apps/application-notes/windows/NoteEditWindow.cpp => module-apps/application-notes/windows/NoteEditWindow.cpp +152 -0
@@ 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 <sstream>
+
+#include <Style.hpp>
+
+#include <module-apps/application-notes/ApplicationNotes.hpp>
+#include <module-apps/application-notes/windows/NotesOptions.hpp>
+#include <module-apps/application-notes/data/NoteSwitchData.hpp>
+#include <module-apps/application-notes/style/NoteEditStyle.hpp>
+#include <module-apps/messages/OptionsWindow.hpp>
+
+#include <module-utils/i18n/i18n.hpp>
+#include <module-utils/time/time_conversion.hpp>
+
+#include <module-gui/gui/widgets/BottomBar.hpp>
+#include <module-gui/gui/widgets/TopBar.hpp>
+
+namespace app::notes
+{
+ namespace
+ {
+ constexpr auto MaxCharactersCount = 4000U;
+ } // namespace
+
+ NoteEditWindow::NoteEditWindow(app::Application *app,
+ std::unique_ptr<NoteEditWindowContract::Presenter> &&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<NoteSwitchData *>(data);
+ if (editData == nullptr) {
+ return;
+ }
+
+ notesRecord = std::make_unique<NotesRecord>(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<NoteSwitchData>(*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<gui::OptionsWindowOptions>(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
A module-apps/application-notes/windows/NoteEditWindow.hpp => module-apps/application-notes/windows/NoteEditWindow.hpp +43 -0
@@ 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 <cstdint>
+
+#include "AppWindow.hpp"
+
+#include <module-db/Interface/NotesRecord.hpp>
+
+#include "gui/widgets/Label.hpp"
+#include "gui/widgets/Text.hpp"
+#include "gui/input/InputEvent.hpp"
+
+#include <module-apps/application-notes/presenter/NoteEditWindowPresenter.hpp>
+
+namespace app::notes
+{
+ class NoteEditWindow : public gui::AppWindow, public NoteEditWindowContract::View
+ {
+ public:
+ NoteEditWindow(app::Application *app, std::unique_ptr<NoteEditWindowContract::Presenter> &&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<NoteEditWindowContract::Presenter> presenter;
+ std::unique_ptr<NotesRecord> notesRecord;
+ gui::Label *charactersCounter;
+ gui::Text *edit;
+ };
+} // namespace app::notes
A module-apps/application-notes/windows/NoteMainWindow.cpp => module-apps/application-notes/windows/NoteMainWindow.cpp +179 -0
@@ 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 <module-apps/application-notes/ApplicationNotes.hpp>
+#include <module-apps/application-notes/data/NoteSwitchData.hpp>
+
+#include <InputEvent.hpp>
+#include <service-db/DBNotesMessage.hpp>
+
+#include <module-utils/i18n/i18n.hpp>
+
+#include <gui/widgets/Label.hpp>
+#include <gui/widgets/BottomBar.hpp>
+#include <gui/widgets/TopBar.hpp>
+
+#include <Style.hpp>
+#include <module-apps/application-notes/style/NotesListStyle.hpp>
+#include <module-apps/application-notes/style/NotesMainWindowStyle.hpp>
+
+namespace app::notes
+{
+ NoteMainWindow::NoteMainWindow(app::Application *app,
+ std::unique_ptr<NotesMainWindowContract::Presenter> &&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<NoteSwitchData>(NotesRecord{}));
+ }
+ }
+ return AppWindow::onInput(inputEvent);
+ }
+
+ bool NoteMainWindow::onDatabaseMessage(sys::Message *msgl)
+ {
+ auto *msg = static_cast<DBNotesResponseMessage *>(msgl);
+ return presenter->updateNotes(std::move(*msg->records));
+ }
+} // namespace app::notes
A module-apps/application-notes/windows/NoteMainWindow.hpp => module-apps/application-notes/windows/NoteMainWindow.hpp +46 -0
@@ 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 <memory>
+
+#include <AppWindow.hpp>
+#include <module-gui/gui/widgets/Image.hpp>
+#include <module-gui/gui/widgets/Icon.hpp>
+#include <module-gui/gui/widgets/ListView.hpp>
+
+#include <module-apps/application-notes/presenter/NotesMainWindowPresenter.hpp>
+
+namespace app::notes
+{
+ class NoteMainWindow : public gui::AppWindow, public NotesMainWindowContract::View
+ {
+ public:
+ NoteMainWindow(app::Application *app, std::unique_ptr<NotesMainWindowContract::Presenter> &&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<NotesMainWindowContract::Presenter> 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
A module-apps/application-notes/windows/NotePreviewWindow.cpp => module-apps/application-notes/windows/NotePreviewWindow.cpp +129 -0
@@ 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 <module-apps/application-notes/ApplicationNotes.hpp>
+#include <module-apps/application-notes/data/NoteSwitchData.hpp>
+#include <module-apps/application-notes/style/NotePreviewStyle.hpp>
+#include <module-apps/application-notes/windows/NotesOptions.hpp>
+#include <module-apps/messages/OptionsWindow.hpp>
+
+#include <module-utils/i18n/i18n.hpp>
+#include <module-utils/time/time_conversion.hpp>
+
+#include <Style.hpp>
+
+#include <module-gui/gui/widgets/BottomBar.hpp>
+#include <module-gui/gui/widgets/TopBar.hpp>
+
+namespace app::notes
+{
+ NotePreviewWindow::NotePreviewWindow(app::Application *app,
+ std::unique_ptr<NotePreviewWindowContract::Presenter> &&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<NoteSwitchData *>(data);
+ if (previewData == nullptr) {
+ return;
+ }
+
+ notesRecord = std::make_unique<NotesRecord>(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<NoteSwitchData>(*notesRecord));
+ }
+ else if (inputEvent.is(gui::KeyCode::KEY_LF)) {
+ application->switchWindow(utils::localize.get("app_phonebook_options_title"),
+ std::make_unique<gui::OptionsWindowOptions>(notePreviewOptions(
+ application, *notesRecord, presenter->getRepository(), note)));
+ }
+ }
+ return AppWindow::onInput(inputEvent);
+ }
+} // namespace app::notes
A module-apps/application-notes/windows/NotePreviewWindow.hpp => module-apps/application-notes/windows/NotePreviewWindow.hpp +39 -0
@@ 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 <module-db/Interface/NotesRecord.hpp>
+#include <module-apps/application-notes/presenter/NotePreviewWindowPresenter.hpp>
+
+#include <module-gui/gui/widgets/Label.hpp>
+#include <module-gui/gui/widgets/TextFixedSize.hpp>
+#include <module-gui/gui/input/InputEvent.hpp>
+
+namespace app::notes
+{
+ class NotePreviewWindow : public gui::AppWindow, public NotePreviewWindowContract::View
+ {
+ public:
+ NotePreviewWindow(app::Application *app,
+ std::unique_ptr<NotePreviewWindowContract::Presenter> &&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<NotePreviewWindowContract::Presenter> presenter;
+ std::unique_ptr<NotesRecord> notesRecord;
+ gui::TextFixedSize *note = nullptr;
+ gui::Label *date = nullptr;
+ };
+} // namespace app::notes
D module-apps/application-notes/windows/NotesEditWindow.cpp => module-apps/application-notes/windows/NotesEditWindow.cpp +0 -88
@@ 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 <memory>
-#include <functional>
-
-#include <service-appmgr/model/ApplicationManager.hpp>
-
-#include "bsp/rtc/rtc.hpp"
-
-#include "../ApplicationNotes.hpp"
-
-#include <service-db/DBMessage.hpp>
-#include "module-utils/i18n/i18n.hpp"
-
-#include "Label.hpp"
-#include "Margins.hpp"
-#include "Text.hpp"
-#include "NotesEditWindow.hpp"
-#include <Style.hpp>
-
-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 */
D module-apps/application-notes/windows/NotesEditWindow.hpp => module-apps/application-notes/windows/NotesEditWindow.hpp +0 -41
@@ 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 <string>
-#include <functional>
-
-#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_ */
D module-apps/application-notes/windows/NotesMainWindow.cpp => module-apps/application-notes/windows/NotesMainWindow.cpp +0 -86
@@ 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 <memory>
-#include <functional>
-
-#include "InputEvent.hpp"
-#include <service-appmgr/model/ApplicationManager.hpp>
-
-#include "../ApplicationNotes.hpp"
-
-#include <service-db/DBNotesMessage.hpp>
-#include "module-utils/i18n/i18n.hpp"
-
-#include "Label.hpp"
-#include "Margins.hpp"
-#include "NotesMainWindow.hpp"
-#include <Style.hpp>
-
-namespace gui
-{
-
- NotesMainWindow::NotesMainWindow(app::Application *app)
- : AppWindow(app, gui::name::window::main_window), notesModel{std::make_shared<NotesModel>(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<DBNotesResponseMessage *>(msgl);
- return notesModel->updateRecords(std::move(*msg->records));
- }
-
-} /* namespace gui */
D module-apps/application-notes/windows/NotesMainWindow.hpp => module-apps/application-notes/windows/NotesMainWindow.hpp +0 -44
@@ 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 <string>
-#include <functional>
-
-#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> 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_ */
A module-apps/application-notes/windows/NotesOptions.cpp => module-apps/application-notes/windows/NotesOptions.cpp +108 -0
@@ 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 <Options.hpp>
+#include <common_data/Clipboard.hpp>
+
+#include <module-apps/windows/DialogMetadata.hpp>
+#include <module-apps/messages/DialogMetadataMessage.hpp>
+
+#include <module-utils/i18n/i18n.hpp>
+
+#include <module-gui/gui/widgets/Text.hpp>
+
+namespace app::notes
+{
+ namespace
+ {
+ void addOption(const std::string &translationId,
+ std::function<bool(gui::Item &)> onClickCallback,
+ std::list<gui::Option> &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<gui::DialogMetadataMessage>(meta));
+ }
+ } // namespace
+
+ std::list<gui::Option> noteListOptions(Application *application,
+ const NotesRecord &record,
+ AbstractNotesRepository ¬esRepository)
+ {
+ std::list<gui::Option> options;
+ addOption(
+ {"app_notes_delete_note"},
+ [application, record, ¬esRepository](gui::Item &item) {
+ removeNote(record, application, notesRepository);
+ return true;
+ },
+ options);
+ return options;
+ }
+
+ std::list<gui::Option> notePreviewOptions(Application *application,
+ const NotesRecord &record,
+ AbstractNotesRepository ¬esRepository,
+ gui::Text *textWidget)
+ {
+ std::list<gui::Option> 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<gui::Option> noteEditOptions(Application *application, const NotesRecord &record, gui::Text *textWidget)
+ {
+ std::list<gui::Option> 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
A module-apps/application-notes/windows/NotesOptions.hpp => module-apps/application-notes/windows/NotesOptions.hpp +25 -0
@@ 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 <module-apps/application-notes/ApplicationNotes.hpp>
+#include <module-db/Interface/NotesRecord.hpp>
+
+namespace gui
+{
+ class Option; // Forward declaration.
+ class Text; // Forward declaration.
+} // namespace gui
+
+namespace app::notes
+{
+ std::list<gui::Option> noteListOptions(Application *application,
+ const NotesRecord &record,
+ AbstractNotesRepository ¬esRepository);
+ std::list<gui::Option> notePreviewOptions(Application *application,
+ const NotesRecord &record,
+ AbstractNotesRepository ¬esRepository,
+ gui::Text *textWidget);
+ std::list<gui::Option> noteEditOptions(Application *application, const NotesRecord &record, gui::Text *textWidget);
+} // namespace app::notes
M module-db/CMakeLists.txt => module-db/CMakeLists.txt +3 -0
@@ 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
M module-db/Interface/NotesRecord.cpp => module-db/Interface/NotesRecord.cpp +104 -51
@@ 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 <cassert>
-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<std::vector<NotesRecord>> NotesRecordInterface::GetLimitOffsetByField(uint32_t offset,
- uint32_t limit,
+std::unique_ptr<std::vector<NotesRecord>> NotesRecordInterface::GetLimitOffsetByField(std::uint32_t offset,
+ std::uint32_t limit,
NotesRecordField field,
const char *str)
{
- return GetLimitOffset(offset, limit);
-}
-
-std::unique_ptr<std::vector<NotesRecord>> NotesRecordInterface::GetLimitOffset(uint32_t offset, uint32_t limit)
-{
- auto notes = notesDB->notes.getLimitOffset(offset, limit);
-
- auto records = std::make_unique<std::vector<NotesRecord>>();
- //
- NotesRecordInterface notesInterface(notesDB);
+ auto records = std::make_unique<std::vector<NotesRecord>>();
+ 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<std::vector<NotesRecord>> NotesRecordInterface::GetLimitOffset(std::uint32_t offset,
+ std::uint32_t limit)
{
+ return std::make_unique<std::vector<NotesRecord>>(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<NotesRecord> NotesRecordInterface::getNotes(std::uint32_t offset, std::uint32_t limit) const
+{
+ std::vector<NotesRecord> 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<db::QueryResult> NotesRecordInterface::runQuery(std::shared_ptr<db::Query> 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<db::QueryResult> NotesRecordInterface::getQuery(const std::shared_ptr<db::Query> &query)
+{
+ const auto localQuery = static_cast<db::query::QueryNotesGet *>(query.get());
+ const auto &records = getNotes(localQuery->getOffset(), localQuery->getLimit());
+ auto response = std::make_unique<db::query::NotesGetResult>(records, GetCount());
+ response->setRequestQuery(query);
+ return response;
+}
+
+std::unique_ptr<db::QueryResult> NotesRecordInterface::storeQuery(const std::shared_ptr<db::Query> &query)
+{
+ const auto localQuery = static_cast<db::query::QueryNoteStore *>(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<db::query::NoteStoreResult>(isSuccess);
+ response->setRequestQuery(query);
+ return response;
+}
+
+std::unique_ptr<db::QueryResult> NotesRecordInterface::removeQuery(const std::shared_ptr<db::Query> &query)
+{
+ const auto localQuery = static_cast<db::query::QueryNoteRemove *>(query.get());
+ const auto isSuccess = RemoveByID(localQuery->getRecordId());
+ auto response = std::make_unique<db::query::NoteRemoveResult>(isSuccess);
+ response->setRequestQuery(query);
+ return response;
}
M module-db/Interface/NotesRecord.hpp => module-db/Interface/NotesRecord.hpp +30 -28
@@ 4,51 4,53 @@
#pragma once
#include "Record.hpp"
-#include <stdint.h>
-#include "../Databases/NotesDB.hpp"
-#include "utf8/UTF8.hpp"
+
+#include <cstdint>
+#include <filesystem>
+
+#include <utf8/UTF8.hpp>
+
+#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<NotesRecord, NotesRecordField>
{
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<std::vector<NotesRecord>> GetLimitOffset(std::uint32_t offset, std::uint32_t limit) override;
+ std::unique_ptr<std::vector<NotesRecord>> GetLimitOffsetByField(std::uint32_t offset,
+ std::uint32_t limit,
+ NotesRecordField field,
+ const char *str) override;
- uint32_t GetCount() override final;
+ std::unique_ptr<db::QueryResult> runQuery(std::shared_ptr<db::Query> query) override;
- std::unique_ptr<std::vector<NotesRecord>> GetLimitOffset(uint32_t offset, uint32_t limit) override final;
+ private:
+ std::vector<NotesRecord> getNotes(std::uint32_t offset, std::uint32_t limit) const;
- std::unique_ptr<std::vector<NotesRecord>> GetLimitOffsetByField(uint32_t offset,
- uint32_t limit,
- NotesRecordField field,
- const char *str) override final;
+ std::unique_ptr<db::QueryResult> getQuery(const std::shared_ptr<db::Query> &query);
+ std::unique_ptr<db::QueryResult> storeQuery(const std::shared_ptr<db::Query> &query);
+ std::unique_ptr<db::QueryResult> removeQuery(const std::shared_ptr<db::Query> &query);
- private:
- const uint32_t snippetLength = 60;
NotesDB *notesDB;
};
M module-db/Interface/Record.hpp => module-db/Interface/Record.hpp +5 -0
@@ 23,6 23,11 @@ template <typename T, typename F> class RecordInterface : public db::Interface
return true;
};
+ virtual bool RemoveAll()
+ {
+ return true;
+ }
+
virtual bool RemoveByID(uint32_t id)
{
return true;
M module-db/Tables/NotesTable.cpp => module-db/Tables/NotesTable.cpp +30 -56
@@ 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<NotesTableRow> NotesTable::getLimitOffset(uint32_t offset, uint32_t limit)
+std::vector<NotesTableRow> 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<NotesTableRow>();
}
std::vector<NotesTableRow> 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<NotesTableRow> NotesTable::getLimitOffsetByField(uint32_t offset,
- uint32_t limit,
+std::vector<NotesTableRow> 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<NotesTableRow> NotesTable::getLimitOffsetByField(uint32_t offset,
case NotesTableFields ::Snippet:
fieldName = "snippet";
break;
- case NotesTableFields ::Path:
- fieldName = "path";
- break;
default:
return std::vector<NotesTableRow>();
}
- 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<NotesTableRow>();
}
std::vector<NotesTableRow> 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();
}
M module-db/Tables/NotesTable.hpp => module-db/Tables/NotesTable.hpp +20 -23
@@ 3,6 3,8 @@
#pragma once
+#include <cstdint>
+
#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<NotesTableRow, NotesTableFields>
{
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<NotesTableRow> getLimitOffset(uint32_t offset, uint32_t limit) override final;
- std::vector<NotesTableRow> 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<NotesTableRow> getLimitOffset(std::uint32_t offset, std::uint32_t limit) override;
+ std::vector<NotesTableRow> 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;
};
M module-db/Tables/Table.hpp => module-db/Tables/Table.hpp +6 -2
@@ 17,8 17,12 @@ template <typename T, typename F> 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)
{
A module-db/queries/notes/QueryNoteRemove.cpp => module-db/queries/notes/QueryNoteRemove.cpp +33 -0
@@ 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
A module-db/queries/notes/QueryNoteRemove.hpp => module-db/queries/notes/QueryNoteRemove.hpp +35 -0
@@ 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 <string>
+
+#include <Common/Query.hpp>
+#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
A module-db/queries/notes/QueryNoteStore.cpp => module-db/queries/notes/QueryNoteStore.cpp +33 -0
@@ 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
A module-db/queries/notes/QueryNoteStore.hpp => module-db/queries/notes/QueryNoteStore.hpp +36 -0
@@ 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 <string>
+
+#include <Common/Query.hpp>
+#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
A module-db/queries/notes/QueryNotesGet.cpp => module-db/queries/notes/QueryNotesGet.cpp +45 -0
@@ 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<NotesRecord> notes, unsigned int dbRecordsCount)
+ : records{std::move(notes)}, dbRecordsCount{dbRecordsCount}
+ {}
+
+ const std::vector<NotesRecord> &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
A module-db/queries/notes/QueryNotesGet.hpp => module-db/queries/notes/QueryNotesGet.hpp +40 -0
@@ 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 <string>
+
+#include <Common/Query.hpp>
+#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<NotesRecord> notes, unsigned int dbRecordsCount);
+
+ [[nodiscard]] const std::vector<NotesRecord> &getRecords() const noexcept;
+ [[nodiscard]] unsigned int getCount() const noexcept;
+ [[nodiscard]] std::string debugInfo() const override;
+
+ private:
+ std::vector<NotesRecord> records;
+ unsigned int dbRecordsCount;
+ };
+} // namespace db::query
M module-db/tests/CMakeLists.txt => module-db/tests/CMakeLists.txt +2 -1
@@ 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"
A module-db/tests/NotesRecord_tests.cpp => module-db/tests/NotesRecord_tests.cpp +67 -0
@@ 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 <catch2/catch.hpp>
+
+#include <Interface/NotesRecord.hpp>
+#include <queries/notes/QueryNotesGet.hpp>
+#include <queries/notes/QueryNoteRemove.hpp>
+#include <queries/notes/QueryNoteStore.hpp>
+
+#include "Database/Database.hpp"
+#include "Databases/NotesDB.hpp"
+
+TEST_CASE("Notes Record tests")
+{
+ Database::initialize();
+
+ auto notesDb = std::make_unique<NotesDB>();
+ 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<db::query::QueryNotesGet>(0, notesRecordInterface.GetCount());
+ auto response = notesRecordInterface.runQuery(std::move(query));
+ auto getResult = static_cast<db::query::NotesGetResult *>(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<db::query::QueryNoteStore>(record);
+ auto response = notesRecordInterface.runQuery(std::move(query));
+ auto addResult = static_cast<db::query::NoteStoreResult *>(response.get());
+
+ REQUIRE(addResult->succeed());
+ REQUIRE(notesRecordInterface.GetCount() == 2);
+ }
+
+ SECTION("Remove a note")
+ {
+ auto query = std::make_unique<db::query::QueryNoteRemove>(1);
+ auto response = notesRecordInterface.runQuery(std::move(query));
+ auto removeResult = static_cast<db::query::NoteRemoveResult *>(response.get());
+
+ REQUIRE(removeResult->succeed());
+ REQUIRE(notesRecordInterface.GetCount() == 0);
+ }
+
+ Database::deinitialize();
+};
A module-db/tests/NotesTable_tests.cpp => module-db/tests/NotesTable_tests.cpp +65 -0
@@ 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 <catch2/catch.hpp>
+
+#include <Tables/NotesTable.hpp>
+#include "Database/Database.hpp"
+#include "Databases/NotesDB.hpp"
+
+TEST_CASE("Notes Table tests")
+{
+ Database::initialize();
+
+ auto notesDb = std::make_unique<NotesDB>();
+ 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