From 1b37e62f421da928fbdb367f49116e05f680e5e4 Mon Sep 17 00:00:00 2001 From: Lefucjusz Date: Thu, 29 Feb 2024 14:51:38 +0100 Subject: [PATCH] [MOS-1067] Fix Pure crash when deleting all contacts Fix of the issue that Pure would crash when trying to delete all contacts from Mudita Center when main window of phonebook was opened and focus was set on different contact than the first one in the list. --- .../windows/PhonebookMainWindow.cpp | 11 +++- module-db/Tables/ContactsTable.cpp | 54 +++++++++---------- module-db/Tables/ContactsTable.hpp | 39 +++++--------- pure_changelog.md | 1 + 4 files changed, 51 insertions(+), 54 deletions(-) diff --git a/module-apps/application-phonebook/windows/PhonebookMainWindow.cpp b/module-apps/application-phonebook/windows/PhonebookMainWindow.cpp index 59ff517ef450f0d2088c1b095ce20f12837a5472..2c8a3e2615a2ff2ac32921273f75242ef620d36d 100644 --- a/module-apps/application-phonebook/windows/PhonebookMainWindow.cpp +++ b/module-apps/application-phonebook/windows/PhonebookMainWindow.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2017-2023, Mudita Sp. z.o.o. All rights reserved. +// Copyright (c) 2017-2024, Mudita Sp. z.o.o. All rights reserved. // For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md #include "PhonebookMainWindow.hpp" @@ -166,7 +166,14 @@ namespace gui if ((msgNotification != nullptr) && (msgNotification->interface == db::Interface::Name::Contact) && msgNotification->dataModified()) { phonebookModel->letterMap = phonebookModel->requestLetterMap(); - rebuild(); + if (msgNotification->type == db::Query::Type::Delete) { + /* Perform full rebuild to prevent crash in case current + * list index > number of remaining elements. */ + contactsList->rebuildList(gui::listview::RebuildType::Full); + } + else { + contactsList->rebuildList(gui::listview::RebuildType::InPlace); + } return true; } return false; diff --git a/module-db/Tables/ContactsTable.cpp b/module-db/Tables/ContactsTable.cpp index 61774fc9eddf04eabffc769cae196ec2dc336cff..588b74e9832ec770e33711198fd157c3ba2bb41a 100644 --- a/module-db/Tables/ContactsTable.cpp +++ b/module-db/Tables/ContactsTable.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2017-2023, Mudita Sp. z.o.o. All rights reserved. +// Copyright (c) 2017-2024, Mudita Sp. z.o.o. All rights reserved. // For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md #include "ContactsTable.hpp" @@ -8,24 +8,24 @@ namespace ColumnName { - const uint8_t id = 0; - const uint8_t name_id = 1; - const uint8_t numbers_id = 2; - const uint8_t ring_id = 3; - const uint8_t address_id = 4; - const uint8_t speeddial = 5; + constexpr std::uint8_t id = 0; + constexpr std::uint8_t name_id = 1; + constexpr std::uint8_t numbers_id = 2; + constexpr std::uint8_t ring_id = 3; + constexpr std::uint8_t address_id = 4; + constexpr std::uint8_t speeddial = 5; }; // namespace ColumnName namespace statements { - const auto selectWithoutTemp = "SELECT * FROM contacts WHERE _id=" u32_ " AND " - " contacts._id NOT IN ( " - " SELECT cmg.contact_id " - " FROM contact_match_groups cmg, contact_groups cg " - " WHERE cmg.group_id = cg._id " - " AND cg.name = 'Temporary' " - " ) "; - const auto selectWithTemp = "SELECT * FROM contacts WHERE _id=" u32_ ";"; + constexpr auto selectWithoutTemp = "SELECT * FROM contacts WHERE _id=" u32_ " AND " + " contacts._id NOT IN ( " + " SELECT cmg.contact_id " + " FROM contact_match_groups cmg, contact_groups cg " + " WHERE cmg.group_id = cg._id " + " AND cg.name = 'Temporary' " + " ) "; + constexpr auto selectWithTemp = "SELECT * FROM contacts WHERE _id=" u32_ ";"; } // namespace statements ContactsTable::ContactsTable(Database *db) : Table(db) @@ -50,12 +50,12 @@ bool ContactsTable::add(ContactsTableRow entry) entry.speedDial.c_str()); } -bool ContactsTable::removeById(uint32_t id) +bool ContactsTable::removeById(std::uint32_t id) { return db->execute("DELETE FROM contacts where _id=" u32_ ";", id); } -bool ContactsTable::BlockByID(uint32_t id, bool shouldBeBlocked) +bool ContactsTable::BlockByID(std::uint32_t id, bool shouldBeBlocked) { return db->execute("UPDATE contacts SET blacklist=" u32_ " WHERE _id=" u32_ ";", shouldBeBlocked ? 1 : 0, id); } @@ -72,13 +72,13 @@ bool ContactsTable::update(ContactsTableRow entry) entry.ID); } -ContactsTableRow ContactsTable::getById(uint32_t id) +ContactsTableRow ContactsTable::getById(std::uint32_t id) { auto retQuery = db->query(statements::selectWithoutTemp, id); return getByIdCommon(std::move(retQuery)); } -ContactsTableRow ContactsTable::getByIdWithTemporary(uint32_t id) +ContactsTableRow ContactsTable::getByIdWithTemporary(std::uint32_t id) { debug_db_data("%s", __FUNCTION__); auto retQuery = db->query(statements::selectWithTemp, id); @@ -218,7 +218,7 @@ std::vector ContactsTable::GetIDsSortedByName(std::uint32_t limit } while (queryRet->nextRow()); if (limit > 0) { - for (uint32_t a = 0; a < limit; a++) { + for (std::uint32_t a = 0; a < limit; a++) { ids_limit.push_back(ids[a + offset]); } return ids_limit; @@ -354,7 +354,7 @@ std::vector ContactsTable::GetIDsSortedByField( return ids; } -std::vector ContactsTable::getLimitOffset(uint32_t offset, uint32_t limit) +std::vector ContactsTable::getLimitOffset(std::uint32_t offset, std::uint32_t limit) { auto retQuery = db->query("SELECT * from contacts WHERE contacts._id NOT IN " " ( SELECT cmg.contact_id " @@ -386,8 +386,8 @@ std::vector ContactsTable::getLimitOffset(uint32_t offset, uin return ret; } -std::vector ContactsTable::getLimitOffsetByField(uint32_t offset, - uint32_t limit, +std::vector ContactsTable::getLimitOffsetByField(std::uint32_t offset, + std::uint32_t limit, ContactTableFields field, const char *str) { @@ -428,7 +428,7 @@ std::vector ContactsTable::getLimitOffsetByField(uint32_t offs return ret; } -uint32_t ContactsTable::count() +std::uint32_t ContactsTable::count() { auto queryRet = db->query("SELECT COUNT(*) FROM contacts " " WHERE contacts._id not in ( " @@ -442,10 +442,10 @@ uint32_t ContactsTable::count() return 0; } - return uint32_t{(*queryRet)[0].getUInt32()}; + return (*queryRet)[0].getUInt32(); } -uint32_t ContactsTable::countByFieldId(const char *field, uint32_t id) +std::uint32_t ContactsTable::countByFieldId(const char *field, std::uint32_t id) { auto queryRet = db->query("SELECT COUNT(*) FROM contacts WHERE %q=" u32_ ";", field, id); @@ -453,5 +453,5 @@ uint32_t ContactsTable::countByFieldId(const char *field, uint32_t id) return 0; } - return uint32_t{(*queryRet)[0].getUInt32()}; + return (*queryRet)[0].getUInt32(); } diff --git a/module-db/Tables/ContactsTable.hpp b/module-db/Tables/ContactsTable.hpp index 35e587f106b0f95382f22f140ef1e8427a1f0d88..0205ada894c3f193ab90e0c829844bd549ebb13a 100644 --- a/module-db/Tables/ContactsTable.hpp +++ b/module-db/Tables/ContactsTable.hpp @@ -1,4 +1,4 @@ -// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved. +// Copyright (c) 2017-2024, Mudita Sp. z.o.o. All rights reserved. // For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md #pragma once @@ -16,10 +16,10 @@ struct ContactsTableRow : public Record { - uint32_t nameID = DB_ID_NONE; + std::uint32_t nameID = DB_ID_NONE; std::string numbersID = ""; - uint32_t ringID = DB_ID_NONE; - uint32_t addressID = DB_ID_NONE; + std::uint32_t ringID = DB_ID_NONE; + std::uint32_t addressID = DB_ID_NONE; std::string speedDial = ""; UTF8 namePrimary = ""; UTF8 nameAlternative = ""; @@ -27,7 +27,7 @@ struct ContactsTableRow : public Record enum class ContactTableFields { - SpeedDial, + SpeedDial }; class ContactsTable : public Table @@ -38,44 +38,33 @@ class ContactsTable : public Table Name, TextNumber, Group, - - None, + None }; ContactsTable(Database *db); - virtual ~ContactsTable(); bool create() override final; - bool add(ContactsTableRow entry) override final; - - bool removeById(uint32_t id) override final; - + bool removeById(std::uint32_t id) override final; bool update(ContactsTableRow entry) override final; - ContactsTableRow getById(uint32_t id) override final; - ContactsTableRow getByIdWithTemporary(uint32_t id); + ContactsTableRow getById(std::uint32_t id) override final; + ContactsTableRow getByIdWithTemporary(std::uint32_t id); - private: - ContactsTableRow getByIdCommon(std::unique_ptr retQuery); - - public: - bool BlockByID(uint32_t id, bool shouldBeBlocked); + bool BlockByID(std::uint32_t id, bool shouldBeBlocked); std::vector Search(const std::string &primaryName, const std::string &alternativeName, const std::string &number); - std::vector getLimitOffset(uint32_t offset, uint32_t limit) override final; - - std::vector getLimitOffsetByField(uint32_t offset, - uint32_t limit, + std::vector getLimitOffset(std::uint32_t offset, std::uint32_t limit) override final; + std::vector getLimitOffsetByField(std::uint32_t offset, + std::uint32_t limit, ContactTableFields field, const char *str) override final; uint32_t count() override final; - uint32_t countByFieldId(const char *field, uint32_t id) override final; std::vector GetIDsSortedByField(MatchType matchType, @@ -83,11 +72,11 @@ class ContactsTable : public Table std::uint32_t groupId, std::uint32_t limit = 0, std::uint32_t offset = 0); - std::vector GetIDsSortedByName(std::uint32_t limit = 0, std::uint32_t offset = 0); ContactsMapData GetPosOfFirstLetters(); std::string GetSortedByNameQueryString(ContactQuerySection section); private: + ContactsTableRow getByIdCommon(std::unique_ptr retQuery); }; diff --git a/pure_changelog.md b/pure_changelog.md index 7219773cce4d1bf9902bf12359f56098a953008a..492999b06a0840cf2e3daea3eb07fd2b73cfd6f8 100644 --- a/pure_changelog.md +++ b/pure_changelog.md @@ -6,6 +6,7 @@ * Fixed no response when editing a contact via Center to have the same number as another. * Fixed occasional screen backlight flash when turning off the phone. * Fixed device freeze after finishing onboarding in Spanish. +* Fixed crash when deleting all contacts from MC with Phonebook app opened. ### Added