Initial commit
This commit is contained in:
commit
b7d90b9afe
16245 files changed
+3396666
No files matched your search
Executable
+28
@@ -0,0 +1,28 @@
|
||||
#
|
||||
# $Id$
|
||||
# $HeadURL$
|
||||
# $Author$
|
||||
# Created by Filip Biedziak, NLE, 2020-07-29
|
||||
#
|
||||
|
||||
ADD_SUBDIRECTORY(Data)
|
||||
ADD_SUBDIRECTORY(Gui)
|
||||
|
||||
#
|
||||
# Gui Plugin Interface
|
||||
#
|
||||
ADD_INTERFACE_LIBRARY(EfmGuiPluginInterface
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/efm_gui_plugin_interface.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/..
|
||||
GuiPluginInterface
|
||||
)
|
||||
|
||||
#
|
||||
# Data Plugin Interface
|
||||
#
|
||||
ADD_INTERFACE_LIBRARY(EfmDataPluginInterface
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/efm_data_plugin_interface.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/..
|
||||
DataPluginInterface
|
||||
svcSomCommon
|
||||
)
|
||||
+24
@@ -0,0 +1,24 @@
|
||||
#
|
||||
# $Id$
|
||||
# $HeadURL$
|
||||
# $Author$
|
||||
# Created by Filip Biedziak, SLSE, 2020-07-29
|
||||
#
|
||||
|
||||
#
|
||||
# Data Plugin
|
||||
#
|
||||
SET(efm_data_SRCS
|
||||
efm_data_plugin.cpp
|
||||
efm_data_plugin.h
|
||||
)
|
||||
|
||||
NGL_ADD_LIBRARY(WS EfmDataPlugin MODULE ${efm_data_SRCS})
|
||||
NGL_TARGET_LINK_LIBRARIES(EfmDataPlugin
|
||||
Qt5::Core
|
||||
EfmDataPluginInterface
|
||||
svcSomClient
|
||||
NGLLogger
|
||||
LtsSessionDataDds
|
||||
)
|
||||
NGL_INSTALL_TARGET(EfmDataPlugin)
|
||||
+40
@@ -0,0 +1,40 @@
|
||||
/**
|
||||
* @RDE_HEADER@
|
||||
* Data Plugin for effect management.
|
||||
* $Id$
|
||||
* $HeadURL$
|
||||
* $Author$
|
||||
* Created by Filip Biedziak, SLSE, 2020-07-29
|
||||
*/
|
||||
|
||||
#include "efm_data_plugin.h"
|
||||
|
||||
#include <DDS/DDSConnector/dds_connector.h>
|
||||
#include <LtsSession/lts_session_data_dds.h>
|
||||
#include <PluginInterfaces/data_plugin_interface.h>
|
||||
|
||||
|
||||
namespace EffectManagement
|
||||
{
|
||||
|
||||
std::shared_ptr<DataPluginBase::Interface> DataPlugin::createDataInterface(LtsSession::LtsSessionDataDds *session)
|
||||
{
|
||||
std::shared_ptr<SoundManagement::Interface::Dtc> dtc;
|
||||
std::shared_ptr<SoundManagement::Interface::Ftc> ftc;
|
||||
|
||||
if (!session->createTopicClient(dtc, ftc, true, true))
|
||||
return std::shared_ptr<DataPluginBase::Interface>();
|
||||
|
||||
return std::make_shared<DataInterfaceImpl>(dtc, ftc);
|
||||
}
|
||||
|
||||
|
||||
DataInterfaceImpl::DataInterfaceImpl(const std::shared_ptr<SoundManagement::Interface::Dtc> &dtc,
|
||||
const std::shared_ptr<SoundManagement::Interface::Ftc> &ftc)
|
||||
: DataInterface()
|
||||
, m_dtc(dtc)
|
||||
, m_ftc(ftc)
|
||||
{
|
||||
}
|
||||
|
||||
} // namespace EffectManagement
|
||||
+57
@@ -0,0 +1,57 @@
|
||||
/**
|
||||
* @RDE_HEADER@
|
||||
* Data Plugin for effect management.
|
||||
* $Id$
|
||||
* $HeadURL$
|
||||
* $Author$
|
||||
* Created by Filip Biedziak, SLSE, 2020-07-29
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <PluginInterfaces/data_plugin_interface.h>
|
||||
#include <Plugins/EffectManagement/efm_data_plugin_interface.h>
|
||||
|
||||
|
||||
namespace EffectManagement
|
||||
{
|
||||
|
||||
class DataPlugin final : public QObject, public DataPluginBase::Plugin
|
||||
{
|
||||
Q_PLUGIN_METADATA(IID "data:3:efm.cevapcici")
|
||||
Q_INTERFACES(DataPluginBase::Plugin)
|
||||
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
DataPlugin() = default;
|
||||
~DataPlugin() = default;
|
||||
|
||||
QString pluginName() const override { return QStringLiteral("EffectManagementDataPlugin"); }
|
||||
std::shared_ptr<DataPluginBase::Interface> createDataInterface(LtsSession::LtsSessionDataDds *session) override;
|
||||
bool availableInPartition(IDL::PartitionType partition) const override
|
||||
{
|
||||
return (partition == IDL::PartitionType::Exercise) ||
|
||||
(partition == IDL::PartitionType::Global);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
class DataInterfaceImpl final : public DataInterface
|
||||
{
|
||||
|
||||
public:
|
||||
DataInterfaceImpl(const std::shared_ptr<SoundManagement::Interface::Dtc> &dtc,
|
||||
const std::shared_ptr<SoundManagement::Interface::Ftc> &ftc);
|
||||
|
||||
std::shared_ptr<SoundManagement::Interface::Dtc> getDtc() override { return m_dtc; }
|
||||
std::shared_ptr<SoundManagement::Interface::Ftc> getFtc() override { return m_ftc; }
|
||||
|
||||
private:
|
||||
std::shared_ptr<SoundManagement::Interface::Dtc> m_dtc;
|
||||
std::shared_ptr<SoundManagement::Interface::Ftc> m_ftc;
|
||||
|
||||
};
|
||||
|
||||
} // namespace EffectManagement
|
||||
+8
@@ -0,0 +1,8 @@
|
||||
#
|
||||
# $Id$
|
||||
# $HeadURL$
|
||||
# $Author$
|
||||
# Created by Filip Biedziak, NLE, 2020-07-29
|
||||
#
|
||||
|
||||
ADD_SUBDIRECTORY(SoundArea)
|
||||
@@ -0,0 +1,56 @@
|
||||
#
|
||||
# $Id$
|
||||
# $HeadURL$
|
||||
# $Author$
|
||||
# Created by Filip Biedziak, NLE, 2020-08-14
|
||||
#
|
||||
|
||||
SET(efm_sound_area_gui_SRCS
|
||||
efm_sound_area_gui_plugin.cpp
|
||||
efm_sound_area_gui_plugin.h
|
||||
|
||||
efm_sound_area.h
|
||||
|
||||
efm_sound_state.cpp
|
||||
efm_sound_state.h
|
||||
|
||||
efm_sound_area_select_dialog.cpp
|
||||
efm_sound_area_select_dialog.h
|
||||
efm_sound_area_edit_dialog.cpp
|
||||
efm_sound_area_edit_dialog.h
|
||||
|
||||
efm_sound_area_select_model.cpp
|
||||
efm_sound_area_select_model.h
|
||||
efm_sound_area_edit_model_playlist.cpp
|
||||
efm_sound_area_edit_model_playlist.h
|
||||
efm_sound_area_edit_model_tree.cpp
|
||||
efm_sound_area_edit_model_tree.h
|
||||
|
||||
efm_sound_area_helper.cpp
|
||||
efm_sound_area_helper.h
|
||||
|
||||
efm_switch_item_delegate.cpp
|
||||
efm_switch_item_delegate.h
|
||||
|
||||
../logger.cpp
|
||||
../logger.h
|
||||
)
|
||||
|
||||
NGL_WRAP_UI(efm_sound_area_gui_SRCS
|
||||
efm_sound_area_select_dialog.ui
|
||||
efm_sound_area_edit_dialog.ui
|
||||
#efm_sound_area_add_sound_process_dialog.ui
|
||||
)
|
||||
|
||||
NGL_ADD_LIBRARY(WS EfmSoundAreaGuiPlugin MODULE ${efm_sound_area_gui_SRCS})
|
||||
NGL_TARGET_LINK_LIBRARIES(EfmSoundAreaGuiPlugin
|
||||
ngltools
|
||||
LtsSession
|
||||
LtsWidgets
|
||||
IsmDataPluginInterface
|
||||
EfmDataPluginInterface
|
||||
EfmGuiPluginInterface
|
||||
Qt5::Widgets
|
||||
LtsUtilsGuiDds
|
||||
)
|
||||
NGL_INSTALL_TARGET(EfmSoundAreaGuiPlugin)
|
||||
+109
@@ -0,0 +1,109 @@
|
||||
/**
|
||||
* @RDE_HEADER@
|
||||
* SoundArea class.
|
||||
* $Id$
|
||||
* $HeadURL$
|
||||
* $Author$
|
||||
* Created by Filip Biedziak, NLE, 2020-08-10
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <InfrastructureManagement/ism.hpp>
|
||||
#include <SoundManagement/som.hpp>
|
||||
|
||||
#include <QHash>
|
||||
#include <QVector>
|
||||
|
||||
|
||||
namespace EffectManagement
|
||||
{
|
||||
|
||||
using SoundKey = QPair<int32_t, int32_t>;
|
||||
|
||||
|
||||
struct SoundArea
|
||||
{
|
||||
SoundArea() = default;
|
||||
explicit SoundArea(const InfrastructureManagement::EffectArea &effectArea)
|
||||
: id(effectArea.id())
|
||||
, areaEgcuId(effectArea.areaEgcuId())
|
||||
#if QT_VERSION >= QT_VERSION_CHECK(5, 14, 0)
|
||||
, egcuIds(QVector<int>(effectArea.egcuIds().begin(), effectArea.egcuIds().end()))
|
||||
#else
|
||||
, egcuIds(QVector<int>::fromStdVector(effectArea.egcuIds()))
|
||||
#endif
|
||||
, displayName(QString::fromStdString(effectArea.name()))
|
||||
{
|
||||
}
|
||||
|
||||
bool addActiveSound(const SoundManagement::SoundState &soundState)
|
||||
{
|
||||
if (activeSounds.contains(soundState.id()))
|
||||
return false;
|
||||
|
||||
activeSounds.insert(soundState.id(), soundState);
|
||||
return true;
|
||||
}
|
||||
bool removeActiveSound(const SoundManagement::SoundState &soundState)
|
||||
{
|
||||
return removeActiveSound(soundState.id());
|
||||
}
|
||||
bool removeActiveSound(const int &id)
|
||||
{
|
||||
return activeSounds.remove(id) == 1;
|
||||
}
|
||||
|
||||
bool hasActiveSound(const SoundManagement::SoundCategory &category, const int &id) const
|
||||
{
|
||||
for (const auto &sound : qAsConst(activeSounds))
|
||||
if ( (sound.category() == category) && (sound.soundId() == id) )
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
bool hasActiveSound(const int32_t &category, const int32_t &id) const
|
||||
{
|
||||
for (const auto &sound : qAsConst(activeSounds))
|
||||
if ( (static_cast<int32_t>(sound.category().underlying()) == category) && (sound.soundId() == id) )
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
bool hasActiveSound(const SoundKey &key) const
|
||||
{
|
||||
for (const auto &sound : qAsConst(activeSounds))
|
||||
if ( (static_cast<int32_t>(sound.category().underlying()) == key.first) && (sound.soundId() == key.second) )
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
QString toString() const
|
||||
{
|
||||
QString str;
|
||||
str += QStringLiteral("SoundArea ") + QString::number(id);
|
||||
str += QStringLiteral(" displayName: ") + displayName;
|
||||
str += QStringLiteral(" areaEgcuId: ") + QString::number(areaEgcuId);
|
||||
return str;
|
||||
}
|
||||
|
||||
std::ostream& operator << (std::ostream& os) const
|
||||
{
|
||||
os << toString().toStdString();
|
||||
return os;
|
||||
}
|
||||
bool operator == (const SoundArea &other) const
|
||||
{
|
||||
return id == other.id;
|
||||
}
|
||||
bool operator != (const SoundArea &other) const
|
||||
{
|
||||
return id != other.id;
|
||||
}
|
||||
|
||||
int id{-1};
|
||||
int32_t areaEgcuId{-1};
|
||||
QVector<int32_t> egcuIds;
|
||||
QString displayName;
|
||||
QHash<int32_t, SoundManagement::SoundState> activeSounds;
|
||||
};
|
||||
|
||||
} // namespace EffectManagement
|
||||
@@ -0,0 +1,257 @@
|
||||
/**
|
||||
* @RDE_HEADER@
|
||||
* Plugin to manage effects.
|
||||
* $Id$
|
||||
* $HeadURL$
|
||||
* $Author$
|
||||
* Created by Filip Biedziak, NLE, 2020-07-29
|
||||
*/
|
||||
|
||||
#include "efm_sound_area_edit_dialog.h"
|
||||
#include "ui_efm_sound_area_edit_dialog.h"
|
||||
#include "efm_sound_area.h"
|
||||
#include "efm_sound_area_helper.h"
|
||||
#include "efm_sound_area_edit_model_playlist.h"
|
||||
#include "efm_sound_area_edit_model_tree.h"
|
||||
#include "efm_switch_item_delegate.h"
|
||||
#include "../logger.h"
|
||||
|
||||
#include <EffectManagement/efm_data_plugin_interface.h>
|
||||
#include <LtsSession/lts_session.h>
|
||||
#include <LtsUtilsGuiDds/request_helper.h>
|
||||
#include <InfrastructureManagement/ism_dtc.h>
|
||||
#include <Plugins/InfrastructureManagement/ism_data_plugin_interface.h>
|
||||
#include <LtsWidgets/lts_global_wait_dialog.h>
|
||||
|
||||
#include <QtWidgets/QGridLayout>
|
||||
#include <QDialogButtonBox>
|
||||
|
||||
|
||||
using namespace SoundManagement;
|
||||
|
||||
namespace EffectManagement
|
||||
{
|
||||
|
||||
//=============================================================================================================================
|
||||
// SOUNDTREEMODEL
|
||||
//=============================================================================================================================
|
||||
|
||||
SoundAreaEditDialog::SoundAreaEditDialog(const SoundArea &soundArea, QWidget *parent)
|
||||
: LtsWidgets::LtsDialog(parent, LtsWidgets::ButtonCombination::CloseOnly)
|
||||
, m_soundArea(new SoundArea(soundArea))
|
||||
, m_ui(new Ui::SoundAreaEditDialog)
|
||||
, m_logger(getLogger("Plugins.Gui.SoundArea.EditDialog"))
|
||||
{
|
||||
m_ui->setupUi(this);
|
||||
m_buttonBox->getButton(LtsWidgets::DialogButton::Hide)->setIcon(QIcon(QStringLiteral("icon:avm_stop.svg")));
|
||||
setOnlineHelpFilename(QStringLiteral("Sound-Area_Edit_Dialog"));
|
||||
}
|
||||
|
||||
SoundAreaEditDialog::~SoundAreaEditDialog()
|
||||
{
|
||||
delete m_ui;
|
||||
}
|
||||
|
||||
void SoundAreaEditDialog::retranslate()
|
||||
{
|
||||
translate(m_ui, tr("Manage Sound Area #%1").arg(m_soundArea->id));
|
||||
m_buttonBox->getButton(LtsWidgets::DialogButton::Hide)->setText(tr("Stop All Sounds"));
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------------------------------------------------------
|
||||
// PRIVATE SLOTS
|
||||
//-----------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
void SoundAreaEditDialog::onPlaySound(SoundManagement::SoundCategory category, int soundId, bool inLoop, int volume)
|
||||
{
|
||||
qWarning() << "onPlaySound" << volume;
|
||||
|
||||
SoundManagement::PlayControl control = inLoop ? SoundManagement::PlayControl_def::PlayLoop : SoundManagement::PlayControl_def::PlaySingle;
|
||||
|
||||
for (const auto &egcuId : qAsConst(m_soundArea->egcuIds))
|
||||
{
|
||||
if (!m_egcuCheckBoxes.value(egcuId)->isChecked())
|
||||
continue;
|
||||
|
||||
SoundManagement::ControlSoundRequest req(
|
||||
egcuId,
|
||||
soundId,
|
||||
category,
|
||||
volume,
|
||||
control
|
||||
);
|
||||
|
||||
auto *reqHandler = new ControlSoundRequester;
|
||||
// FIXME: reqHandler leaks if controlSoundRequest fails
|
||||
if (!m_somFtc->controlSoundRequest(req, reqHandler))
|
||||
return;
|
||||
|
||||
connect(reqHandler, &ControlSoundRequester::finished,
|
||||
this, [this, reqHandler/*, category, soundId, inLoop, volume, egcuId*/](const QString &msg)
|
||||
{
|
||||
if (!msg.isEmpty())
|
||||
{
|
||||
LtsWidgets::LtsMessageDialogNew(this, msg);//tr("Playing sound failed: %1").arg(msg));
|
||||
return;
|
||||
}
|
||||
|
||||
reqHandler->deleteLater();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
void SoundAreaEditDialog::onStopAllSounds()
|
||||
{
|
||||
DEBUG_LOG(m_logger) << "onStopAllSounds";
|
||||
|
||||
QList<int32_t> egcuIds; // search for active EGCUs only to reduce DDS load
|
||||
|
||||
|
||||
for (const auto &egcu : qAsConst(m_soundArea->egcuIds))
|
||||
{
|
||||
if (!m_egcuCheckBoxes.value(egcu)->isChecked())
|
||||
continue;
|
||||
DEBUG_LOG(m_logger) << "onStopAllSounds add egcu=" << egcu;
|
||||
egcuIds.append(egcu);
|
||||
}
|
||||
|
||||
for (const auto &egcu : qAsConst(egcuIds))
|
||||
{
|
||||
DEBUG_LOG(m_logger) << "onStopAllSounds egcu=" << egcu;
|
||||
SoundManagement::StopAllSoundsRequest req(egcu);
|
||||
/* m_requestHelper->startSingleRequest([this, req]()
|
||||
{
|
||||
return */m_somFtc->stopAllSoundsRequest(req, nullptr);/*this);
|
||||
});*/
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------------------------------------------------------
|
||||
// PUBLIC MEMBER FUNCTIONS
|
||||
//-----------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
bool SoundAreaEditDialog::init(LtsSession::LtsSessionDataDds *session)
|
||||
{
|
||||
DEBUG_LOG(m_logger) << "init";
|
||||
|
||||
m_session = session;
|
||||
|
||||
// connect to DDS
|
||||
std::shared_ptr<InfrastructureManagement::Interface::Dtc> ismDtc;
|
||||
if (!m_session->getDtc<InfrastructureManagement::DataInterface>(ismDtc))
|
||||
{
|
||||
ERROR_LOG(m_logger) << "connection to ISM-DTC failed";
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!m_session->getDtc<EffectManagement::DataInterface>(m_somDtc))
|
||||
{
|
||||
ERROR_LOG(m_logger) << "connection to SOM-DTC failed";
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!m_session->getFtc<EffectManagement::DataInterface>(m_somFtc))
|
||||
{
|
||||
ERROR_LOG(m_logger) << "connection to SOM-FTC failed";
|
||||
return false;
|
||||
}
|
||||
|
||||
m_helper = std::make_shared<SoundAreaHelper>(new SoundAreaHelper(ismDtc, m_somDtc));
|
||||
|
||||
// add checkboxes for EGCU and label them with their respective names from ISM
|
||||
QGridLayout *layout = new QGridLayout();
|
||||
int i = 0;
|
||||
for (const auto &egcu : qAsConst(m_soundArea->egcuIds))
|
||||
{
|
||||
QCheckBox *chBox = new QCheckBox(m_helper->egcuName(egcu));
|
||||
chBox->setChecked(true);
|
||||
m_egcuCheckBoxes.insert(egcu, chBox);
|
||||
layout->addWidget(m_egcuCheckBoxes.value(egcu), int(i / 2), i % 2);
|
||||
++i;
|
||||
} // for
|
||||
m_ui->wEgcu->setLayout(layout);
|
||||
|
||||
// model initialization
|
||||
delete m_treeModel;
|
||||
m_treeModel = new SoundAreaTreeModel(m_soundArea->egcuIds, m_helper, this);
|
||||
m_treeModel->init(m_somDtc);
|
||||
m_ui->tvSounds->setModel(m_treeModel);
|
||||
m_ui->tvSounds->expandAll();
|
||||
m_ui->tvSounds->header()->resizeSection(SoundAreaTreeModel::Column::Loop, 50);
|
||||
m_ui->tvSounds->header()->setSectionResizeMode(SoundAreaTreeModel::Column::Category, QHeaderView::Interactive);
|
||||
m_ui->tvSounds->header()->setSectionResizeMode(SoundAreaTreeModel::Column::Sound, QHeaderView::Stretch);
|
||||
m_ui->tvSounds->header()->setSectionResizeMode(SoundAreaTreeModel::Column::Loop, QHeaderView::Fixed);
|
||||
|
||||
delete m_playlistModel;
|
||||
m_playlistModel = new SoundAreaPlaylistModel(m_soundArea->egcuIds, m_helper, this);
|
||||
m_playlistModel->init(m_somDtc);
|
||||
m_ui->tvPlaylist->setModel(m_playlistModel);
|
||||
m_ui->tvPlaylist->horizontalHeader()->resizeSection(SoundAreaPlaylistModel::Column::Duration, 100);
|
||||
m_ui->tvPlaylist->horizontalHeader()->resizeSection(SoundAreaPlaylistModel::Column::Option, 50);
|
||||
// m_ui->tvPlaylist->horizontalHeader()->setSectionResizeMode(SoundAreaPlaylistModel::Column::Category, QHeaderView::Interactive);
|
||||
m_ui->tvPlaylist->horizontalHeader()->setSectionResizeMode(SoundAreaPlaylistModel::Column::Sound, QHeaderView::Stretch);
|
||||
// m_ui->tvPlaylist->horizontalHeader()->setSectionResizeMode(SoundAreaPlaylistModel::Column::Egcu, QHeaderView::Interactive);
|
||||
//m_ui->tvPlaylist->horizontalHeader()->setSectionResizeMode(SoundAreaPlaylistModel::Column::Duration, QHeaderView::Fixed);
|
||||
m_ui->tvPlaylist->horizontalHeader()->setSectionResizeMode(SoundAreaPlaylistModel::Column::Option, QHeaderView::Fixed);
|
||||
|
||||
m_ui->tvSounds->setItemDelegateForColumn(SoundAreaTreeModel::Column::Loop, new SwitchItemDelegate(m_treeModel));
|
||||
m_ui->tvSounds->setItemDelegateForColumn(SoundAreaTreeModel::Column::Volume, new SpinBoxDelegate(m_treeModel));
|
||||
|
||||
m_ui->tvPlaylist->setItemDelegate(new SoundAreaEditPlaylistDelegate(m_playlistModel));
|
||||
|
||||
// connects
|
||||
connect(m_treeModel, &SoundAreaTreeModel::playSound, this, &SoundAreaEditDialog::onPlaySound);
|
||||
connect(m_ui->tvSounds, &QTreeView::clicked, m_treeModel, &SoundAreaTreeModel::onSoundTreeItemActivated);
|
||||
connect(m_ui->tvPlaylist, &QTableView::clicked, this, [this](const QModelIndex &index)
|
||||
{
|
||||
if (index.column() != SoundAreaPlaylistModel::Column::Option)
|
||||
return;
|
||||
|
||||
// ControlSoundRequester *csr = new ControlSoundRequester;
|
||||
const SoundState ss(m_playlistModel->getRowData(index.row()));
|
||||
|
||||
// connect(csr, &ControlSoundRequester::finished,
|
||||
// this, [this, ss](const QString &msg)
|
||||
// {
|
||||
// //LtsWidgets::LtsGlobalWaitDialog::getInstance()->done();
|
||||
|
||||
// if (!msg.isEmpty())
|
||||
// return;
|
||||
|
||||
// m_playlistModel->removeRow(m_playlistModel->indexOf(ss));
|
||||
// });
|
||||
|
||||
|
||||
|
||||
auto *reqHandler = new ControlSoundRequester;
|
||||
// FIXME: reqHandler leaks if controlSoundRequest fails
|
||||
if (!m_somFtc->controlSoundRequest(ControlSoundRequest(ss.egcuId(), ss.soundId(), ss.category(), 0, PlayControl::StopSound), reqHandler))
|
||||
{
|
||||
new LtsWidgets::LtsMessageDialogNew(this, tr("Stopping sound failed with unknown error"));
|
||||
return;
|
||||
}
|
||||
|
||||
connect(reqHandler, &ControlSoundRequester::finished,
|
||||
this, [this, reqHandler](const QString &msg)
|
||||
{
|
||||
if (!msg.isEmpty())
|
||||
{
|
||||
new LtsWidgets::LtsMessageDialogNew(this, msg);//tr("Stopping sound failed: %1").arg(msg));
|
||||
return;
|
||||
}
|
||||
|
||||
reqHandler->deleteLater();
|
||||
});
|
||||
|
||||
|
||||
// {
|
||||
// LtsWidgets::LtsGlobalWaitDialog::getInstance()->wait();
|
||||
// }
|
||||
});
|
||||
|
||||
m_buttonBox->connectButton(LtsWidgets::DialogButton::Hide, this, &SoundAreaEditDialog::onStopAllSounds);
|
||||
|
||||
DEBUG_LOG(m_logger) << "init successful";
|
||||
return true;
|
||||
}
|
||||
} // namespace EffectManagement
|
||||
@@ -0,0 +1,165 @@
|
||||
/**
|
||||
* @RDE_HEADER@
|
||||
* Plugin to manage effects.
|
||||
* $Id$
|
||||
* $HeadURL$
|
||||
* $Author$
|
||||
* Created by Filip Biedziak, NLE, 2020-07-29
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <LtsWidgets/lts_dialog.h>
|
||||
#include <LtsUtilsGuiDds/request_helper.h>
|
||||
#include <SoundManagement/som_dtc.h>
|
||||
#include <SoundManagement/som_ftc.h>
|
||||
|
||||
|
||||
namespace NGL
|
||||
{
|
||||
class INGLLogger;
|
||||
}
|
||||
|
||||
namespace LtsSession
|
||||
{
|
||||
class LtsSessionDataDds;
|
||||
}
|
||||
|
||||
namespace LtsUtils
|
||||
{
|
||||
class RequestHelper;
|
||||
}
|
||||
|
||||
namespace Ui
|
||||
{
|
||||
class SoundAreaEditDialog;
|
||||
class AddSoundProcessDialog;
|
||||
}
|
||||
|
||||
|
||||
namespace EffectManagement
|
||||
{
|
||||
|
||||
struct SoundArea;
|
||||
class SoundAreaHelper;
|
||||
class SoundAreaTreeModel;
|
||||
class SoundAreaPlaylistModel;
|
||||
class SoundAreaEditDialog;
|
||||
|
||||
|
||||
|
||||
///// AddSoundProcessDialog
|
||||
//class AddSoundProcessDialog : public QWidget
|
||||
//{
|
||||
// Q_OBJECT
|
||||
//public:
|
||||
// AddSoundProcessDialog(QWidget *parent);
|
||||
|
||||
//signals:
|
||||
// void accepted();
|
||||
// void rejected();
|
||||
|
||||
//private:
|
||||
// Ui::AddSoundProcessDialog *m_ui;
|
||||
//};
|
||||
|
||||
|
||||
|
||||
///// AddSoundProcess
|
||||
//class AddSoundProcess : public QObject
|
||||
//{
|
||||
// Q_OBJECT
|
||||
//public:
|
||||
// friend class SoundAreaEditDialog;
|
||||
|
||||
// AddSoundProcess(const SoundManagement::SoundCategory category, const int soundId, const bool inLoop, SoundAreaEditDialog *parent);
|
||||
|
||||
//private:
|
||||
// const SoundManagement::SoundCategory m_category;
|
||||
// const int m_soundId;
|
||||
// const bool m_inLoop;
|
||||
// SoundAreaEditDialog *m_dialog;
|
||||
// std::unique_ptr<AddSoundProcessDialog> m_overlay;
|
||||
//};
|
||||
|
||||
|
||||
|
||||
/// ControlSoundRequester
|
||||
class ControlSoundRequester
|
||||
: public QObject
|
||||
, public SoundManagement::Interface::Ftc::ControlSoundReplyHandler
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
void onControlSoundReply(const Core::FunctionReplyObject &reply) override final
|
||||
{
|
||||
m_reply = reply;
|
||||
emit finished(m_reply.translated());
|
||||
deleteLater();
|
||||
}
|
||||
|
||||
signals:
|
||||
void finished(const QString &msg);
|
||||
|
||||
private:
|
||||
Core::FunctionReplyObject m_reply;
|
||||
};
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @brief The SoundAreaEditDialog class implements the ability to activate and deactivate Sounds
|
||||
* inside a specified SoundArea. Sounds can be played either once or in a loop.
|
||||
*/
|
||||
class SoundAreaEditDialog
|
||||
: public LtsWidgets::LtsDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit SoundAreaEditDialog(const SoundArea &soundArea, QWidget *parent = nullptr);
|
||||
~SoundAreaEditDialog();
|
||||
|
||||
|
||||
private slots:
|
||||
/**
|
||||
* @brief onPlaySound adds a Sound selected in the TreeView to the playlist.
|
||||
* @param category SoundCategory
|
||||
* @param soundId ID of the Sound within its category
|
||||
* @param inLoop whether to play the Sound in a loop
|
||||
*/
|
||||
void onPlaySound(SoundManagement::SoundCategory category, int soundId, bool inLoop, int volume);
|
||||
|
||||
/**
|
||||
* @brief onStopAllSounds stops all active Sounds.
|
||||
*/
|
||||
void onStopAllSounds();
|
||||
|
||||
|
||||
public:
|
||||
bool init(LtsSession::LtsSessionDataDds *session);
|
||||
|
||||
private:
|
||||
void retranslate() override;
|
||||
|
||||
|
||||
std::shared_ptr<SoundManagement::Interface::Dtc> m_somDtc{nullptr};
|
||||
std::shared_ptr<SoundManagement::Interface::Ftc> m_somFtc{nullptr};
|
||||
|
||||
std::shared_ptr<SoundAreaHelper> m_helper{nullptr};
|
||||
|
||||
QString m_menuGroup;
|
||||
SoundArea *m_soundArea;
|
||||
|
||||
SoundAreaTreeModel *m_treeModel{nullptr};
|
||||
SoundAreaPlaylistModel *m_playlistModel{nullptr};
|
||||
|
||||
QHash<int32_t, QCheckBox *> m_egcuCheckBoxes;
|
||||
|
||||
LtsSession::LtsSessionDataDds *m_session{nullptr};
|
||||
Ui::SoundAreaEditDialog *m_ui{nullptr};
|
||||
NGL::INGLLogger &m_logger;
|
||||
|
||||
}; // class EffectManagementDialog
|
||||
|
||||
} // namespace EffectManagement
|
||||
@@ -0,0 +1,62 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>SoundAreaEditDialog</class>
|
||||
<widget class="QWidget" name="SoundAreaEditDialog">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>1056</width>
|
||||
<height>525</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Form</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout">
|
||||
<item row="0" column="2">
|
||||
<widget class="QLabel" name="lbxPlaylist">
|
||||
<property name="text">
|
||||
<string>Playlist</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0">
|
||||
<widget class="QLabel" name="lbxEgcu">
|
||||
<property name="text">
|
||||
<string>EGCU:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="lbxSounds">
|
||||
<property name="text">
|
||||
<string>Sounds</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="2" colspan="2">
|
||||
<widget class="QTableView" name="tvPlaylist">
|
||||
<attribute name="horizontalHeaderStretchLastSection">
|
||||
<bool>false</bool>
|
||||
</attribute>
|
||||
<attribute name="verticalHeaderVisible">
|
||||
<bool>false</bool>
|
||||
</attribute>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0" colspan="2">
|
||||
<widget class="QTreeView" name="tvSounds">
|
||||
<attribute name="headerStretchLastSection">
|
||||
<bool>false</bool>
|
||||
</attribute>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="1" colspan="3">
|
||||
<widget class="QWidget" name="wEgcu" native="true"/>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
||||
+275
@@ -0,0 +1,275 @@
|
||||
/**
|
||||
* @RDE_HEADER@
|
||||
* Playlist model for SoundAreas.
|
||||
* $Id$
|
||||
* $HeadURL$
|
||||
* $Author$
|
||||
* Created by Filip Biedziak, NLE, 2020-08-10
|
||||
*/
|
||||
|
||||
#include "efm_sound_area_edit_model_playlist.h"
|
||||
#include "efm_sound_area_helper.h"
|
||||
#include "../logger.h"
|
||||
|
||||
#include <QMouseEvent>
|
||||
#include <QApplication>
|
||||
#include <QTimer>
|
||||
#include <QTime>
|
||||
#include <QSpinBox>
|
||||
#include <QDebug>
|
||||
|
||||
|
||||
namespace EffectManagement
|
||||
{
|
||||
|
||||
//=============================================================================================================================
|
||||
// SOUNDPLAYLISTDELEGATE
|
||||
//=============================================================================================================================
|
||||
|
||||
QIcon SoundAreaEditPlaylistDelegate::s_iconInf = QIcon(QStringLiteral("icon:infinity.svg"));
|
||||
|
||||
|
||||
SoundAreaEditPlaylistDelegate::SoundAreaEditPlaylistDelegate(QObject *parent)
|
||||
: QStyledItemDelegate(parent)
|
||||
{
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------------------------------------------------------
|
||||
// PUBLIC MEMBER FUNCTIONS
|
||||
//-----------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
void SoundAreaEditPlaylistDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const
|
||||
{
|
||||
const QVariant data(index.data(Qt::DisplayRole));
|
||||
|
||||
if ((index.column() == SoundAreaPlaylistModel::Column::Duration) && (data.toString().isEmpty()))
|
||||
{
|
||||
s_iconInf.paint(painter, option.rect, Qt::AlignCenter);
|
||||
return;
|
||||
}
|
||||
|
||||
if (index.column() != SoundAreaPlaylistModel::Column::Option)
|
||||
{
|
||||
QStyledItemDelegate::paint(painter, option, index);
|
||||
return;
|
||||
}
|
||||
|
||||
QStyleOptionButton button;
|
||||
button.rect = option.rect;
|
||||
button.state = QStyle::State_Enabled;
|
||||
button.iconSize = QSize(25, 25);
|
||||
button.icon = QIcon(QStringLiteral("icon:delete.svg"));
|
||||
|
||||
QApplication::style()->drawControl(QStyle::CE_PushButton, &button, painter);
|
||||
}
|
||||
|
||||
|
||||
|
||||
//=============================================================================================================================
|
||||
// SOUNDPLAYLISTMODEL
|
||||
//=============================================================================================================================
|
||||
|
||||
SoundAreaPlaylistModel::SoundAreaPlaylistModel(const QVector<int32_t> &egcuIds, std::shared_ptr<SoundAreaHelper> &helper, QWidget *parent)
|
||||
: LtsAbstractTableModel<SoundState>({tr("Category"),
|
||||
tr("Sound"),
|
||||
tr("EGCU"),
|
||||
tr("Duration"),
|
||||
tr("Option")},
|
||||
parent)
|
||||
, m_helper(helper)
|
||||
, m_egcuIds(egcuIds)
|
||||
, m_logger(getLogger("Plugins.Gui.SoundArea.EditModelPlaylist"))
|
||||
{
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------------------------------------------------------
|
||||
// PUBLIC SLOTS
|
||||
//-----------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
//-----------------------------------------------------------------------------------------------------------------------------
|
||||
// PRIVATE SLOTS
|
||||
//-----------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
void SoundAreaPlaylistModel::onTimeout()
|
||||
{
|
||||
for (int i = 0; i < m_vecData.count(); ++i)
|
||||
m_vecData[i].duration(std::max(0, m_vecData[i].duration() - 1000));
|
||||
emit dataChanged({}, {});
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------------------------------------------------------
|
||||
// PUBLIC MEMBER FUNCTIONS
|
||||
//-----------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
bool SoundAreaPlaylistModel::init(std::shared_ptr<SoundManagement::Interface::Dtc> &somDtc)
|
||||
{
|
||||
DEBUG_LOG(m_logger) << "init";
|
||||
|
||||
const QMap<int32_t, SoundManagement::SoundState> soundStates = somDtc->soundStates();
|
||||
for (const auto &data : qAsConst(soundStates))
|
||||
{
|
||||
if (!m_egcuIds.contains(data.egcuId()))
|
||||
continue;
|
||||
|
||||
addActiveSound(SoundState(data));
|
||||
}
|
||||
|
||||
somDtc->enableSoundState(true);
|
||||
|
||||
connect(somDtc.get(), &SoundManagement::Interface::Dtc::soundStateChanged, this,
|
||||
[this](const SoundManagement::SoundState &data, DataModification modType)
|
||||
{
|
||||
onDataChanged(SoundState(data), modType);
|
||||
});
|
||||
|
||||
m_timer = new QTimer(this);
|
||||
connect(m_timer, &QTimer::timeout, this, &SoundAreaPlaylistModel::onTimeout);
|
||||
m_timer->start(1000);
|
||||
|
||||
DEBUG_LOG(m_logger) << "init successful";
|
||||
return true;
|
||||
}
|
||||
|
||||
int SoundAreaPlaylistModel::indexOf(const SoundState &data) const
|
||||
{
|
||||
int idx = 0;
|
||||
for (const auto &item : qAsConst(m_vecData))
|
||||
{
|
||||
if ( (item.category() == data.category()) &&
|
||||
(item.soundId() == data.soundId()) &&
|
||||
(item.egcuId() == data.egcuId()) )
|
||||
return idx;
|
||||
++idx;
|
||||
} // for
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
bool SoundAreaPlaylistModel::addActiveSound(SoundState data)
|
||||
{
|
||||
data.duration(m_helper->soundDuration(data.category(), data.soundId()));
|
||||
const int row = indexOf(data);
|
||||
const QString name(m_helper->soundName(data.category(), data.soundId()));
|
||||
|
||||
if (row != -1)
|
||||
{
|
||||
ERROR_LOG(m_logger) << "'" << name << "' is already active";
|
||||
return false;
|
||||
}
|
||||
|
||||
data.status(SoundState::Status::Active);
|
||||
insertRow(data);
|
||||
|
||||
DEBUG_LOG(m_logger) << "adding '" << name << "' to active Sounds";
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool SoundAreaPlaylistModel::removeActiveSound(const QModelIndex &index)
|
||||
{
|
||||
if (!index.isValid())
|
||||
return false;
|
||||
|
||||
return removeRow(index.row());
|
||||
}
|
||||
|
||||
|
||||
QVariant SoundAreaPlaylistModel::data(const QModelIndex &index, int role) const
|
||||
{
|
||||
if (!index.isValid())
|
||||
return QVariant();
|
||||
|
||||
const SoundState &soundState = m_vecData.at(index.row());
|
||||
|
||||
switch (role)
|
||||
{
|
||||
case Qt::DisplayRole:
|
||||
case Qt::EditRole:
|
||||
switch (index.column())
|
||||
{
|
||||
case Column::Category:
|
||||
return m_helper->categoryName(soundState.category());
|
||||
|
||||
case Column::Sound:
|
||||
return m_helper->soundName(soundState.category(), soundState.soundId());
|
||||
|
||||
case Column::Egcu:
|
||||
return m_helper->egcuName(soundState.egcuId());
|
||||
|
||||
case Column::Duration:
|
||||
return soundState.inLoop() ? QString() : QTime(0, 0).addMSecs(soundState.duration()).toString(QStringLiteral("hh:mm:ss.zzz"));
|
||||
|
||||
case Column::Option:
|
||||
default:
|
||||
return soundState.status();
|
||||
} // switch
|
||||
|
||||
case Qt::BackgroundColorRole:
|
||||
if ( (index.column() != Column::Category) && (index.column() != Column::Sound))
|
||||
return QVariant();
|
||||
return m_helper->soundCategoryBackgroundColor(static_cast<int32_t>(soundState.category().underlying()));
|
||||
|
||||
case Qt::TextColorRole:
|
||||
if ( (index.column() != Column::Category) && (index.column() != Column::Sound))
|
||||
return QVariant();
|
||||
return m_helper->soundCategoryTextColor(static_cast<int32_t>(soundState.category().underlying()));
|
||||
|
||||
case Qt::TextAlignmentRole:
|
||||
return index.column() == Column::Duration ? Qt::AlignCenter : Qt::AlignVCenter;
|
||||
|
||||
default:
|
||||
return QVariant();
|
||||
} // switch
|
||||
}
|
||||
|
||||
bool SoundAreaPlaylistModel::onDataChanged(const SoundState &data, DataModification modType)
|
||||
{
|
||||
if (!m_egcuIds.contains(data.egcuId())) // not inside the SoundArea
|
||||
return false;
|
||||
|
||||
int row;
|
||||
QModelIndex idx;
|
||||
|
||||
switch (modType)
|
||||
{
|
||||
case DataModification::eAdded:
|
||||
return addActiveSound(data);
|
||||
|
||||
case DataModification::eModified:
|
||||
WARNING_LOG(m_logger) << "handling eModified for sound states not implemented yet";
|
||||
return false;
|
||||
|
||||
case DataModification::eRemoved:
|
||||
row = indexOf(data);
|
||||
idx = SoundAreaPlaylistModel::index(m_vecData.indexOf(data), 0);
|
||||
if (row == -1)
|
||||
{
|
||||
ERROR_LOG(m_logger) << "'" << m_helper->soundName(data.category(), data.soundId()) << "' is neither scheduled nor active";
|
||||
return false;
|
||||
} // if
|
||||
return removeActiveSound(idx);
|
||||
|
||||
default:
|
||||
Q_UNREACHABLE();
|
||||
return false;
|
||||
} // switch
|
||||
}
|
||||
|
||||
bool SoundAreaPlaylistModel::insertRow(const SoundState &item)
|
||||
{
|
||||
beginInsertRows(QModelIndex(), m_vecData.size(), m_vecData.size());
|
||||
m_vecData.push_back(item);
|
||||
endInsertRows();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool SoundAreaPlaylistModel::removeRow(int row)
|
||||
{
|
||||
return removeRows(row, 1);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------------------------------------------------------
|
||||
// PRIVATE MEMBER FUNCTIONS
|
||||
//-----------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
} // namespace EffectManagement
|
||||
+125
@@ -0,0 +1,125 @@
|
||||
/**
|
||||
* @RDE_HEADER@
|
||||
* Playlist model for SoundAreas.
|
||||
* $Id$
|
||||
* $HeadURL$
|
||||
* $Author$
|
||||
* Created by Filip Biedziak, NLE, 2020-08-10
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "efm_sound_state.h"
|
||||
|
||||
#include <LtsWidgets/lts_abstract_table_model.h>
|
||||
#include <SoundManagement/som_dtc.h>
|
||||
|
||||
#include <QStyledItemDelegate>
|
||||
|
||||
|
||||
class QTimer;
|
||||
|
||||
namespace NGL
|
||||
{
|
||||
class INGLLogger;
|
||||
}
|
||||
|
||||
|
||||
namespace EffectManagement
|
||||
{
|
||||
|
||||
using SoundKey = QPair<int32_t, int32_t>;
|
||||
|
||||
class SoundAreaHelper;
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @brief The SoundPlaylistDelegate class inherits from QItemDelegate and is used to draw specific
|
||||
* elements inside the SoundPlayListModel.
|
||||
*/
|
||||
class SoundAreaEditPlaylistDelegate
|
||||
: public QStyledItemDelegate
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
SoundAreaEditPlaylistDelegate(QObject *parent = nullptr);
|
||||
void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const override;
|
||||
|
||||
private:
|
||||
static QIcon s_iconInf;
|
||||
|
||||
}; // SoundAreaEditPlaylistDelegate
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @brief The SoundPlaylistModel class implements a model to organize active SoundStates of a given
|
||||
* SoundArea.
|
||||
* @details The purpose of this class is to plan changes to the active Sounds of a SoundArea. It
|
||||
* inherits LtsAbstractTableModel with SoundState (s. efm_sound_state.h) as template argument. This
|
||||
* class does NOT send any requests to DDS whatsoever. Its only connection to DDS is a connection to
|
||||
* the soundStateChanged signal from the Sound Management. An implicit conversion from
|
||||
* SoundManagement::SoundState to a SoundState is provided. A distinction is made between active
|
||||
* Sounds and scheduled / planned Sounds. Active Sounds are currently being played inside the
|
||||
* SoundArea while scheduled / planned Sounds are not. In order to play a scheduled Sound you need
|
||||
* to obtain all scheduled Sounds from this model, e.g. by getRowData(int). The returned object does
|
||||
* contain all information required to send a request to the Sound Management.
|
||||
*/
|
||||
class SoundAreaPlaylistModel
|
||||
: public LtsWidgets::LtsAbstractTableModel<SoundState>
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
enum Column { Category, Sound, Egcu, Duration, Option };
|
||||
|
||||
explicit SoundAreaPlaylistModel(const QVector<int32_t> &egcuIds, std::shared_ptr<SoundAreaHelper> &helper, QWidget *parent = nullptr);
|
||||
|
||||
private slots:
|
||||
/**
|
||||
* @brief onTimeout updates the time left for each active Sound.
|
||||
*/
|
||||
void onTimeout();
|
||||
|
||||
public:
|
||||
bool init(std::shared_ptr<SoundManagement::Interface::Dtc> &somDtc);
|
||||
|
||||
/**
|
||||
* @brief indexOf returns the index/row of a SoundState in the model.
|
||||
* @param data a SoundState
|
||||
* @return index in m_vecData, -1 if not found
|
||||
*/
|
||||
int indexOf(const SoundState &data) const;
|
||||
|
||||
/**
|
||||
* @brief addActiveSound adds an active Sound to the model by inserting it at the end of all
|
||||
* active Sounds (before scheduled Sounds).
|
||||
* @param data a SoundState object
|
||||
* @return true for success, false otherwise
|
||||
*/
|
||||
bool addActiveSound(SoundState data);
|
||||
|
||||
/**
|
||||
* @brief removeActiveSound removes an active Sound from the model.
|
||||
* @param index QModelIndex of a selected element
|
||||
* @return true for success, false otherwise
|
||||
*/
|
||||
bool removeActiveSound(const QModelIndex &index);
|
||||
|
||||
protected:
|
||||
QVariant data(const QModelIndex &index, int role) const override;
|
||||
bool onDataChanged(const SoundState &data, DataModification modType) override;
|
||||
bool insertRow(const SoundState &item) override;
|
||||
bool removeRow(int row) override;
|
||||
|
||||
private:
|
||||
std::shared_ptr<SoundAreaHelper> m_helper{nullptr};
|
||||
QVector<int32_t> m_egcuIds;
|
||||
QTimer *m_timer{nullptr};
|
||||
NGL::INGLLogger &m_logger;
|
||||
|
||||
}; // class SoundPlaylistModel
|
||||
|
||||
} // namespace EffectManagement
|
||||
+408
@@ -0,0 +1,408 @@
|
||||
/**
|
||||
* @RDE_HEADER@
|
||||
* Model for Sound selection.
|
||||
* $Id$
|
||||
* $HeadURL$
|
||||
* $Author$
|
||||
* Created by Filip Biedziak, NLE, 2020-08-10
|
||||
*/
|
||||
|
||||
#include "efm_sound_area_edit_model_tree.h"
|
||||
#include "efm_sound_area.h"
|
||||
#include "efm_sound_area_helper.h"
|
||||
#include "../logger.h"
|
||||
|
||||
#include <QSpinBox>
|
||||
#include <QApplication>
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#include <QDebug>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
namespace EffectManagement
|
||||
{
|
||||
|
||||
|
||||
|
||||
/// SpinBoxDelegate
|
||||
SpinBoxDelegate::SpinBoxDelegate(QObject *parent)
|
||||
: QStyledItemDelegate(parent)
|
||||
{}
|
||||
|
||||
QWidget *SpinBoxDelegate::createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const
|
||||
{
|
||||
if (index.column() != SoundAreaTreeModel::Column::Volume)
|
||||
return QStyledItemDelegate::createEditor(parent, option, index);
|
||||
auto *sb = new QSpinBox(parent);
|
||||
sb->setFrame(false);
|
||||
sb->setSuffix(QStringLiteral(" %"));
|
||||
sb->setRange(0, 100);
|
||||
return sb;
|
||||
}
|
||||
|
||||
void SpinBoxDelegate::setEditorData(QWidget *editor, const QModelIndex &index) const
|
||||
{
|
||||
if (index.column() != SoundAreaTreeModel::Column::Volume)
|
||||
{
|
||||
QStyledItemDelegate::setEditorData(editor, index);
|
||||
return;
|
||||
}
|
||||
|
||||
qWarning() << index << index.data();
|
||||
const int val = index.data(Qt::EditRole).toInt();
|
||||
|
||||
auto *sb = qobject_cast<QSpinBox *>(editor);
|
||||
sb->setValue(val);
|
||||
return;
|
||||
}
|
||||
|
||||
void SpinBoxDelegate::setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const
|
||||
{
|
||||
if (index.column() != SoundAreaTreeModel::Column::Volume)
|
||||
{
|
||||
QStyledItemDelegate::setModelData(editor, model, index);
|
||||
return;
|
||||
}
|
||||
|
||||
auto *sb = qobject_cast<QSpinBox *>(editor);
|
||||
const int val = sb->value();
|
||||
model->setData(index, val, Qt::EditRole);
|
||||
}
|
||||
|
||||
void SpinBoxDelegate::updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option, const QModelIndex &/*index*/) const
|
||||
{
|
||||
editor->setGeometry(option.rect);
|
||||
}
|
||||
|
||||
|
||||
|
||||
//=============================================================================================================================
|
||||
// SOUNDTREEITEM
|
||||
//=============================================================================================================================
|
||||
|
||||
SoundTreeItem::SoundTreeItem(const QVector<QVariant> &data, const SoundKey &key, SoundTreeItem *parent)
|
||||
: m_parent(parent)
|
||||
, m_data(data)
|
||||
, m_soundKey(key)
|
||||
{
|
||||
}
|
||||
|
||||
SoundTreeItem::~SoundTreeItem()
|
||||
{
|
||||
qDeleteAll(m_children);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------------------------------------------------------
|
||||
// PUBLIC MEMBER FUNCTIONS
|
||||
//-----------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
void SoundTreeItem::appendChild(SoundTreeItem *item)
|
||||
{
|
||||
m_children.append(item);
|
||||
}
|
||||
|
||||
void SoundTreeItem::toogleLoop()
|
||||
{
|
||||
if (isRepeatable())
|
||||
m_data[SoundAreaTreeModel::Column::Loop] = -1 * m_data[SoundAreaTreeModel::Column::Loop].toInt();
|
||||
}
|
||||
|
||||
void SoundTreeItem::toggleLoop(int inLoop)
|
||||
{
|
||||
if (isRepeatable())
|
||||
{
|
||||
if ( (inLoop != -1) && (inLoop != 1) )
|
||||
return;
|
||||
m_data[SoundAreaTreeModel::Column::Loop] = inLoop;
|
||||
} // if
|
||||
}
|
||||
|
||||
|
||||
QString SoundTreeItem::toString() const
|
||||
{
|
||||
return QStringLiteral("SoundTreeItem( category : ") + QString::number(m_soundKey.first) + QStringLiteral(" | id : ") +
|
||||
QString::number(m_soundKey.second) + QStringLiteral(" )");
|
||||
}
|
||||
|
||||
//=============================================================================================================================
|
||||
// SOUNDTREEMODEL
|
||||
//=============================================================================================================================
|
||||
|
||||
SoundAreaTreeModel::SoundAreaTreeModel(const QVector<int> &egcuIds, std::shared_ptr<SoundAreaHelper> &helper, QWidget *parent)
|
||||
: QAbstractItemModel(parent)
|
||||
, m_helper(helper)
|
||||
, m_root(new SoundTreeItem({tr("Category"), tr("Sound"), tr("Loop"), tr("Volume")}, SoundKey(0, 0)))
|
||||
, m_egcuIds(egcuIds)
|
||||
, m_logger(getLogger("Plugins.Gui.SoundArea.EditModelTree"))
|
||||
{
|
||||
}
|
||||
|
||||
SoundAreaTreeModel::~SoundAreaTreeModel()
|
||||
{
|
||||
delete m_root;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------------------------------------------------------
|
||||
// PUBLIC SLOTS
|
||||
//-----------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
void SoundAreaTreeModel::onSoundTreeItemActivated(const QModelIndex &index)
|
||||
{
|
||||
if (!index.isValid())
|
||||
return;
|
||||
|
||||
switch (index.column())
|
||||
{
|
||||
case Column::Loop:
|
||||
{
|
||||
onToggleLoop(index);
|
||||
break;
|
||||
}
|
||||
|
||||
case Column::Volume:
|
||||
break;
|
||||
|
||||
default:
|
||||
{
|
||||
onPlaySound(index);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------------------------------------------------------
|
||||
// PRIVATE SLOTS
|
||||
//-----------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
bool SoundAreaTreeModel::onPlaySound(const QModelIndex &index)
|
||||
{
|
||||
SoundTreeItem *item = static_cast<SoundTreeItem *>(index.internalPointer());
|
||||
emit playSound(m_helper->soundCategory(item->soundKey().first), item->soundKey().second, item->inLoop(), item->volume());
|
||||
// => onAddSoundToPlaylist(SoundManagement::SoundCategory category, int soundId, bool inLoop, int volume)
|
||||
return true;
|
||||
}
|
||||
|
||||
bool SoundAreaTreeModel::onToggleLoop(const QModelIndex &index)
|
||||
{
|
||||
SoundTreeItem *item = static_cast<SoundTreeItem *>(index.internalPointer());
|
||||
item->toogleLoop();
|
||||
emit dataChanged(index, index);
|
||||
return true;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------------------------------------------------------
|
||||
// PUBLIC MEMBER FUNCTIONS
|
||||
//-----------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
bool SoundAreaTreeModel::init(const std::shared_ptr<SoundManagement::Interface::Dtc> &somDtc)
|
||||
{
|
||||
DEBUG_LOG(m_logger) << "init";
|
||||
|
||||
// add sound categories
|
||||
SoundKey key;
|
||||
QVector<SoundManagement::SoundCategory> categories = m_helper->soundCategories();
|
||||
for (const auto &category : qAsConst(categories))
|
||||
{
|
||||
QString name{m_helper->categoryName(category)};
|
||||
QVector<QVariant> data{QVector<QVariant>{name, QVariant(), 0, 100}};
|
||||
key.first = static_cast<int32_t>(category.underlying());
|
||||
key.second = 0; // invalid sound index for category
|
||||
m_root->appendChild(new SoundTreeItem(data, key, m_root));
|
||||
} // for
|
||||
|
||||
// add sounds
|
||||
SoundManagement::Sounds sounds = somDtc->sounds(); // undefined behaviour for somDtc->sounds().sounds()
|
||||
for (const auto &sound : qAsConst(sounds.sounds()))
|
||||
{
|
||||
for (auto &category : m_root->children())
|
||||
{
|
||||
if (category->soundKey().first == static_cast<int32_t>(sound.category().underlying()))
|
||||
{
|
||||
QString displayName = m_helper->soundName(sound.category(), sound.soundId());
|
||||
QVector<QVariant> data{QVector<QVariant>{category->data(0).toString(), displayName, sound.isRepeatable() ? 1 : 0, 100}};
|
||||
key.first = static_cast<int32_t>(sound.category().underlying());
|
||||
key.second = sound.soundId();
|
||||
category->appendChild(new SoundTreeItem(data, key, category));
|
||||
break;
|
||||
} // if
|
||||
} // for
|
||||
} // for
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool SoundAreaTreeModel::setData(const QModelIndex &index, const QVariant &value, int role)
|
||||
{
|
||||
if (index.column() != SoundAreaTreeModel::Column::Volume
|
||||
|| role != Qt::EditRole)
|
||||
return QAbstractItemModel::setData(index, value, role);
|
||||
|
||||
bool k;
|
||||
int val = value.toInt(&k);
|
||||
if (!k)
|
||||
return false;
|
||||
|
||||
static_cast<SoundTreeItem *>(index.internalPointer())->setVolume(val);
|
||||
emit dataChanged(index, index);
|
||||
return true;
|
||||
}
|
||||
|
||||
SoundTreeItem * SoundAreaTreeModel::find(const SoundKey &key)
|
||||
{
|
||||
QVector<SoundTreeItem *> categories = m_root->children();
|
||||
for (auto category : qAsConst(categories))
|
||||
{
|
||||
if (category->soundKey() == key)
|
||||
return category;
|
||||
|
||||
QVector<SoundTreeItem *> sounds = category->children();
|
||||
for (auto sound : qAsConst(sounds))
|
||||
if (sound->soundKey() == key)
|
||||
return sound;
|
||||
} // for
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
Qt::ItemFlags SoundAreaTreeModel::flags(const QModelIndex &index) const
|
||||
{
|
||||
if (!index.isValid())
|
||||
return Qt::NoItemFlags;
|
||||
|
||||
if (index.column() != SoundAreaTreeModel::Column::Volume)
|
||||
return QAbstractItemModel::flags(index);
|
||||
return QAbstractItemModel::flags(index).setFlag(Qt::ItemFlag::ItemIsEditable);
|
||||
}
|
||||
|
||||
QVariant SoundAreaTreeModel::data(const QModelIndex &index, int role) const
|
||||
{
|
||||
if (!index.isValid())
|
||||
return QVariant();
|
||||
|
||||
if ( (role != Qt::DisplayRole) && (role != Qt::ToolTipRole) &&
|
||||
(role != Qt::BackgroundColorRole) && (role != Qt::TextColorRole) &&
|
||||
(role != Qt::EditRole))
|
||||
return QVariant();
|
||||
|
||||
SoundTreeItem *item = static_cast<SoundTreeItem *>(index.internalPointer());
|
||||
|
||||
switch (role)
|
||||
{
|
||||
case Qt::EditRole:
|
||||
switch (index.column())
|
||||
{
|
||||
case Column::Volume: return item->volume();
|
||||
default:
|
||||
Q_UNREACHABLE();
|
||||
return QVariant();
|
||||
}
|
||||
case Qt::DisplayRole:
|
||||
if (item->soundKey().second == 0)
|
||||
return index.column() == Column::Category ? item->data(index.column()) : QVariant();
|
||||
switch (index.column())
|
||||
{
|
||||
case Column::Category: return QVariant();
|
||||
case Column::Sound: return item->data(index.column());
|
||||
case Column::Loop: return item->isRepeatable() ? item->data(index.column()) : QVariant();
|
||||
case Column::Volume: return QStringLiteral("%1 %").arg(item->volume());
|
||||
default:
|
||||
Q_UNREACHABLE();
|
||||
return QVariant();
|
||||
} // switch
|
||||
|
||||
case Qt::ToolTipRole:
|
||||
if ( (item->soundKey().second == 0) && (index.column() != Column::Category) )
|
||||
return QVariant();
|
||||
switch (index.column())
|
||||
{
|
||||
case Column::Category: return item->data(Column::Category).toString();
|
||||
case Column::Sound: return item->data(Column::Sound).toString();
|
||||
case Column::Loop: return item->inLoop() ? tr("play in loop") : tr("play once");
|
||||
case Column::Volume: return tr("Volume: %1 %").arg(item->volume());
|
||||
default:
|
||||
Q_UNREACHABLE();
|
||||
return QVariant();
|
||||
} // switch
|
||||
|
||||
case Qt::BackgroundRole:
|
||||
if ( (index.column() == Column::Category) ||
|
||||
( (index.column() == Column::Sound) && (item->soundKey().second != 0) ) )
|
||||
return m_helper->soundCategoryBackgroundColor(item->soundKey().first);
|
||||
return QVariant();
|
||||
|
||||
case Qt::TextColorRole:
|
||||
if ((index.column() == Column::Category) || (index.column() == Column::Sound))
|
||||
return m_helper->soundCategoryTextColor(item->soundKey().first);
|
||||
return QVariant();
|
||||
|
||||
default: // unreachable
|
||||
Q_UNREACHABLE();
|
||||
return QVariant();
|
||||
}
|
||||
}
|
||||
|
||||
QVariant SoundAreaTreeModel::headerData(int section, Qt::Orientation orientation, int role) const
|
||||
{
|
||||
return ( (orientation == Qt::Horizontal) && (role == Qt::DisplayRole) ) ? m_root->data(section) : QVariant();
|
||||
}
|
||||
|
||||
QModelIndex SoundAreaTreeModel::index(int row, int column, const QModelIndex &parent) const
|
||||
{
|
||||
if (!hasIndex(row, column, parent))
|
||||
return {};
|
||||
|
||||
SoundTreeItem *item;
|
||||
if(!parent.isValid())
|
||||
item = m_root;
|
||||
else
|
||||
item = static_cast<SoundTreeItem *>(parent.internalPointer());
|
||||
SoundTreeItem *child = item->child(row);
|
||||
return child ? createIndex(row, column, child) : QModelIndex();
|
||||
}
|
||||
|
||||
QModelIndex SoundAreaTreeModel::parent(const QModelIndex &index) const
|
||||
{
|
||||
if (!index.isValid())
|
||||
return {};
|
||||
|
||||
SoundTreeItem *parent = static_cast<SoundTreeItem *>(index.internalPointer())->parent(); // parent of the item at index
|
||||
return parent == m_root ? QModelIndex() : createIndex(parent->row(), 0, parent);
|
||||
}
|
||||
|
||||
int SoundAreaTreeModel::rowCount(const QModelIndex &index) const
|
||||
{
|
||||
if (index.column() > 0)
|
||||
return 0;
|
||||
|
||||
SoundTreeItem *parent;
|
||||
if (!index.isValid())
|
||||
parent = m_root;
|
||||
else
|
||||
parent = static_cast<SoundTreeItem *>(index.internalPointer());
|
||||
return parent->childCount();
|
||||
}
|
||||
|
||||
int SoundAreaTreeModel::columnCount(const QModelIndex &index) const
|
||||
{
|
||||
return index.isValid() ? static_cast<SoundTreeItem *>(index.internalPointer())->columnCount() : m_root->columnCount();
|
||||
}
|
||||
|
||||
} // namespace EffectManagement
|
||||
+180
@@ -0,0 +1,180 @@
|
||||
/**
|
||||
* @RDE_HEADER@
|
||||
* Model for Sound selection.
|
||||
* $Id$
|
||||
* $HeadURL$
|
||||
* $Author$
|
||||
* Created by Filip Biedziak, NLE, 2020-08-10
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <LtsWidgets/lts_abstract_table_model.h>
|
||||
#include <SoundManagement/som_dtc.h>
|
||||
|
||||
#include <QAbstractItemModel>
|
||||
#include <QStyledItemDelegate>
|
||||
|
||||
|
||||
namespace NGL
|
||||
{
|
||||
class INGLLogger;
|
||||
}
|
||||
|
||||
|
||||
namespace EffectManagement
|
||||
{
|
||||
|
||||
using SoundKey = QPair<int32_t, int32_t>;
|
||||
|
||||
struct SoundArea;
|
||||
class SoundAreaHelper;
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @brief The SoundTreeItem class represents an item in a QTreeView with a parent and children.
|
||||
*/
|
||||
class SoundTreeItem
|
||||
{
|
||||
|
||||
public:
|
||||
enum Column { Category, Sound, Loop, Volume };
|
||||
|
||||
explicit SoundTreeItem(const QVector<QVariant> &data, const SoundKey &key, SoundTreeItem *parent = nullptr);
|
||||
~SoundTreeItem();
|
||||
|
||||
/**
|
||||
* @brief appendChild adds a child to the list of children.
|
||||
* @param item a SoundTreeItem
|
||||
*/
|
||||
void appendChild(SoundTreeItem *item);
|
||||
/**
|
||||
* @brief toogleLoop changes the setting to play a Sound in a loop or only once.
|
||||
*/
|
||||
void toogleLoop();
|
||||
/**
|
||||
* @brief toggleLoop sets the setting to play a Sound in a loop or only once.
|
||||
* @param inLoop 1 for playing a Sound in a loop, -1 to play it only once
|
||||
*/
|
||||
void toggleLoop(int inLoop);
|
||||
|
||||
QVariant data(const int &column) const { return (column < 0 || column >= m_data.size()) ? QVariant() : m_data.at(column); }
|
||||
SoundKey soundKey() const { return m_soundKey; }
|
||||
|
||||
bool isRepeatable() const { return m_data[Column::Loop] != 0; }
|
||||
bool inLoop() const { return m_data[Column::Loop] == 1; }
|
||||
int volume() const { return m_data[Column::Volume].toInt(); }
|
||||
void setVolume(int volume) { m_data[Column::Volume] = volume; }
|
||||
|
||||
SoundTreeItem *parent() { return m_parent; }
|
||||
SoundTreeItem *child(int row) { return (row < 0 || row >= m_children.size()) ? nullptr : m_children.at(row); }
|
||||
QVector<SoundTreeItem *> children() const { return m_children; }
|
||||
|
||||
int row() const { return m_parent ? m_parent->m_children.indexOf(const_cast<SoundTreeItem *>(this)) : 0; }
|
||||
int columnCount() const { return m_data.count(); }
|
||||
int childCount() const { return m_children.count(); }
|
||||
|
||||
QString toString() const;
|
||||
|
||||
private:
|
||||
QVector<SoundTreeItem *> m_children;
|
||||
SoundTreeItem *m_parent{nullptr};
|
||||
QVector<QVariant> m_data;
|
||||
SoundKey m_soundKey;
|
||||
|
||||
}; // class SoundTreeItem
|
||||
|
||||
|
||||
|
||||
/// SpinBoxDelegate
|
||||
class SpinBoxDelegate : public QStyledItemDelegate
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
SpinBoxDelegate(QObject *parent = nullptr);
|
||||
|
||||
protected:
|
||||
QWidget *createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const override;
|
||||
void setEditorData(QWidget *editor, const QModelIndex &index) const override;
|
||||
void setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const override;
|
||||
void updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option, const QModelIndex &index) const override;
|
||||
};
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @brief The SoundTreeModel class provides a hierarchical model for SoundCategory and Sound to
|
||||
* visualize in a QTreeView.
|
||||
*/
|
||||
class SoundAreaTreeModel
|
||||
: public QAbstractItemModel
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
enum Column { Category, Sound, Loop, Volume };
|
||||
|
||||
explicit SoundAreaTreeModel(const QVector<int> &egcuIds, std::shared_ptr<SoundAreaHelper> &helper, QWidget *parent = nullptr);
|
||||
~SoundAreaTreeModel();
|
||||
|
||||
signals:
|
||||
/**
|
||||
* @brief playSound can be used to connect to the FTC in order to play a Sound.
|
||||
*/
|
||||
void playSound(const SoundManagement::SoundCategory, const int, const bool, const int);
|
||||
|
||||
public slots:
|
||||
/**
|
||||
* @brief onSoundTreeItemActivated delegates to onPlaySound or onToggleLoop when the TreeView is clicked.
|
||||
* @param index QModelIndex of the Sound.
|
||||
*/
|
||||
void onSoundTreeItemActivated(const QModelIndex &index);
|
||||
|
||||
private slots:
|
||||
/**
|
||||
* @brief onPlaySound emits the playSound signal that can be connected to start a request.
|
||||
* @param index QModelIndex of the selected Sound
|
||||
* @return true for success, false otherwise
|
||||
*/
|
||||
bool onPlaySound(const QModelIndex &index);
|
||||
/**
|
||||
* @brief onToggleLoop flips the setting to play a Sound in a loop or only once.
|
||||
* @param index QModelIndex of the Sound
|
||||
* @return true for success, false otherwise
|
||||
*/
|
||||
bool onToggleLoop(const QModelIndex &index);
|
||||
|
||||
|
||||
public:
|
||||
bool init(const std::shared_ptr<SoundManagement::Interface::Dtc> &somDtc);
|
||||
|
||||
/**
|
||||
* @brief find returns the SoundTreeItem defined by its SoundKey.
|
||||
* @param key a SoundKey with the SoundCategory and Sound ID as integers
|
||||
* @return corresponding SoundTreeItem
|
||||
*/
|
||||
SoundTreeItem * find(const SoundKey &key);
|
||||
|
||||
protected:
|
||||
bool setData(const QModelIndex &index, const QVariant &value, int role) override;
|
||||
Qt::ItemFlags flags(const QModelIndex &index) const override;
|
||||
QVariant data(const QModelIndex &index, int role) const override;
|
||||
QVariant headerData(int section, Qt::Orientation orientation, int role) const override;
|
||||
QModelIndex index(int row, int column, const QModelIndex &parent) const override;
|
||||
QModelIndex parent(const QModelIndex &index) const override;
|
||||
int rowCount(const QModelIndex &index) const override;
|
||||
int columnCount(const QModelIndex &index) const override;
|
||||
|
||||
private:
|
||||
std::shared_ptr<SoundAreaHelper> m_helper{nullptr};
|
||||
|
||||
SoundTreeItem *m_root{nullptr};
|
||||
QVector<int32_t> m_egcuIds;
|
||||
|
||||
NGL::INGLLogger &m_logger;
|
||||
|
||||
}; // class SoundModel
|
||||
|
||||
} // namespace EffectManagement
|
||||
@@ -0,0 +1,79 @@
|
||||
/**
|
||||
* @RDE_HEADER@
|
||||
* SoundArea Plugin for effect management.
|
||||
* $Id$
|
||||
* $HeadURL$
|
||||
* $Author$
|
||||
* Created by Filip Biedziak, NLE, 2020-07-29
|
||||
*/
|
||||
|
||||
#include "efm_sound_area_gui_plugin.h"
|
||||
#include "efm_sound_area_edit_dialog.h"
|
||||
#include "efm_sound_area_select_dialog.h"
|
||||
#include "../logger.h"
|
||||
|
||||
#include <LtsSession/lts_session.h>
|
||||
|
||||
|
||||
namespace EffectManagement
|
||||
{
|
||||
|
||||
std::shared_ptr<GuiPluginBase::Interface> GuiPlugin::createGuiInterface(LtsSession::LtsSession *session)
|
||||
{
|
||||
return std::make_shared<InterfaceImpl>(session);
|
||||
}
|
||||
|
||||
|
||||
|
||||
InterfaceImpl::InterfaceImpl(LtsSession::LtsSession *session)
|
||||
: GuiPluginBase::Interface(session, getLogger("Plugins.Gui.SoundArea"))
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
bool InterfaceImpl::fetchInterfaces()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
void InterfaceImpl::clearInterfaces()
|
||||
{
|
||||
}
|
||||
|
||||
QString InterfaceImpl::menuGroup() const
|
||||
{
|
||||
return tr("Effect Management");
|
||||
}
|
||||
|
||||
QVector<LtsWidgets::PluginData> InterfaceImpl::getActions()
|
||||
{
|
||||
QVector<LtsWidgets::PluginData> ret;
|
||||
|
||||
{
|
||||
LtsWidgets::PluginData plData;
|
||||
plData.menuGroup = menuGroup();
|
||||
plData.menuText = tr("Sound Area Selection");
|
||||
plData.menuIcon = QIcon(QStringLiteral("icon:sound_area.svg"));
|
||||
plData.identifier = QStringLiteral("efmSoundAreaSelect");
|
||||
// plData.operatorRight = OperatorRights::ScreenRecording::RecordScreen;
|
||||
plData.exercisePart = LtsWidgets::ExercisePart::eExecution;
|
||||
plData.createWidgetFunc = [this](QWidget *parent)
|
||||
{
|
||||
return onSoundAreaSelectSlot(parent);
|
||||
};
|
||||
ret.append(plData);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
LtsWidgets::LtsDialog *InterfaceImpl::onSoundAreaSelectSlot(QWidget *parent)
|
||||
{
|
||||
DEBUG_LOG(m_logger) << "Starting Sound Area Select";
|
||||
SoundAreaSelectDialog *dialog = new SoundAreaSelectDialog(parent);
|
||||
dialog->init(m_session, menuGroup());
|
||||
return dialog;
|
||||
}
|
||||
|
||||
} // namespace EffectManagement
|
||||
@@ -0,0 +1,69 @@
|
||||
/**
|
||||
* @RDE_HEADER@
|
||||
* SoundArea Plugin for effect management.
|
||||
* $Id$
|
||||
* $HeadURL$
|
||||
* $Author$
|
||||
* Created by Filip Biedziak, NLE, 2020-07-29
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <PluginInterfaces/gui_plugin_interface.h>
|
||||
#include <Plugins/EffectManagement/efm_gui_plugin_interface.h>
|
||||
|
||||
|
||||
namespace EffectManagement
|
||||
{
|
||||
|
||||
class GuiPlugin final : public QObject, public GuiPluginBase::Plugin
|
||||
{
|
||||
Q_PLUGIN_METADATA(IID "gui:3:efm.sound_areas")
|
||||
Q_INTERFACES(GuiPluginBase::Plugin)
|
||||
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit GuiPlugin() = default;
|
||||
~GuiPlugin() = default;
|
||||
|
||||
QString pluginName() override { return QStringLiteral("EffectManagementSoundAreaGuiPlugin"); }
|
||||
std::shared_ptr<GuiPluginBase::Interface> createGuiInterface(LtsSession::LtsSession *session) override;
|
||||
bool availableInPartition(IDL::PartitionType partition) const override
|
||||
{
|
||||
return (partition == IDL::PartitionType::Exercise) ||
|
||||
(partition == IDL::PartitionType::Global);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
class InterfaceImpl final : public QObject, public GuiPluginBase::Interface
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit InterfaceImpl(LtsSession::LtsSession *session);
|
||||
|
||||
bool fetchInterfaces() override;
|
||||
void clearInterfaces() override;
|
||||
QString menuGroup() const override;
|
||||
QVector<LtsWidgets::PluginData> getActions() override;
|
||||
bool availableInPartition(IDL::PartitionType partition) const override
|
||||
{
|
||||
return (partition == IDL::PartitionType::Exercise) ||
|
||||
(partition == IDL::PartitionType::Global);
|
||||
}
|
||||
|
||||
private slots:
|
||||
/**
|
||||
* @brief onSoundAreaSelectSlot creates a SoundAreaSelectDialog.
|
||||
* @param parent pointer to the parent
|
||||
* @return SoundAreaSelectDialog instance
|
||||
*/
|
||||
LtsWidgets::LtsDialog *onSoundAreaSelectSlot(QWidget *parent);
|
||||
|
||||
private:
|
||||
|
||||
};
|
||||
|
||||
} // namespace EffectManagement
|
||||
@@ -0,0 +1,287 @@
|
||||
/**
|
||||
* @RDE_HEADER@
|
||||
* Helper class for SoundAreas.
|
||||
* $Id$
|
||||
* $HeadURL$
|
||||
* $Author$
|
||||
* Created by Filip Biedziak, NLE, 2020-08-10
|
||||
*/
|
||||
|
||||
#include "efm_sound_area_helper.h"
|
||||
#include "../logger.h"
|
||||
|
||||
#include <QVector>
|
||||
#include <QColor>
|
||||
|
||||
|
||||
namespace EffectManagement
|
||||
{
|
||||
|
||||
//=============================================================================================================================
|
||||
// SOUNDMANAGEMENTHELPER
|
||||
//=============================================================================================================================
|
||||
|
||||
SoundAreaHelper::SoundAreaHelper(SoundAreaHelper *helper)
|
||||
: m_ismDtc(helper->ismDtc())
|
||||
, m_somDtc(helper->somDtc())
|
||||
, m_logger(getLogger("Plugins.Gui.SoundArea.Helper"))
|
||||
{
|
||||
QMap<int32_t, InfrastructureManagement::InstrumentationAsset> assets = m_ismDtc->instrumentationAssets();
|
||||
for (const auto &asset : qAsConst(assets))
|
||||
if (asset.mountingPointTypeId() == InfrastructureManagement::MountingPointType_def::EffectGenerationControlUnit)
|
||||
m_egcuNames.insert(asset.id(), QString::fromStdString(asset.name()));
|
||||
|
||||
SoundManagement::Sounds sounds = m_somDtc->sounds();
|
||||
for (const auto &sound : qAsConst(sounds.sounds()))
|
||||
m_soundDuration.insert(SoundKey(sound.category().underlying(), sound.soundId()), sound.duration());
|
||||
}
|
||||
|
||||
SoundAreaHelper::SoundAreaHelper(std::shared_ptr<InfrastructureManagement::Interface::Dtc> &ismDtc,
|
||||
std::shared_ptr<SoundManagement::Interface::Dtc> &somDtc)
|
||||
: m_ismDtc(ismDtc)
|
||||
, m_somDtc(somDtc)
|
||||
, m_logger(getLogger("Plugins.Gui.SoundArea.Helper"))
|
||||
{
|
||||
QMap<int32_t, InfrastructureManagement::InstrumentationAsset> assets = m_ismDtc->instrumentationAssets();
|
||||
for (const auto &asset : qAsConst(assets))
|
||||
if (asset.mountingPointTypeId() == InfrastructureManagement::MountingPointType_def::EffectGenerationControlUnit)
|
||||
m_egcuNames.insert(asset.id(), QString::fromStdString(asset.name()));
|
||||
|
||||
SoundManagement::Sounds sounds = m_somDtc->sounds();
|
||||
for (const auto &sound : qAsConst(sounds.sounds()))
|
||||
m_soundDuration.insert(SoundKey(sound.category().underlying(), sound.soundId()), sound.duration());
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------------------------------------------------------
|
||||
// PUBLIC MEMBER FUNCTIONS
|
||||
//-----------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
QVector<SoundManagement::SoundCategory> SoundAreaHelper::soundCategories()
|
||||
{
|
||||
QVector<SoundManagement::SoundCategory> categories = QVector<SoundManagement::SoundCategory>
|
||||
{
|
||||
SoundManagement::SoundCategory_def::Aircraft,
|
||||
SoundManagement::SoundCategory_def::Battlefield,
|
||||
SoundManagement::SoundCategory_def::Boat,
|
||||
SoundManagement::SoundCategory_def::Explosion,
|
||||
SoundManagement::SoundCategory_def::Helicopter,
|
||||
SoundManagement::SoundCategory_def::MotorsAndUrbanTraffic,
|
||||
SoundManagement::SoundCategory_def::Vehicle,
|
||||
SoundManagement::SoundCategory_def::InsideBuilding
|
||||
};
|
||||
return categories;
|
||||
}
|
||||
|
||||
|
||||
QString SoundAreaHelper::categoryName(SoundManagement::SoundCategory category)
|
||||
{
|
||||
switch (category.underlying())
|
||||
{
|
||||
case SoundManagement::SoundCategory_def::Aircraft: return QStringLiteral("Aircraft");
|
||||
case SoundManagement::SoundCategory_def::Battlefield: return QStringLiteral("Battlefield");
|
||||
case SoundManagement::SoundCategory_def::Boat: return QStringLiteral("Boat");
|
||||
case SoundManagement::SoundCategory_def::Explosion: return QStringLiteral("Explosion");
|
||||
case SoundManagement::SoundCategory_def::Helicopter: return QStringLiteral("Helicopter");
|
||||
case SoundManagement::SoundCategory_def::MotorsAndUrbanTraffic: return QStringLiteral("MotorsAndUrbanTraffic");
|
||||
case SoundManagement::SoundCategory_def::Vehicle: return QStringLiteral("Vehicle");
|
||||
case SoundManagement::SoundCategory_def::InsideBuilding: return QStringLiteral("InsideBuilding");
|
||||
case SoundManagement::SoundCategory_def::Unknown: return QStringLiteral("Unknown");
|
||||
default:
|
||||
return QString();
|
||||
} // switch
|
||||
}
|
||||
|
||||
QString SoundAreaHelper::categoryName(const int32_t &category)
|
||||
{
|
||||
return categoryName(soundCategory(category));
|
||||
}
|
||||
|
||||
|
||||
QString SoundAreaHelper::soundName(SoundManagement::SoundCategory category, const int &id)
|
||||
{
|
||||
switch (category.underlying())
|
||||
{
|
||||
case SoundManagement::SoundCategory_def::Aircraft:
|
||||
switch (id)
|
||||
{
|
||||
case 1: return QStringLiteral("Jet_Pass_by_Military");
|
||||
case 2: return QStringLiteral("Military_Aircraft_Fires");
|
||||
case 3: return QStringLiteral("Military_Aircraft_Fly_By");
|
||||
case 4: return QStringLiteral("Military_Airplane_Drops");
|
||||
default:
|
||||
return QStringLiteral("Error");
|
||||
} // switch
|
||||
|
||||
case SoundManagement::SoundCategory_def::Battlefield:
|
||||
switch (id)
|
||||
{
|
||||
case 1: return QStringLiteral("Battlefield_Ambience_Noise");
|
||||
case 2: return QStringLiteral("Battlefield_Ambience_Tank");
|
||||
case 3: return QStringLiteral("Battlefield_Ambience_War");
|
||||
case 4: return QStringLiteral("Explosions_Battlefield");
|
||||
case 5: return QStringLiteral("Explosions_Battlefield_1");
|
||||
case 6: return QStringLiteral("Ground_Battle_with_Machine_Guns");
|
||||
case 7: return QStringLiteral("Modern_Battlefield");
|
||||
default:
|
||||
return QStringLiteral("Error");
|
||||
} // switch
|
||||
|
||||
case SoundManagement::SoundCategory_def::Boat:
|
||||
switch (id)
|
||||
{
|
||||
default:
|
||||
return QStringLiteral("Error");
|
||||
} // switch
|
||||
|
||||
case SoundManagement::SoundCategory_def::Explosion:
|
||||
switch (id)
|
||||
{
|
||||
case 1: return QStringLiteral("Explosion_Building_Crash");
|
||||
default:
|
||||
return QStringLiteral("Error");
|
||||
} // switch
|
||||
|
||||
case SoundManagement::SoundCategory_def::Helicopter:
|
||||
switch (id)
|
||||
{
|
||||
case 1: return QStringLiteral("Helicopter_Crash");
|
||||
case 2: return QStringLiteral("Helicopter_Fly_Overhead");
|
||||
case 3: return QStringLiteral("Helicopter_Landing");
|
||||
case 4: return QStringLiteral("Helicopter_Pass_by_Military");
|
||||
case 5: return QStringLiteral("Helicopter_Take_off");
|
||||
default:
|
||||
return QStringLiteral("Error");
|
||||
} // switch
|
||||
|
||||
case SoundManagement::SoundCategory_def::MotorsAndUrbanTraffic:
|
||||
switch (id)
|
||||
{
|
||||
case 1: return QStringLiteral("Big_City_Street_Traffic");
|
||||
case 2: return QStringLiteral("City_Crossroads_Traffic");
|
||||
case 3: return QStringLiteral("City_Street_Heavy_Traffic");
|
||||
case 4: return QStringLiteral("City_Street_Noisy_Walking");
|
||||
case 5: return QStringLiteral("Construction_Building_Ambient");
|
||||
case 6: return QStringLiteral("Demonstration_and_Rioting");
|
||||
case 7: return QStringLiteral("Noisy_City_Street");
|
||||
case 8: return QStringLiteral("Stadium_Crowd_Ambient");
|
||||
case 9: return QStringLiteral("Stadium_Crowd_Applause");
|
||||
case 10: return QStringLiteral("Traffic_from_Car");
|
||||
case 11: return QStringLiteral("Muezzincalling");
|
||||
default:
|
||||
return QStringLiteral("Error");
|
||||
} // switch
|
||||
|
||||
case SoundManagement::SoundCategory_def::Vehicle:
|
||||
switch (id)
|
||||
{
|
||||
case 1: return QStringLiteral("Tank_Starting_and_Stopping");
|
||||
default:
|
||||
return QStringLiteral("Error");
|
||||
} // switch
|
||||
|
||||
case SoundManagement::SoundCategory_def::InsideBuilding:
|
||||
switch (id)
|
||||
{
|
||||
case 1: return QStringLiteral("Fire_quietly");
|
||||
case 2: return QStringLiteral("Fire_a_little_louder");
|
||||
case 3: return QStringLiteral("Fire_louder");
|
||||
case 4: return QStringLiteral("Fire_loud");
|
||||
case 5: return QStringLiteral("Extinguishing_Noise");
|
||||
case 7: return QStringLiteral("This_Room_is_Destroyed");
|
||||
case 8: return QStringLiteral("This_Building_is_Destroyed");
|
||||
default:
|
||||
return QStringLiteral("Error");
|
||||
} // switch
|
||||
|
||||
case SoundManagement::SoundCategory_def::Unknown:
|
||||
switch(id)
|
||||
{
|
||||
default:
|
||||
return QStringLiteral("Error");
|
||||
} // switch
|
||||
|
||||
default:
|
||||
return QStringLiteral("Error");
|
||||
} // switch
|
||||
}
|
||||
|
||||
QString SoundAreaHelper::soundName(const int &category, const int &id)
|
||||
{
|
||||
return soundName(soundCategory(category), id);
|
||||
}
|
||||
|
||||
|
||||
int SoundAreaHelper::soundDuration(SoundManagement::SoundCategory category, const int &id) const
|
||||
{
|
||||
return soundDuration(static_cast<int>(category.underlying()), id);
|
||||
}
|
||||
|
||||
int SoundAreaHelper::soundDuration(const int &category, const int &id) const
|
||||
{
|
||||
SoundKey key{category, id};
|
||||
return m_soundDuration.contains(key) ? m_soundDuration.value(key) : 0;
|
||||
}
|
||||
|
||||
|
||||
QString SoundAreaHelper::egcuName(const int &id) const
|
||||
{
|
||||
return m_egcuNames.contains(id) ? m_egcuNames.value(id) : QString();
|
||||
}
|
||||
|
||||
|
||||
QColor SoundAreaHelper::soundCategoryTextColor(const int32_t &category)
|
||||
{
|
||||
switch (category)
|
||||
{
|
||||
case SoundManagement::SoundCategory_def::Aircraft: return {Qt::white};
|
||||
case SoundManagement::SoundCategory_def::Battlefield: return {Qt::white};
|
||||
case SoundManagement::SoundCategory_def::Boat: return {Qt::black};
|
||||
case SoundManagement::SoundCategory_def::Explosion: return {Qt::white};
|
||||
case SoundManagement::SoundCategory_def::Helicopter: return {Qt::white};
|
||||
case SoundManagement::SoundCategory_def::MotorsAndUrbanTraffic: return {Qt::white};
|
||||
case SoundManagement::SoundCategory_def::Vehicle: return {Qt::black};
|
||||
case SoundManagement::SoundCategory_def::InsideBuilding: return {Qt::black};
|
||||
case SoundManagement::SoundCategory_def::Unknown: return {Qt::white};
|
||||
default:
|
||||
return {Qt::black};
|
||||
} // switch
|
||||
}
|
||||
|
||||
QColor SoundAreaHelper::soundCategoryBackgroundColor(const int32_t &category)
|
||||
{
|
||||
switch (category)
|
||||
{
|
||||
case SoundManagement::SoundCategory_def::Aircraft: return QColor::fromRgb( 25, 25, 112);
|
||||
case SoundManagement::SoundCategory_def::Battlefield: return QColor::fromRgb(160, 82, 45);
|
||||
case SoundManagement::SoundCategory_def::Boat: return QColor::fromRgb(127, 255, 212);
|
||||
case SoundManagement::SoundCategory_def::Explosion: return QColor::fromRgb(255, 0, 0);
|
||||
case SoundManagement::SoundCategory_def::Helicopter: return QColor::fromRgb(153, 50, 204);
|
||||
case SoundManagement::SoundCategory_def::MotorsAndUrbanTraffic: return QColor::fromRgb( 85, 107, 47);
|
||||
case SoundManagement::SoundCategory_def::Vehicle: return QColor::fromRgb(255, 255, 0);
|
||||
case SoundManagement::SoundCategory_def::InsideBuilding: return QColor::fromRgb(255, 160, 122);
|
||||
case SoundManagement::SoundCategory_def::Unknown: return QColor::fromRgb(119, 136, 153);
|
||||
default:
|
||||
return {Qt::white};
|
||||
} // switch
|
||||
}
|
||||
|
||||
|
||||
SoundManagement::SoundCategory SoundAreaHelper::soundCategory(const int &i)
|
||||
{
|
||||
switch (i)
|
||||
{
|
||||
case 1: return SoundManagement::SoundCategory_def::Aircraft;
|
||||
case 2: return SoundManagement::SoundCategory_def::Battlefield;
|
||||
case 3: return SoundManagement::SoundCategory_def::Boat;
|
||||
case 4: return SoundManagement::SoundCategory_def::Explosion;
|
||||
case 5: return SoundManagement::SoundCategory_def::Helicopter;
|
||||
case 6: return SoundManagement::SoundCategory_def::MotorsAndUrbanTraffic;
|
||||
case 7: return SoundManagement::SoundCategory_def::Vehicle;
|
||||
case 8: return SoundManagement::SoundCategory_def::InsideBuilding;
|
||||
case 9:
|
||||
default:
|
||||
return SoundManagement::SoundCategory_def::Unknown;
|
||||
} // switch
|
||||
}
|
||||
|
||||
} // namespace EffectManagement
|
||||
@@ -0,0 +1,136 @@
|
||||
/**
|
||||
* @RDE_HEADER@
|
||||
* Helper class for SoundAreas.
|
||||
* $Id$
|
||||
* $HeadURL$
|
||||
* $Author$
|
||||
* Created by Filip Biedziak, NLE, 2020-08-10
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
|
||||
#include <SoundManagement/som_dtc.h>
|
||||
#include <InfrastructureManagement/ism_dtc.h>
|
||||
|
||||
|
||||
namespace NGL
|
||||
{
|
||||
class INGLLogger;
|
||||
}
|
||||
|
||||
|
||||
namespace EffectManagement
|
||||
{
|
||||
|
||||
using SoundKey = QPair<int32_t, int32_t>;
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @brief The SoundAreaHelper class provides utility functions for Infrastructure and Sound
|
||||
* Management. Connections to the ISM-DTC and SOM-DTC are used.
|
||||
*/
|
||||
class SoundAreaHelper
|
||||
{
|
||||
|
||||
public:
|
||||
explicit SoundAreaHelper(SoundAreaHelper *helper);
|
||||
explicit SoundAreaHelper(std::shared_ptr<InfrastructureManagement::Interface::Dtc> &ismDtc,
|
||||
std::shared_ptr<SoundManagement::Interface::Dtc> &somDtc);
|
||||
|
||||
public:
|
||||
std::shared_ptr<InfrastructureManagement::Interface::Dtc> ismDtc() const { return m_ismDtc; }
|
||||
std::shared_ptr<SoundManagement::Interface::Dtc> somDtc() const { return m_somDtc; }
|
||||
|
||||
/**
|
||||
* @brief soundCategories returns a list with the SoundCategory enum from the Sound Management.
|
||||
* @return a vector with all SoundCategory
|
||||
*/
|
||||
static QVector<SoundManagement::SoundCategory> soundCategories();
|
||||
|
||||
/**
|
||||
* @brief categoryName returns the display name of a SoundCategory.
|
||||
* @param category element of SoundCategory enum from Sound Management
|
||||
* @return name of the SoundCategory
|
||||
*/
|
||||
static QString categoryName(SoundManagement::SoundCategory category);
|
||||
/**
|
||||
* @brief categoryName returns the display name of a SoundCategory.
|
||||
* @param category integer corresponding to a SoundCategory enum element from Sound Management
|
||||
* @return name of the SoundCategory
|
||||
*/
|
||||
static QString categoryName(const int32_t &category);
|
||||
|
||||
/**
|
||||
* @brief soundName returns the display name of a Sound.
|
||||
* @param category SoundCategory of the Sound
|
||||
* @param id index of the Sound
|
||||
* @return name of the Sound
|
||||
*/
|
||||
static QString soundName(SoundManagement::SoundCategory category, const int &id);
|
||||
/**
|
||||
* @brief soundName returns the display name of a Sound.
|
||||
* @param category integer corresponding to a SoundCategory enum element from Sound Management
|
||||
* @param id index of the Sound
|
||||
* @return name of the Sound
|
||||
*/
|
||||
static QString soundName(const int &category, const int &id);
|
||||
|
||||
|
||||
/**
|
||||
* @brief soundDuration returns the duration of a Sound when played once.
|
||||
* @param category SoundCategory of the Sound
|
||||
* @param id ID of the Sound within its category
|
||||
* @return duration of the Sound
|
||||
*/
|
||||
int soundDuration(SoundManagement::SoundCategory category, const int &id) const;
|
||||
|
||||
/**
|
||||
* @brief soundDuraiton returns the duration of a Sound when played once.
|
||||
* @param category SoundCategory of the Sound
|
||||
* @param id ID of the Sound within its category
|
||||
* @return duration of the Sound
|
||||
*/
|
||||
int soundDuration(const int &category, const int &id) const;
|
||||
|
||||
|
||||
/**
|
||||
* @brief egcuName returns the display name of an EGCU.
|
||||
* @param id index of the EGCU
|
||||
* @return name of the EGCU
|
||||
*/
|
||||
QString egcuName(const int &id) const;
|
||||
|
||||
/**
|
||||
* @brief soundCategoryTextColor returns a QColor as background color of a SoundCategory.
|
||||
* @param category integer corresponding to the SoundCategory enum value
|
||||
* @return color of the SoundCategory background
|
||||
*/
|
||||
static QColor soundCategoryTextColor(const int32_t &category);
|
||||
/**
|
||||
* @brief soundCategoryTextColor returns a QColor as text color of a SoundCategory.
|
||||
* @param category integer corresponding to the SoundCategory enum value
|
||||
* @return color of the SoundCategory text
|
||||
*/
|
||||
static QColor soundCategoryBackgroundColor(const int32_t &category);
|
||||
|
||||
/**
|
||||
* @brief soundCategory returns the index of a SoundCategory as a SoundCategory enum value.
|
||||
* @param i integer index of a SoundCategory
|
||||
* @return corresponding SoundCategory enum value
|
||||
*/
|
||||
static SoundManagement::SoundCategory soundCategory(const int &i);
|
||||
|
||||
private:
|
||||
std::shared_ptr<InfrastructureManagement::Interface::Dtc> m_ismDtc;
|
||||
std::shared_ptr<SoundManagement::Interface::Dtc> m_somDtc;
|
||||
|
||||
QMap<int32_t, QString> m_egcuNames;
|
||||
QMap<SoundKey, int> m_soundDuration;
|
||||
|
||||
NGL::INGLLogger &m_logger;
|
||||
|
||||
}; // class SoundManagementHelper
|
||||
|
||||
} // namespace EffectManagement
|
||||
+173
@@ -0,0 +1,173 @@
|
||||
/**
|
||||
* @RDE_HEADER@
|
||||
* Plugin to watch the currently active sounds.
|
||||
* $Id$
|
||||
* $HeadURL$
|
||||
* $Author$
|
||||
* Created by Filip Biedziak, NLE, 2020-07-29
|
||||
*/
|
||||
|
||||
#include "efm_sound_area_select_dialog.h"
|
||||
#include "ui_efm_sound_area_select_dialog.h"
|
||||
#include "efm_sound_area_select_model.h"
|
||||
#include "efm_sound_area_edit_dialog.h"
|
||||
#include "../logger.h"
|
||||
|
||||
#include <LtsSession/lts_session.h>
|
||||
#include <LtsUtilsGuiDds/request_helper.h>
|
||||
#include <Plugins/InfrastructureManagement/ism_data_plugin_interface.h>
|
||||
#include <Plugins/EffectManagement/efm_data_plugin_interface.h>
|
||||
|
||||
|
||||
namespace EffectManagement
|
||||
{
|
||||
|
||||
//=============================================================================================================================
|
||||
// SOUNDAREASELECTDIALOG
|
||||
//=============================================================================================================================
|
||||
|
||||
SoundAreaSelectDialog::SoundAreaSelectDialog(QWidget *parent)
|
||||
: LtsWidgets::LtsDialog(parent)
|
||||
, m_requestHelper(new LtsUtils::RequestHelper(this))
|
||||
, m_model(new SoundAreaSelectModel(this))
|
||||
, m_ui(new Ui::SoundAreasDialog)
|
||||
, m_logger(getLogger("Plugins.Gui.SoundArea.SelectDialog"))
|
||||
{
|
||||
m_ui->setupUi(this);
|
||||
|
||||
m_buttonBox->getButton(LtsWidgets::DialogButton::Edit)->setText(tr("Stop All Sounds"));
|
||||
m_buttonBox->getButton(LtsWidgets::DialogButton::Edit)->setIcon(QIcon(QStringLiteral("icon:avm_stop.svg")));
|
||||
}
|
||||
|
||||
SoundAreaSelectDialog::~SoundAreaSelectDialog()
|
||||
{
|
||||
delete m_ui;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------------------------------------------------------
|
||||
// PRIVATE SLOTS
|
||||
//-----------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
void SoundAreaSelectDialog::onSelectSoundArea(const QModelIndex &index)
|
||||
{
|
||||
if (!index.isValid())
|
||||
return;
|
||||
|
||||
if (index.column() == SoundAreaSelectModel::Column::Stop)
|
||||
{
|
||||
onStopSounds(index);
|
||||
return;
|
||||
} // if
|
||||
|
||||
SoundArea soundArea = m_model->getRowData(index.row());
|
||||
SoundAreaEditDialog *dialog = new SoundAreaEditDialog(soundArea);
|
||||
dialog->init(m_session);
|
||||
addDialog(dialog, menuGroup(), soundArea.displayName, LtsWidgets::LayoutArea::eDialogTab);
|
||||
}
|
||||
|
||||
void SoundAreaSelectDialog::onStopSounds(const QModelIndex &index)
|
||||
{
|
||||
SoundArea soundArea = m_model->getRowData(index.row());
|
||||
|
||||
if ( soundArea.egcuIds.isEmpty())
|
||||
return;
|
||||
|
||||
const QVector<int> &egcuIds = soundArea.egcuIds;
|
||||
for (const auto &egcu : qAsConst(egcuIds))
|
||||
{
|
||||
SoundManagement::StopAllSoundsRequest req(egcu);
|
||||
m_requestHelper->startSingleRequest([this, req]()
|
||||
{
|
||||
return m_somFtc->stopAllSoundsRequest(req, this);
|
||||
});
|
||||
} // for
|
||||
}
|
||||
|
||||
void SoundAreaSelectDialog::onStopAllSounds()
|
||||
{
|
||||
const QVector<SoundArea> &soundAreas = m_model->soundAreas();
|
||||
for (const auto &soundArea : qAsConst(soundAreas))
|
||||
{
|
||||
|
||||
const QVector<int> &egcuIds = soundArea.egcuIds;
|
||||
for (const auto &egcu : qAsConst(egcuIds))
|
||||
{
|
||||
SoundManagement::StopAllSoundsRequest req(egcu);
|
||||
m_requestHelper->startSingleRequest([this, req]() {
|
||||
return m_somFtc->stopAllSoundsRequest(req, this);
|
||||
});
|
||||
}
|
||||
} // for
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------------------------------------------------------
|
||||
// PUBLIC MEMBER FUNCTIONS
|
||||
//-----------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
bool SoundAreaSelectDialog::init(LtsSession::LtsSessionDataDds *session, const QString &menuGroup)
|
||||
{
|
||||
DEBUG_LOG(m_logger) << "init";
|
||||
|
||||
m_session = session;
|
||||
setMenuGroup(menuGroup);
|
||||
|
||||
std::shared_ptr<InfrastructureManagement::Interface::Dtc> ismDtc;
|
||||
std::shared_ptr<SoundManagement::Interface::Dtc> somDtc;
|
||||
|
||||
if (!m_session->getDtc<InfrastructureManagement::DataInterface>(ismDtc))
|
||||
{
|
||||
ERROR_LOG(m_logger) << "connection to ISM-DTC failed";
|
||||
return false;
|
||||
} // if
|
||||
|
||||
if (!m_session->getDtc<EffectManagement::DataInterface>(somDtc))
|
||||
{
|
||||
ERROR_LOG(m_logger) << "connection to SOM-DTC failed";
|
||||
return false;
|
||||
} // if
|
||||
|
||||
if (!m_session->getFtc<EffectManagement::DataInterface>(m_somFtc))
|
||||
{
|
||||
ERROR_LOG(m_logger) << "connection to SOM-FTC failed";
|
||||
return false;
|
||||
} // if
|
||||
|
||||
if (!m_model->init(ismDtc, somDtc))
|
||||
{
|
||||
ERROR_LOG(m_logger) << "sound area select model initialization failed";
|
||||
return false;
|
||||
} // if
|
||||
|
||||
m_ui->tvSoundlist->setModel(m_model);
|
||||
|
||||
SoundAreaSelectDelegate *delegate = new SoundAreaSelectDelegate(m_model);
|
||||
m_ui->tvSoundlist->setItemDelegate(delegate);
|
||||
|
||||
m_ui->tvSoundlist->horizontalHeader()->resizeSection(SoundAreaSelectModel::Column::Id, 50);
|
||||
m_ui->tvSoundlist->horizontalHeader()->resizeSection(SoundAreaSelectModel::Column::Stop, 100);
|
||||
m_ui->tvSoundlist->horizontalHeader()->setSectionResizeMode(SoundAreaSelectModel::Column::Id, QHeaderView::Fixed);
|
||||
m_ui->tvSoundlist->horizontalHeader()->setSectionResizeMode(SoundAreaSelectModel::Column::Name, QHeaderView::ResizeToContents);
|
||||
m_ui->tvSoundlist->horizontalHeader()->setSectionResizeMode(SoundAreaSelectModel::Column::AreaEgcu, QHeaderView::ResizeToContents);
|
||||
m_ui->tvSoundlist->horizontalHeader()->setSectionResizeMode(SoundAreaSelectModel::Column::Egcus, QHeaderView::Stretch);
|
||||
m_ui->tvSoundlist->horizontalHeader()->setSectionResizeMode(SoundAreaSelectModel::Column::ActiveSounds, QHeaderView::ResizeToContents);
|
||||
m_ui->tvSoundlist->horizontalHeader()->setSectionResizeMode(SoundAreaSelectModel::Column::Stop, QHeaderView::Fixed);
|
||||
|
||||
connect(m_ui->tvSoundlist, &QTableView::clicked, this, &SoundAreaSelectDialog::onSelectSoundArea);
|
||||
m_buttonBox->connectButton(LtsWidgets::DialogButton::Edit, this, &SoundAreaSelectDialog::onStopAllSounds);
|
||||
|
||||
DEBUG_LOG(m_logger) << "init successful";
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
void SoundAreaSelectDialog::retranslate()
|
||||
{
|
||||
translate(m_ui, tr("Sound Area Select"));
|
||||
}
|
||||
|
||||
void SoundAreaSelectDialog::onStopAllSoundsReply(const Core::FunctionReplyObject &replyObject)
|
||||
{
|
||||
m_requestHelper->requestReply(replyObject);
|
||||
}
|
||||
|
||||
} // namespace EffectManagement
|
||||
@@ -0,0 +1,95 @@
|
||||
/**
|
||||
* @RDE_HEADER@
|
||||
* Plugin to watch the currently active sounds.
|
||||
* $Id$
|
||||
* $HeadURL$
|
||||
* $Author$
|
||||
* Created by Filip Biedziak, NLE, 2020-07-29
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <SoundManagement/som_ftc.h>
|
||||
#include <LtsWidgets/lts_dialog.h>
|
||||
|
||||
|
||||
namespace NGL
|
||||
{
|
||||
class INGLLogger;
|
||||
}
|
||||
|
||||
namespace LtsSession
|
||||
{
|
||||
class LtsSessionDataDds;
|
||||
}
|
||||
|
||||
namespace LtsUtils
|
||||
{
|
||||
class RequestHelper;
|
||||
}
|
||||
|
||||
namespace Ui
|
||||
{
|
||||
class SoundAreasDialog;
|
||||
}
|
||||
|
||||
|
||||
namespace EffectManagement
|
||||
{
|
||||
|
||||
class SoundAreaSelectModel;
|
||||
|
||||
/**
|
||||
* @brief The SoundAreaSelectDialog class implements the dialog used to choose a SoundArea from a
|
||||
* list of all SoundAreas, instead of picking one via the SituationMap.
|
||||
*/
|
||||
class SoundAreaSelectDialog
|
||||
: public LtsWidgets::LtsDialog
|
||||
, protected SoundManagement::Interface::Ftc::StopAllSoundsReplyHandler
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit SoundAreaSelectDialog(QWidget *parent = nullptr);
|
||||
~SoundAreaSelectDialog();
|
||||
|
||||
|
||||
private slots:
|
||||
/**
|
||||
* @brief onSelectSoundArea opens a SoundAreaEditDialog for the selected SoundArea or redirects
|
||||
* to onStopSounds if the index' column corresponds to the stop button.
|
||||
* @param index the selected SoundArea's model index
|
||||
*/
|
||||
void onSelectSoundArea(const QModelIndex &index);
|
||||
/**
|
||||
* @brief onStopSounds stops all currently playing sounds of the SoundArea.
|
||||
* @param index the selected SoundAreas's model index
|
||||
*/
|
||||
void onStopSounds(const QModelIndex &index);
|
||||
/**
|
||||
* @brief onStopAllSounds stops all Sounds in all SoundAreas.
|
||||
*/
|
||||
void onStopAllSounds();
|
||||
|
||||
|
||||
public:
|
||||
bool init(LtsSession::LtsSessionDataDds *session, const QString &menuGroup);
|
||||
|
||||
private:
|
||||
void retranslate() override;
|
||||
void onStopAllSoundsReply(const Core::FunctionReplyObject &replyObject) override final;
|
||||
|
||||
|
||||
std::shared_ptr<SoundManagement::Interface::Ftc> m_somFtc{nullptr};
|
||||
LtsUtils::RequestHelper *m_requestHelper{nullptr};
|
||||
|
||||
SoundAreaSelectModel *m_model{nullptr};
|
||||
|
||||
LtsSession::LtsSessionDataDds *m_session{nullptr};
|
||||
Ui::SoundAreasDialog *m_ui{nullptr};
|
||||
NGL::INGLLogger &m_logger;
|
||||
|
||||
|
||||
}; // class SoundAreasDialog
|
||||
|
||||
} // namespace EffectManagement
|
||||
@@ -0,0 +1,47 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>SoundAreasDialog</class>
|
||||
<widget class="QWidget" name="SoundAreasDialog">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>1065</width>
|
||||
<height>486</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Form</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout">
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="lbxSoundlist">
|
||||
<property name="text">
|
||||
<string>Soundlist</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QTableView" name="tvSoundlist">
|
||||
<property name="alternatingRowColors">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="selectionMode">
|
||||
<enum>QAbstractItemView::SingleSelection</enum>
|
||||
</property>
|
||||
<property name="selectionBehavior">
|
||||
<enum>QAbstractItemView::SelectRows</enum>
|
||||
</property>
|
||||
<attribute name="horizontalHeaderCascadingSectionResizes">
|
||||
<bool>false</bool>
|
||||
</attribute>
|
||||
<attribute name="verticalHeaderVisible">
|
||||
<bool>false</bool>
|
||||
</attribute>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
||||
+290
@@ -0,0 +1,290 @@
|
||||
/**
|
||||
* @RDE_HEADER@
|
||||
* Model for the overall sound area table.
|
||||
* $Id$
|
||||
* $HeadURL$
|
||||
* $Author$
|
||||
* Created by Filip Biedziak, NLE, 2020-07-29
|
||||
*/
|
||||
|
||||
#include "efm_sound_area_select_model.h"
|
||||
#include "efm_sound_area_helper.h"
|
||||
#include "../logger.h"
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
#include <QApplication>
|
||||
#include <QTime>
|
||||
|
||||
|
||||
namespace EffectManagement
|
||||
{
|
||||
|
||||
//=============================================================================================================================
|
||||
// SOUNDSELECTDELEGATE
|
||||
//=============================================================================================================================
|
||||
|
||||
SoundAreaSelectDelegate::SoundAreaSelectDelegate(QObject *parent)
|
||||
: QItemDelegate(parent)
|
||||
{
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------------------------------------------------------
|
||||
// PUBLIC MEMBER FUNCTIONS
|
||||
//-----------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
void SoundAreaSelectDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const
|
||||
{
|
||||
if (index.column() != SoundAreaSelectModel::Column::Stop)
|
||||
{
|
||||
QItemDelegate::paint(painter, option, index);
|
||||
return;
|
||||
} // if
|
||||
|
||||
QStyleOptionButton button;
|
||||
button.rect = option.rect;
|
||||
button.state = index.data().toBool() ? QStyle::State_Enabled : QStyle::State_ReadOnly;
|
||||
button.iconSize = QSize(25, 25);
|
||||
button.icon = QIcon(QStringLiteral("icon:avm_stop.svg"));
|
||||
|
||||
QApplication::style()->drawControl(QStyle::CE_PushButton, &button, painter);
|
||||
}
|
||||
|
||||
//=============================================================================================================================
|
||||
// SOUNDAREASELECTMODEL
|
||||
//=============================================================================================================================
|
||||
|
||||
SoundAreaSelectModel::SoundAreaSelectModel(QWidget *parent)
|
||||
: LtsWidgets::LtsAbstractTableModel<SoundArea>(
|
||||
{
|
||||
tr("ID"),
|
||||
tr("Name"),
|
||||
tr("Main EGCU"),
|
||||
tr("Sound Area EGCUs"),
|
||||
tr("Active Sounds"),
|
||||
tr("Stop")
|
||||
}, parent)
|
||||
, m_logger(getLogger("Plugins.Gui.SoundArea.SelectModel"))
|
||||
{
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------------------------------------------------------
|
||||
// PRIVATE SLOTS
|
||||
//-----------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
bool SoundAreaSelectModel::onSoundStateChanged(const SoundManagement::SoundState &data, DataModification modType)
|
||||
{
|
||||
for (auto &soundArea : m_vecData) // search SoundAreas
|
||||
{
|
||||
if (soundArea.egcuIds.contains(data.egcuId())) // found SoundArea with corresponding EGCU
|
||||
{
|
||||
QHash<int32_t, SoundManagement::SoundState>::iterator it = soundArea.activeSounds.find(data.id());
|
||||
switch (modType)
|
||||
{
|
||||
case DataModification::eAdded:
|
||||
if (it != soundArea.activeSounds.end()) // prevent duplicates
|
||||
{
|
||||
DEBUG_LOG(m_logger) << "'" << m_helper->soundName(data.category(), data.soundId()) << "' is already active";
|
||||
return false;
|
||||
} // if
|
||||
else
|
||||
{
|
||||
soundArea.activeSounds.insert(data.id(), data);
|
||||
emit dataChanged(
|
||||
SoundAreaSelectModel::index(0, Column::ActiveSounds),
|
||||
SoundAreaSelectModel::index(m_vecData.size(), Column::ActiveSounds)
|
||||
);
|
||||
return true;
|
||||
} // else
|
||||
|
||||
case DataModification::eRemoved:
|
||||
if (it == soundArea.activeSounds.end()) // this should not happen
|
||||
{
|
||||
DEBUG_LOG(m_logger) << "'" << m_helper->soundName(data.category(), data.soundId()) << "' is not active";
|
||||
return false;
|
||||
} // if
|
||||
else
|
||||
{
|
||||
soundArea.activeSounds.remove(it.key());
|
||||
emit dataChanged(
|
||||
SoundAreaSelectModel::index(0, Column::ActiveSounds),
|
||||
SoundAreaSelectModel::index(m_vecData.size(), Column::ActiveSounds)
|
||||
);
|
||||
return true;
|
||||
} // else
|
||||
|
||||
case DataModification::eModified:
|
||||
default:
|
||||
return false;
|
||||
} // switch
|
||||
} // if
|
||||
} // for
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------------------------------------------------------
|
||||
// PUBLIC MEMBER FUNCTIONS
|
||||
//-----------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
bool SoundAreaSelectModel::init(const std::shared_ptr<InfrastructureManagement::Interface::Dtc> &ismDtc,
|
||||
const std::shared_ptr<SoundManagement::Interface::Dtc> &somDtc)
|
||||
{
|
||||
DEBUG_LOG(m_logger) << "init";
|
||||
|
||||
m_ismDtc = ismDtc;
|
||||
m_somDtc = somDtc;
|
||||
|
||||
m_helper = std::make_shared<SoundAreaHelper>(new SoundAreaHelper(m_ismDtc, m_somDtc));
|
||||
|
||||
// SoundAreas
|
||||
connect(m_ismDtc.get(), &InfrastructureManagement::Interface::Dtc::effectAreaChanged, this,
|
||||
[this](const InfrastructureManagement::EffectArea &data, DataModification modType)
|
||||
{
|
||||
return onDataChanged(SoundArea(data), modType);
|
||||
});
|
||||
|
||||
m_ismDtc->effectAreas([this](const InfrastructureManagement::EffectArea &effectArea)
|
||||
{
|
||||
insertRow(SoundArea(effectArea));
|
||||
});
|
||||
|
||||
// active Sounds
|
||||
connect(m_somDtc.get(), &SoundManagement::Interface::Dtc::soundStateChanged, this,
|
||||
[this](const SoundManagement::SoundState &data, DataModification modType)
|
||||
{
|
||||
return onSoundStateChanged(data, modType);
|
||||
});
|
||||
|
||||
m_somDtc->soundStates([this](const SoundManagement::SoundState &soundState)
|
||||
{
|
||||
onSoundStateChanged(soundState, DataModification::eAdded);
|
||||
});
|
||||
|
||||
DEBUG_LOG(m_logger) << "init successful";
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool SoundAreaSelectModel::insertRow(const SoundArea &item)
|
||||
{
|
||||
beginInsertRows(QModelIndex(), m_vecData.size(), m_vecData.size());
|
||||
m_vecData.push_back(item);
|
||||
endInsertRows();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool SoundAreaSelectModel::removeRow(int row)
|
||||
{
|
||||
removeRows(row, 1);
|
||||
return true;
|
||||
}
|
||||
|
||||
QVariant SoundAreaSelectModel::data(const QModelIndex &index, int role) const
|
||||
{
|
||||
if (!index.isValid())
|
||||
return QVariant();
|
||||
|
||||
if ( (role != Qt::DisplayRole) && (role != Qt::ToolTipRole) )
|
||||
return QVariant{};
|
||||
|
||||
const SoundArea &soundArea = m_vecData.at(index.row());
|
||||
std::string str = "";
|
||||
|
||||
switch (role)
|
||||
{
|
||||
case Qt::DisplayRole:
|
||||
switch (index.column())
|
||||
{
|
||||
case Column::Id: return soundArea.id;
|
||||
|
||||
case Column::Name: return soundArea.displayName;
|
||||
|
||||
case Column::AreaEgcu: return m_helper->egcuName(soundArea.areaEgcuId);
|
||||
|
||||
case Column::Egcus:
|
||||
for (const auto &egcu : soundArea.egcuIds)
|
||||
str += m_helper->egcuName(egcu).toStdString() + ", ";
|
||||
if (str.size() > 1)
|
||||
str = str.substr(0, str.length() - 2); // remove ", "
|
||||
return QString::fromStdString(str);
|
||||
|
||||
case Column::ActiveSounds:
|
||||
if (soundArea.activeSounds.size() > 0)
|
||||
{
|
||||
SoundManagement::SoundState sound = soundArea.activeSounds.begin().value();
|
||||
return m_helper->soundName(sound.category(), sound.soundId());
|
||||
} // if
|
||||
return QString();
|
||||
|
||||
case Column::Stop:
|
||||
return soundArea.activeSounds.size() > 0;
|
||||
|
||||
default:
|
||||
Q_UNREACHABLE();
|
||||
return QVariant{};
|
||||
} // switch
|
||||
|
||||
case Qt::ToolTipRole:
|
||||
switch (index.column())
|
||||
{
|
||||
case Column::Id:
|
||||
case Column::Name:
|
||||
case Column::AreaEgcu:
|
||||
return data(index, Qt::DisplayRole);
|
||||
|
||||
case Column::Egcus:
|
||||
for (const auto &egcu : soundArea.egcuIds)
|
||||
str += m_helper->egcuName(egcu).toStdString() + "\n";
|
||||
if (str.size() > 1)
|
||||
str = str.substr(0, str.length() - 1);
|
||||
return QString::fromStdString(str);
|
||||
|
||||
case Column::ActiveSounds:
|
||||
for (const auto &sound : soundArea.activeSounds)
|
||||
str += m_helper->soundName(sound.category(), sound.soundId()).toStdString() + "\n";
|
||||
if (str.size() > 1)
|
||||
str = str.substr(0, str.length() - 1);
|
||||
return QString::fromStdString(str);
|
||||
|
||||
case Column::Stop:
|
||||
return QStringLiteral("Stop all Sounds");
|
||||
|
||||
default:
|
||||
Q_UNREACHABLE();
|
||||
return QVariant();
|
||||
} // switch
|
||||
|
||||
default:
|
||||
Q_UNREACHABLE();
|
||||
return QVariant();
|
||||
} // switch
|
||||
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------------------------------------------------------
|
||||
// PROTECTED MEMBER FUNCTIONS
|
||||
//-----------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
bool SoundAreaSelectModel::onDataChanged(const SoundArea &data, DataModification modType)
|
||||
{
|
||||
if (modType == DataModification::eAdded)
|
||||
return insertRow(data);
|
||||
|
||||
int row = indexOf(data);
|
||||
if (modType == DataModification::eRemoved)
|
||||
return removeRow(row);
|
||||
|
||||
return setRowData(row, data);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------------------------------------------------------
|
||||
// PRIVATE MEMBER FUNCTIONS
|
||||
//-----------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
int SoundAreaSelectModel::indexOf(const SoundArea &data) const
|
||||
{
|
||||
return m_vecData.indexOf(data);
|
||||
}
|
||||
|
||||
} // namespace EffectManagement
|
||||
@@ -0,0 +1,112 @@
|
||||
/**
|
||||
* @RDE_HEADER@
|
||||
* Model for the overall sound area table.
|
||||
* $Id$
|
||||
* $HeadURL$
|
||||
* $Author$
|
||||
* Created by Filip Biedziak, NLE, 2020-07-29
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "efm_sound_area.h"
|
||||
|
||||
#include <LtsWidgets/lts_abstract_table_model.h>
|
||||
#include <LtsUtilsGuiDds/request_helper.h>
|
||||
#include <InfrastructureManagement/ism_dtc.h>
|
||||
#include <SoundManagement/som_dtc.h>
|
||||
#include <SoundManagement/som_ftc.h>
|
||||
|
||||
#include <QItemDelegate>
|
||||
|
||||
|
||||
namespace NGL
|
||||
{
|
||||
class INGLLogger;
|
||||
}
|
||||
|
||||
|
||||
namespace EffectManagement
|
||||
{
|
||||
|
||||
using SoundKey = QPair<int32_t, int32_t>;
|
||||
|
||||
class SoundAreaHelper;
|
||||
|
||||
|
||||
|
||||
class SoundAreaSelectDelegate
|
||||
: public QItemDelegate
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
SoundAreaSelectDelegate(QObject *parent = nullptr);
|
||||
void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const;
|
||||
|
||||
}; // SoundAreaSelectDelegate
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @brief The SoundAreasDialogModel class provides a model for an overview over all SoundAreas.
|
||||
* @details It inherits LtsAbstractTableModel and has SoundArea (declared in efm_sound_area.h) as
|
||||
* its template type. 7 columns will be displayed with the SoundArea ID, name, its main EGCU's ID, a
|
||||
* list of all its EGCUs' IDs (including the main EGCU), a list of all active sounds, the remaining
|
||||
* time until all sounds stop playing and the last column showing a stop button that lets the user
|
||||
* stop all sound inside the SoundArea.
|
||||
*/
|
||||
class SoundAreaSelectModel final
|
||||
: public LtsWidgets::LtsAbstractTableModel<SoundArea>
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
enum Column { Id, Name, AreaEgcu, Egcus, ActiveSounds, Stop };
|
||||
|
||||
explicit SoundAreaSelectModel(QWidget *parent = nullptr);
|
||||
|
||||
|
||||
private slots:
|
||||
/**
|
||||
* @brief onSoundStateChanged updates all active sounds by catching the soundStateChanged signal
|
||||
* from the Sound Management.
|
||||
* @param soundState SoundState from Sound Management
|
||||
* @param modType data modification type (eAdded, eModified or eRemoved)
|
||||
* @return true for success, false otherwise
|
||||
*/
|
||||
bool onSoundStateChanged(const SoundManagement::SoundState &data, DataModification modType);
|
||||
|
||||
|
||||
public:
|
||||
bool init(const std::shared_ptr<InfrastructureManagement::Interface::Dtc> &ismDtc,
|
||||
const std::shared_ptr<SoundManagement::Interface::Dtc> &somDtc);
|
||||
|
||||
QVector<SoundArea> soundAreas() const { return m_vecData; }
|
||||
|
||||
bool insertRow(const SoundArea &item) override;
|
||||
bool removeRow(int row) override;
|
||||
QVariant data(const QModelIndex &index, int role) const override;
|
||||
|
||||
protected:
|
||||
bool onDataChanged(const SoundArea &data, DataModification modType) override;
|
||||
|
||||
private:
|
||||
/**
|
||||
* @brief indexOf returns the index of a given SoundArea.
|
||||
* @param data the SoundArea
|
||||
* @return index of the SoundArea
|
||||
*/
|
||||
int indexOf(const SoundArea &data) const;
|
||||
|
||||
|
||||
std::shared_ptr<InfrastructureManagement::Interface::Dtc> m_ismDtc{nullptr};
|
||||
std::shared_ptr<SoundManagement::Interface::Dtc> m_somDtc{nullptr};
|
||||
|
||||
std::shared_ptr<SoundAreaHelper> m_helper{nullptr};
|
||||
|
||||
NGL::INGLLogger &m_logger;
|
||||
|
||||
}; // class SoundAreaSelectModel
|
||||
|
||||
} // namespace EffectManagement
|
||||
@@ -0,0 +1,60 @@
|
||||
/**
|
||||
* @RDE_HEADER@
|
||||
* SoundState class derivation for custom purposes.
|
||||
* $Id$
|
||||
* $HeadURL$
|
||||
* $Author$
|
||||
* Created by Filip Biedziak, NLE, 2020-08-26
|
||||
*/
|
||||
|
||||
#include "efm_sound_state.h"
|
||||
|
||||
|
||||
namespace EffectManagement
|
||||
{
|
||||
|
||||
//=============================================================================================================================
|
||||
// SOUNDSTATE
|
||||
//=============================================================================================================================
|
||||
|
||||
SoundState::SoundState(const SoundManagement::SoundState &soundState)
|
||||
: SoundManagement::SoundState(soundState)
|
||||
{
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------------------------------------------------------
|
||||
// PUBLIC MEMBER FUNCTIONS
|
||||
//-----------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
void SoundState::status(Status stat)
|
||||
{
|
||||
m_status = stat;
|
||||
}
|
||||
|
||||
void SoundState::duration(int secs)
|
||||
{
|
||||
if (secs > 0)
|
||||
m_duration = std::max(0, secs);
|
||||
}
|
||||
|
||||
void SoundState::timeLeft(int secs)
|
||||
{
|
||||
if (secs >= 0)
|
||||
m_timeLeft = secs;
|
||||
}
|
||||
|
||||
void SoundState::volume(int vol)
|
||||
{
|
||||
if (vol >= 0)
|
||||
m_volume = vol;
|
||||
}
|
||||
|
||||
|
||||
QString SoundState::statusToString() const
|
||||
{
|
||||
if (m_status == Status::Active)
|
||||
return QStringLiteral("Active");
|
||||
return m_status == Status::Stop ? QStringLiteral("Stop") : QStringLiteral("Scheduled");
|
||||
}
|
||||
|
||||
} // namespace EffectManagement
|
||||
@@ -0,0 +1,52 @@
|
||||
/**
|
||||
* @RDE_HEADER@
|
||||
* SoundState class derivation for custom purposes.
|
||||
* $Id$
|
||||
* $HeadURL$
|
||||
* $Author$
|
||||
* Created by Filip Biedziak, NLE, 2020-08-10
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <SoundManagement/som.hpp>
|
||||
|
||||
#include <QString>
|
||||
|
||||
|
||||
namespace EffectManagement
|
||||
{
|
||||
|
||||
class SoundState
|
||||
: public SoundManagement::SoundState
|
||||
{
|
||||
|
||||
public:
|
||||
enum Status { Active, Stop, Scheduled };
|
||||
|
||||
SoundState() = default;
|
||||
explicit SoundState(const SoundManagement::SoundState &soundState);
|
||||
|
||||
public:
|
||||
Status status() const { return m_status; }
|
||||
int duration() const { return m_duration; }
|
||||
int timeLeft() const { return m_timeLeft; }
|
||||
int volume() const { return m_volume; }
|
||||
|
||||
void status(Status stat);
|
||||
void duration(int secs);
|
||||
void timeLeft(int secs);
|
||||
void volume(int vol);
|
||||
|
||||
QString statusToString() const;
|
||||
|
||||
|
||||
private:
|
||||
Status m_status{Status::Scheduled};
|
||||
int m_volume{100};
|
||||
int m_duration{0};
|
||||
int m_timeLeft{0};
|
||||
|
||||
}; // class SoundState
|
||||
|
||||
} // namespace EffectManagement
|
||||
@@ -0,0 +1,37 @@
|
||||
/**
|
||||
* @RDE_HEADER@
|
||||
* Item Delegate class to show On/Off switch buttons.
|
||||
* $Id$
|
||||
* $HeadURL$
|
||||
* $Author$
|
||||
* Created by Filip Biedziak, NLE, 2020-08-10
|
||||
*/
|
||||
|
||||
#include "efm_switch_item_delegate.h"
|
||||
#include "../logger.h"
|
||||
#include <QDebug>
|
||||
|
||||
|
||||
namespace EffectManagement
|
||||
{
|
||||
|
||||
const QIcon SwitchItemDelegate::s_iconOn = QIcon(QStringLiteral("icon:switch_on.svg"));
|
||||
|
||||
const QIcon SwitchItemDelegate::s_iconOff = QIcon(QStringLiteral("icon:switch_off.svg"));
|
||||
|
||||
|
||||
SwitchItemDelegate::SwitchItemDelegate(QObject *parent)
|
||||
: QStyledItemDelegate(parent)
|
||||
, m_logger(getLogger("Plugins.Gui.SoundArea.SwitchItemDelegate"))
|
||||
{
|
||||
}
|
||||
|
||||
void SwitchItemDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const
|
||||
{
|
||||
if (index.data().toInt() == 1)
|
||||
s_iconOn.paint(painter, option.rect, Qt::AlignCenter);
|
||||
else if (index.data().toInt() == -1)
|
||||
s_iconOff.paint(painter, option.rect, Qt::AlignCenter);
|
||||
}
|
||||
|
||||
} // namespace EffectManagement
|
||||
@@ -0,0 +1,42 @@
|
||||
/**
|
||||
* @RDE_HEADER@
|
||||
* Item Delegate class to show On/Off switch buttons.
|
||||
* $Id$
|
||||
* $HeadURL$
|
||||
* $Author$
|
||||
* Created by Filip Biedziak, NLE, 2020-08-10
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <QStyledItemDelegate>
|
||||
|
||||
|
||||
namespace NGL
|
||||
{
|
||||
class INGLLogger;
|
||||
}
|
||||
|
||||
|
||||
namespace EffectManagement
|
||||
{
|
||||
|
||||
class SwitchItemDelegate
|
||||
: public QStyledItemDelegate
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
SwitchItemDelegate(QObject *parent = nullptr);
|
||||
|
||||
void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const;
|
||||
|
||||
private:
|
||||
static const QIcon s_iconOn;
|
||||
static const QIcon s_iconOff;
|
||||
|
||||
NGL::INGLLogger &m_logger;
|
||||
|
||||
}; // SwitchItemDelegate
|
||||
|
||||
} // namespace EffectManagement
|
||||
@@ -0,0 +1,91 @@
|
||||
/**
|
||||
* @RDE_HEADER@
|
||||
* Plugin to manage effects.
|
||||
* $Id$
|
||||
* $HeadURL$
|
||||
* $Author$
|
||||
* Created by Filip Biedziak, NLE, 2020-07-29
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "efm_effect_area.h"
|
||||
#include "efm_sound_helper.h"
|
||||
|
||||
#include <LtsWidgets/lts_dialog.h>
|
||||
#include <LtsUtilsGuiDds/request_helper.h>
|
||||
#include <SoundManagement/som_dtc.h>
|
||||
#include <SoundManagement/som_ftc.h>
|
||||
|
||||
|
||||
namespace NGL
|
||||
{
|
||||
class INGLLogger;
|
||||
}
|
||||
|
||||
namespace LtsSession
|
||||
{
|
||||
class LtsSessionDataDds;
|
||||
}
|
||||
|
||||
namespace LtsUtils
|
||||
{
|
||||
class RequestHelper;
|
||||
}
|
||||
|
||||
namespace Ui
|
||||
{
|
||||
class SoundManagementDialog;
|
||||
}
|
||||
|
||||
|
||||
namespace EffectManagement
|
||||
{
|
||||
|
||||
class SoundTreeModel;
|
||||
class SoundPlaylistModel;
|
||||
|
||||
|
||||
class SoundManagementDialog
|
||||
: public LtsWidgets::LtsDialog
|
||||
, protected SoundManagement::Interface::Ftc::ControlSoundReplyHandler
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit SoundManagementDialog(const EffectAreaData &data, QWidget *parent = nullptr);
|
||||
~SoundManagementDialog();
|
||||
|
||||
|
||||
private slots:
|
||||
void onAddSoundToPlaylist(const SoundKey &key);
|
||||
void onStopAllSounds();
|
||||
|
||||
public:
|
||||
bool init(LtsSession::LtsSessionDataDds *session, const QString &menuGroup);
|
||||
|
||||
private:
|
||||
void onControlSoundReply(const Core::FunctionReplyObject &replyObject) override final;
|
||||
void retranslate() override;
|
||||
bool apply() override;
|
||||
|
||||
std::shared_ptr<SoundManagement::Interface::Dtc> m_somDtc{nullptr};
|
||||
std::shared_ptr<SoundManagement::Interface::Ftc> m_somFtc{nullptr};
|
||||
std::shared_ptr<SoundManagementHelper> m_helper{nullptr};
|
||||
|
||||
LtsUtils::RequestHelper *m_requestHelper{nullptr};
|
||||
LtsSession::LtsSessionDataDds *m_session{nullptr};
|
||||
|
||||
EffectAreaData *m_data{nullptr};
|
||||
SoundTreeModel *m_treeModel{nullptr};
|
||||
SoundPlaylistModel *m_playlistModel{nullptr};
|
||||
|
||||
QHash<int32_t, QCheckBox *> m_egcuCheckBoxes;
|
||||
QString m_menuGroup;
|
||||
|
||||
Ui::SoundManagementDialog *m_ui{nullptr};
|
||||
NGL::INGLLogger &m_logger;
|
||||
|
||||
}; // class EffectManagementDialog
|
||||
|
||||
} // namespace EffectManagement
|
||||
Executable
+38
@@ -0,0 +1,38 @@
|
||||
/**
|
||||
* @RDE_HEADER@
|
||||
* Logging for EffectManagement Plugin
|
||||
* $Id$
|
||||
* $HeadURL$
|
||||
* $Author$
|
||||
*/
|
||||
|
||||
#include "logger.h"
|
||||
|
||||
#include <NGLLogger/NGLLoggerBootstrap.h>
|
||||
|
||||
|
||||
namespace EffectManagement
|
||||
{
|
||||
|
||||
LOGGER_T getLogger(const char *name)
|
||||
{
|
||||
static const char ns[] = "EFM.";
|
||||
std::string loggerName;
|
||||
const size_t len = strlen(name);
|
||||
loggerName.reserve(sizeof(ns) + len);
|
||||
loggerName.append(ns, sizeof(ns) - 1);
|
||||
loggerName.append(name, len);
|
||||
|
||||
try
|
||||
{
|
||||
return NGL::NGLLoggerBootstrap::getNGLRootLogger().
|
||||
getNGLLogger(loggerName);
|
||||
}
|
||||
catch (const std::exception &ex)
|
||||
{
|
||||
fprintf(stderr, "Error retrieving logger: %s", ex.what());
|
||||
abort();
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace EffectManagement
|
||||
Executable
+26
@@ -0,0 +1,26 @@
|
||||
/**
|
||||
* @RDE_HEADER@
|
||||
* Logging for EffectManagement Plugin
|
||||
* $Id$
|
||||
* $HeadURL$
|
||||
* $Author$
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <NGLLogger/INGLLogger.h>
|
||||
|
||||
|
||||
namespace EffectManagement
|
||||
{
|
||||
|
||||
using LOGGER_T = NGL::INGLLogger &;
|
||||
|
||||
LOGGER_T getLogger(const char *name);
|
||||
|
||||
inline LOGGER_T getLogger(const QString &loggerName)
|
||||
{
|
||||
return getLogger(loggerName.toUtf8().constData());
|
||||
}
|
||||
|
||||
} // namespace EffectManagement
|
||||
@@ -0,0 +1,52 @@
|
||||
/**
|
||||
* @RDE_HEADER@
|
||||
* HMI Plugin for effect management (Interface for access from other Plugins)
|
||||
* $Id$
|
||||
* $HeadURL$
|
||||
* $Author$
|
||||
* Created by Filip Biedziak, SLSE, 2020-07-29
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <PluginInterfaces/data_plugin_interface.h>
|
||||
#include <SoundManagement/som_dtc.h>
|
||||
#include <SoundManagement/som_ftc.h>
|
||||
|
||||
|
||||
namespace EffectManagement
|
||||
{
|
||||
|
||||
/**
|
||||
* @brief The DataInterface class provides the Topics Clients only for the GUI Plugins
|
||||
*/
|
||||
class DataInterface : public DataPluginBase::Interface
|
||||
{
|
||||
|
||||
public:
|
||||
using DataPluginBase::Interface::Interface;
|
||||
|
||||
virtual std::shared_ptr<SoundManagement::Interface::Dtc> getDtc() = 0;
|
||||
virtual std::shared_ptr<SoundManagement::Interface::Ftc> getFtc() = 0;
|
||||
};
|
||||
|
||||
} // namespace EffectManagement
|
||||
|
||||
|
||||
//namespace SoundManagement
|
||||
//{
|
||||
|
||||
///**
|
||||
// * @brief The DataInterface class provides the Topics Clients only for the GUI Plugins
|
||||
// */
|
||||
//class DataInterface : public DataPluginBase::Interface
|
||||
//{
|
||||
|
||||
//public:
|
||||
// using DataPluginBase::Interface::Interface;
|
||||
|
||||
// virtual std::shared_ptr<SoundManagement::Interface::Dtc> getDtc() = 0;
|
||||
// virtual std::shared_ptr<SoundManagement::Interface::Ftc> getFtc() = 0;
|
||||
//};
|
||||
|
||||
//} // namespace SoundManagement
|
||||
+24
@@ -0,0 +1,24 @@
|
||||
/**
|
||||
* @RDE_HEADER@
|
||||
* HMI Plugin for effect managemt (Interface for access from other Plugins)
|
||||
* $Id$
|
||||
* $HeadURL$
|
||||
* $Author$
|
||||
* Created by Filip Biedziak, NLE, 2020-07-29
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
|
||||
namespace EffectManagement
|
||||
{
|
||||
|
||||
class ForeignGuiInterface
|
||||
{
|
||||
|
||||
public:
|
||||
ForeignGuiInterface() = default;
|
||||
virtual ~ForeignGuiInterface() = default;
|
||||
};
|
||||
|
||||
} // namespace ExerciseManagement
|
||||
Reference in new issue
Block a user