Adds NmeaManagement tests, fixes codegen includes and Qt6 SerialPort CMake target.
263 lines
7.1 KiB
C++
Executable File
263 lines
7.1 KiB
C++
Executable File
/**
|
|
* @RDE_HEADER@
|
|
* $Id$
|
|
* $HeadURL$
|
|
* $Author$
|
|
*/
|
|
|
|
|
|
#include "object_menu_struct.h"
|
|
#include "handler_menu_struct.h"
|
|
#include "main_handler.h"
|
|
#include "dds_handler.h"
|
|
#include "logger.h"
|
|
#include <AudioVideoManagement/avm_dts.h>
|
|
#include <AudioVideoManagement/avm_db.h>
|
|
#include <DDS/Core/function_reply_object.h>
|
|
#include <ngldb/dbtransaction.h>
|
|
#include <vector>
|
|
#include <set>
|
|
#include <algorithm>
|
|
#include <cstdint>
|
|
|
|
|
|
namespace
|
|
{
|
|
|
|
AudioVideoManagement::Database::AvmMenuStruct toDb(const AudioVideoManagement::AvMenuEntry &ddsItem, int32_t parentId)
|
|
{
|
|
AudioVideoManagement::Database::AvmMenuStruct dbItem;
|
|
|
|
dbItem.id = ddsItem.id <= 0 ? 0 : ddsItem.id;
|
|
dbItem.parentId = parentId;
|
|
dbItem.isGroup = ddsItem.isGroup;
|
|
dbItem.rowid = ddsItem.rowId;
|
|
|
|
if (ddsItem.isGroup)
|
|
dbItem.name = QString::fromStdString(ddsItem.name.get());
|
|
else
|
|
dbItem.mountingPointId = ddsItem.mountingPointId.get();
|
|
|
|
return dbItem;
|
|
}
|
|
|
|
void checkHierarchy(const std::vector<AudioVideoManagement::AvMenuEntry> &entries_, int32_t toplevelId)
|
|
{
|
|
std::vector<AudioVideoManagement::AvMenuEntry> entries = entries_;
|
|
|
|
auto isToplevel = [toplevelId] (const AudioVideoManagement::AvMenuEntry &entry) { return entry.parentId == toplevelId; };
|
|
auto sublevelStart = std::partition(entries.begin(), entries.end(), isToplevel);
|
|
|
|
std::set<int32_t> ids;
|
|
std::set<int32_t> groupIds;
|
|
for (auto entry = entries.begin(); entry != sublevelStart; ++entry)
|
|
{
|
|
auto result = ids.insert(entry->id);
|
|
Q_ASSERT(result.second);
|
|
|
|
if (entry->isGroup)
|
|
groupIds.insert(entry->id);
|
|
}
|
|
|
|
for (auto entry = sublevelStart; entry != entries.end(); ++entry)
|
|
{
|
|
auto result = ids.insert(entry->id);
|
|
Q_ASSERT(result.second);
|
|
|
|
Q_ASSERT(!entry->isGroup);
|
|
Q_ASSERT(groupIds.count(entry->parentId) > 0);
|
|
}
|
|
}
|
|
|
|
} // anonymous namespace
|
|
|
|
|
|
namespace AudioVideoManagement
|
|
{
|
|
|
|
ObjectMenuStruct::ObjectMenuStruct(Interface::Dts *dts, DatabaseInterface *db)
|
|
: m_dts(dts)
|
|
, m_db(db)
|
|
, m_logger(getLogger("ObjectMenuStruct"))
|
|
{
|
|
Q_ASSERT(dts);
|
|
Q_ASSERT(db);
|
|
}
|
|
|
|
ObjectMenuStruct::~ObjectMenuStruct()
|
|
{
|
|
m_dts->removeMenuStructByKey(m_data.id);
|
|
}
|
|
|
|
Core::FunctionReplyObject ObjectMenuStruct::createFromDds(const MenuStruct &data)
|
|
{
|
|
Q_ASSERT(data.id <= 0 && m_data.id <= 0);
|
|
auto reply = insertUpdateDb(data);
|
|
onPublishData();
|
|
return reply;
|
|
}
|
|
|
|
Core::FunctionReplyObject ObjectMenuStruct::updateFromDds(const MenuStruct &data)
|
|
{
|
|
Q_ASSERT(data.id > 0 && data.id == m_data.id);
|
|
auto reply = insertUpdateDb(data);
|
|
onPublishData();
|
|
return reply;
|
|
}
|
|
|
|
void ObjectMenuStruct::createFromDb(const MenuStruct &data)
|
|
{
|
|
Q_ASSERT(data.id > 0 && m_data.id <= 0);
|
|
checkHierarchy(data.menuEntries, data.id);
|
|
m_data = data;
|
|
onPublishData();
|
|
}
|
|
|
|
void ObjectMenuStruct::updateFromDb(const MenuStruct &data)
|
|
{
|
|
Q_ASSERT(data.id > 0 && data.id == m_data.id);
|
|
if (data == m_data)
|
|
return;
|
|
|
|
checkHierarchy(data.menuEntries, data.id);
|
|
m_data = data;
|
|
onPublishData();
|
|
}
|
|
|
|
Core::FunctionReplyObject ObjectMenuStruct::remove()
|
|
{
|
|
DBTransaction trans(m_db->database());
|
|
|
|
INFO_LOG(m_logger) << "menuEntries.size(): " << m_data.menuEntries.size();
|
|
for (const AudioVideoManagement::AvMenuEntry &me : m_data.menuEntries)
|
|
{
|
|
INFO_LOG(m_logger) << "Remove entries with id/parentId: " << me.id;
|
|
// no recursion needed, only 2 levels allowed
|
|
if (me.isGroup)
|
|
if (!m_db->removeAvmMenuStructByParentId(me.id))
|
|
return Core::FunctionReplyObject(m_data.id, "Error while removing menu entries");
|
|
if (!m_db->removeAvmMenuStruct(me.id))
|
|
return Core::FunctionReplyObject(m_data.id, "Error while removing menu entries");
|
|
}
|
|
if (!m_db->removeAvmMenuStruct(m_data.id))
|
|
return Core::FunctionReplyObject(m_data.id, "Error while removing menu struct");
|
|
|
|
trans.commit();
|
|
|
|
m_dts->removeMenuStructByKey(m_data.id);
|
|
|
|
return Core::FunctionReplyObject(m_data.id);
|
|
}
|
|
|
|
void ObjectMenuStruct::onPublishData()
|
|
{
|
|
|
|
INFO_LOG(m_logger) << "Publish MenuStruct-data to dds (" << m_data.id << ") ...";
|
|
|
|
if (!m_dts->publish(m_data))
|
|
ERROR_LOG(m_logger) << "Error publishing MenuStruct-data to dds";
|
|
}
|
|
|
|
|
|
Core::FunctionReplyObject ObjectMenuStruct::insertUpdateDb(const MenuStruct &data)
|
|
{
|
|
checkHierarchy(data.menuEntries, data.id);
|
|
|
|
const auto oldEntries = m_data.menuEntries;
|
|
m_data = data;
|
|
|
|
Database::AvmMenuStruct ms;
|
|
|
|
// Insert Parent
|
|
ms.parentId = 0;
|
|
ms.name = QString::fromStdString(data.name);
|
|
ms.isAudio = data.isAudio;
|
|
ms.isGroup = true;
|
|
|
|
DBTransaction trans(m_db->database());
|
|
|
|
if (m_data.id > 0)
|
|
{
|
|
ms.id = m_data.id;
|
|
if (!m_db->update(ms))
|
|
return Core::FunctionReplyObject(0, tr_lts("dds", "Error inserting AvmMenuStruct-data into database"));
|
|
}
|
|
else
|
|
{
|
|
if (!m_db->insert(ms))
|
|
return Core::FunctionReplyObject(0, tr_lts("dds", "Error inserting AvmMenuStruct-data into database"));
|
|
}
|
|
|
|
m_data.id = ms.id;
|
|
const int virtualMenuStructId = data.id;
|
|
const int realMenuStructId = m_data.id;
|
|
|
|
std::vector<AvMenuEntry> newEntries;
|
|
newEntries.reserve(data.menuEntries.size());
|
|
|
|
auto ret = insertUpdateChildren(virtualMenuStructId, realMenuStructId, data.menuEntries, newEntries);
|
|
if (ret.error())
|
|
return ret;
|
|
|
|
DEBUG_LOG(m_logger) << "old entries: " << m_data;
|
|
for (const AvMenuEntry &me : oldEntries)
|
|
{
|
|
// new entries - ignore
|
|
if (me.id <= 0)
|
|
continue;
|
|
|
|
auto found = std::find_if(newEntries.begin(), newEntries.end(), [&me] (const AvMenuEntry &newEntry) { return me.id == newEntry.id; });
|
|
if (found == newEntries.end())
|
|
{
|
|
DEBUG_LOG(m_logger) << "Menu Entry with id not found - was removed: " << me.id;
|
|
m_db->removeAvmMenuStruct(me.id);
|
|
}
|
|
}
|
|
|
|
m_data.menuEntries = newEntries;
|
|
HandlerMenuStruct::sortEntries(m_data);
|
|
DEBUG_LOG(m_logger) << "new entries: " << m_data;
|
|
|
|
trans.commit();
|
|
return Core::FunctionReplyObject(m_data.id);
|
|
}
|
|
|
|
Core::FunctionReplyObject ObjectMenuStruct::insertUpdateChildren(int virtualParentId,
|
|
int realParentId,
|
|
const std::vector<AudioVideoManagement::AvMenuEntry>& entries,
|
|
std::vector<AudioVideoManagement::AvMenuEntry> &newEntries)
|
|
{
|
|
for(const AudioVideoManagement::AvMenuEntry &ddsItem : entries)
|
|
{
|
|
if (ddsItem.parentId != virtualParentId)
|
|
continue;
|
|
|
|
Database::AvmMenuStruct dbEntry = ::toDb(ddsItem, realParentId);
|
|
|
|
if (dbEntry.id == 0)
|
|
{
|
|
if (!m_db->insert(dbEntry))
|
|
return Core::FunctionReplyObject(0, tr_lts("dds", "Error inserting AvmMenuStruct-data into database"));
|
|
}
|
|
else
|
|
{
|
|
if (!m_db->update(dbEntry))
|
|
return Core::FunctionReplyObject(0, tr_lts("dds", "Error updating AvmMenuStruct-data into database"));
|
|
}
|
|
|
|
// update database ids in dds data
|
|
newEntries.push_back(HandlerMenuStruct::toDds(dbEntry));
|
|
|
|
if (dbEntry.isGroup)
|
|
{
|
|
const int virtualId = ddsItem.id;
|
|
const int realId = dbEntry.id;
|
|
insertUpdateChildren(virtualId, realId, entries, newEntries);
|
|
}
|
|
}
|
|
|
|
return Core::FunctionReplyObject();
|
|
}
|
|
|
|
} // namespace AudioVideoManagement
|