Initial commit
This commit is contained in:
commit
b7d90b9afe
16245 files changed
+3396666
No files matched your search
+295
@@ -0,0 +1,295 @@
|
||||
/**
|
||||
* @RDE_HEADER@
|
||||
* $Id$
|
||||
* $HeadURL$
|
||||
* $Author$
|
||||
*/
|
||||
|
||||
#include "handler_menu_struct.h"
|
||||
#include "main_handler.h"
|
||||
#include "dds_handler.h"
|
||||
#include "object_menu_struct.h"
|
||||
#include "audio_video_handler_impl.h"
|
||||
#include <AudioVideoManagement/avm_dts.h>
|
||||
#include <QVector>
|
||||
#include <tuple>
|
||||
|
||||
namespace
|
||||
{
|
||||
|
||||
|
||||
AudioVideoManagement::MenuStruct toDdsToplevel(const AudioVideoManagement::Database::AvmMenuStruct &dbEntry)
|
||||
{
|
||||
Q_ASSERT(dbEntry.parentId == 0);
|
||||
Q_ASSERT(dbEntry.isGroup);
|
||||
Q_ASSERT(dbEntry.name.isValid());
|
||||
|
||||
AudioVideoManagement::MenuStruct ms;
|
||||
ms.id(dbEntry.id);
|
||||
ms.name(dbEntry.name.toString().toStdString());
|
||||
ms.isAudio(dbEntry.isAudio);
|
||||
|
||||
return ms;
|
||||
}
|
||||
|
||||
void insertChildren(std::vector<AudioVideoManagement::AvMenuEntry>& contToAdd,
|
||||
int parentId,
|
||||
const QVector<AudioVideoManagement::Database::AvmMenuStruct> &vecMenuStructs)
|
||||
{
|
||||
using namespace AudioVideoManagement;
|
||||
|
||||
for (const Database::AvmMenuStruct &ms : vecMenuStructs)
|
||||
if (ms.parentId == parentId)
|
||||
contToAdd.push_back(HandlerMenuStruct::toDds(ms));
|
||||
}
|
||||
|
||||
bool lessToplevel(const AudioVideoManagement::AvMenuEntry &a,
|
||||
const AudioVideoManagement::AvMenuEntry &b)
|
||||
{
|
||||
return a.id() < b.id();
|
||||
}
|
||||
|
||||
bool lessSublevel(const AudioVideoManagement::AvMenuEntry &a,
|
||||
const AudioVideoManagement::AvMenuEntry &b)
|
||||
{
|
||||
return std::make_tuple(a.parentId(), a.rowId(), a.id()) < std::make_tuple(b.parentId(), b.rowId(), b.id());
|
||||
}
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
|
||||
namespace AudioVideoManagement
|
||||
{
|
||||
|
||||
AvMenuEntry HandlerMenuStruct::toDds(const Database::AvmMenuStruct &dbEntry)
|
||||
{
|
||||
Q_ASSERT(dbEntry.parentId > 0);
|
||||
|
||||
AvMenuEntry ddsItem;
|
||||
|
||||
ddsItem.id(dbEntry.id);
|
||||
ddsItem.parentId(dbEntry.parentId);
|
||||
ddsItem.isGroup(dbEntry.isGroup);
|
||||
ddsItem.rowId(dbEntry.rowid);
|
||||
if (dbEntry.isGroup)
|
||||
{
|
||||
Q_ASSERT(dbEntry.name.isValid());
|
||||
ddsItem.name().set(dbEntry.name.toString().toStdString());
|
||||
}
|
||||
else
|
||||
{
|
||||
// If it's not a group it represents a stream for a given MountignPoint.
|
||||
// For the name we then use the internal stream name for that MountingPoint.
|
||||
// That name is not saved in the DB.
|
||||
// Using the internal stream name here makes it easy for clients to directly
|
||||
// use those when communicating with AVS.
|
||||
Q_ASSERT(dbEntry.mountingPointId.isValid());
|
||||
ddsItem.mountingPointId(dbEntry.mountingPointId.toInt());
|
||||
ddsItem.name().set(AudioVideoHandlerImpl::internalStreamName(dbEntry.mountingPointId.toInt()).toStdString());
|
||||
}
|
||||
|
||||
return ddsItem;
|
||||
}
|
||||
|
||||
void HandlerMenuStruct::sortEntries(MenuStruct &menu)
|
||||
{
|
||||
auto isToplevel = [&menu] (const AvMenuEntry& entry) { return entry.parentId() == menu.id(); };
|
||||
auto sublevelStart = std::partition(menu.menuEntries().begin(), menu.menuEntries().end(), isToplevel);
|
||||
|
||||
std::sort(menu.menuEntries().begin(), sublevelStart, lessToplevel);
|
||||
std::sort(sublevelStart, menu.menuEntries().end(), lessSublevel);
|
||||
}
|
||||
|
||||
HandlerMenuStruct::HandlerMenuStruct(Interface::Dts *dts, Interface::Fts *fts, DatabaseInterface *db)
|
||||
: Interface::Fts::ModifyMenuStructRequestHandler(nullptr)
|
||||
, Interface::Fts::RemoveMenuStructRequestHandler(nullptr)
|
||||
, m_dts(dts)
|
||||
, m_fts(fts)
|
||||
, m_db(db)
|
||||
, m_logger(getLogger("HandlerMenuStruct"))
|
||||
{
|
||||
Q_ASSERT(dts);
|
||||
Q_ASSERT(fts);
|
||||
Q_ASSERT(db);
|
||||
m_fts->setModifyMenuStructRequestHandler(this);
|
||||
m_fts->setRemoveMenuStructRequestHandler(this);
|
||||
|
||||
connect(m_db, &DatabaseInterface::notifyDeleteAvmMenuStruct, this, &HandlerMenuStruct::onDbDeletedAvmMenuStruct);
|
||||
}
|
||||
|
||||
HandlerMenuStruct::~HandlerMenuStruct()
|
||||
{
|
||||
m_fts->setModifyMenuStructRequestHandler(nullptr);
|
||||
m_fts->setRemoveMenuStructRequestHandler(nullptr);
|
||||
qDeleteAll(m_objMap);
|
||||
}
|
||||
|
||||
bool HandlerMenuStruct::init()
|
||||
{
|
||||
return initObjects();
|
||||
}
|
||||
|
||||
bool HandlerMenuStruct::initObjects()
|
||||
{
|
||||
bool status = false;
|
||||
const QList<MenuStruct> dbItems = loadFromDb(status);
|
||||
if (!status)
|
||||
return false;
|
||||
|
||||
for (const auto &ms : dbItems)
|
||||
{
|
||||
ObjectMenuStruct *objMs = new ObjectMenuStruct(m_dts, m_db);
|
||||
objMs->createFromDb(ms);
|
||||
m_objMap.insert(objMs->getId(), objMs);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Will be called whenever a row from avm.menu_struct is removed.
|
||||
* The remove-operation itself can be a result of the following:
|
||||
* 1. we ourselves are about to remove a row as a result of a RemoveRequest
|
||||
* 2. one of our foreign key dependencies was removed (mounting_point) and our row
|
||||
* was removed as a result of a cascading delete
|
||||
* 3. someone removed the row by hand.
|
||||
*/
|
||||
void HandlerMenuStruct::reload()
|
||||
{
|
||||
bool status = false;
|
||||
const QList<MenuStruct> dbItems = loadFromDb(status);
|
||||
if (!status)
|
||||
return;
|
||||
|
||||
for (const auto &ms : dbItems)
|
||||
{
|
||||
auto found = m_objMap.find(ms.id());
|
||||
Q_ASSERT(found != m_objMap.end());
|
||||
(*found)->updateFromDb(ms);
|
||||
}
|
||||
}
|
||||
|
||||
QList<MenuStruct> HandlerMenuStruct::loadFromDb(bool &status)
|
||||
{
|
||||
status = false;
|
||||
|
||||
QVector<Database::AvmMenuStruct> vecMenuStruct;
|
||||
if (!m_db->select(vecMenuStruct))
|
||||
return {};
|
||||
|
||||
auto isToplevel = [] (const Database::AvmMenuStruct& dbEntry) { return dbEntry.parentId == 0; };
|
||||
auto sublevelStart = std::partition(vecMenuStruct.begin(), vecMenuStruct.end(), isToplevel);
|
||||
|
||||
QMap<qint32, MenuStruct> msMap;
|
||||
for (auto dbEntry = vecMenuStruct.begin(); dbEntry != sublevelStart; ++dbEntry)
|
||||
{
|
||||
MenuStruct ms = toDdsToplevel(*dbEntry);
|
||||
msMap.insert(ms.id(), ms);
|
||||
}
|
||||
|
||||
// Go over all non-toplevel entries and create AvMenuEntries for those
|
||||
// and connect them to their parent MenuStruct.
|
||||
for (auto dbEntry = sublevelStart; dbEntry != vecMenuStruct.end(); ++dbEntry)
|
||||
{
|
||||
auto it = msMap.find(dbEntry->parentId);
|
||||
if (it == msMap.end())
|
||||
continue; // this entry is probably not a direct child of a toplevel entry.
|
||||
|
||||
MenuStruct &parent = it.value();
|
||||
|
||||
AudioVideoManagement::AvMenuEntry me = toDds(*dbEntry);
|
||||
parent.menuEntries().push_back(me);
|
||||
|
||||
insertChildren(parent.menuEntries(), me.id(), vecMenuStruct);
|
||||
}
|
||||
|
||||
|
||||
// For each MenuStruct sort its entries.
|
||||
// Also: Consistency check that for each dbEntry there was created an element.
|
||||
// Or in other words that the hierarchy is consistent.
|
||||
int totalCount = msMap.size();
|
||||
for (auto &ms : msMap)
|
||||
{
|
||||
sortEntries(ms);
|
||||
totalCount += ms.menuEntries().size();
|
||||
}
|
||||
Q_ASSERT(totalCount == vecMenuStruct.size());
|
||||
|
||||
status = true;
|
||||
return msMap.values();
|
||||
}
|
||||
|
||||
|
||||
void HandlerMenuStruct::onModifyMenuStructRequest(const rti::core::SampleIdentity &cookie,
|
||||
const MenuStruct &request)
|
||||
{
|
||||
DEBUG_LOG(m_logger) << "onModifyMenuStructRequest: " << request;
|
||||
auto ret = request.id() > 0 ? modifyMenuStructRequest(request) : createMenuStructRequest(request);
|
||||
if (ret.error())
|
||||
WARNING_LOG(m_logger) << ret();
|
||||
m_fts->modifyMenuStructReply(cookie, ret);
|
||||
}
|
||||
|
||||
Core::FunctionReplyObject HandlerMenuStruct::createMenuStructRequest(const MenuStruct &request)
|
||||
{
|
||||
ObjectMenuStruct *ifs = new ObjectMenuStruct(m_dts, m_db);
|
||||
|
||||
DEBUG_LOG(m_logger) << "request.menuEntries.size() : " << request.menuEntries().size();
|
||||
Core::FunctionReplyObject ret = ifs->createFromDds(request);
|
||||
|
||||
if (ret.error())
|
||||
delete ifs;
|
||||
else
|
||||
m_objMap.insert(ifs->getId(), ifs);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
Core::FunctionReplyObject HandlerMenuStruct::modifyMenuStructRequest(const MenuStruct &request)
|
||||
{
|
||||
ObjectMenuStruct *ifs = m_objMap.value(request.id());
|
||||
if (ifs == nullptr)
|
||||
return Core::FunctionReplyObject(request.id(), tr_lts("dds", "MenuStruct with id %1 not found")).arg(request.id());
|
||||
|
||||
auto ret = ifs->updateFromDds(request);
|
||||
if (ret.error())
|
||||
return ret;
|
||||
|
||||
Q_ASSERT(ifs->getId() == request.id());
|
||||
return ret;
|
||||
}
|
||||
|
||||
void HandlerMenuStruct::onRemoveMenuStructRequest(const rti::core::SampleIdentity &cookie,
|
||||
const Core::RemoveElementRequest &request)
|
||||
{
|
||||
Core::FunctionReplyObject ret;
|
||||
|
||||
INFO_LOG(m_logger) << "onRemoveMenuStructRequest id = " << request.id();
|
||||
|
||||
ObjectMenuStruct *ifs = m_objMap.value(request.id());
|
||||
if (ifs == nullptr)
|
||||
{
|
||||
ret = Core::FunctionReplyObject(request.id(), tr_lts("dds", "MenuStruct with id %1 not found")).arg(request.id());
|
||||
}
|
||||
else
|
||||
{
|
||||
ret = ifs->remove();
|
||||
|
||||
if (!ret.error())
|
||||
{
|
||||
m_objMap.remove(request.id());
|
||||
delete ifs;
|
||||
}
|
||||
}
|
||||
|
||||
m_fts->removeMenuStructReply(cookie, ret);
|
||||
}
|
||||
|
||||
void HandlerMenuStruct::onDbDeletedAvmMenuStruct(const QVariant &id_)
|
||||
{
|
||||
int id = id_.toInt();
|
||||
DEBUG_LOG(m_logger) << "DB deleted AvmMenuStruct with id: " << id;
|
||||
reload();
|
||||
}
|
||||
|
||||
} // namespace AudioVideoManagement
|
||||
Reference in new issue
Block a user