Initial commit
This commit is contained in:
commit
b7d90b9afe
16245 files changed
+3396666
No files matched your search
+359
@@ -0,0 +1,359 @@
|
||||
/**
|
||||
* @RDE_HEADER@
|
||||
* $Id$
|
||||
* $HeadURL$
|
||||
* $Author$
|
||||
* Created by Philipp Last, SLSE, 2017-09-18
|
||||
*/
|
||||
|
||||
#include "bdv_building_edit.h"
|
||||
#include "bdv_edit_item.h"
|
||||
#include "ui_bdv_building_edit.h"
|
||||
|
||||
#include <LtsSession/lts_session_data.h>
|
||||
#include <LtsUtilsSettings/settings.h>
|
||||
|
||||
#include <Buildings/bld_operator_rights.h>
|
||||
#include <Buildings/bld.hpp>
|
||||
#include <Buildings/bld_ftc.h>
|
||||
|
||||
#include <nglwidgets/ngltreeitem.h>
|
||||
|
||||
namespace BuildingViewer
|
||||
{
|
||||
BuildingEdit::BuildingEdit(QWidget *parent)
|
||||
: LtsWidgets::LtsDialog(parent, LtsWidgets::ButtonCombination::OkApplyCancel)
|
||||
, m_requestHelper(new LtsUtils::RequestHelper(this))
|
||||
, m_ui(new Ui::BuildingEdit)
|
||||
, m_logger(getLogger("BuildingViewer::BuildingEdit"))
|
||||
{
|
||||
m_ui->setupUi(this);
|
||||
|
||||
m_buttonBox->getButton(LtsWidgets::DialogButton::Ok)->hide();
|
||||
m_buttonBox->connectButton(LtsWidgets::DialogButton::Edit, this, &BuildingEdit::slotEditItem);
|
||||
|
||||
bool userHasRightsToEdit = LtsSessionData::LtsSessionData::getInstance()->hasOperatorRight(OperatorRights::BuildingViewerSettingsEdit);
|
||||
m_buttonBox->getButton(LtsWidgets::DialogButton::Edit)->setVisible(userHasRightsToEdit);
|
||||
m_buttonBox->getButton(LtsWidgets::DialogButton::Apply)->setVisible(userHasRightsToEdit);
|
||||
|
||||
m_buttonBox->getButton(LtsWidgets::DialogButton::Edit)->setEnabled(false);
|
||||
|
||||
LtsUtils::ProjectSettings *ps = LtsUtils::ProjectSettings::getInstance();
|
||||
const bool enableGuiDestroyRooms = ps->value(QStringLiteral("bld"),
|
||||
QStringLiteral("enableGuiDestroyRooms")).toBool();
|
||||
// Todo: Create Buttons for Destroying (and resetting?) rooms.
|
||||
auto btnDestroy = m_buttonBox->getButton(LtsWidgets::DialogButton::Add);
|
||||
btnDestroy->setText(tr("Destroy"));
|
||||
btnDestroy->setVisible(enableGuiDestroyRooms);
|
||||
// btnDestroy->setEnabled(false);
|
||||
connect(btnDestroy, &QPushButton::pressed, this, &BuildingEdit::onDestroyElement);
|
||||
|
||||
|
||||
setOnlineHelpFilename(QStringLiteral("Building_Viewer-Building_List"));
|
||||
}
|
||||
|
||||
|
||||
BuildingEdit::~BuildingEdit()
|
||||
{
|
||||
delete m_ui;
|
||||
}
|
||||
|
||||
|
||||
void BuildingEdit::retranslate()
|
||||
{
|
||||
translate(m_ui, tr("Building Edit: %1").arg(m_buildingName));
|
||||
}
|
||||
|
||||
|
||||
bool BuildingEdit::init(int32_t buildingDatabaseId,
|
||||
const std::shared_ptr<InfrastructureManagement::Interface::Dtc> &ismDtc,
|
||||
const std::shared_ptr<InfrastructureManagement::Interface::Ftc> &ismFtc,
|
||||
const std::shared_ptr<Buildings::Interface::Dtc> &bldDtc,
|
||||
const std::shared_ptr<Buildings::Interface::Ftc> &bldFtc)
|
||||
{
|
||||
if (m_ismDtc)
|
||||
return false;
|
||||
m_buildingDatabaseId = buildingDatabaseId;
|
||||
|
||||
m_ismDtc = ismDtc;
|
||||
m_ismFtc = ismFtc;
|
||||
m_bldDtc = bldDtc;
|
||||
m_bldFtc = bldFtc;
|
||||
|
||||
// Get building name to create a proper tab title
|
||||
InfrastructureManagement::MainStructureElement building = m_ismDtc->mainStructureElement(m_buildingDatabaseId);
|
||||
m_buildingId = building.id();
|
||||
|
||||
buildModel();
|
||||
m_buildingName = m_model->getBuildingName();
|
||||
|
||||
if (LtsSessionData::LtsSessionData::getInstance()->hasOperatorRight(OperatorRights::BuildingViewerSettingsEdit))
|
||||
{
|
||||
connect(m_ui->treeViewEdit, &QTreeView::clicked, this, &BuildingEdit::slotTreeViewClicked);
|
||||
connect(m_ui->treeViewEdit, &QTreeView::doubleClicked, this, &BuildingEdit::slotDoubleClicked);
|
||||
connect(m_model, &BuildingEditModel::signalModelDataChanged, this, &BuildingEdit::slotChangesMade); // 'slotChangesMade' belongs to LtsWidgets::LtsDialog and enables apply button
|
||||
}
|
||||
|
||||
connect(m_ismDtc.get(), &InfrastructureManagement::Interface::Dtc::mainStructureElementChanged,
|
||||
this, &BuildingEdit::slotMainStructureElementChanged);
|
||||
|
||||
connect(m_bldDtc.get(), &Buildings::Interface::Dtc::buildingStateChanged,
|
||||
this, &BuildingEdit::slotBuildingStateChanged);
|
||||
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
void BuildingEdit::slotTreeViewClicked()
|
||||
{
|
||||
m_buttonBox->getButton(LtsWidgets::DialogButton::Edit)->setEnabled(selectedIndexView().isValid());
|
||||
}
|
||||
|
||||
|
||||
void BuildingEdit::buildModel()
|
||||
{
|
||||
m_model = new BuildingEditModel(this, m_ismDtc, m_bldDtc);
|
||||
|
||||
// SortFilterProxyModel:
|
||||
m_proxyModel = new BuildingEditProxyModel(this);
|
||||
m_proxyModel->setSourceModel(m_model);
|
||||
|
||||
// View treeView :
|
||||
m_ui->treeViewEdit->setModel(m_proxyModel);
|
||||
m_ui->treeViewEdit->expandAll();
|
||||
m_ui->treeViewEdit->sortByColumn(BuildingEditModel::Building, Qt::AscendingOrder);
|
||||
|
||||
// ContextMenu :
|
||||
m_ui->treeViewEdit->setContextMenuPolicy(Qt::CustomContextMenu);
|
||||
|
||||
m_model->init(m_buildingDatabaseId);
|
||||
m_ui->treeViewEdit->expandAll();
|
||||
m_ui->treeViewEdit->setColumnWidth(BuildingEditModel::Building, 230);
|
||||
#ifdef LTS_DEBUG
|
||||
m_ui->treeViewEdit->setColumnWidth(BuildingEditModel::Name, 150);
|
||||
m_ui->treeViewEdit->setColumnWidth(BuildingEditModel::MountingPointId, 120);
|
||||
m_ui->treeViewEdit->setColumnWidth(BuildingEditModel::StructureElementId, 80);
|
||||
#else
|
||||
m_ui->treeViewEdit->hideColumn(BuildingEditModel::Name);
|
||||
m_ui->treeViewEdit->hideColumn(BuildingEditModel::MountingPointId);
|
||||
m_ui->treeViewEdit->hideColumn(BuildingEditModel::StructureElementId);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
QModelIndex BuildingEdit::selectedIndexView() const
|
||||
{
|
||||
QItemSelectionModel *selectionModel = m_ui->treeViewEdit->selectionModel();
|
||||
QModelIndexList indexL = selectionModel->selectedRows(0);
|
||||
if (indexL.size() == 0)
|
||||
return QModelIndex();
|
||||
|
||||
return m_proxyModel->mapToSource(indexL.at(0));
|
||||
}
|
||||
|
||||
|
||||
void BuildingEdit::slotEditItem()
|
||||
{
|
||||
QModelIndex selIndex = selectedIndexView();
|
||||
if (!selIndex.isValid())
|
||||
return;
|
||||
|
||||
BuildingViewer::TreeItem data = m_model->privateData(selIndex)->data().value<TreeItem>();
|
||||
|
||||
ParticipantEditItemWidget *newItemDlg = new ParticipantEditItemWidget(m_buildingName, data, this);
|
||||
newItemDlg->setAttribute(Qt::WA_DeleteOnClose);
|
||||
|
||||
connect(newItemDlg, &ParticipantEditItemWidget::signalItemUpdated,
|
||||
m_model, &BuildingEditModel::slotUpdateRow);
|
||||
|
||||
newItemDlg->show();
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Applies changes to the Dds structures. The actual updating of the room names and fortify factors
|
||||
* is done by the 'BuildingViewerDdsController' * which listen on changes related to the MainStructureElements
|
||||
* (See slot 'BuildingViewerDdsController::onMainStructureElementChanged')
|
||||
*/
|
||||
bool BuildingEdit::apply()
|
||||
{
|
||||
/*
|
||||
* FortifyFactor is set by using 'Building', room names are set by 'InfraStructureManagement'.
|
||||
* Hence, we have two reply handler. Both of them must return without a failure.
|
||||
*
|
||||
* However, it may be possible that only room names OR fortify factors have been changed.
|
||||
* E.g., if only fortify factors changed we set 'm_ismFtcReplySuccess' to true to indicate that
|
||||
* changing the room names was successful (-> nothing changed)
|
||||
*/
|
||||
const auto fortifyFactors = m_model->getRoomsWithChangedFortifyFactors();
|
||||
//m_blgFtcReplySuccess = fortifyFactors.size() ? false : true;
|
||||
|
||||
// Change fortify factors
|
||||
DEBUG_LOG(m_logger) << "fortifyFactors.size()=" << fortifyFactors.size();
|
||||
if (fortifyFactors.size())
|
||||
{
|
||||
m_requestHelper->addRequest([this, fortifyFactors]()
|
||||
{
|
||||
Buildings::SetFortifyFactorRequest fortifyRequest;
|
||||
fortifyRequest.buildingId(m_buildingDatabaseId);
|
||||
|
||||
// Get all factors for this building
|
||||
fortifyRequest.fortifyFactors().reserve(fortifyFactors.size());
|
||||
for (const auto &e : fortifyFactors)
|
||||
{
|
||||
DEBUG_LOG(m_logger) << "push_back= databaseId=" << e.structureElementId()
|
||||
<< " fortifyFactor=" << e.fortifyFactor();
|
||||
fortifyRequest.fortifyFactors().push_back(Buildings::FortifyFactor(e.structureElementId(), e.fortifyFactor()));
|
||||
}
|
||||
|
||||
return m_bldFtc->setFortifyFactorRequest(fortifyRequest, this);
|
||||
});
|
||||
}
|
||||
|
||||
// Change room display names
|
||||
const auto displayNames = m_model->getRoomsWithChangedDisplayNames();
|
||||
//m_ismFtcReplySuccess = mapDisplayNames.size() ? false : true;
|
||||
|
||||
|
||||
if (displayNames.size())
|
||||
{
|
||||
std::vector<InfrastructureManagement::StructureElement> vecModifiedRooms;
|
||||
vecModifiedRooms.reserve(displayNames.size());
|
||||
InfrastructureManagement::MainStructureElement building = m_ismDtc->mainStructureElement(m_buildingDatabaseId);
|
||||
|
||||
for (const auto &treeItem : displayNames)
|
||||
{
|
||||
// Get latest room data
|
||||
for (const auto &room : building.elements())
|
||||
{
|
||||
if (room.id() == treeItem.structureElementId())
|
||||
{
|
||||
auto copy = room;
|
||||
copy.displayName(treeItem.displayName().toStdString());
|
||||
vecModifiedRooms.push_back(copy);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
m_requestHelper->addRequest([this, vecModifiedRooms]()
|
||||
{
|
||||
InfrastructureManagement::StructureElementModifyRequest request(m_buildingDatabaseId, vecModifiedRooms);
|
||||
return m_ismFtc->structureElementModifyRequest(request, this);
|
||||
});
|
||||
}
|
||||
return m_requestHelper->startRequests();
|
||||
}
|
||||
|
||||
|
||||
void BuildingEdit::selectRoomRow(int mountingPointId)
|
||||
{
|
||||
QModelIndex mIndex = m_model->modelIndexByStructureElementId(mountingPointId);
|
||||
m_ui->treeViewEdit->setCurrentIndex(mIndex); // Bug/ToDo: Row is not selected even though mIndex seems to be valid and correct
|
||||
m_ui->treeViewEdit->selectionModel()->setCurrentIndex(mIndex, QItemSelectionModel::ClearAndSelect);
|
||||
}
|
||||
|
||||
|
||||
void BuildingEdit::reinitModel()
|
||||
{
|
||||
m_model->init(m_buildingDatabaseId);
|
||||
m_ui->treeViewEdit->expandAll();
|
||||
}
|
||||
|
||||
|
||||
void BuildingEdit::slotDoubleClicked(const QModelIndex &selIndex)
|
||||
{
|
||||
if (!selIndex.isValid())
|
||||
return;
|
||||
|
||||
slotEditItem();
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Related to the usage of 'm_ismFtcReplySuccess' and 'm_blgFtcReplySuccess':
|
||||
* Changed received: -> Ftc was successful
|
||||
* Reply received: -> Ftc was successful
|
||||
*
|
||||
* However, a change might be received before receiving the reply and vice versa. Both are indicating success.
|
||||
* Hence, we simply set the appropriate variable to true in both cases.
|
||||
*/
|
||||
void BuildingEdit::slotMainStructureElementChanged(const InfrastructureManagement::MainStructureElement &mse, DataModification modType)
|
||||
{
|
||||
if(modType == DataModification::eRemoved)
|
||||
return;
|
||||
|
||||
if(mse.id() == m_buildingDatabaseId)
|
||||
{
|
||||
//m_ismFtcReplySuccess = true;
|
||||
slotHandleExternalDdsChange();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void BuildingEdit::slotBuildingStateChanged(const Buildings::BuildingState &state, DataModification modType)
|
||||
{
|
||||
if(modType == DataModification::eRemoved)
|
||||
return;
|
||||
|
||||
if(state.id() == m_buildingDatabaseId)
|
||||
{
|
||||
//m_blgFtcReplySuccess = true;
|
||||
slotHandleExternalDdsChange();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void BuildingEdit::slotHandleExternalDdsChange()
|
||||
{
|
||||
reinitModel();
|
||||
}
|
||||
|
||||
bool BuildingEdit::sendBuildingStateRequest(ProjectDataManagement::VulnerabilityState state, std::vector<int32_t> structureElementIds)
|
||||
{
|
||||
// aktuellen state aus Cbx ermitteln und LTS-SetBuildingState aufrufen
|
||||
m_requestHelper->addRequest([this, state, structureElementIds]()
|
||||
{
|
||||
Buildings::Building building;
|
||||
std::vector< Buildings::Building > buildings;
|
||||
buildings.resize(1);
|
||||
Buildings::SetBuildingStatesRequest requestData;
|
||||
//requestData.buildingId(m_buildingId);
|
||||
building.buildingId(m_buildingId);
|
||||
building.roomIds().set(structureElementIds);
|
||||
buildings[0] = building;
|
||||
requestData.buildings(buildings);
|
||||
requestData.vulnerabilityState(state);
|
||||
|
||||
DEBUG_LOG(m_logger) << LOGFUNCTION << "currentData: " << state;
|
||||
|
||||
return m_bldFtc->setBuildingStatesRequest(requestData, this);
|
||||
});
|
||||
|
||||
return m_requestHelper->startRequests();
|
||||
}
|
||||
|
||||
void BuildingEdit::onDestroyElement()
|
||||
{
|
||||
QModelIndex selIndex = selectedIndexView();
|
||||
if (!selIndex.isValid())
|
||||
return;
|
||||
|
||||
std::vector<int32_t> structureElementIds;
|
||||
getStructureElementIds(m_model->privateData(selIndex), structureElementIds);
|
||||
|
||||
sendBuildingStateRequest(ProjectDataManagement::VulnerabilityState_def::CatastrophicKill, structureElementIds);
|
||||
}
|
||||
|
||||
void BuildingEdit::getStructureElementIds(NGLTreeItem *item, std::vector<int32_t> &structureElementIds)
|
||||
{
|
||||
for (NGLTreeItem *child : item->children())
|
||||
getStructureElementIds(child, structureElementIds);
|
||||
|
||||
BuildingViewer::TreeItem data = item->data().value<TreeItem>();
|
||||
if (data.isRoom())
|
||||
structureElementIds.push_back(data.structureElementId());
|
||||
}
|
||||
|
||||
}
|
||||
+92
@@ -0,0 +1,92 @@
|
||||
/**
|
||||
* @RDE_HEADER@
|
||||
* $Id$
|
||||
* $HeadURL$
|
||||
* $Author$
|
||||
* Created by Philipp Last, SLSE, 2017-09-18
|
||||
*/
|
||||
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "bdv_edit_model.h"
|
||||
|
||||
|
||||
#include <Common/logger.h>
|
||||
#include <Plugins/Buildings/bld_data_plugin_interface.h>
|
||||
#include <Plugins/InfrastructureManagement/ism_data_plugin_interface.h>
|
||||
|
||||
#include <LtsWidgets/lts_dialog.h>
|
||||
#include <LtsUtilsGuiDds/request_helper.h>
|
||||
|
||||
namespace Ui
|
||||
{
|
||||
class BuildingEdit;
|
||||
}
|
||||
|
||||
namespace BuildingViewer
|
||||
{
|
||||
class BuildingEdit : public LtsWidgets::LtsDialog
|
||||
, protected Buildings::Interface::Ftc::SetFortifyFactorReplyHandler
|
||||
, protected Buildings::Interface::Ftc::SetBuildingStatesReplyHandler
|
||||
, protected InfrastructureManagement::Interface::Ftc::StructureElementModifyReplyHandler
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit BuildingEdit(QWidget *parent = nullptr);
|
||||
~BuildingEdit();
|
||||
|
||||
bool init(int32_t buildingDatabaseId,
|
||||
const std::shared_ptr<InfrastructureManagement::Interface::Dtc> &ismDtc,
|
||||
const std::shared_ptr<InfrastructureManagement::Interface::Ftc> &ismFtc,
|
||||
const std::shared_ptr<Buildings::Interface::Dtc> &bldDtc,
|
||||
const std::shared_ptr<Buildings::Interface::Ftc> &bldFtc);
|
||||
|
||||
void onSetFortifyFactorReply(const Core::FunctionReplyObject &replyObject) override final { m_requestHelper->requestReply(replyObject); }
|
||||
void onSetBuildingStatesReply(const Core::FunctionReplyObject &replyObject) override final { m_requestHelper->requestReply(replyObject); }
|
||||
void onStructureElementModifyReply(const Core::FunctionReplyObject &replyObject) override final { m_requestHelper->requestReply(replyObject); }
|
||||
void selectRoomRow(int mountingPointId);
|
||||
|
||||
signals:
|
||||
void signalAccept();
|
||||
|
||||
private slots:
|
||||
void slotEditItem();
|
||||
void slotDoubleClicked(const QModelIndex &selIndex);
|
||||
void slotMainStructureElementChanged(const InfrastructureManagement::MainStructureElement &mse, DataModification modType);
|
||||
void slotBuildingStateChanged(const Buildings::BuildingState &state, DataModification modType);
|
||||
void slotHandleExternalDdsChange();
|
||||
void slotTreeViewClicked();
|
||||
|
||||
bool sendBuildingStateRequest(ProjectDataManagement::VulnerabilityState state, std::vector<int32_t> structureElementId);
|
||||
void onDestroyElement();
|
||||
|
||||
protected:
|
||||
void retranslate() override;
|
||||
bool apply() override;
|
||||
|
||||
private:
|
||||
void getStructureElementIds(NGLTreeItem *item, std::vector<int32_t> &structureElementIds);
|
||||
void buildModel();
|
||||
QModelIndex selectedIndexView() const;
|
||||
void reinitModel();
|
||||
|
||||
private:
|
||||
std::shared_ptr<InfrastructureManagement::Interface::Dtc> m_ismDtc;
|
||||
std::shared_ptr<InfrastructureManagement::Interface::Ftc> m_ismFtc;
|
||||
std::shared_ptr<Buildings::Interface::Dtc> m_bldDtc;
|
||||
std::shared_ptr<Buildings::Interface::Ftc> m_bldFtc;
|
||||
|
||||
BuildingEditModel *m_model = nullptr;
|
||||
BuildingEditProxyModel *m_proxyModel = nullptr;
|
||||
LtsUtils::RequestHelper *m_requestHelper = nullptr;
|
||||
Ui::BuildingEdit *m_ui = nullptr;
|
||||
|
||||
QString m_buildingName;
|
||||
int32_t m_buildingDatabaseId = 0;
|
||||
int32_t m_buildingId = 0;
|
||||
NGL::INGLLogger &m_logger;
|
||||
};
|
||||
|
||||
} //ParticipantManagement
|
||||
+40
@@ -0,0 +1,40 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>BuildingEdit</class>
|
||||
<widget class="QWidget" name="BuildingEdit">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>279</width>
|
||||
<height>246</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="MinimumExpanding" vsizetype="MinimumExpanding">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string notr="true">setwindowtitle in source</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout">
|
||||
<item row="1" column="0" colspan="2">
|
||||
<widget class="QTreeView" name="treeViewEdit">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="MinimumExpanding" vsizetype="MinimumExpanding">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<attribute name="headerShowSortIndicator" stdset="0">
|
||||
<bool>false</bool>
|
||||
</attribute>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
||||
+86
@@ -0,0 +1,86 @@
|
||||
/**
|
||||
* @RDE_HEADER@
|
||||
* $Id$
|
||||
* $HeadURL$
|
||||
* $Author$
|
||||
* Created by Philipp Last, SLSE, 2017-09-18
|
||||
*/
|
||||
|
||||
#include "bdv_edit_item.h"
|
||||
#include "ui_bdv_edit_item.h"
|
||||
|
||||
namespace BuildingViewer
|
||||
{
|
||||
ParticipantEditItemWidget::ParticipantEditItemWidget(const QString &buildingName,
|
||||
const BuildingViewer::TreeItem &itemValue,
|
||||
QWidget *parent)
|
||||
: LtsWidgets::LtsFramelessDialog(parent, LtsWidgets::Behaviour::Modal)
|
||||
, m_itemValue(itemValue)
|
||||
, m_ui(new Ui::BuildingEditItemWidget)
|
||||
, m_buttonBox(new LtsWidgets::LtsDialogButtonBox(this))
|
||||
{
|
||||
m_ui->setupUi(this);
|
||||
|
||||
m_ui->leBuildingDescription->setText(buildingName);
|
||||
m_ui->leRoomDesription->setText(m_itemValue.displayName());
|
||||
m_ui->sbFortifyFactor->setValue(m_itemValue.fortifyFactor());
|
||||
|
||||
layout()->addWidget(m_buttonBox);
|
||||
connect(m_buttonBox->getButton(LtsWidgets::DialogButton::Apply), &QPushButton::clicked, this, &ParticipantEditItemWidget::slotApply);
|
||||
connect(m_buttonBox->getButton(LtsWidgets::DialogButton::Close), &QPushButton::clicked, this, &ParticipantEditItemWidget::accept);
|
||||
|
||||
if ( itemValue.isBuilding() )
|
||||
{
|
||||
m_ui->lbBuildingName->hide();
|
||||
m_ui->leBuildingDescription->hide();
|
||||
m_ui->lbRoomDesription->setText(tr("Building Name:"));
|
||||
m_ui->sbFortifyFactor->setValue(1.0);
|
||||
}
|
||||
else if ( itemValue.isFloor() )
|
||||
{
|
||||
m_ui->lbRoomDesription->setText(tr("Floor:"));
|
||||
m_ui->sbFortifyFactor->setValue(1.0);
|
||||
}
|
||||
|
||||
//hide ok and apply
|
||||
m_buttonBox->getButton(LtsWidgets::DialogButton::Apply)->show();
|
||||
m_buttonBox->getButton(LtsWidgets::DialogButton::Apply)->setEnabled(false);
|
||||
m_buttonBox->getButton(LtsWidgets::DialogButton::Ok)->hide();
|
||||
connect(m_ui->leRoomDesription, &QLineEdit::textChanged, this, [this]()
|
||||
{
|
||||
m_buttonBox->getButton(LtsWidgets::DialogButton::Apply)->setEnabled(true);
|
||||
});
|
||||
connect(m_ui->sbFortifyFactor, QOverload<double>::of(&QDoubleSpinBox::valueChanged), this, [this]()
|
||||
{
|
||||
m_fortifyFactorChanged = true;
|
||||
m_buttonBox->getButton(LtsWidgets::DialogButton::Apply)->setEnabled(true);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
ParticipantEditItemWidget::~ParticipantEditItemWidget()
|
||||
{
|
||||
delete m_ui;
|
||||
}
|
||||
|
||||
void ParticipantEditItemWidget::slotApply()
|
||||
{
|
||||
if (m_ui->leRoomDesription->text().isEmpty())
|
||||
{
|
||||
LtsWidgets::LtsMessageDialog::showMessage(this, tr("Enter at least one character"));
|
||||
return;
|
||||
}
|
||||
|
||||
m_itemValue.setDisplayName(m_ui->leRoomDesription->text());
|
||||
|
||||
if (m_itemValue.isRoom() || !m_itemValue.hasDisplayNameChanged() || m_fortifyFactorChanged)
|
||||
m_itemValue.setFortifyFactor(m_ui->sbFortifyFactor->value());
|
||||
|
||||
if (m_itemValue.hasDisplayNameChanged() || m_itemValue.hasFortifyFactorChanged())
|
||||
emit signalItemUpdated(m_itemValue, m_fortifyFactorChanged);
|
||||
|
||||
accept();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
/**
|
||||
* @RDE_HEADER@
|
||||
* $Id$
|
||||
* $HeadURL$
|
||||
* $Author$
|
||||
* Created by Philipp Last, SLSE, 2017-09-18
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
|
||||
#include "bdv_treemodel_item.h"
|
||||
|
||||
#include <LtsWidgets/lts_frameless_dialog.h>
|
||||
#include <LtsWidgets/lts_dialog_button_box.h>
|
||||
|
||||
namespace Ui
|
||||
{
|
||||
class BuildingEditItemWidget;
|
||||
}
|
||||
namespace BuildingViewer
|
||||
{
|
||||
|
||||
class ParticipantEditItemWidget : public LtsWidgets::LtsFramelessDialog
|
||||
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit ParticipantEditItemWidget(const QString &buildingName,
|
||||
const TreeItem &itemValue,
|
||||
QWidget *parent = nullptr);
|
||||
~ParticipantEditItemWidget();
|
||||
|
||||
signals:
|
||||
void signalItemUpdated(const TreeItem &editData, const bool fortifyChanged);
|
||||
|
||||
private slots:
|
||||
void slotApply();
|
||||
|
||||
private:
|
||||
bool m_fortifyFactorChanged = false;
|
||||
TreeItem m_itemValue;
|
||||
Ui::BuildingEditItemWidget *m_ui;
|
||||
LtsWidgets::LtsDialogButtonBox *m_buttonBox;
|
||||
};
|
||||
}
|
||||
+132
@@ -0,0 +1,132 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>BuildingEditItemWidget</class>
|
||||
<widget class="QWidget" name="BuildingEditItemWidget">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>350</width>
|
||||
<height>109</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>350</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string notr="true"/>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<layout class="QGridLayout" name="gridLayout">
|
||||
<property name="sizeConstraint">
|
||||
<enum>QLayout::SetDefaultConstraint</enum>
|
||||
</property>
|
||||
<item row="2" column="1">
|
||||
<widget class="QDoubleSpinBox" name="sbFortifyFactor">
|
||||
<property name="toolTip">
|
||||
<string>Specify a value between 0 and 8</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
<property name="decimals">
|
||||
<number>1</number>
|
||||
</property>
|
||||
<property name="minimum">
|
||||
<double>0.100000000000000</double>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<double>8.000000000000000</double>
|
||||
</property>
|
||||
<property name="singleStep">
|
||||
<double>0.100000000000000</double>
|
||||
</property>
|
||||
<property name="value">
|
||||
<double>1.230000000000000</double>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="lbFortifyFactor">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Fixed" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Fortify Factor:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QLabel" name="leBuildingDescription">
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QLineEdit" name="leRoomDesription">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="maxLength">
|
||||
<number>40</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="lbBuildingName">
|
||||
<property name="text">
|
||||
<string>Building Name:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="lbRoomDesription">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Fixed" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Room Name:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="verticalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeType">
|
||||
<enum>QSizePolicy::MinimumExpanding</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>17</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<tabstops>
|
||||
<tabstop>leRoomDesription</tabstop>
|
||||
<tabstop>sbFortifyFactor</tabstop>
|
||||
</tabstops>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
||||
+315
@@ -0,0 +1,315 @@
|
||||
/**
|
||||
* @RDE_HEADER@
|
||||
* Created by Philipp Last, SLSE, 2017-09-18
|
||||
*/
|
||||
|
||||
#include "bdv_edit_model.h"
|
||||
#include <Common/logger.h>
|
||||
#include <Services/InfrastructureManagement/ism.hpp>
|
||||
#include <QtCore/QDebug>
|
||||
#include <QTableWidget>
|
||||
#include <QPalette>
|
||||
#include <QApplication>
|
||||
|
||||
#include <nglwidgets/ngltreeitem.h>
|
||||
|
||||
namespace BuildingViewer
|
||||
{
|
||||
BuildingEditModel::BuildingEditModel(QObject *parent,
|
||||
const std::shared_ptr<InfrastructureManagement::Interface::Dtc> &ismDtc,
|
||||
const std::shared_ptr<Buildings::Interface::Dtc> &bldDtc)
|
||||
: NGLTreeModel(parent, new NGLTreeItem(QVariant()), {
|
||||
tr("Selected Building"),
|
||||
QStringLiteral("Name (DEBUG)"),
|
||||
QStringLiteral("MountingPointId (DEBUG)"),
|
||||
QStringLiteral("StructureElementId (DEBUG)"),
|
||||
tr("Fortify Factor"),
|
||||
tr("Damage Percent")})
|
||||
, m_ismDtc(ismDtc)
|
||||
, m_bldDtc(bldDtc)
|
||||
, m_buildingName(QString())
|
||||
, m_logger(getLogger("BuildingViewer::BuildingEdit"))
|
||||
{}
|
||||
|
||||
QVariant BuildingEditModel::data(const QModelIndex &index, int role) const
|
||||
{
|
||||
if (!index.isValid() || (role != Qt::BackgroundRole && role != Qt::DisplayRole))
|
||||
return {};
|
||||
|
||||
|
||||
NGLTreeItem *pNGLTreeItem = privateData(index);
|
||||
|
||||
if (pNGLTreeItem->data().canConvert<BuildingViewer::TreeItem>())
|
||||
{
|
||||
BuildingViewer::TreeItem item = pNGLTreeItem->data().value<BuildingViewer::TreeItem>();
|
||||
|
||||
if (role == Qt::BackgroundRole)
|
||||
{
|
||||
if (item.hasDisplayNameChanged() || item.hasFortifyFactorChanged())
|
||||
return QGuiApplication::palette().color(QPalette::Highlight);
|
||||
}
|
||||
else if (role == Qt::DisplayRole)
|
||||
{
|
||||
switch (index.column())
|
||||
{
|
||||
case BuildingEditModel::Building: // Column "Building" also includes Floors and Rooms
|
||||
return item.displayName();
|
||||
case BuildingEditModel::Name:
|
||||
return item.name();
|
||||
case BuildingEditModel::MountingPointId:
|
||||
if (item.hasMountingPointId())
|
||||
return item.mountingPointId();
|
||||
break;
|
||||
case BuildingEditModel::StructureElementId:
|
||||
return item.structureElementId();
|
||||
case BuildingEditModel::FortifyFactor:
|
||||
if (item.isRoom())
|
||||
return QString::number(item.fortifyFactor(),'f',1);
|
||||
break;
|
||||
case BuildingEditModel::DamagePercent:
|
||||
if (item.isRoom())
|
||||
return QString::number(item.damagePercent());
|
||||
}
|
||||
}
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
||||
|
||||
bool BuildingEditModel::slotUpdateRow(const BuildingViewer::TreeItem &room, const bool fortifyChanged)
|
||||
{
|
||||
DEBUG_LOG(m_logger) << "slotUpdateRow isBuilding=" << room.isBuilding()
|
||||
<< " isFloor" << room.isFloor()
|
||||
<< " isRoom" << room.isRoom();
|
||||
|
||||
|
||||
QModelIndex idx = modelIndexByStructureElementId(room.structureElementId());
|
||||
|
||||
if (fortifyChanged && ( !room.isRoom() || !qFuzzyIsNull(room.fortifyFactor())))
|
||||
{
|
||||
for (auto *item : privateData(idx)->children())
|
||||
{
|
||||
TreeItem childItem = item->data().value<TreeItem>();
|
||||
childItem.setFortifyFactor(room.fortifyFactor());
|
||||
slotUpdateRow(childItem, fortifyChanged);
|
||||
}
|
||||
}
|
||||
|
||||
if (room.hasDisplayNameChanged())
|
||||
m_mapRoomsWithChangedDisplayName[room.structureElementId()] = room;
|
||||
if (fortifyChanged && (room.isRoom() && room.hasFortifyFactorChanged()))
|
||||
m_mapRoomsWithChangedFortifyFactor[room.structureElementId()] = room;
|
||||
|
||||
QVariant data;
|
||||
data.setValue(room);
|
||||
|
||||
emit signalModelDataChanged();
|
||||
return setItemData(idx, data, QIcon());
|
||||
}
|
||||
|
||||
|
||||
bool BuildingEditModel::onInsertRow(int &row, const QModelIndex &parent, const BuildingViewer::TreeItem &folderData)
|
||||
{
|
||||
row = rowCount(parent);
|
||||
QVariant data;
|
||||
data.setValue(folderData);
|
||||
NGLTreeItem *item = new NGLTreeItem(data, QIcon());
|
||||
item->setModified(true);
|
||||
|
||||
emit signalModelDataChanged();
|
||||
|
||||
return NGLTreeModel::insertRow(row, parent, item);
|
||||
}
|
||||
|
||||
|
||||
bool BuildingEditModel::init(int32_t mseId)
|
||||
{
|
||||
INFO_LOG(m_logger) << "init mseId=" << mseId;
|
||||
NGLTreeModel::resetModel();
|
||||
m_mapRoomsWithChangedFortifyFactor.clear();
|
||||
|
||||
QMap<qint32, BuildingViewer::TreeItem> treemap;
|
||||
QMap<qint32, qint32> lookupFloorId2TreeId;
|
||||
QString rootName;
|
||||
|
||||
/*
|
||||
* Get Fortify Factors for current Building.
|
||||
* Important: Only the modified rooms (BuildingStates) are returned. E.g.,
|
||||
* if a building has 12 rooms and the fortify factor of 4 rooms have been changed in the past
|
||||
* 'm_mapRoomIdFortifyFactors' will only contain the ids auf these 4 rooms
|
||||
*/
|
||||
|
||||
// Retreive tree model data
|
||||
InfrastructureManagement::MainStructureElement building = m_ismDtc->mainStructureElement(mseId);
|
||||
int rootId = 0;
|
||||
qint32 mapId = 0;
|
||||
|
||||
const std::vector<InfrastructureManagement::StructureElement> &vecElements = building.elements();
|
||||
for (const auto &se : vecElements)
|
||||
{
|
||||
DEBUG_LOG(m_logger) << "se: " << se;
|
||||
if (se.structureElementTypeId() == InfrastructureManagement::StructureElementType::Building)
|
||||
{
|
||||
BuildingViewer::TreeItem rootItemBuilding(se);
|
||||
rootName =rootItemBuilding.name();
|
||||
m_buildingName = rootItemBuilding.displayName();
|
||||
mapId = rootId;
|
||||
treemap[mapId++] = rootItemBuilding;
|
||||
}
|
||||
}
|
||||
|
||||
//qint32 mapId = rootId;
|
||||
//BuildingViewer::TreeItem rootItemBuilding(building);
|
||||
//treemap[mapId++] = rootItemBuilding;
|
||||
|
||||
/*
|
||||
* The MainStructureElement, in our case the building, contains a vector which includes (among other things)
|
||||
* all floors and rooms belonging to this building. This vector may not be ordered. Hence, we first extract all
|
||||
* floors.
|
||||
*
|
||||
* Afterwards the same vector is iterated to identify all room. The map 'lookupFloorId2TreeId' is used to identify the
|
||||
* tree parent node (= Floor) of an identified room.
|
||||
*/
|
||||
// Identify building floors
|
||||
//const std::vector<InfrastructureManagement::StructureElement> &vecElements = building.elements();
|
||||
|
||||
for (const auto &se : vecElements)
|
||||
{
|
||||
DEBUG_LOG(m_logger) << "se: =" << se;
|
||||
if (se.structureElementTypeId() == InfrastructureManagement::StructureElementType_def::Floor)
|
||||
{
|
||||
BuildingViewer::TreeItem itemRoom(se);
|
||||
itemRoom.setSuperior(rootId);
|
||||
|
||||
lookupFloorId2TreeId[se.id()] = mapId;
|
||||
treemap[mapId++] = itemRoom;
|
||||
}
|
||||
}
|
||||
|
||||
m_bldDtc->enableBuildingState();
|
||||
m_bldDtc->waitForHistoricalDataBuildingState(1000);
|
||||
|
||||
auto bs = m_bldDtc->buildingState(mseId);
|
||||
|
||||
QMap<int32_t, Buildings::RoomState> roomStates;
|
||||
for (const auto &e : bs.roomStates())
|
||||
roomStates[e.id()] = e;
|
||||
|
||||
// Identify building rooms and assign them to the correct floors by using map 'lookupFloorId2TreeId'
|
||||
for (const auto &se : vecElements)
|
||||
{
|
||||
if (se.structureElementTypeId() == InfrastructureManagement::StructureElementType_def::Room)
|
||||
{
|
||||
// Default value if the fortify factor has not been changed so far (-> no entry in 'm_mapRoomIdFortifyFactors')
|
||||
double fortifyFactor = 1.0;
|
||||
qint32 damagePercent = bs.damagePercent();
|
||||
if (roomStates.contains(se.id()))
|
||||
{
|
||||
fortifyFactor = roomStates[se.id()].fortifyFactor();
|
||||
damagePercent = roomStates[se.id()].damagePercent();
|
||||
}
|
||||
|
||||
BuildingViewer::TreeItem itemRoom(se, fortifyFactor, damagePercent);
|
||||
|
||||
try
|
||||
{
|
||||
/*
|
||||
* A room belongs to a floor which belongs to a building. Hence, se.path().size() must contain
|
||||
* at least three elements:
|
||||
*
|
||||
* building id | floor id | room id
|
||||
*
|
||||
* Therefore it MUST be possible to directly access the floor id located at index 1.
|
||||
*/
|
||||
int32_t floorID = se.path()[1]; // Throws 'std::out_of_range' if 1 is out of bounds
|
||||
itemRoom.setSuperior(lookupFloorId2TreeId[floorID]);
|
||||
}
|
||||
catch (const std::out_of_range &e)
|
||||
{
|
||||
WARNING_LOG(m_logger) << "Caught exception while trying to get superior id for building " << rootName << " with room with mounting point id: " << se.mountingPointId() << ": " << e.what();
|
||||
return false;
|
||||
}
|
||||
|
||||
treemap[mapId++] = itemRoom;
|
||||
}
|
||||
}
|
||||
|
||||
// Finally, build Tree
|
||||
QHash<int, QPersistentModelIndex> parentItemIndexCache;
|
||||
parentItemIndexCache.insert(rootId, QModelIndex());
|
||||
|
||||
for (auto iter = treemap.constBegin(); iter != treemap.constEnd(); ++iter)
|
||||
{
|
||||
int itemDatabaseId = iter.key();
|
||||
const BuildingViewer::TreeItem &item = iter.value();
|
||||
|
||||
QVariant data;
|
||||
data.setValue(item);
|
||||
|
||||
int parentId = item.hasSuperior() ? item.getSuperior() : rootId;
|
||||
if (!parentItemIndexCache.contains(parentId))
|
||||
{
|
||||
ERROR_LOG(m_logger) << "Invalid building structure! Tree can not be built!";
|
||||
return false;
|
||||
}
|
||||
|
||||
QModelIndex pIndex = parentItemIndexCache.value(parentId);
|
||||
int rowPos = -1;
|
||||
|
||||
onInsertRow(rowPos, pIndex, item);
|
||||
|
||||
QPersistentModelIndex mIndex = index(rowPos, 0, pIndex);
|
||||
m_mapModelIndices[item.structureElementId()] = mIndex;
|
||||
parentItemIndexCache.insert(itemDatabaseId, mIndex);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
QModelIndex BuildingEditModel::modelIndexByMountingPointId(int mountingPointId) const
|
||||
{
|
||||
for(const QPersistentModelIndex &mi : qAsConst(m_mapModelIndices))
|
||||
{
|
||||
if (privateData(mi)->data().value<TreeItem>().mountingPointId() == mountingPointId)
|
||||
return mi;
|
||||
}
|
||||
WARNING_LOG(m_logger)<<"Could not find modelindex for given room mountig point id: " << mountingPointId;
|
||||
return {};
|
||||
}
|
||||
|
||||
|
||||
QModelIndex BuildingEditModel::modelIndexByStructureElementId(int structureElementId) const
|
||||
{
|
||||
auto it = m_mapModelIndices.find(structureElementId);
|
||||
if (it == m_mapModelIndices.end())
|
||||
{
|
||||
WARNING_LOG(m_logger)<<"Could not find modelindex for given room structreElementId: " << structureElementId;
|
||||
return {};
|
||||
}
|
||||
return it.value();
|
||||
}
|
||||
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
void BuildingEditProxyModel::setSourceModel(QAbstractItemModel *sourceModel)
|
||||
{
|
||||
m_sourceModel = qobject_cast<BuildingEditModel*>(sourceModel);
|
||||
QSortFilterProxyModel::setSourceModel(m_sourceModel);
|
||||
}
|
||||
|
||||
bool BuildingEditProxyModel::lessThan(const QModelIndex &left, const QModelIndex &right) const
|
||||
{
|
||||
if (!m_sourceModel ||
|
||||
left.column() != 0 || right.column() != 0)
|
||||
return QSortFilterProxyModel::lessThan(left, right);
|
||||
|
||||
NGLTreeItem *itemLeft = m_sourceModel->privateData(left);
|
||||
NGLTreeItem *itemRight = m_sourceModel->privateData(right);
|
||||
if (itemLeft && itemRight)
|
||||
return (itemLeft->row() < itemRight->row());
|
||||
|
||||
return QSortFilterProxyModel::lessThan(left, right);
|
||||
}
|
||||
|
||||
|
||||
} //namespace BuildingViewer
|
||||
+92
@@ -0,0 +1,92 @@
|
||||
/**
|
||||
* @RDE_HEADER@
|
||||
* $Id$
|
||||
* $HeadURL$
|
||||
* $Author$
|
||||
* Created by Philipp Last, SLSE, 2017-09-18
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include <Common/logger.h>
|
||||
|
||||
#include <Plugins/Buildings/bld_data_plugin_interface.h>
|
||||
#include <Plugins/InfrastructureManagement/ism_data_plugin_interface.h>
|
||||
|
||||
#include "bdv_treemodel_item.h"
|
||||
|
||||
#include <QMap>
|
||||
#include <QSortFilterProxyModel>
|
||||
#include <functional>
|
||||
#include <nglwidgets/ngltreemodel.h>
|
||||
|
||||
namespace BuildingViewer
|
||||
{
|
||||
class BuildingEditModel : public NGLTreeModel
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
enum Columns
|
||||
{
|
||||
Building,
|
||||
Name,
|
||||
MountingPointId,
|
||||
StructureElementId,
|
||||
FortifyFactor,
|
||||
DamagePercent,
|
||||
ColumnCount,
|
||||
};
|
||||
|
||||
BuildingEditModel(QObject *parent,
|
||||
const std::shared_ptr<InfrastructureManagement::Interface::Dtc> &ismDtc,
|
||||
const std::shared_ptr<Buildings::Interface::Dtc> &bldDtc);
|
||||
|
||||
QList<BuildingViewer::TreeItem> getRoomsWithChangedFortifyFactors() const { return m_mapRoomsWithChangedFortifyFactor.values(); }
|
||||
QList<BuildingViewer::TreeItem> getRoomsWithChangedDisplayNames() const { return m_mapRoomsWithChangedDisplayName.values(); }
|
||||
|
||||
bool init(int32_t buildingDatabaseId);
|
||||
QModelIndex modelIndexByMountingPointId(int mountingPointId) const;
|
||||
QModelIndex modelIndexByStructureElementId(int structureElementId) const;
|
||||
QString getBuildingName() const {return m_buildingName;}
|
||||
|
||||
public slots:
|
||||
bool slotUpdateRow(const BuildingViewer::TreeItem &room, const bool fortifyChanged);
|
||||
|
||||
signals:
|
||||
void signalModelDataChanged(); // Causes the BuildingEdit apply button to get active
|
||||
|
||||
private:
|
||||
QVariant data(const QModelIndex &index, int role) const override final;
|
||||
bool onInsertRow(int &row, const QModelIndex &parent, const BuildingViewer::TreeItem &folderData);
|
||||
|
||||
QMap<int, QPersistentModelIndex> m_mapModelIndices; // room structureElementIds to tree QModelIndex
|
||||
|
||||
// SE-id to room
|
||||
QMap<int32_t, BuildingViewer::TreeItem> m_mapRoomsWithChangedFortifyFactor;
|
||||
QMap<int32_t, BuildingViewer::TreeItem> m_mapRoomsWithChangedDisplayName;
|
||||
|
||||
std::shared_ptr<InfrastructureManagement::Interface::Dtc> m_ismDtc;
|
||||
std::shared_ptr<Buildings::Interface::Dtc> m_bldDtc;
|
||||
|
||||
QString m_buildingName;
|
||||
|
||||
NGL::INGLLogger &m_logger;
|
||||
};
|
||||
|
||||
|
||||
|
||||
class BuildingEditProxyModel final : public QSortFilterProxyModel
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
using QSortFilterProxyModel::QSortFilterProxyModel;
|
||||
|
||||
void setSourceModel(QAbstractItemModel *sourceModel) override;
|
||||
bool lessThan(const QModelIndex &left, const QModelIndex &right) const override;
|
||||
private:
|
||||
BuildingEditModel *m_sourceModel = nullptr;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
Q_DECLARE_METATYPE(BuildingViewer::TreeItem)
|
||||
|
||||
+184
@@ -0,0 +1,184 @@
|
||||
/**
|
||||
* @RDE_HEADER@
|
||||
* $Id$
|
||||
* $HeadURL$
|
||||
* $Author$
|
||||
* Created by Philipp Last, SLSE, 2017-09-18
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include <QString>
|
||||
#include <Services/InfrastructureManagement/ism.hpp>
|
||||
|
||||
namespace BuildingViewer
|
||||
{
|
||||
class TreeItem
|
||||
{
|
||||
public:
|
||||
TreeItem() = default;
|
||||
|
||||
// For Buildings
|
||||
explicit TreeItem(const InfrastructureManagement::MainStructureElement &mse)
|
||||
: m_displayName(toQString(mse.name()))
|
||||
, m_structureElementId(mse.id())
|
||||
, m_name(toQString(mse.name()) + QStringLiteral(" (ModelId: ") + QString::number(mse.modelId()) + QStringLiteral(")"))
|
||||
{}
|
||||
|
||||
// For Floors
|
||||
explicit TreeItem(const InfrastructureManagement::StructureElement &se)
|
||||
: m_displayName(toQString(se.displayName()))
|
||||
, m_isFloor(true)
|
||||
, m_structureElementId(se.id())
|
||||
, m_mountingPointId(se.mountingPointId())
|
||||
, m_name(toQString(se.name()))
|
||||
{}
|
||||
|
||||
// For Rooms
|
||||
explicit TreeItem(const InfrastructureManagement::StructureElement &se
|
||||
, double fortifyFactor
|
||||
, qint32 damagePercent)
|
||||
: m_displayName(toQString(se.displayName()))
|
||||
, m_fortifyFactor(fortifyFactor)
|
||||
, m_damagePercent(damagePercent)
|
||||
, m_isRoom(true)
|
||||
, m_structureElementId(se.id())
|
||||
, m_mountingPointId(se.mountingPointId())
|
||||
, m_name(toQString(se.name()))
|
||||
{}
|
||||
|
||||
int32_t structureElementId() const
|
||||
{
|
||||
return m_structureElementId;
|
||||
}
|
||||
|
||||
|
||||
bool hasSuperior() const
|
||||
{
|
||||
return m_hasSuperior;
|
||||
}
|
||||
|
||||
qint32 getSuperior() const
|
||||
{
|
||||
return m_superior;
|
||||
}
|
||||
|
||||
void setSuperior(int id)
|
||||
{
|
||||
m_hasSuperior = true;
|
||||
m_superior = id;
|
||||
}
|
||||
|
||||
bool hasMountingPointId() const
|
||||
{
|
||||
// The MainStructureElement has no mounting point id information
|
||||
return !isBuilding();
|
||||
}
|
||||
|
||||
bool isBuilding() const
|
||||
{
|
||||
return !m_hasSuperior;
|
||||
}
|
||||
|
||||
bool isFloor() const
|
||||
{
|
||||
return m_isFloor;
|
||||
}
|
||||
|
||||
bool isRoom() const
|
||||
{
|
||||
return m_isRoom;
|
||||
}
|
||||
|
||||
|
||||
|
||||
const QString &name() const
|
||||
{
|
||||
return m_name;
|
||||
}
|
||||
|
||||
|
||||
void setStructureElementId(const int32_t structureElementId)
|
||||
{
|
||||
m_structureElementId = structureElementId;
|
||||
}
|
||||
|
||||
qint32 mountingPointId() const
|
||||
{
|
||||
return m_mountingPointId;
|
||||
}
|
||||
|
||||
void setDisplayName(const QString &strDisplayName)
|
||||
{
|
||||
m_displayNameChanged = m_displayNameChanged || (strDisplayName != m_displayName);
|
||||
m_displayName = strDisplayName;
|
||||
}
|
||||
|
||||
const QString &displayName() const
|
||||
{
|
||||
return m_displayName;
|
||||
}
|
||||
|
||||
bool hasDisplayNameChanged() const
|
||||
{
|
||||
return m_displayNameChanged;
|
||||
}
|
||||
|
||||
void setFortifyFactor(double fortifyFactor)
|
||||
{
|
||||
m_fortifyFactorChanged = m_fortifyFactorChanged || !qFuzzyCompare(fortifyFactor, m_fortifyFactor);
|
||||
m_fortifyFactor = fortifyFactor;
|
||||
}
|
||||
|
||||
double fortifyFactor() const
|
||||
{
|
||||
return m_fortifyFactor;
|
||||
}
|
||||
|
||||
bool hasFortifyFactorChanged() const
|
||||
{
|
||||
return m_fortifyFactorChanged;
|
||||
}
|
||||
|
||||
void setDamagePercent(qint32 damagePercent)
|
||||
{
|
||||
m_damagePercentChanged = m_damagePercentChanged || (damagePercent != m_damagePercent);
|
||||
m_damagePercent = damagePercent;
|
||||
}
|
||||
|
||||
qint32 damagePercent() const
|
||||
{
|
||||
return m_damagePercent;
|
||||
}
|
||||
|
||||
bool hasDamagePercentChanged() const
|
||||
{
|
||||
return m_damagePercentChanged;
|
||||
}
|
||||
|
||||
private:
|
||||
static QString toQString(const std::string &strDds)
|
||||
{
|
||||
return QString::fromStdString(strDds);
|
||||
}
|
||||
|
||||
// DisplayName and FortifyFactor are different Dds Function Topic calls. Let's save some bandwidth
|
||||
QString m_displayName;
|
||||
double m_fortifyFactor = 0.0;
|
||||
qint32 m_damagePercent = 0;
|
||||
|
||||
bool m_displayNameChanged = false;
|
||||
bool m_fortifyFactorChanged = false;
|
||||
bool m_damagePercentChanged = false;
|
||||
|
||||
bool m_hasSuperior = false;
|
||||
qint32 m_superior = 0;
|
||||
|
||||
bool m_isFloor = false;
|
||||
bool m_isRoom = false;
|
||||
|
||||
int32_t m_structureElementId = 0;
|
||||
|
||||
qint32 m_mountingPointId = 0;
|
||||
QString m_name;
|
||||
};
|
||||
} // BuildingViewer
|
||||
@@ -0,0 +1,80 @@
|
||||
#
|
||||
# $Id$
|
||||
# $HeadURL$
|
||||
# $Author$
|
||||
#
|
||||
# Created by Mike Wille, SLSE, 2017-05-15
|
||||
#
|
||||
|
||||
SET(SRCS
|
||||
BuildingEdit/bdv_building_edit.cpp
|
||||
BuildingEdit/bdv_building_edit.h
|
||||
BuildingEdit/bdv_edit_item.cpp
|
||||
BuildingEdit/bdv_edit_item.h
|
||||
BuildingEdit/bdv_edit_model.cpp
|
||||
BuildingEdit/bdv_edit_model.h
|
||||
BuildingEdit/bdv_treemodel_item.h
|
||||
bdv_viewer_gui_plugin.h
|
||||
bdv_viewer_gui_plugin.cpp
|
||||
bdv_viewer_gui_plugin_provider.h
|
||||
bdv_viewer_gui_plugin_provider.cpp
|
||||
bdv_viewer_data_dialog.cpp
|
||||
bdv_viewer_data_dialog.h
|
||||
bdv_viewer_data_model.cpp
|
||||
bdv_viewer_data_model.h
|
||||
bdv_viewer_data_view.cpp
|
||||
bdv_viewer_data_view.h
|
||||
bdv_replay_handler.cpp
|
||||
bdv_replay_handler.h
|
||||
bdv_thread_video_exporter.cpp
|
||||
bdv_thread_video_exporter.h
|
||||
bdv_topic_replay_interface.cpp
|
||||
bdv_topic_replay_interface.h
|
||||
bdv_viewer_settings.cpp
|
||||
bdv_viewer_settings.h
|
||||
bdv_viewer_state_model.cpp
|
||||
bdv_viewer_state_model.h
|
||||
bdv_viewer_state.cpp
|
||||
bdv_viewer_state.h
|
||||
TopicEditor/topic_editor.cpp
|
||||
TopicEditor/topic_editor.h
|
||||
)
|
||||
|
||||
NGL_WRAP_UI(SRCS
|
||||
BuildingEdit/bdv_building_edit.ui
|
||||
BuildingEdit/bdv_edit_item.ui
|
||||
bdv_viewer_data_dialog.ui
|
||||
bdv_viewer_data_view.ui
|
||||
bdv_viewer_settings.ui
|
||||
bdv_viewer_state.ui
|
||||
TopicEditor/topic_editor.ui
|
||||
)
|
||||
|
||||
NGL_ADD_LIBRARY(WS BdvViewerGuiPlugin MODULE ${SRCS})
|
||||
|
||||
NGL_TARGET_LINK_LIBRARIES(BdvViewerGuiPlugin
|
||||
BdvViewerGuiPluginInterface
|
||||
BldDataPluginInterface
|
||||
BuildingViewerCommon
|
||||
PreScriptTimelineGuiPluginInterface # Export
|
||||
svcBldCommon
|
||||
svcBldClient
|
||||
svcAesClient
|
||||
svcSrpClient
|
||||
LtsDataView
|
||||
LtsPluginManager
|
||||
LtsScriptTimeline # TopicEditor
|
||||
LtsSession
|
||||
LtsWidgets
|
||||
NGLLogger
|
||||
nglwidgets
|
||||
Qt5::Core
|
||||
Qt5::Widgets
|
||||
Qt5::Xml
|
||||
TopicEditorBase
|
||||
LtsUtilsGuiDds
|
||||
LtsUtilsSettings
|
||||
ngltools
|
||||
ExportBdvTopicSetting
|
||||
)
|
||||
NGL_INSTALL_TARGET(BdvViewerGuiPlugin)
|
||||
+156
@@ -0,0 +1,156 @@
|
||||
/**
|
||||
* @RDE_HEADER@
|
||||
* $Id$
|
||||
* $HeadURL$
|
||||
* $Author$
|
||||
*
|
||||
* Created by Philipp Last, SLSY, 2017-07-04
|
||||
*/
|
||||
|
||||
#include "topic_editor.h"
|
||||
#include "ui_topic_editor.h"
|
||||
|
||||
#include <Common/bdv_controller.h>
|
||||
#include <LtsWidgets/lts_base_layout_widget.h>
|
||||
#include <LtsAppManager/lts_app_manager.h>
|
||||
#include <LtsPluginManager/lts_plugin_manager.h>
|
||||
#include <QDebug>
|
||||
|
||||
|
||||
namespace BuildingViewer
|
||||
{
|
||||
|
||||
TopicEditor::TopicEditor(LtsSession::LtsSession *session, BgViewerController *bgViewerController, BgViewerDataView *bgViewerDataView, QWidget *parent)
|
||||
: TopicEditorBase::TopicEditor(parent)
|
||||
, m_bgViewerController(bgViewerController)
|
||||
, m_bgViewerDataView(bgViewerDataView)
|
||||
, m_session(session)
|
||||
, m_ui(new Ui::BuildingViewerTopicEditor)
|
||||
{
|
||||
m_ui->setupUi(this);
|
||||
init(m_ui->widget);
|
||||
|
||||
connect(m_bgViewerDataView, &BgViewerDataView::signalUserActionPerformend,
|
||||
this, &TopicEditor::slotChangesMade);
|
||||
|
||||
m_ui->verticalLayout->addWidget(m_bgViewerDataView);
|
||||
m_bgViewerController->closeBuilding();
|
||||
setOnlineHelpFilename(QStringLiteral("Script_Editor-Add_Building_Topic"));
|
||||
}
|
||||
|
||||
TopicEditor::~TopicEditor()
|
||||
{
|
||||
delete m_ui;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// PRIVATE
|
||||
|
||||
void TopicEditor::updateInternalData()
|
||||
{
|
||||
if (m_isFirst)
|
||||
QTimer::singleShot(1 * 1000, this, &TopicEditor::delayedStuff);
|
||||
else
|
||||
delayedStuff();
|
||||
}
|
||||
|
||||
void TopicEditor::delayedStuff()
|
||||
{
|
||||
if (hasTopicDataProperties())
|
||||
m_bgViewerController->excRestoreViewState(getTopicDataValue(QStringLiteral("arrBuildingStates")));
|
||||
m_bgViewerDataView->fetchBuildingList(); // Important to call this here to get a list with valid 'visible' attributes since 'excRestoreViewState' may have open some windows
|
||||
if (m_isFirst)
|
||||
__unchange__();
|
||||
|
||||
m_isFirst = false;
|
||||
}
|
||||
void TopicEditor::retranslate()
|
||||
{
|
||||
translate(m_ui, tr("Building Viewer Topic Editor"));
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// PRIVATE SLOTS
|
||||
|
||||
bool TopicEditor::apply2()
|
||||
{
|
||||
connect(m_bgViewerController, &BgViewerController::signalReceivedViewState,
|
||||
this, &TopicEditor::onViewStateReceived, Qt::UniqueConnection);
|
||||
|
||||
if (m_session)
|
||||
{
|
||||
QVector<LtsPluginManager::LtsPluginManager *> plugManager = LtsAppManager::LtsAppManager::getInstance()->getAppList();
|
||||
for (auto pluginManager : plugManager )
|
||||
{
|
||||
for (auto session: pluginManager->sessions())
|
||||
{
|
||||
if( session->app() == LtsAppDescriptor::App::ScriptEditorEssentialsView)
|
||||
{
|
||||
LtsWidgets::LtsBaseLayoutWidget *blw = session->baseLayout();
|
||||
m_bgViewerSession = session;
|
||||
m_menuVisible = blw->isMenuVisible();
|
||||
m_topBarVisible = blw->isTopBarVisible();
|
||||
|
||||
// make room for a full sized geometry by removing the top bar, the detail bar and the menu - reshow after the image was successfully created
|
||||
blw->setMenuVisible(false);
|
||||
blw->setTopBarVisible(false);
|
||||
blw->hideVisibleLayouts();
|
||||
|
||||
QTimer::singleShot(5000, this, [this]()
|
||||
{
|
||||
if (m_bgViewerSession)
|
||||
{
|
||||
WARNING_LOG(m_logger) << "Asked for BgViewer Viewstate but no replay, resetting Layout";
|
||||
LtsWidgets::LtsBaseLayoutWidget *blw = m_bgViewerSession->baseLayout();
|
||||
blw->setMenuVisible(m_menuVisible);
|
||||
blw->setTopBarVisible(m_topBarVisible);
|
||||
blw->resetLayoutVisibility();
|
||||
m_bgViewerSession = nullptr;
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Request view state from BgViewer process
|
||||
QTimer::singleShot(1000, this, [this]() { m_bgViewerController->excGetViewState(); } );
|
||||
|
||||
/*
|
||||
* P.L.: 'saveTopicData' darf hier NICHT direkt aufgerufen werden! saveTopicData darf erst aufgerufen werden,
|
||||
* wenn der externe BgViewer die Antwort auf obigen Aufruf von 'excGetViewState' gesendet hat.
|
||||
* Das wäre dann der slot 'onViewStateReceived'.
|
||||
*
|
||||
* Deswegen wird in dem slot auch der Zugriff auf 'm_widget' zwingend benoetigt.
|
||||
*/
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
void TopicEditor::onViewStateReceived(const QJsonValue &state) // evaluates the response of 'excGetViewState'
|
||||
{
|
||||
disconnect(m_bgViewerController, &BgViewerController::signalReceivedViewState,
|
||||
this, &TopicEditor::onViewStateReceived);
|
||||
|
||||
if(m_bgViewerSession)
|
||||
{
|
||||
LtsWidgets::LtsBaseLayoutWidget *blw = m_bgViewerSession->baseLayout();
|
||||
blw->setMenuVisible(m_menuVisible);
|
||||
blw->setTopBarVisible(m_topBarVisible);
|
||||
blw->resetLayoutVisibility();
|
||||
m_bgViewerSession = nullptr;
|
||||
}
|
||||
|
||||
// if (m_ui->widget->description().isEmpty())
|
||||
// setDescription(!state.isArray() ? tr("No buildings selected") : tr("%n building(s) selected", "", state.toArray().size()));
|
||||
// else
|
||||
// setDescription(m_ui->widget->description());
|
||||
setDescription(m_ui->widget->description());
|
||||
setTopicDataProperty(QStringLiteral("arrBuildingStates"), state);
|
||||
m_ui->widget->setTopicData(m_topicData);
|
||||
applied();
|
||||
__unchange__();
|
||||
}
|
||||
|
||||
} // namespace BuildingViewer
|
||||
@@ -0,0 +1,53 @@
|
||||
/**
|
||||
* @RDE_HEADER@
|
||||
* $Id$
|
||||
* $HeadURL$
|
||||
* $Author$
|
||||
*
|
||||
* Created by Philipp Last, SLSY, 2017-07-04
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <Plugins/BuildingViewer/Gui/BuildingViewer/bdv_viewer_data_view.h>
|
||||
#include <TopicEditorBase/topic_editor_base.h>
|
||||
#include <LtsSession/lts_session.h>
|
||||
|
||||
namespace Ui { class BuildingViewerTopicEditor; }
|
||||
|
||||
|
||||
namespace BuildingViewer
|
||||
{
|
||||
|
||||
class BgViewerController;
|
||||
|
||||
|
||||
class TopicEditor : public TopicEditorBase::TopicEditor
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit TopicEditor(LtsSession::LtsSession *session, BgViewerController *bgViewerController, BgViewerDataView *bgViewerDataView, QWidget *parent = nullptr);
|
||||
~TopicEditor();
|
||||
|
||||
private:
|
||||
void updateInternalData() override final;
|
||||
void retranslate() override final;
|
||||
|
||||
private slots:
|
||||
bool apply2() override final;
|
||||
void delayedStuff();
|
||||
void onViewStateReceived(const QJsonValue &state);
|
||||
|
||||
private:
|
||||
BgViewerController *m_bgViewerController { nullptr };
|
||||
BgViewerDataView *m_bgViewerDataView { nullptr };
|
||||
LtsSession::LtsSession *m_session { nullptr };
|
||||
LtsSession::LtsSession *m_bgViewerSession { nullptr };
|
||||
bool m_isFirst = true;
|
||||
bool m_topBarVisible = false;
|
||||
bool m_menuVisible = false;
|
||||
Ui::BuildingViewerTopicEditor *m_ui { nullptr };
|
||||
};
|
||||
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>BuildingViewerTopicEditor</class>
|
||||
<widget class="QWidget" name="BuildingViewerTopicEditor">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>742</width>
|
||||
<height>347</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="MinimumExpanding" vsizetype="MinimumExpanding">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string notr="true">Building Viewer Topic Editor</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="m_pLayout">
|
||||
<property name="sizeConstraint">
|
||||
<enum>QLayout::SetMinimumSize</enum>
|
||||
</property>
|
||||
<item>
|
||||
<layout class="QVBoxLayout" name="verticalLayout"/>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="TopicEditorBase::TopicPreviewWidget" name="widget" native="true"/>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<customwidgets>
|
||||
<customwidget>
|
||||
<class>TopicEditorBase::TopicPreviewWidget</class>
|
||||
<extends>QWidget</extends>
|
||||
<header>TopicEditorBase/topic_preview_widget.h</header>
|
||||
<container>1</container>
|
||||
</customwidget>
|
||||
</customwidgets>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
||||
@@ -0,0 +1,100 @@
|
||||
/**
|
||||
* @RDE_HEADER@
|
||||
* $Id$
|
||||
* $HeadURL$
|
||||
* $Author$
|
||||
* Created by Philipp Last, SLSE, 2017-05-23
|
||||
*/
|
||||
|
||||
#include "bdv_replay_handler.h"
|
||||
|
||||
|
||||
namespace BuildingViewer
|
||||
{
|
||||
ReplayHandler::ReplayHandler(int buildingTopicStart_s, int buildingTopicEnd_s, const TopicReplay::Interface::SituationReplayTime &replay, QObject *parent)
|
||||
: QObject(parent)
|
||||
, m_actualReplayStart_ms(0)
|
||||
, m_actualReplayEnd_ms(0)
|
||||
, m_replayDuration_ms(0)
|
||||
, m_startOffset_ms(0)
|
||||
, m_replayInfo(replay)
|
||||
, m_logger(getLogger("ReplayHandler"))
|
||||
{
|
||||
DEBUG_LOG(m_logger) << "buildingTopicStart_s = " << buildingTopicStart_s
|
||||
<< ", buildingTopicEnd_s = " << buildingTopicEnd_s
|
||||
<< ", replay.topicStart_s = " << replay.topicStart_s
|
||||
<< ", replay.topicEnd_s = " << replay.topicEnd_s
|
||||
<< ", replay.replayStart_ms = " << replay.replayStart_ms
|
||||
<< ", replay.replayEnd_ms = " << replay.replayEnd_ms;
|
||||
|
||||
// Identify actual replay start
|
||||
int start_diff_ms = (buildingTopicStart_s - replay.topicStart_s) * 1000;
|
||||
|
||||
if (start_diff_ms >= 0)
|
||||
{
|
||||
/*
|
||||
* Building topic is started with or after replay. This means,
|
||||
* the replay is already running.
|
||||
*/
|
||||
m_actualReplayStart_ms = replay.replayStart_ms + start_diff_ms;
|
||||
m_startOffset_ms = 0;
|
||||
DEBUG_LOG(m_logger) << "Replay starts before Building-Topic: Shift replay starting point to m_actualReplayStart_ms = " << m_actualReplayStart_ms;
|
||||
}
|
||||
else
|
||||
{
|
||||
/*
|
||||
* Replay topic starts after the building topic is already playing.
|
||||
* Hence, we have to record the video first without any replay
|
||||
* and start the replay with an offset.
|
||||
*/
|
||||
m_actualReplayStart_ms = replay.replayStart_ms;
|
||||
m_startOffset_ms = std::abs(start_diff_ms);
|
||||
DEBUG_LOG(m_logger) << "Building-Topic starts before Replay: Starting Replay after " << m_startOffset_ms << "msec";
|
||||
}
|
||||
|
||||
// Identify actual replay end
|
||||
m_actualReplayEnd_ms = replay.replayEnd_ms;
|
||||
// Cut replay if it is running longer than the building topic
|
||||
if (replay.topicEnd_s > buildingTopicEnd_s)
|
||||
{
|
||||
m_actualReplayEnd_ms -= (replay.topicEnd_s - buildingTopicEnd_s) * 1000;
|
||||
DEBUG_LOG(m_logger) << "Replay longer than Building-Topic, cutting replay end to m_actualReplayEnd_ms = " << m_actualReplayEnd_ms;
|
||||
}
|
||||
|
||||
m_replayDuration_ms = m_actualReplayEnd_ms - m_actualReplayStart_ms;
|
||||
|
||||
DEBUG_LOG(m_logger) << "Replay from " << m_actualReplayStart_ms << " to " << m_actualReplayEnd_ms << " (duration = " << m_replayDuration_ms << ")";
|
||||
|
||||
if (m_startOffset_ms == 0)
|
||||
m_startOffset_ms = -1; // Immediate start
|
||||
}
|
||||
|
||||
|
||||
void ReplayHandler::tick(qint64 diffSinceLastTick)
|
||||
{
|
||||
if (isExpired())
|
||||
return;
|
||||
|
||||
m_replayDuration_ms -= diffSinceLastTick;
|
||||
if (m_replayDuration_ms <= 0)
|
||||
{
|
||||
emit signalStopReplay();
|
||||
return;
|
||||
}
|
||||
|
||||
DEBUG_LOG(m_logger) << "ReplayHandler::tick(): Remaining: " << m_replayDuration_ms << "msec";
|
||||
|
||||
if (m_startOffset_ms == -1)
|
||||
{
|
||||
emit signalStartReplay(m_actualReplayStart_ms, m_actualReplayEnd_ms, m_replayInfo.replaySpeedFactor);
|
||||
m_startOffset_ms = 0;
|
||||
}
|
||||
|
||||
if (m_startOffset_ms > 0)
|
||||
{
|
||||
m_startOffset_ms -= diffSinceLastTick;
|
||||
if (m_startOffset_ms <= 0)
|
||||
emit signalStartReplay(m_actualReplayStart_ms, m_actualReplayEnd_ms, m_replayInfo.replaySpeedFactor);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
/**
|
||||
* @RDE_HEADER@
|
||||
*
|
||||
* $Id$
|
||||
* $HeadURL$
|
||||
* $Author$
|
||||
* Created by Philipp Last, SLSE, 2017-05-23
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <QObject>
|
||||
#include <Plugins/SituationReplay/srp_gui_plugin_interface.h>
|
||||
#include <Plugins/BuildingViewer/bdv_viewer_gui_plugin_interface.h>
|
||||
#include <Plugins/BuildingViewer/Common/logger.h>
|
||||
|
||||
namespace BuildingViewer
|
||||
{
|
||||
class ReplayHandler : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
ReplayHandler(int buildingTopicStart_s, int buildingTopicEnd_s, const TopicReplay::Interface::SituationReplayTime &replay, QObject *parent = nullptr);
|
||||
|
||||
void tick(qint64 diffSinceLastTick);
|
||||
|
||||
bool isExpired() const { return m_replayDuration_ms == 0; }
|
||||
|
||||
signals:
|
||||
void signalStartReplay(qint64 start, qint64 end, double speed);
|
||||
void signalStopReplay();
|
||||
|
||||
private:
|
||||
qint64 m_actualReplayStart_ms;
|
||||
qint64 m_actualReplayEnd_ms;
|
||||
|
||||
qint64 m_replayDuration_ms;
|
||||
qint64 m_startOffset_ms;
|
||||
TopicReplay::Interface::SituationReplayTime m_replayInfo;
|
||||
|
||||
NGL::INGLLogger &m_logger;
|
||||
};
|
||||
}
|
||||
+114
@@ -0,0 +1,114 @@
|
||||
/**
|
||||
* @RDE_HEADER@
|
||||
* $Id$
|
||||
* $HeadURL$
|
||||
* $Author$
|
||||
* Created by Philipp Last, SLSE, 2017-05-23
|
||||
*/
|
||||
|
||||
#include "bdv_thread_video_exporter.h"
|
||||
#include "bdv_replay_handler.h"
|
||||
|
||||
#include <QElapsedTimer>
|
||||
#include <QThread>
|
||||
|
||||
#include <Common/TopicEditorBase/topic_editor_base.h>
|
||||
|
||||
namespace BuildingViewer
|
||||
{
|
||||
VideoExporter::VideoExporter(QObject *parent)
|
||||
: QObject(parent)
|
||||
, m_logger(getLogger("ThreadVideoExporter"))
|
||||
{
|
||||
DEBUG_LOG(m_logger) << "ThreadVideoExporter has been created";
|
||||
}
|
||||
|
||||
void VideoExporter::init(const VideoInformation &videoInfo)
|
||||
{
|
||||
m_vecVideosToExport.push_back(videoInfo);
|
||||
}
|
||||
|
||||
|
||||
void VideoExporter::sendAliveSignals()
|
||||
{
|
||||
DEBUG_LOG(m_logger) << "sendAliveSignals() called";
|
||||
|
||||
for (auto &e : qAsConst(m_vecVideosToExport))
|
||||
emit e.m_pExportNotifier->stillAlive();
|
||||
|
||||
DEBUG_LOG(m_logger) << "\tSignals emitted, mutex unlocked";
|
||||
}
|
||||
|
||||
|
||||
void VideoExporter::doExport()
|
||||
{
|
||||
while (!m_vecVideosToExport.isEmpty())
|
||||
{
|
||||
if (QThread::currentThread()->isInterruptionRequested())
|
||||
break;
|
||||
VideoInformation toExport = m_vecVideosToExport.takeFirst();
|
||||
DEBUG_LOG(m_logger) << "Starting export of " << toExport.m_strFolderPath;
|
||||
|
||||
const auto state = toExport.m_bgViewerState.value(QStringLiteral("arrBuildingStates"));
|
||||
|
||||
if (!state.isArray())
|
||||
{
|
||||
WARNING_LOG(m_logger) << "No opened buildings, nothing to export, skipping video!";
|
||||
continue;
|
||||
}
|
||||
|
||||
DEBUG_LOG(m_logger) << "Emitting 'signalStartRecording'";
|
||||
emit signalStartRecording(toExport.m_strFolderPath, state);
|
||||
|
||||
QSharedPointer<ReplayHandler> pHandler;
|
||||
|
||||
QElapsedTimer elapsedTimer;
|
||||
qint64 last_tick_elapsed = 0;
|
||||
qint64 elapsed_sum_ms = 0;
|
||||
const qint64 record_duration_ms = toExport.m_record_duration_s * 1000;
|
||||
|
||||
elapsedTimer.start();
|
||||
while (elapsed_sum_ms <= record_duration_ms)
|
||||
{
|
||||
const qint64 curElapsed = elapsedTimer.restart();
|
||||
elapsed_sum_ms += curElapsed;
|
||||
sendAliveSignals();
|
||||
emit toExport.m_pExportNotifier->stillAlive(); // Object behind 'toExport' is no longer included in vector, signal separately
|
||||
|
||||
if (!pHandler && toExport.m_vecReplayHandler.size())
|
||||
{
|
||||
pHandler = toExport.m_vecReplayHandler.front();
|
||||
connect(pHandler.data(), &ReplayHandler::signalStartReplay, this, &VideoExporter::signalStartReplay);
|
||||
connect(pHandler.data(), &ReplayHandler::signalStopReplay, this, &VideoExporter::signalStopReplay);
|
||||
toExport.m_vecReplayHandler.pop_front();
|
||||
}
|
||||
|
||||
const qint64 diff_ms = elapsed_sum_ms - last_tick_elapsed;
|
||||
|
||||
if (diff_ms >= 1000)
|
||||
{
|
||||
last_tick_elapsed = elapsed_sum_ms;
|
||||
DEBUG_LOG(m_logger) << "Export: " << elapsed_sum_ms / 1000 << "/" << record_duration_ms / 1000 << "[s] passed";
|
||||
}
|
||||
|
||||
if (pHandler)
|
||||
{
|
||||
pHandler->tick(curElapsed);
|
||||
|
||||
if (pHandler->isExpired())
|
||||
break;
|
||||
}
|
||||
QThread::msleep(100);
|
||||
if (QThread::currentThread()->isInterruptionRequested())
|
||||
break;
|
||||
}
|
||||
DEBUG_LOG(m_logger) << "Done. Emitting 'signalStopRecording'";
|
||||
emit signalStopRecording();
|
||||
|
||||
DEBUG_LOG(m_logger) <<"Export done, emitting 'signalExportSuccessful'";
|
||||
toExport.m_pExportNotifier->setExportSuccessful(toExport.m_strFolderPath);
|
||||
DEBUG_LOG(m_logger) <<"\tsignal emitted";
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,67 @@
|
||||
/**
|
||||
* @RDE_HEADER@
|
||||
*
|
||||
* $Id$
|
||||
* $HeadURL$
|
||||
* $Author$
|
||||
* Created by Philipp Last, SLSE, 2017-05-23
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <SituationReplay/srp_gui_plugin_interface.h>
|
||||
#include <BuildingViewer/bdv_viewer_gui_plugin_interface.h>
|
||||
#include <Common/logger.h>
|
||||
#include <QSharedPointer>
|
||||
|
||||
namespace BuildingViewer
|
||||
{
|
||||
class ReplayHandler;
|
||||
|
||||
class VideoInformation
|
||||
{
|
||||
public:
|
||||
VideoInformation() = default;
|
||||
VideoInformation(TopicEditorBase::ExportNotifier *pExportNotifier,
|
||||
const QString &strFolderPath,
|
||||
const QJsonObject &attributes,
|
||||
const QVector<QSharedPointer<ReplayHandler>> &vecReplayHandler,
|
||||
qint64 record_duration_s)
|
||||
: m_pExportNotifier(pExportNotifier)
|
||||
, m_record_duration_s(record_duration_s)
|
||||
, m_strFolderPath(strFolderPath)
|
||||
, m_bgViewerState(attributes)
|
||||
, m_vecReplayHandler(vecReplayHandler)
|
||||
{}
|
||||
|
||||
TopicEditorBase::ExportNotifier *m_pExportNotifier = nullptr;
|
||||
qint64 m_record_duration_s = -1;
|
||||
QString m_strFolderPath;
|
||||
QJsonObject m_bgViewerState;
|
||||
QVector<QSharedPointer<ReplayHandler>> m_vecReplayHandler;
|
||||
};
|
||||
|
||||
|
||||
class VideoExporter : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
VideoExporter(QObject *parent = nullptr);
|
||||
|
||||
void init(const VideoInformation &videoInfo);
|
||||
void doExport();
|
||||
|
||||
signals:
|
||||
void signalStartReplay(qint64 start, qint64 end, double speed);
|
||||
void signalStopReplay();
|
||||
|
||||
void signalStartRecording(const QString &strFolderPath, const QJsonValue &state);
|
||||
void signalStopRecording();
|
||||
|
||||
private:
|
||||
void sendAliveSignals();
|
||||
|
||||
QVector<VideoInformation> m_vecVideosToExport;
|
||||
NGL::INGLLogger &m_logger;
|
||||
};
|
||||
}
|
||||
+330
@@ -0,0 +1,330 @@
|
||||
/**
|
||||
* @RDE_HEADER@
|
||||
* $Id$
|
||||
* $HeadURL$
|
||||
* $Author$
|
||||
* Created by Philipp Last, SLSE, 2017-05-23
|
||||
*/
|
||||
|
||||
#include "bdv_topic_replay_interface.h"
|
||||
#include "bdv_viewer_gui_plugin.h"
|
||||
#include "bdv_thread_video_exporter.h"
|
||||
#include "bdv_replay_handler.h"
|
||||
#include <Common/bdv_controller.h>
|
||||
#include <LtsSession/lts_session.h>
|
||||
|
||||
#include <QDir>
|
||||
#include <QJsonDocument>
|
||||
#include <ngltools/ngltools_filesystem.h>
|
||||
|
||||
#ifdef EXPORT_BDV_TOPIC_AS_JSON
|
||||
#include <QFile>
|
||||
#include <LtsUtilsCore/qpoint3d.h>
|
||||
#include <Common/bdv_helper.h>
|
||||
#include <Common/BgViewer/viewerCtrl/viewwidgetstate.h>
|
||||
#else
|
||||
#include <QThread>
|
||||
#endif
|
||||
|
||||
namespace BuildingViewer
|
||||
{
|
||||
|
||||
// --------------------------------------------------------------------------------------------------------------
|
||||
// Script Player
|
||||
// --------------------------------------------------------------------------------------------------------------
|
||||
TopicReplayInterface::TopicReplayInterface(BgViewerController *bgvController, LtsSession::LtsSession *session)
|
||||
: m_bgvController(bgvController)
|
||||
, m_session(session)
|
||||
, m_logger(getLogger("TopicReplayInterface"))
|
||||
{
|
||||
session->getForeignGuiInterface<SituationReplay::ForeignGuiInterface>(m_replayIfc);
|
||||
}
|
||||
|
||||
|
||||
QWidget *TopicReplayInterface::createWidget()
|
||||
{
|
||||
delete m_pBgViewerWidget;
|
||||
m_pBgViewerWidget = m_bgvController ? m_bgvController->getBgViewerWidget() : nullptr;
|
||||
return m_pBgViewerWidget;
|
||||
}
|
||||
|
||||
|
||||
TopicReplayInterface::~TopicReplayInterface()
|
||||
{
|
||||
#ifndef EXPORT_BDV_TOPIC_AS_JSON
|
||||
if (m_tveThread)
|
||||
{
|
||||
m_tveThread->requestInterruption();
|
||||
m_tveThread->quit();
|
||||
m_tveThread->wait(20000);
|
||||
m_tveThread->terminate();
|
||||
}
|
||||
delete m_tveThread;
|
||||
#endif
|
||||
/*
|
||||
* deleteLater is not sufficient depending on the topic arrangement in skripteditor.
|
||||
* E.g., if a building topic should start directly after another building topic
|
||||
* deleteLater (and therefore releasing BgViewerWidget) will happen to late since
|
||||
* releasing and starting topics happens in one QTimer slot in SkriptPlayer
|
||||
*/
|
||||
delete m_pBgViewerWidget;
|
||||
m_pBgViewerWidget = nullptr;
|
||||
}
|
||||
|
||||
|
||||
bool TopicReplayInterface::playbackInit(const QJsonObject &attributes)
|
||||
{
|
||||
if (!m_bgvController)
|
||||
return false;
|
||||
m_bgvController->closeBuilding();
|
||||
m_bgvController->excRestoreViewState(attributes.value(QStringLiteral("arrBuildingStates")));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
void TopicReplayInterface::slotStartReplay(qint64 start, qint64 end, double speed)
|
||||
{
|
||||
if (m_replayIfc)
|
||||
m_replayIfc->startReplay(start, end, speed);
|
||||
}
|
||||
|
||||
void TopicReplayInterface::slotStopReplay()
|
||||
{
|
||||
if (m_replayIfc)
|
||||
m_replayIfc->stopReplay();
|
||||
}
|
||||
|
||||
|
||||
void TopicReplayInterface::setExportPlaybackTimes(qint64 startTimeSec,
|
||||
qint64 durationSec,
|
||||
const QVector<SituationReplayTime> &sitReplayTimes)
|
||||
{
|
||||
m_startTimeSec = startTimeSec;
|
||||
m_durationSec = durationSec;
|
||||
m_sitReplayTimes = sitReplayTimes;
|
||||
}
|
||||
|
||||
bool TopicReplayInterface::exportTopic(const QJsonObject &attributes,
|
||||
const QString &folderPath,
|
||||
TopicEditorBase::ExportNotifier *pExportNotifier)
|
||||
{
|
||||
#ifdef EXPORT_BDV_TOPIC_AS_JSON
|
||||
const QJsonArray states = attributes[QStringLiteral("arrBuildingStates")].toArray();
|
||||
if (states.isEmpty())
|
||||
{
|
||||
INFO_LOG(m_logger) << "Nothing to export";
|
||||
emit pExportNotifier->exportSuccessful(QString());
|
||||
return true;
|
||||
}
|
||||
|
||||
const QString filename(QStringLiteral("buildingViewer.json"));
|
||||
QFile f(folderPath + QLatin1Char('/') + filename);
|
||||
if (!f.open(QIODevice::WriteOnly))
|
||||
{
|
||||
WARNING_LOG(m_logger) << "Can not open file '" << f.fileName() << "' for writing!";
|
||||
pExportNotifier->setExportFailed();
|
||||
return false;
|
||||
}
|
||||
QJsonObject obj;
|
||||
obj[QStringLiteral("attributes")] = attributes;
|
||||
obj[QStringLiteral("timeInPresentation")] = timeRange(m_startTimeSec * 1000,
|
||||
(m_startTimeSec + m_durationSec) * 1000);
|
||||
|
||||
QJsonArray arr;
|
||||
for (const SituationReplayTime &rt : qAsConst(m_sitReplayTimes))
|
||||
{
|
||||
if (m_startTimeSec > rt.topicEnd_s)
|
||||
continue;
|
||||
const double lenReplay = rt.replayEnd_ms - rt.replayStart_ms;
|
||||
const double endReplay = rt.replayStart_ms + lenReplay;
|
||||
// TODO: check - looks not correct
|
||||
const double maxReplay = std::min(rt.replayStart_ms + m_durationSec * 1000. * rt.replaySpeedFactor, endReplay);
|
||||
arr.push_back(rt.toJson(maxReplay));
|
||||
}
|
||||
obj[QStringLiteral("replays")] = arr;
|
||||
f.write(QJsonDocument(obj).toJson(QJsonDocument::Indented));
|
||||
f.close();
|
||||
DEBUG_LOG(m_logger) << "BDV filename: " << f.fileName();
|
||||
|
||||
QVector<int> buildingIds;
|
||||
buildingIds.reserve(states.size());
|
||||
for (const auto &ele : states)
|
||||
{
|
||||
const ViewWidgetState vws(ele.toObject());
|
||||
int buildingId = featureId2DatabaseId(QString::fromStdString(vws.m_featureID));
|
||||
if (buildingId <= 0)
|
||||
{
|
||||
WARNING_LOG(m_logger) << "Could not retrieve building id from '" << vws.m_featureID << "' - skipping";
|
||||
continue;
|
||||
}
|
||||
buildingIds += buildingId;
|
||||
}
|
||||
|
||||
emit pExportNotifier->stillAlive();
|
||||
if (!exportBuildings(buildingIds) ||
|
||||
!exportShaders())
|
||||
{
|
||||
pExportNotifier->setExportFailed();
|
||||
return false;
|
||||
}
|
||||
//COPY buildings into directory
|
||||
const QString outputPath(m_basePath + QStringLiteral("BuildingModels/"));
|
||||
QFile fBdv(outputPath + QStringLiteral("/buildings.json"));
|
||||
if (fBdv.exists())
|
||||
{
|
||||
fBdv.copy(folderPath + QStringLiteral("/../buildings.json"));
|
||||
}
|
||||
|
||||
emit pExportNotifier->exportSuccessful(filename);
|
||||
#else
|
||||
// Assumes that the essentials view is open
|
||||
if (!m_replayIfc || !m_bgvController)
|
||||
{
|
||||
ERROR_LOG(m_logger) << "BuildingViewer exportTopic: m_replayIfc==nullptr, can not start replay, aborting export";
|
||||
emit pExportNotifier->exportFailed();
|
||||
Q_ASSERT(false);
|
||||
return false;
|
||||
}
|
||||
|
||||
playbackInit(attributes);
|
||||
|
||||
qint64 record_duration_s = m_durationSec + 2; // Add 2 seconds since actual output seems always to be shorter than desired
|
||||
// Get replays for building (if any)
|
||||
QVector<QSharedPointer<ReplayHandler>> vecReplayHandler;
|
||||
vecReplayHandler.reserve(m_sitReplayTimes.size());
|
||||
for (const SituationReplayTime &srt : qAsConst(m_sitReplayTimes))
|
||||
vecReplayHandler.push_back(QSharedPointer<ReplayHandler>(new ReplayHandler(m_startTimeSec, m_startTimeSec + m_durationSec, srt)));
|
||||
|
||||
VideoInformation info(pExportNotifier, folderPath, attributes, vecReplayHandler, record_duration_s);
|
||||
|
||||
VideoExporter *videoExporter = new VideoExporter;
|
||||
videoExporter->init(info);
|
||||
|
||||
Q_ASSERT(!m_tveThread);
|
||||
m_tveThread = new QThread(this);
|
||||
videoExporter->moveToThread(m_tveThread);
|
||||
|
||||
connect(videoExporter, &VideoExporter::signalStartReplay,
|
||||
this, &TopicReplayInterface::slotStartReplay);
|
||||
connect(videoExporter, &VideoExporter::signalStopReplay,
|
||||
this, &TopicReplayInterface::slotStopReplay);
|
||||
|
||||
/*
|
||||
* Qt::BlockingQueuedConnection
|
||||
* Same as Qt::QueuedConnection, except that the signaling thread blocks until the slot returns.
|
||||
* This connection must not be used if the receiver lives in the signalling thread, or else the application will deadlock.
|
||||
*
|
||||
* -> Video thread signals "startrecording" and waits until 'slotStartRecording' in main thread has been processed
|
||||
*/
|
||||
connect(videoExporter, &VideoExporter::signalStartRecording,
|
||||
m_bgvController, &BgViewerController::slotStartRecording, Qt::BlockingQueuedConnection);
|
||||
connect(videoExporter, &VideoExporter::signalStopRecording,
|
||||
m_bgvController, &BgViewerController::slotStopRecording, Qt::BlockingQueuedConnection);
|
||||
|
||||
connect(m_tveThread, &QThread::started, videoExporter, &VideoExporter::doExport);
|
||||
connect(m_tveThread, &QThread::finished, videoExporter, &VideoExporter::deleteLater);
|
||||
|
||||
m_tveThread->start();
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
||||
bool TopicReplayInterface::exportBuildings(const QVector<int> &buildingIds) const
|
||||
{
|
||||
std::shared_ptr<InfrastructureManagement::Interface::Dtc> ismDtc;
|
||||
if (!m_session->getDtc<InfrastructureManagement::DataInterface>(ismDtc))
|
||||
return false;
|
||||
const QString modelPath = BgViewerController::buildingModelPath();
|
||||
if (modelPath.isEmpty())
|
||||
{
|
||||
WARNING_LOG(m_logger) << "Could not find path with building models - can not copy models";
|
||||
return false;
|
||||
}
|
||||
|
||||
const QString outputPath(m_basePath + QStringLiteral("BuildingModels/"));
|
||||
QDir dir(outputPath);
|
||||
if (!dir.exists() && !dir.mkpath(outputPath))
|
||||
{
|
||||
WARNING_LOG(m_logger) << "Could not create path " << outputPath;
|
||||
return false;
|
||||
}
|
||||
QFile f(outputPath + QStringLiteral("/buildings.json"));
|
||||
if (!f.open(QIODevice::ReadWrite))
|
||||
{
|
||||
WARNING_LOG(m_logger) << "Could not open file " << f.fileName() << " for read/write: " << f.errorString();
|
||||
return false;
|
||||
}
|
||||
const QJsonArray arr(QJsonDocument::fromJson(f.readAll()).array());
|
||||
QVector<BuildingInfo> knownBuildings;
|
||||
knownBuildings.reserve(arr.size());
|
||||
for (const auto &ele : arr)
|
||||
{
|
||||
const auto bi = BuildingInfo::fromJson(ele.toObject());
|
||||
if (bi.isValid())
|
||||
knownBuildings += bi;
|
||||
}
|
||||
|
||||
BuildingInfo bi;
|
||||
for (const int buildingId : buildingIds)
|
||||
{
|
||||
const auto mse = ismDtc->mainStructureElement(buildingId);
|
||||
if (mse.id() != buildingId)
|
||||
{
|
||||
WARNING_LOG(m_logger) << "Could not find MainStructureElement for building with id " << buildingId << " - skipping";
|
||||
continue;
|
||||
}
|
||||
const QString fnIve = QString::fromStdString(mse.name()) + QStringLiteral(".flt.ive");
|
||||
const QString fnXml = QString::fromStdString(mse.name()) + QStringLiteral(".flt.xml");
|
||||
if (!copyFile(fnIve, modelPath, outputPath) ||
|
||||
!copyFile(fnXml, modelPath, outputPath))
|
||||
return false;
|
||||
bi.name = QString::fromStdString(mse.name());
|
||||
bi.position = LtsUtils::QPoint3D(mse.geoPosition().lon(), mse.geoPosition().lat(), mse.geoPosition().z());
|
||||
bi.angleDegree = mse.angle();
|
||||
bi.id = mse.id();
|
||||
|
||||
knownBuildings += bi;
|
||||
}
|
||||
|
||||
std::sort(knownBuildings.begin(), knownBuildings.end(),
|
||||
[](const BuildingInfo &a, const BuildingInfo &b)
|
||||
{
|
||||
return a.id < b.id;
|
||||
});
|
||||
knownBuildings.erase(std::unique(knownBuildings.begin(), knownBuildings.end()), knownBuildings.end());
|
||||
QJsonArray arrOut;
|
||||
for (const auto &b : qAsConst(knownBuildings))
|
||||
arrOut += b.toJson();
|
||||
|
||||
f.resize(0);
|
||||
f.seek(0);
|
||||
f.write(QJsonDocument(arrOut).toJson());
|
||||
f.close();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool TopicReplayInterface::exportShaders() const
|
||||
{
|
||||
const QString shaderPath(NGL::findFile(NGL::FileType::ConfigFile, QStringLiteral("shaders")));
|
||||
const QString outputPath(m_basePath + QStringLiteral("BuildingModels/shaders/"));
|
||||
DEBUG_LOG(m_logger) << "shaderPath: " << shaderPath << ", outputPath: " << outputPath;
|
||||
return NGL::copyDirContentsToDir(shaderPath, outputPath);
|
||||
}
|
||||
|
||||
|
||||
bool TopicReplayInterface::copyFile(const QString &srcFn, const QString &srcDir, const QString &dstDir) const
|
||||
{
|
||||
const QString src = srcDir + QLatin1Char('/') + srcFn;
|
||||
const QString dst = dstDir + QLatin1Char('/') + srcFn;
|
||||
QFile f(src);
|
||||
if (!f.exists() || (!QFile::exists(dst) && !f.copy(dst)))
|
||||
{
|
||||
WARNING_LOG(m_logger) << "Could not copy " << src << " to " << dst << ": " << f.errorString();
|
||||
return false;
|
||||
}
|
||||
DEBUG_LOG(m_logger) << "Copied from " << src << " to " << dst;
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,73 @@
|
||||
/**
|
||||
* @RDE_HEADER@
|
||||
*
|
||||
* $Id$
|
||||
* $HeadURL$
|
||||
* $Author$
|
||||
* Created by Philipp Last, SLSE, 2017-05-23
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <QObject>
|
||||
#include <QVector>
|
||||
#include <Plugins/SituationReplay/srp_gui_plugin_interface.h>
|
||||
#include <Plugins/BuildingViewer/bdv_viewer_gui_plugin_interface.h>
|
||||
#include <memory>
|
||||
|
||||
namespace NGL
|
||||
{
|
||||
class INGLLogger;
|
||||
}
|
||||
namespace LtsSession
|
||||
{
|
||||
class LtsSession;
|
||||
}
|
||||
|
||||
namespace BuildingViewer
|
||||
{
|
||||
class InterfaceImpl;
|
||||
class BgViewerController;
|
||||
|
||||
//Scriptplayer
|
||||
class TopicReplayInterface final : public QObject, public TopicReplay::Interface
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit TopicReplayInterface(BgViewerController *bgvController, LtsSession::LtsSession *session);
|
||||
~TopicReplayInterface();
|
||||
|
||||
QWidget *createWidget() override;
|
||||
bool playbackInit(const QJsonObject &attributes) override;
|
||||
void setExportPlaybackTimes(qint64 startTimeSec,
|
||||
qint64 durationSec,
|
||||
const QVector<SituationReplayTime> &sitReplayTimes) override;
|
||||
bool exportTopic(const QJsonObject &attributes,
|
||||
const QString &folderPath,
|
||||
TopicEditorBase::ExportNotifier *pExportNotifier) override;
|
||||
|
||||
void setBasePath(const QString &basePath) override { m_basePath = basePath; }
|
||||
|
||||
private slots:
|
||||
void slotStartReplay(qint64 start, qint64 end, double speed);
|
||||
void slotStopReplay();
|
||||
private:
|
||||
bool exportBuildings(const QVector<int> &buildingIds) const;
|
||||
bool exportShaders() const;
|
||||
bool copyFile(const QString &srcFn, const QString &srcDir, const QString &dstDir) const;
|
||||
private:
|
||||
qint64 m_startTimeSec = 0;
|
||||
qint64 m_durationSec = 0;
|
||||
QVector<SituationReplayTime> m_sitReplayTimes;
|
||||
std::shared_ptr<SituationReplay::ForeignGuiInterface> m_replayIfc;
|
||||
QString m_basePath;
|
||||
QWidget *m_pBgViewerWidget = nullptr;
|
||||
#ifndef EXPORT_BDV_TOPIC_AS_JSON
|
||||
QThread *m_tveThread = nullptr;
|
||||
#endif
|
||||
BgViewerController *m_bgvController = nullptr;
|
||||
LtsSession::LtsSession *m_session = nullptr;
|
||||
NGL::INGLLogger &m_logger;
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,70 @@
|
||||
/**
|
||||
* @RDE_HEADER@
|
||||
* HMI Plugin for MeteoDataManagement - Meteo Data Overview Dialog
|
||||
* $Id$
|
||||
* $HeadURL$
|
||||
* $Author$
|
||||
* Created by Patric Karwat, SLSE, 2016-10-05
|
||||
*/
|
||||
|
||||
#include "bdv_viewer_data_dialog.h"
|
||||
#include "ui_bdv_viewer_data_dialog.h"
|
||||
|
||||
#include <LtsSession/lts_session_data.h>
|
||||
#include <Proxies/Buildings/bld_operator_rights.h>
|
||||
|
||||
namespace BuildingViewer
|
||||
{
|
||||
BgViewerDataViewDialog::BgViewerDataViewDialog(QWidget *parent)
|
||||
: LtsWidgets::LtsDialog(parent, LtsWidgets::ButtonCombination::CloseOnly)
|
||||
, m_ui(new Ui::BgViewerDataViewDialog)
|
||||
, m_logger(getLogger("BgViewerDataViewDialog"))
|
||||
{
|
||||
m_ui->setupUi(this);
|
||||
|
||||
bool userHasRightsToEdit = LtsSessionData::LtsSessionData::getInstance()->hasOperatorRight(OperatorRights::BuildingViewerSettingsEdit);
|
||||
if (!userHasRightsToEdit)
|
||||
m_buttonBox->getButton(LtsWidgets::DialogButton::Edit)->setText(tr("Show details"));
|
||||
|
||||
m_buttonBox->connectButton(LtsWidgets::DialogButton::Edit, m_ui->widget, &BgViewerDataView::onLtsDataView_onEditBuilding);
|
||||
m_buttonBox->connectButton(LtsWidgets::DialogButton::Show, m_ui->widget, &BgViewerDataView::onLtsDataView_DoubleClicked);
|
||||
|
||||
m_buttonBox->getButton(LtsWidgets::DialogButton::Edit)->setEnabled(false);
|
||||
m_buttonBox->getButton(LtsWidgets::DialogButton::Show)->setEnabled(false);
|
||||
connect(m_ui->widget, &BgViewerDataView::signalCurrentSelectionChanged, this, [this](const QModelIndex & idx)
|
||||
{
|
||||
m_buttonBox->getButton(LtsWidgets::DialogButton::Edit)->setEnabled(idx.isValid());
|
||||
m_buttonBox->getButton(LtsWidgets::DialogButton::Show)->setEnabled(idx.isValid());
|
||||
});
|
||||
|
||||
connect(m_ui->widget, &BgViewerDataView::signalEditBuilding,
|
||||
this, &BgViewerDataViewDialog::signalEditBuilding);
|
||||
|
||||
setOnlineHelpFilename(QStringLiteral("Building_Viewer-Building_List"));
|
||||
}
|
||||
|
||||
|
||||
BgViewerDataViewDialog::~BgViewerDataViewDialog()
|
||||
{
|
||||
delete m_ui;
|
||||
}
|
||||
|
||||
void BgViewerDataViewDialog::fetchBuildingList()
|
||||
{
|
||||
m_ui->widget->fetchBuildingList();
|
||||
}
|
||||
|
||||
bool BgViewerDataViewDialog::init(BgViewerController *pBdvController,
|
||||
const std::shared_ptr<InfrastructureManagement::Interface::Dtc> &ismDtc,
|
||||
bool fetchBuildingDataOnCreation)
|
||||
{
|
||||
return m_ui->widget->init(pBdvController, ismDtc, fetchBuildingDataOnCreation);
|
||||
}
|
||||
|
||||
void BgViewerDataViewDialog::retranslate()
|
||||
{
|
||||
translate(m_ui, tr("Building List"));
|
||||
}
|
||||
|
||||
} // namespace BuildingViewer
|
||||
|
||||
@@ -0,0 +1,50 @@
|
||||
/**
|
||||
* @RDE_HEADER@
|
||||
* HMI Plugin for MeteoDataManagement - Meteo Data Overview Dialog
|
||||
* $Id$
|
||||
* $HeadURL$
|
||||
* $Author$
|
||||
* Created by Patric Karwat, SLSE, 2016-10-05
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <LtsWidgets/lts_dialog.h>
|
||||
#include <Plugins/InfrastructureManagement/ism_data_plugin_interface.h>
|
||||
#include <Common/logger.h>
|
||||
|
||||
namespace Ui
|
||||
{
|
||||
class BgViewerDataViewDialog;
|
||||
}
|
||||
|
||||
|
||||
namespace BuildingViewer
|
||||
{
|
||||
class BgViewerController;
|
||||
|
||||
class BgViewerDataViewDialog : public LtsWidgets::LtsDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit BgViewerDataViewDialog(QWidget *parent = nullptr);
|
||||
~BgViewerDataViewDialog();
|
||||
|
||||
bool init(BgViewerController *pBdvController,
|
||||
const std::shared_ptr<InfrastructureManagement::Interface::Dtc> &ismDtc,
|
||||
bool fetchBuildingDataOnCreation);
|
||||
|
||||
public Q_SLOTS:
|
||||
void fetchBuildingList();
|
||||
protected:
|
||||
void retranslate() override;
|
||||
|
||||
signals:
|
||||
void signalEditBuilding(const QString &strFeatureID);
|
||||
|
||||
private:
|
||||
Ui::BgViewerDataViewDialog *m_ui;
|
||||
NGL::INGLLogger &m_logger;
|
||||
};
|
||||
} // namespace BuildingViewer
|
||||
@@ -0,0 +1,32 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>BgViewerDataViewDialog</class>
|
||||
<widget class="QWidget" name="BgViewerDataViewDialog">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>18</width>
|
||||
<height>28</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string notr="true">Form</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<widget class="BuildingViewer::BgViewerDataView" name="widget" native="true"/>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<customwidgets>
|
||||
<customwidget>
|
||||
<class>BuildingViewer::BgViewerDataView</class>
|
||||
<extends>QWidget</extends>
|
||||
<header>bdv_viewer_data_view.h</header>
|
||||
<container>1</container>
|
||||
</customwidget>
|
||||
</customwidgets>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
||||
@@ -0,0 +1,90 @@
|
||||
/**
|
||||
* @RDE_HEADER@
|
||||
* HMI Plugin for ParticipantManagement - Party Overview Model
|
||||
* $Id$
|
||||
* $HeadURL$
|
||||
* $Author$
|
||||
* Created by Philipp Last, SLSY, 2017-05-23
|
||||
*/
|
||||
|
||||
#include "bdv_viewer_data_model.h"
|
||||
|
||||
#include <QColor>
|
||||
#include <QPalette>
|
||||
#include <QGuiApplication>
|
||||
|
||||
|
||||
namespace BuildingViewer
|
||||
{
|
||||
BgViewerDataViewModel::BgViewerDataViewModel(QObject *parent)
|
||||
: LtsAbstractTableModel({
|
||||
tr("Id"),
|
||||
tr("Feature Id"),
|
||||
tr("Visible"),
|
||||
tr("Description"),
|
||||
QStringLiteral("Entity Id")
|
||||
},
|
||||
parent)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
void BgViewerDataViewModel::onViewerEventWidgetClosed(const QString &buildingId)
|
||||
{
|
||||
for (int row = 0; row < m_vecData.size(); ++row)
|
||||
{
|
||||
if (m_vecData.at(row).buildingId == buildingId)
|
||||
{
|
||||
m_vecData[row].isShown = false;
|
||||
emit dataChanged(index(row, 0), index(row, eColEntityId), {Qt::DisplayRole, Qt::BackgroundRole});
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
QModelIndex BgViewerDataViewModel::getModelIndex(const QString &buildingId) const
|
||||
{
|
||||
for (int row = 0; row < m_vecData.size(); ++row)
|
||||
{
|
||||
if (m_vecData[row].buildingId == buildingId)
|
||||
return index(row, 0);
|
||||
}
|
||||
|
||||
return QModelIndex();
|
||||
}
|
||||
|
||||
|
||||
QVariant BgViewerDataViewModel::data(const QModelIndex &index, int role) const
|
||||
{
|
||||
if ((role != Qt::BackgroundRole && role != Qt::DisplayRole) || !indexIsValid(index))
|
||||
return QVariant();
|
||||
|
||||
const BuildingTuple &row = m_vecData.at(index.row());
|
||||
if (role == Qt::BackgroundRole)
|
||||
{
|
||||
if (row.isShown)
|
||||
return QGuiApplication::palette().color(QPalette::Highlight);
|
||||
}
|
||||
|
||||
if (role == Qt::DisplayRole)
|
||||
{
|
||||
switch (index.column())
|
||||
{
|
||||
case eColId:
|
||||
return index.row() + 1;
|
||||
case eColFeatureId:
|
||||
return row.buildingId;
|
||||
case eColVisible:
|
||||
return row.isShown ? tr("Yes") : tr("No");
|
||||
case eColDescription:
|
||||
return row.description;
|
||||
case eColEntityId:
|
||||
return row.entityId;
|
||||
}
|
||||
}
|
||||
|
||||
return QVariant();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
/**
|
||||
* @RDE_HEADER@
|
||||
*
|
||||
* $Id$
|
||||
* $HeadURL$
|
||||
* $Author$
|
||||
* Created by Philipp Last, SLSY, 2017-05-23
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <LtsWidgets/lts_abstract_table_model.h>
|
||||
#include <Common/bdv_helper.h>
|
||||
|
||||
namespace BuildingViewer
|
||||
{
|
||||
class ForeignDataInterface;
|
||||
|
||||
class BgViewerDataViewModel : public LtsWidgets::LtsAbstractTableModel<BuildingTuple>
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
enum Columns
|
||||
{
|
||||
eColId,
|
||||
eColFeatureId,
|
||||
eColVisible,
|
||||
eColDescription,
|
||||
eColEntityId
|
||||
};
|
||||
explicit BgViewerDataViewModel(QObject *parent = nullptr);
|
||||
|
||||
QVariant data(const QModelIndex &index, int role) const override;
|
||||
QModelIndex getModelIndex(const QString &buildingId) const;
|
||||
|
||||
public slots:
|
||||
void onViewerEventWidgetClosed(const QString &buildingId);
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,190 @@
|
||||
/**
|
||||
* @RDE_HEADER@
|
||||
* HMI Plugin for MeteoDataManagement - Meteo Data Overview Dialog
|
||||
* $Id$
|
||||
* $HeadURL$
|
||||
* $Author$
|
||||
* Created by Patric Karwat, SLSE, 2016-10-05
|
||||
*/
|
||||
|
||||
#include "bdv_viewer_data_view.h"
|
||||
#include "ui_bdv_viewer_data_view.h"
|
||||
#include "bdv_viewer_data_model.h"
|
||||
|
||||
#include <Common/bdv_controller.h>
|
||||
|
||||
#include <QKeyEvent>
|
||||
|
||||
namespace BuildingViewer
|
||||
{
|
||||
BgViewerDataView::BgViewerDataView(QWidget *parent)
|
||||
: QWidget(parent)
|
||||
, m_ui(new Ui::BgViewerDataView)
|
||||
, m_pModel(new BgViewerDataViewModel(this))
|
||||
, m_logger(getLogger("BgViewerDataView"))
|
||||
{
|
||||
m_ui->setupUi(this);
|
||||
|
||||
m_ui->widget->setSelectionMode(QAbstractItemView::SingleSelection);
|
||||
connect(m_ui->widget, &LtsDataView::LtsDataView::signalDoubleClicked, this, &BgViewerDataView::onLtsDataView_DoubleClicked);
|
||||
connect(m_ui->widget, &LtsDataView::LtsDataView::signalEnterPressed, this, &BgViewerDataView::onLtsDataView_DoubleClicked);
|
||||
connect(m_ui->widget, &LtsDataView::LtsDataView::signalSelectionChanged, this, &BgViewerDataView::onLtsDataView_selectionChanged);
|
||||
|
||||
m_ui->widget->setModel(m_pModel);
|
||||
m_ui->widget->installEventFilter(this);
|
||||
|
||||
#ifndef LTS_DEBUG
|
||||
m_ui->widget->hideColumn(BgViewerDataViewModel::eColId);
|
||||
m_ui->widget->hideColumn(BgViewerDataViewModel::eColEntityId);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
BgViewerDataView::~BgViewerDataView()
|
||||
{
|
||||
delete m_ui;
|
||||
}
|
||||
|
||||
bool BgViewerDataView::init(BgViewerController *pBgvController,
|
||||
const std::shared_ptr<InfrastructureManagement::Interface::Dtc> &ismDtc,
|
||||
bool fetchBuildingDataOnCreation)
|
||||
{
|
||||
if (!pBgvController || !ismDtc)
|
||||
return false;
|
||||
|
||||
if (m_pBgvController)
|
||||
{
|
||||
m_pBgvController->disconnect(this);
|
||||
m_pBgvController->disconnect(m_pModel);
|
||||
}
|
||||
m_pBgvController = pBgvController;
|
||||
connect(ismDtc.get(), &InfrastructureManagement::Interface::Dtc::mainStructureElementChanged,
|
||||
this, &BgViewerDataView::fetchBuildingList, Qt::UniqueConnection);
|
||||
connect(m_pBgvController, &BgViewerController::signalReceivedBuildingList,
|
||||
m_pModel, &BgViewerDataViewModel::setData);
|
||||
connect(m_pBgvController, &BgViewerController::signalViewerEventWidgetMaximized,
|
||||
this, &BgViewerDataView::onViewerEventWidgetMaximized);
|
||||
connect(m_pBgvController, &BgViewerController::signalViewerEventWidgetFocused,
|
||||
this, &BgViewerDataView::onViewerEventWidgetFocused);
|
||||
connect(m_pBgvController, &BgViewerController::signalViewerEventWidgetClosed,
|
||||
this, &BgViewerDataView::signalUserActionPerformend);
|
||||
connect(m_pBgvController, &BgViewerController::signalViewerEventWidgetClosed,
|
||||
m_pModel, &BgViewerDataViewModel::onViewerEventWidgetClosed);
|
||||
connect(m_pBgvController, &BgViewerController::signalViewerZoomChanged,
|
||||
this, &BgViewerDataView::signalUserActionPerformend);
|
||||
connect(m_pBgvController, &BgViewerController::signalViewerEventButton,
|
||||
this, &BgViewerDataView::signalUserActionPerformend);
|
||||
|
||||
if (fetchBuildingDataOnCreation)
|
||||
fetchBuildingList();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void BgViewerDataView::fetchBuildingList()
|
||||
{
|
||||
m_pBgvController->excGetBuildingList();
|
||||
}
|
||||
|
||||
|
||||
void BgViewerDataView::onViewerEventWidgetMaximized(const QString &featureID)
|
||||
{
|
||||
QModelIndex idx = m_pModel->getModelIndex(featureID);
|
||||
|
||||
if (idx.isValid())
|
||||
{
|
||||
m_ui->widget->selectRow(idx);
|
||||
emit signalUserActionPerformend();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void BgViewerDataView::onViewerEventWidgetFocused(const QString &featureID)
|
||||
{
|
||||
QModelIndex idx = m_pModel->getModelIndex(featureID);
|
||||
|
||||
if (idx.isValid())
|
||||
m_ui->widget->selectRow(idx);
|
||||
}
|
||||
|
||||
|
||||
bool BgViewerDataView::eventFilter(QObject *object, QEvent *event)
|
||||
{
|
||||
if (object == m_ui->widget)
|
||||
{
|
||||
if (event->type() == QEvent::KeyPress)
|
||||
{
|
||||
QKeyEvent *pKeyEvent = static_cast<QKeyEvent *>(event);
|
||||
if (pKeyEvent->key() == Qt::Key_Delete)
|
||||
{
|
||||
const QModelIndex idx = m_ui->widget->currentIndex();
|
||||
|
||||
if (idx.row() >= 0)
|
||||
{
|
||||
BuildingTuple row = m_pModel->getRowData(idx.row());
|
||||
m_pBgvController->closeBuilding(row.buildingId);
|
||||
emit signalUserActionPerformend();
|
||||
}
|
||||
}
|
||||
else if (pKeyEvent->key() == Qt::Key_F5)
|
||||
fetchBuildingList();
|
||||
}
|
||||
}
|
||||
|
||||
return QWidget::eventFilter(object, event);
|
||||
}
|
||||
|
||||
|
||||
void BgViewerDataView::onLtsDataView_DoubleClicked()
|
||||
{
|
||||
const QModelIndex idx = m_ui->widget->currentIndex();
|
||||
|
||||
if (idx.row() >= 0)
|
||||
{
|
||||
BuildingTuple row = m_pModel->getRowData(idx.row());
|
||||
|
||||
/* Try to open the requested building in any case.
|
||||
* If it is not opened, it will be opened.
|
||||
* If it is already opened, it will be highlighted
|
||||
*/
|
||||
m_pBgvController->openBuilding(row.buildingId);
|
||||
emit signalUserActionPerformend();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void BgViewerDataView::onLtsDataView_selectionChanged()
|
||||
{
|
||||
/*
|
||||
* This function is not only called when "a selection changed" (as assumed) but also
|
||||
* if the user, e.g., double clicks on a row. Hence, we check the column here again.
|
||||
*/
|
||||
const auto mil = m_ui->widget->selectedRows();
|
||||
|
||||
if (mil.size() == 1)
|
||||
{
|
||||
const auto &idx = mil.first();
|
||||
if (idx.row() != m_lastSelectedRow)
|
||||
{
|
||||
m_lastSelectedRow = idx.row();
|
||||
BuildingTuple row = m_pModel->getRowData(idx.row());
|
||||
m_pBgvController->excHighlightView(row.buildingId);
|
||||
emit signalCurrentSelectionChanged(idx);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void BgViewerDataView::onLtsDataView_onEditBuilding()
|
||||
{
|
||||
const auto mil = m_ui->widget->selectedRows();
|
||||
if (mil.size() == 1)
|
||||
{
|
||||
BuildingTuple row = m_pModel->getRowData(mil.first().row());
|
||||
emit signalEditBuilding(row.buildingId);
|
||||
emit signalUserActionPerformend();
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace BuildingViewer
|
||||
|
||||
@@ -0,0 +1,66 @@
|
||||
/**
|
||||
* @RDE_HEADER@
|
||||
* HMI Plugin for MeteoDataManagement - Meteo Data Overview Dialog
|
||||
* $Id$
|
||||
* $HeadURL$
|
||||
* $Author$
|
||||
* Created by Patric Karwat, SLSE, 2016-10-05
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <QWidget>
|
||||
#include <Plugins/InfrastructureManagement/ism_data_plugin_interface.h>
|
||||
#include <Common/logger.h>
|
||||
|
||||
|
||||
namespace Ui
|
||||
{
|
||||
class BgViewerDataView;
|
||||
}
|
||||
|
||||
|
||||
namespace BuildingViewer
|
||||
{
|
||||
class BgViewerDataViewModel;
|
||||
class BgViewerController;
|
||||
|
||||
class BgViewerDataView final : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit BgViewerDataView(QWidget *parent = nullptr);
|
||||
~BgViewerDataView();
|
||||
|
||||
bool init(BgViewerController *pBgvController,
|
||||
const std::shared_ptr<InfrastructureManagement::Interface::Dtc> &ismDtc,
|
||||
bool fetchBuildingDataOnCreation);
|
||||
|
||||
bool eventFilter(QObject *object, QEvent *event) override;
|
||||
|
||||
public slots:
|
||||
void fetchBuildingList();
|
||||
void onLtsDataView_DoubleClicked();
|
||||
void onLtsDataView_selectionChanged();
|
||||
void onLtsDataView_onEditBuilding();
|
||||
|
||||
signals:
|
||||
void signalUserActionPerformend(); // Emitted when user open, closes, etc. a building view. Solely used by the topic editor to detect changes and to enable the "Apply" button
|
||||
void signalCurrentSelectionChanged(const QModelIndex &idx);
|
||||
void signalEditBuilding(const QString &strFeatureID);
|
||||
|
||||
|
||||
public slots:
|
||||
void onViewerEventWidgetMaximized(const QString &featureID);
|
||||
void onViewerEventWidgetFocused(const QString &featureID);
|
||||
|
||||
private:
|
||||
Ui::BgViewerDataView *m_ui = nullptr;
|
||||
BgViewerDataViewModel *m_pModel = nullptr;
|
||||
BgViewerController *m_pBgvController = nullptr;
|
||||
int m_lastSelectedRow { -1 };
|
||||
|
||||
NGL::INGLLogger &m_logger;
|
||||
};
|
||||
} // namespace BuildingViewer
|
||||
@@ -0,0 +1,37 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>BgViewerDataView</class>
|
||||
<widget class="QWidget" name="BgViewerDataView">
|
||||
<property name="windowTitle">
|
||||
<string notr="true"/>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<widget class="LtsDataView::LtsDataView" name="widget">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="MinimumExpanding" vsizetype="MinimumExpanding">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>250</height>
|
||||
</size>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<customwidgets>
|
||||
<customwidget>
|
||||
<class>LtsDataView::LtsDataView</class>
|
||||
<extends>QWidget</extends>
|
||||
<header>LtsDataView/lts_data_view.h</header>
|
||||
<container>1</container>
|
||||
</customwidget>
|
||||
</customwidgets>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
||||
@@ -0,0 +1,551 @@
|
||||
/**
|
||||
* @RDE_HEADER@
|
||||
* Gui Plugin for BuildingViewer
|
||||
* $Id$
|
||||
* $HeadURL$
|
||||
* $Author$
|
||||
*
|
||||
* Created by Mike Wille, SLSE, 2017-05-15
|
||||
*/
|
||||
|
||||
#include "bdv_viewer_gui_plugin.h"
|
||||
|
||||
#include <Proxies/Buildings/bld_operator_rights.h>
|
||||
#include <Plugins/BuildingViewer/Common/logger.h>
|
||||
#include <LtsSession/lts_session.h>
|
||||
#include <LtsWidgets/lts_dialog.h>
|
||||
#include <LtsWidgets/lts_splash.h>
|
||||
#include <LtsWidgets/lts_message_dialog.h>
|
||||
#include <LtsWidgets/lts_base_layout_widget.h>
|
||||
#include <LtsAppManager/lts_app_manager.h>
|
||||
|
||||
#include <QTimer>
|
||||
#include <QVBoxLayout>
|
||||
|
||||
#include "bdv_viewer_data_dialog.h"
|
||||
#include "bdv_viewer_data_view.h"
|
||||
#include "BuildingEdit/bdv_building_edit.h"
|
||||
#include "bdv_viewer_state.h"
|
||||
#include "bdv_viewer_settings.h"
|
||||
#include "bdv_replay_handler.h"
|
||||
#include "bdv_thread_video_exporter.h"
|
||||
#include "bdv_topic_replay_interface.h"
|
||||
#include "bdv_viewer_gui_plugin_provider.h"
|
||||
|
||||
#include <Common/bdv_helper.h>
|
||||
#include <Common/bdv_controller.h>
|
||||
#include <Common/bdv_plugin_provider.h>
|
||||
|
||||
|
||||
namespace BuildingViewer
|
||||
{
|
||||
|
||||
std::shared_ptr<GuiPluginBase::Interface> GuiPlugin::createGuiInterface(LtsSession::LtsSession *session)
|
||||
{
|
||||
return std::make_shared<BuildingViewer::InterfaceImpl>(session);
|
||||
}
|
||||
|
||||
|
||||
InterfaceImpl::InterfaceImpl(LtsSession::LtsSession *session)
|
||||
: GuiPluginBase::Interface(session, getLogger("InterfaceImpl"))
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
void InterfaceImpl::init()
|
||||
{
|
||||
connect(this, &InterfaceImpl::signalInitDone,
|
||||
m_session, &LtsSession::LtsSession::slotPluginInitDone,
|
||||
static_cast<Qt::ConnectionType>(Qt::QueuedConnection | Qt::UniqueConnection));
|
||||
|
||||
connect (m_session, &LtsSession::LtsSession::sessionAboutToBeDestroyed,
|
||||
this, &InterfaceImpl::closeAll);
|
||||
|
||||
connect(m_session, &LtsSession::LtsSession::signalTakeOverBdv,
|
||||
this, &InterfaceImpl::takeOverBdv);
|
||||
|
||||
if (!m_bgViewerController)
|
||||
{
|
||||
auto ts = getOrCreateBgViewer(true);
|
||||
if (ts.get()->currentDdsConnParams() == m_session->connParams() || ts.get()->currentDdsConnParams().exerciseId == -1)
|
||||
m_bgViewerController = ts;
|
||||
}
|
||||
|
||||
emit signalInitDone();
|
||||
}
|
||||
|
||||
|
||||
bool InterfaceImpl::fetchInterfaces()
|
||||
{
|
||||
if (m_session->partitionType() == IDL::PartitionType::Global)
|
||||
return false;
|
||||
|
||||
DEBUG_LOG(m_logger) << std::hex << this << " BgViewer fetchInterfaces";
|
||||
|
||||
// if (!m_session->getDtc<InfrastructureManagement::DataInterface>(m_ismDtc))
|
||||
// {
|
||||
// ERROR_LOG(m_logger) << "Fetching 'm_ismDtc' failed!";
|
||||
// return false;
|
||||
// }
|
||||
|
||||
// if (!m_session->getFtc<InfrastructureManagement::DataInterface>(m_ismFtc))
|
||||
// {
|
||||
// ERROR_LOG(m_logger) << "Fetching 'm_ismFtc' failed!";
|
||||
// return false;
|
||||
// }
|
||||
|
||||
if (!m_session->getDtc<Buildings::DataInterface>(m_bldDtc))
|
||||
{
|
||||
ERROR_LOG(m_logger) << "Fetching 'm_bldDtc' failed!";
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!m_session->getFtc<Buildings::DataInterface>(m_bldFtc))
|
||||
{
|
||||
ERROR_LOG(m_logger) << "Fetching 'm_bldFtc' failed!";
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!m_pluginProvider)
|
||||
m_pluginProvider = new BdvPluginProvider(m_session, this);
|
||||
if (!m_pluginProvider->init())
|
||||
{
|
||||
delete m_pluginProvider;
|
||||
m_pluginProvider = nullptr;
|
||||
}
|
||||
return m_pluginProvider != nullptr;
|
||||
}
|
||||
|
||||
|
||||
void InterfaceImpl::clearInterfaces()
|
||||
{
|
||||
if (m_bgViewerController && m_bgViewerController->activeSession() == m_pluginProvider)
|
||||
m_bgViewerController->clearInterfaces(m_session->connParams());
|
||||
delete m_pluginProvider;
|
||||
m_pluginProvider = nullptr;
|
||||
|
||||
// why?
|
||||
if (m_session->partitionType() == IDL::PartitionType::Global || !m_iamTheApp)
|
||||
return;
|
||||
|
||||
DEBUG_LOG(m_logger) << std::hex << this << " clearInterfaces";
|
||||
|
||||
//m_ismDtc = nullptr;
|
||||
//m_ismFtc = nullptr;
|
||||
m_bldDtc = nullptr;
|
||||
m_bldFtc = nullptr;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Called by 'BgViewerDataView' if the user selected a building from the building list and hit the "edit" button.
|
||||
*/
|
||||
BuildingViewer::BuildingEdit *InterfaceImpl::onEditBuilding(const QString &featureId)
|
||||
{
|
||||
int32_t buildingDatabaseId = BuildingViewer::featureId2DatabaseId(featureId);
|
||||
|
||||
if (buildingDatabaseId <= 0)
|
||||
{
|
||||
QString strWarning = QStringLiteral("'featureId2DatabaseId()' did not return a valid database id. Has model with featureID '") + featureId + QStringLiteral("' been loaded with the debug dialog? In this case there is no mapping for this model in the database!");
|
||||
WARNING_LOG(m_logger) << strWarning;
|
||||
|
||||
#ifdef LTS_DEBUG
|
||||
LtsWidgets::LtsMessageDialog::showMessage(m_pDialog, QStringLiteral("DEBUG:\n") + strWarning);
|
||||
#endif
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
std::shared_ptr<InfrastructureManagement::Interface::Dtc> ismDtc;
|
||||
std::shared_ptr<InfrastructureManagement::Interface::Ftc> ismFtc;
|
||||
if (!m_session->getDtc<InfrastructureManagement::DataInterface>(ismDtc) ||
|
||||
!m_session->getFtc<InfrastructureManagement::DataInterface>(ismFtc))
|
||||
{
|
||||
new LtsWidgets::LtsMessageDialogNew(m_session->baseLayout(), tr("The Infrastructure Management is not available!"), tr("Cannot open Building Edit"));
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
BuildingViewer::BuildingEdit *pBuildingEditDialog = new BuildingViewer::BuildingEdit(m_pDialog);
|
||||
pBuildingEditDialog->init(buildingDatabaseId, ismDtc, ismFtc, m_bldDtc, m_bldFtc);
|
||||
m_pDialog->addDialog(pBuildingEditDialog, menuGroup(), QLatin1String("bdvBuildingEdit") + QString::number(buildingDatabaseId), LtsWidgets::LayoutArea::eDialogTab);
|
||||
return pBuildingEditDialog;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Directly called by 'BuildingViewer::CommunicationInterface' if 'signalViewerEventRoomNameClicked' is received.
|
||||
* Does exaclty the same what 'onEditBuilding(const QString& featureId)' does. In addition, the room id causes
|
||||
* a row selection within the newly created dialog.
|
||||
*/
|
||||
void InterfaceImpl::onRoomNameClicked(const QString &featureId, const QString &strRoomId)
|
||||
{
|
||||
BuildingViewer::BuildingEdit *pBuildingEditDialog = onEditBuilding(featureId);
|
||||
|
||||
if (!pBuildingEditDialog)
|
||||
return;
|
||||
|
||||
bool convertOk = false;
|
||||
int32_t roomMountingPointId = strRoomId.toInt(&convertOk);
|
||||
|
||||
if (!convertOk)
|
||||
{
|
||||
QString strWarning = QStringLiteral("onEditBuilding: Could not convert strRoomId to int but this should be possible since the roomId is actually a mountpoint id. featureId: ") + featureId + QStringLiteral(", strRoomId: ") + strRoomId;
|
||||
WARNING_LOG(m_logger) << strWarning;
|
||||
|
||||
#ifdef LTS_DEBUG
|
||||
LtsWidgets::LtsMessageDialog::showMessage(m_pDialog, QStringLiteral("DEBUG:\n") + strWarning);
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
|
||||
pBuildingEditDialog->selectRoomRow(roomMountingPointId);
|
||||
}
|
||||
|
||||
void InterfaceImpl::closeAll(LtsSession::LtsSession *session)
|
||||
{
|
||||
DEBUG_LOG(m_logger) << "close all " << m_session;
|
||||
|
||||
if(!m_bgViewerController)
|
||||
return;
|
||||
|
||||
if(m_session == session && m_bgViewerController->currentDdsConnParams() == session->connParams())
|
||||
{
|
||||
WARNING_LOG(m_logger) << "!!!! I DIE NOW MY FELLOW";
|
||||
m_bgViewerController->closeAll();
|
||||
}
|
||||
}
|
||||
|
||||
bool InterfaceImpl::takeOverBdv()
|
||||
{
|
||||
DEBUG_LOG(m_logger) << "It's me << " << m_session <<" I'll take care of it now" ;
|
||||
if (!m_bgViewerController)
|
||||
m_bgViewerController = getOrCreateBgViewer();
|
||||
connect(m_bgViewerController.get(), &BgViewerController::signalReceivedViewState, this, &InterfaceImpl::onReceivedViewState);
|
||||
if (!m_pluginProvider)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
m_bgViewerController->excGetViewState();
|
||||
if (!m_bgViewerController->startBgViewerAppInSession(m_pluginProvider))
|
||||
return false;
|
||||
|
||||
if (!m_bgViewerController->forceInit(m_pluginProvider))
|
||||
return false;
|
||||
if (!m_viewState.isUndefined())
|
||||
m_bgViewerController->excRestoreViewState(m_viewState);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
LtsWidgets::LtsDialog *InterfaceImpl::onShowSettings(QWidget *parent)
|
||||
{
|
||||
if (!m_bgViewerController)
|
||||
return nullptr;
|
||||
BgViewerSettingsView *dialog = new BgViewerSettingsView(m_bgViewerController.get(),
|
||||
parent);
|
||||
return dialog;
|
||||
}
|
||||
|
||||
|
||||
LtsWidgets::LtsDialog *InterfaceImpl::onShowData(QWidget *parent)
|
||||
{
|
||||
if (!m_bgViewerController)
|
||||
{
|
||||
new LtsWidgets::LtsMessageDialogNew(m_session->baseLayout(), tr("The Building Viewer COntroller is not available!"), tr("Cannot open Show Data"));
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
std::shared_ptr<InfrastructureManagement::Interface::Dtc> ismDtc;
|
||||
if (!m_session->getDtc<InfrastructureManagement::DataInterface>(ismDtc))
|
||||
{
|
||||
new LtsWidgets::LtsMessageDialogNew(m_session->baseLayout(), tr("The Infrastructure Management is not available!"), tr("Cannot open Show Data"));
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
BgViewerDataViewDialog *dialog = new BgViewerDataViewDialog(parent);
|
||||
if (!dialog->init(m_bgViewerController.get(), ismDtc, true))
|
||||
{
|
||||
delete dialog;
|
||||
ERROR_LOG(m_logger) << "cannot initialize BgViewerDataViewDialog";
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
connect(m_bgViewerController.get(), &BgViewerController::bgvAppIsInitialized,
|
||||
dialog, &BgViewerDataViewDialog::fetchBuildingList);
|
||||
connect(this, &InterfaceImpl::signalFetchBuildingList,
|
||||
dialog, &BgViewerDataViewDialog::fetchBuildingList);
|
||||
connect(dialog, &BgViewerDataViewDialog::signalEditBuilding,
|
||||
this, &InterfaceImpl::onEditBuilding);
|
||||
|
||||
return dialog;
|
||||
}
|
||||
|
||||
|
||||
LtsWidgets::LtsDialog *InterfaceImpl::onShowState(QWidget *parent)
|
||||
{
|
||||
if (!m_bgViewerController)
|
||||
return nullptr;
|
||||
BgViewerStateView *dialog = new BgViewerStateView(m_bgViewerController.get(), parent);
|
||||
connect(dialog, &BgViewerStateView::signalFetchBuildingList, this, &InterfaceImpl::signalFetchBuildingList);
|
||||
|
||||
return dialog;
|
||||
}
|
||||
|
||||
|
||||
QVector<LtsWidgets::PluginData> InterfaceImpl::getActions()
|
||||
{
|
||||
QVector<LtsWidgets::PluginData> ret;
|
||||
|
||||
LtsWidgets::PluginData plData;
|
||||
plData.menuGroup = menuGroup();
|
||||
|
||||
bool skriptEditorMode = (m_session->app() == LtsAppDescriptor::App::ScriptEditorEssentialsView);
|
||||
|
||||
if (!skriptEditorMode)
|
||||
{
|
||||
plData.menuText = tr("Global Settings");
|
||||
plData.identifier = QLatin1String("PluginDataSettings");
|
||||
plData.menuIcon = QIcon(QLatin1String("icon:show_building_configuration.svg"));
|
||||
plData.operatorRight = OperatorRights::BuildingViewerSettingsView;
|
||||
plData.createWidgetFunc = [this](QWidget * parent)
|
||||
{
|
||||
return onShowSettings(parent);
|
||||
};
|
||||
ret.append(plData);
|
||||
|
||||
|
||||
plData.menuText = tr("Building List");
|
||||
plData.identifier = QLatin1String("PluginDataBuildingList");
|
||||
plData.menuIcon = QIcon(QLatin1String("icon:evaluate.svg"));
|
||||
plData.operatorRight = OperatorRights::BuildingListView;
|
||||
plData.createWidgetFunc = [this](QWidget * parent)
|
||||
{
|
||||
return onShowData(parent);
|
||||
};
|
||||
ret.append(plData);
|
||||
|
||||
|
||||
#ifdef LTS_DEBUG
|
||||
plData.menuText = QStringLiteral("View State (Debug)");
|
||||
plData.identifier = QLatin1String("PluginDataViewStateDebug");
|
||||
plData.menuIcon = QIcon(QLatin1String("icon:configure_buildings.svg"));
|
||||
plData.operatorRight = OperatorRights::ViewStateDebug;
|
||||
plData.createWidgetFunc = [this](QWidget * parent)
|
||||
{
|
||||
return onShowState(parent);
|
||||
};
|
||||
ret.append(plData);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
if (getFlags().testFlag(LtsAppDescriptor::PluginInfo::Flag::MAIN))
|
||||
{
|
||||
plData.layoutArea = LtsWidgets::LayoutArea::eMainTab;
|
||||
plData.createInstant = LtsWidgets::CreateInstantType::CreateInstantAndDiscardAction;
|
||||
} // else (as dialog) = rather unlikely..
|
||||
|
||||
plData.menuText = tr("Show Building Viewer");
|
||||
plData.identifier = QLatin1String("bdvShowBdv");
|
||||
plData.operatorRight = OperatorRights::BuildingViewerShow;
|
||||
plData.createWidgetFunc = [this](QWidget *)
|
||||
{
|
||||
return onShowBuildingViewerDialog();
|
||||
};
|
||||
ret.append(plData);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
std::shared_ptr<BgViewerController> InterfaceImpl::getOrCreateBgViewer(bool bCreateIfNotExists)
|
||||
{
|
||||
static std::weak_ptr<BgViewerController> s_singleton;
|
||||
auto sp = s_singleton.lock();
|
||||
if (!sp)
|
||||
{
|
||||
if (!bCreateIfNotExists)
|
||||
return {};
|
||||
sp = std::make_shared<BgViewerController>(); // no parent!
|
||||
s_singleton = sp;
|
||||
}
|
||||
return sp;
|
||||
}
|
||||
|
||||
LtsWidgets::LtsDialog *InterfaceImpl::onShowBuildingViewerDialog()
|
||||
{
|
||||
DEBUG_LOG(m_logger) << this << ", onShowBuildingViewerDialog()";
|
||||
// Building edit dialog should also be displayed if the user clicks on a room name and the appropriate dialog has not been opened so far.
|
||||
|
||||
if (!m_bgViewerController)
|
||||
m_bgViewerController = getOrCreateBgViewer();
|
||||
|
||||
if (!m_bgViewerController->init(m_pluginProvider, true))
|
||||
return nullptr;
|
||||
|
||||
// NOTE: do not set dependency here, as onShowBuildingViewerDialog is always called from within the building viewer app's session itself
|
||||
|
||||
m_pDialog = new BuildingViewerLtsDialog;
|
||||
m_pLayout = new QVBoxLayout(m_pDialog);
|
||||
m_pLayout->addWidget(m_bgViewerController->getBgViewerWidget());
|
||||
|
||||
connect(m_bgViewerController.get(), &BgViewerController::signalViewerEventRoomNameClicked,
|
||||
this, &InterfaceImpl::onRoomNameClicked);
|
||||
|
||||
m_iamTheApp = true;
|
||||
return m_pDialog;
|
||||
}
|
||||
|
||||
//void InterfaceImpl::setBgViewerSessionDependency(/*LtsSession::LtsSession *parentSession*/) // prevents mmm to let a secondary widget be placed above this app => jetzt doch: GUEZE-2619
|
||||
//{
|
||||
// // prevent mmm from replacing
|
||||
// auto app = m_bgViewerController->app();
|
||||
// if (app)
|
||||
// {
|
||||
// LtsSession::LtsSession *session = app->getSession(m_pluginProvider->connParams().partitionType, m_pluginProvider->connParams().partitionId);
|
||||
// if (session)
|
||||
// {
|
||||
// session->setDependency(m_session);
|
||||
// /*DEBUG_*/ERROR_LOG(m_logger) << "session " << session << " now has dependency to parent session " << m_session;
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// ERROR_LOG(m_logger) << "failed to set dependency for bgv app (session unavailable)";
|
||||
// }
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// ERROR_LOG(m_logger) << "failed to set dependency for bgv app (app unavailable)";
|
||||
// }
|
||||
//}
|
||||
|
||||
bool InterfaceImpl::showBuildingViewer(LtsSession::LtsSession *parentSession, int buildingId)
|
||||
{
|
||||
Q_UNUSED(parentSession);
|
||||
DEBUG_LOG(m_logger) << "showBuildingViewer (" << m_bgViewerController << ") - starting";
|
||||
|
||||
DEBUG_LOG(m_logger) << this << ", showBuildingViewer (" << buildingId << ")";
|
||||
if (!m_bgViewerController)
|
||||
m_bgViewerController = getOrCreateBgViewer();
|
||||
bool needStart = !m_bgViewerController->isBgViewerApplicationRunning();
|
||||
|
||||
if (!m_pluginProvider || m_pluginProvider->connParams() != m_bgViewerController->currentDdsConnParams())
|
||||
{
|
||||
delete m_pluginProvider;
|
||||
m_pluginProvider = new BdvPluginProvider(m_session, this);
|
||||
if (!m_pluginProvider->init())
|
||||
{
|
||||
delete m_pluginProvider;
|
||||
m_pluginProvider = nullptr;
|
||||
return false;
|
||||
}
|
||||
needStart = true;
|
||||
}
|
||||
if (needStart)
|
||||
{
|
||||
DEBUG_LOG(m_logger) << "showBuildingViewer (" << buildingId << ") - starting";
|
||||
if (!m_bgViewerController->startBgViewerAppInSession(m_pluginProvider))
|
||||
return false;
|
||||
|
||||
if (!m_bgViewerController->init(m_pluginProvider))
|
||||
return false;
|
||||
}
|
||||
|
||||
// setBgViewerSessionDependency(/*parentSession*/);
|
||||
|
||||
if (buildingId > 0)
|
||||
{
|
||||
m_buildingId= buildingId;
|
||||
int time = needStart ? 3000 : 500;
|
||||
QTimer::singleShot(time, this , [this]()
|
||||
{
|
||||
m_bgViewerController->openBuilding(BuildingViewer::databaseId2FeatureId(m_buildingId));
|
||||
m_buildingId=0;
|
||||
});
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------------------------------------------
|
||||
// Script Editor Topic Editor:
|
||||
// --------------------------------------------------------------------------------------------------------------
|
||||
bool InterfaceImpl::initTopicEditor()
|
||||
{
|
||||
if (!m_pluginProvider)
|
||||
m_pluginProvider = new BdvPluginProvider(m_session, this);
|
||||
if (!m_pluginProvider->init())
|
||||
{
|
||||
delete m_pluginProvider;
|
||||
m_pluginProvider = nullptr;
|
||||
return false;
|
||||
}
|
||||
|
||||
// We don't start BG here when we are NOT in replay!
|
||||
// the EssentialsView will start the right one no worries
|
||||
|
||||
if (m_pluginProvider->isReplayPartition())
|
||||
{
|
||||
m_bgViewerController = getOrCreateBgViewer(/*false*/); // no create since we won't/can't do an init here
|
||||
|
||||
if(!m_bgViewerController->forceInit(m_pluginProvider))
|
||||
return false;
|
||||
|
||||
if (!m_bgViewerController->init(m_pluginProvider, true))
|
||||
return false;
|
||||
|
||||
// setBgViewerSessionDependency(/*m_session*/);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
void InterfaceImpl::finishTopicEditor()
|
||||
{
|
||||
if (m_bgViewerController)
|
||||
m_bgViewerController->clearInterfaces(m_session->connParams());
|
||||
}
|
||||
|
||||
|
||||
TopicEditorBase::TopicEditor *InterfaceImpl::createTopicEditor(const TopicEditorBase::TopicData &data)
|
||||
{
|
||||
if (!m_bgViewerController)
|
||||
m_bgViewerController = getOrCreateBgViewer(false); // no create since we won't/can't do an init here
|
||||
|
||||
PluginProvider *session = m_bgViewerController ? m_bgViewerController->activeSession() : nullptr;
|
||||
|
||||
if (session == nullptr)
|
||||
{
|
||||
ERROR_LOG(m_logger) << this << ", bgv controller has no active session";
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
||||
std::shared_ptr<InfrastructureManagement::Interface::Dtc> ismDtc = session->ismDtc();
|
||||
if (!ismDtc)
|
||||
{
|
||||
ERROR_LOG(m_logger) << "cannot fetch ism dtc from bgv controller's active session";
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
||||
BgViewerDataView *pBgvDataView = new BgViewerDataView;
|
||||
if (!pBgvDataView->init(m_bgViewerController.get(), ismDtc, false))
|
||||
{
|
||||
delete pBgvDataView;
|
||||
ERROR_LOG(m_logger) << "cannot initialize BgViewerDataView";
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
BuildingViewer::TopicEditor *editor = new BuildingViewer::TopicEditor(m_session, m_bgViewerController.get(), pBgvDataView);
|
||||
editor->setTopicData(data);
|
||||
return editor;
|
||||
}
|
||||
|
||||
|
||||
TopicReplay::Interface *InterfaceImpl::createInterface(TopicEditorBase::TopicType)
|
||||
{
|
||||
if (!initTopicEditor() || !m_bgViewerController)
|
||||
return nullptr;
|
||||
return new TopicReplayInterface(m_bgViewerController.get(), m_session);
|
||||
}
|
||||
|
||||
} // namespace BuildingViewer
|
||||
@@ -0,0 +1,157 @@
|
||||
/**
|
||||
* @RDE_HEADER@
|
||||
* Gui Plugin for BuildingViewer
|
||||
* $Id$
|
||||
* $HeadURL$
|
||||
* $Author$
|
||||
*
|
||||
* Created by Mike Wille, SLSE, 2017-05-15
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <PluginInterfaces/gui_plugin_interface.h>
|
||||
#include <BuildingViewer/bdv_viewer_gui_plugin_interface.h>
|
||||
#include <Plugins/InfrastructureManagement/ism_data_plugin_interface.h>
|
||||
#include <Plugins/Buildings/bld_data_plugin_interface.h>
|
||||
#include <LtsWidgets/lts_dialog.h>
|
||||
#include <Common/logger.h>
|
||||
#include "TopicEditor/topic_editor.h"
|
||||
#include <QTimer>
|
||||
|
||||
|
||||
class QVBoxLayout;
|
||||
namespace BuildingViewer
|
||||
{
|
||||
class BuildingEdit;
|
||||
class BgViewerController;
|
||||
class BdvPluginProvider;
|
||||
|
||||
class GuiPlugin final : public QObject, public GuiPluginBase::Plugin
|
||||
{
|
||||
Q_PLUGIN_METADATA(IID "gui:3:bdv")
|
||||
Q_INTERFACES(GuiPluginBase::Plugin)
|
||||
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit GuiPlugin() = default;
|
||||
~GuiPlugin() = default;
|
||||
|
||||
QString pluginName() override
|
||||
{
|
||||
return QLatin1String("BuildingViewerGuiPlugin");
|
||||
}
|
||||
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::Replay);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* Main widget of the BuildingViewer-Plugin.
|
||||
* Used by InterfaceImpl::onShowBuildingViewerDialog
|
||||
*/
|
||||
class BuildingViewerLtsDialog : public LtsWidgets::LtsDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
BuildingViewerLtsDialog()
|
||||
: LtsWidgets::LtsDialog(nullptr, LtsWidgets::ButtonCombination::SeamlessDialog, false)
|
||||
{
|
||||
setUnchangeable(true);
|
||||
}
|
||||
|
||||
void aboutToClose() override
|
||||
{
|
||||
emit signalHideLiveVideo();
|
||||
}
|
||||
|
||||
signals:
|
||||
void signalHideLiveVideo();
|
||||
|
||||
private:
|
||||
void retranslate() override
|
||||
{
|
||||
// lupdate doesn't like translate(tr("foo")) ...
|
||||
const QString txt(tr("Building Viewer"));
|
||||
translate(txt);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
class InterfaceImpl final : public QObject, public GuiPluginBase::Interface, public BuildingViewer::ForeignGuiInterface
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit InterfaceImpl(LtsSession::LtsSession *session);
|
||||
|
||||
QVector<LtsWidgets::PluginData> getActions() override;
|
||||
QString menuGroup() const override
|
||||
{
|
||||
return tr("Building Viewer");
|
||||
}
|
||||
|
||||
void init() override;
|
||||
bool fetchInterfaces() override;
|
||||
void clearInterfaces() override;
|
||||
|
||||
bool availableInPartition(IDL::PartitionType partition) const override
|
||||
{
|
||||
return (partition == IDL::PartitionType::Exercise ||
|
||||
partition == IDL::PartitionType::Replay);
|
||||
}
|
||||
|
||||
bool showBuildingViewer(LtsSession::LtsSession *parentSession, int buildingId = 0) override;
|
||||
|
||||
// Script Editor Topic Editor:
|
||||
bool initTopicEditor() override;
|
||||
void finishTopicEditor() override;
|
||||
TopicEditorBase::TopicEditor *createTopicEditor(const TopicEditorBase::TopicData &data) override;
|
||||
|
||||
signals:
|
||||
void signalFetchBuildingList();
|
||||
void signalInitDone();
|
||||
|
||||
private slots:
|
||||
BuildingViewer::BuildingEdit* onEditBuilding(const QString& featureId);
|
||||
void onRoomNameClicked(const QString& featureId, const QString &strRoomId);
|
||||
void closeAll(LtsSession::LtsSession *session);
|
||||
bool takeOverBdv();
|
||||
void onReceivedViewState(const QJsonValue &state) {m_viewState = state;}
|
||||
|
||||
private:
|
||||
LtsWidgets::LtsDialog *onShowBuildingViewerDialog();
|
||||
static std::shared_ptr<BgViewerController> getOrCreateBgViewer(bool bCreateIfNotExists = true);
|
||||
// void setBgViewerSessionDependency(/*LtsSession::LtsSession *parentSession*/);
|
||||
|
||||
QJsonValue m_viewState;
|
||||
/*
|
||||
* 'InterfaceImpl::init()' is blocking the whole session/application.
|
||||
* This timer emits 'slotPluginInitDone' in case the BuildingViewer
|
||||
* initialization failed
|
||||
*/
|
||||
QTimer m_timerInitSaver;
|
||||
|
||||
LtsWidgets::LtsDialog *onShowSettings(QWidget *parent);
|
||||
LtsWidgets::LtsDialog *onShowData(QWidget *parent);
|
||||
LtsWidgets::LtsDialog *onShowState(QWidget *parent);
|
||||
|
||||
//std::shared_ptr<InfrastructureManagement::Interface::Dtc> m_ismDtc;
|
||||
//std::shared_ptr<InfrastructureManagement::Interface::Ftc> m_ismFtc;
|
||||
std::shared_ptr<Buildings::Interface::Dtc> m_bldDtc;
|
||||
std::shared_ptr<Buildings::Interface::Ftc> m_bldFtc;
|
||||
|
||||
LtsWidgets::LtsDialog *m_pDialog = nullptr;
|
||||
QVBoxLayout *m_pLayout = nullptr;
|
||||
BdvPluginProvider *m_pluginProvider = nullptr;
|
||||
std::shared_ptr<BgViewerController> m_bgViewerController;
|
||||
int m_buildingId = 0;
|
||||
bool m_iamTheApp = false;
|
||||
|
||||
TopicReplay::Interface *createInterface(TopicEditorBase::TopicType) override;
|
||||
};
|
||||
|
||||
} // namespace BuildingViewer
|
||||
+96
@@ -0,0 +1,96 @@
|
||||
/**
|
||||
* @RDE_HEADER@
|
||||
* Plugin Provider for BuildingViewer
|
||||
* $Id$
|
||||
* $HeadURL$
|
||||
* $Author$
|
||||
*
|
||||
* Created by Christian Ehrlicher , NLE, 2020-03-18
|
||||
*/
|
||||
|
||||
#include "bdv_viewer_gui_plugin_provider.h"
|
||||
|
||||
#include <LtsSession/lts_session.h>
|
||||
#include <PluginInterfaces/gui_plugin_interface.h>
|
||||
#include <AdvancedSymbology/asb_data_plugin_interface.h>
|
||||
#include <AreaEffectSimulation/aes_data_plugin_interface.h>
|
||||
#include <AudioVideoManagement/avm_data_plugin_interface.h>
|
||||
#include <Buildings/bld_data_plugin_interface.h>
|
||||
#include <Buildings/bld_info_gui_plugin_interface.h>
|
||||
#include <InfrastructureManagement/ism_data_plugin_interface.h>
|
||||
#include <SituationReplay/srp_data_plugin_interface.h>
|
||||
#include <ParticipantManagement/ppm_data_plugin_interface.h>
|
||||
#include <ProjectDataManagement/pdm_data_plugin_interface.h>
|
||||
#include <ParticipantManagement/ppm_participant_info_gui_plugin_interface.h>
|
||||
|
||||
namespace BuildingViewer
|
||||
{
|
||||
|
||||
BdvPluginProvider::BdvPluginProvider(LtsSession::LtsSession *session, QObject *parent)
|
||||
: PluginProvider(parent)
|
||||
, m_session(session)
|
||||
, m_logger(getLogger("BdvPluginProvider"))
|
||||
{}
|
||||
|
||||
bool BdvPluginProvider::init()
|
||||
{
|
||||
m_session->getForeignDataInterface<AdvancedSymbology::DataInterface>(m_asbIfc); // optional
|
||||
m_session->getDtc<SituationReplay::DataInterface>(m_srpDtc); // optionalb
|
||||
m_session->getDtc<ProjectDataManagement::DataInterface>(m_pdmDtc); // optionalb
|
||||
m_session->getDtc<AreaEffectSimulation::DataInterface>(m_aesDtc); // optionalb
|
||||
|
||||
m_session->getForeignDataInterface_NEW<AudioVideoManagement::DataInterface>(m_avmDataIfc); //optional
|
||||
|
||||
|
||||
if (!m_session->getDtc<Buildings::DataInterface>(m_bldDtc))
|
||||
{
|
||||
ERROR_LOG(m_logger) << "Fetching 'm_bldDtc' failed!";
|
||||
return false;
|
||||
}
|
||||
m_session->getForeignGuiInterface<Buildings::ForeignInfoGuiInterface>(m_bldInfoIfc); // optional
|
||||
// if (!m_session->getDtc<InfrastructureManagement::DataInterface>(m_ismDtc))
|
||||
// {
|
||||
// ERROR_LOG(m_logger) << "Fetching 'm_ismDtc' failed!";
|
||||
// return false;
|
||||
// }
|
||||
// if (!m_session->getForeignDataInterface<InfrastructureManagement::DataInterface>(m_ismDataIfc))
|
||||
// {
|
||||
// ERROR_LOG(m_logger) << "Fetching 'm_ismDataIfc' failed!";
|
||||
// return false;
|
||||
// }
|
||||
if (!m_session->getDtc<ParticipantManagement::DataInterface>(m_ppmDtc))
|
||||
{
|
||||
ERROR_LOG(m_logger) << "Fetching 'm_ppmDtc' failed!";
|
||||
return false;
|
||||
}
|
||||
m_session->getForeignGuiInterface<ParticipantManagement::ForeignParticipantInfoGuiInterface>(m_ppmParticipantInfoIfc); // optional
|
||||
return true;
|
||||
}
|
||||
|
||||
QString BdvPluginProvider::toString() const
|
||||
{
|
||||
return m_session ? m_session->toString() : QStringLiteral("????");
|
||||
}
|
||||
|
||||
LtsSession::DdsConnectionParams BdvPluginProvider::connParams() const
|
||||
{
|
||||
return m_session ? m_session->connParams() : LtsSession::DdsConnectionParams();
|
||||
}
|
||||
|
||||
std::shared_ptr<InfrastructureManagement::ForeignDataInterface> BdvPluginProvider::ismDataIfc() const
|
||||
{
|
||||
if (!m_ismDataIfc)
|
||||
m_session->getForeignDataInterface<InfrastructureManagement::DataInterface>(m_ismDataIfc);
|
||||
|
||||
return m_ismDataIfc;
|
||||
}
|
||||
|
||||
std::shared_ptr<InfrastructureManagement::Interface::Dtc> BdvPluginProvider::ismDtc() const
|
||||
{
|
||||
if (!m_ismDtc)
|
||||
m_session->getDtc<InfrastructureManagement::DataInterface>(m_ismDtc);
|
||||
|
||||
return m_ismDtc;
|
||||
}
|
||||
|
||||
} // namespace BuildingViewer
|
||||
+77
@@ -0,0 +1,77 @@
|
||||
/**
|
||||
* @RDE_HEADER@
|
||||
* Plugin Provider for BuildingViewer
|
||||
* $Id$
|
||||
* $HeadURL$
|
||||
* $Author$
|
||||
*
|
||||
* Created by Christian Ehrlicher , NLE, 2020-03-18
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <Common/bdv_plugin_provider.h>
|
||||
#include <Common/logger.h>
|
||||
#include <LtsSession/lts_session.h>
|
||||
#include <LtsSession/lts_session_data.h>
|
||||
|
||||
namespace LtsSession
|
||||
{
|
||||
class LtsSession;
|
||||
}
|
||||
namespace BuildingViewer
|
||||
{
|
||||
|
||||
class BdvPluginProvider : public PluginProvider
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit BdvPluginProvider(LtsSession::LtsSession *session, QObject *parent = nullptr);
|
||||
|
||||
bool init();
|
||||
|
||||
QString toString() const override;
|
||||
|
||||
int exerciseId() const override { return m_session ? m_session->exerciseId() : -1; }
|
||||
qint64 partitionTime() const override { return m_session ? m_session->partitionTime() : 0; }
|
||||
bool isReplayPartition() const override { return m_session ? m_session->isReplayPartition() : false; }
|
||||
bool isVisibleParty(int partyId) const override { return LtsSessionData::LtsSessionData::getInstance()->isVisibleParty(exerciseId(), partyId); }
|
||||
quintptr adr() const override {return (quintptr)m_session;}
|
||||
|
||||
LtsSession::DdsConnectionParams connParams() const override;
|
||||
|
||||
std::shared_ptr<AdvancedSymbology::ForeignDataInterface> asbIfc() const override { return m_asbIfc; }
|
||||
std::shared_ptr<AudioVideoManagement::ForeignDataInterface> avmDataIfc() const override { return m_avmDataIfc; }
|
||||
std::shared_ptr<Buildings::Interface::Dtc> bldDtc() const override { return m_bldDtc; }
|
||||
std::shared_ptr<Buildings::ForeignInfoGuiInterface> bldInfoIfc() const override { return m_bldInfoIfc; }
|
||||
std::shared_ptr<InfrastructureManagement::Interface::Dtc> ismDtc() const override;
|
||||
std::shared_ptr<InfrastructureManagement::ForeignDataInterface> ismDataIfc() const override;
|
||||
std::shared_ptr<AreaEffectSimulation::Interface::Dtc> aesDtc() const override { return m_aesDtc; }
|
||||
std::shared_ptr<ParticipantManagement::Interface::Dtc> ppmDtc() const override { return m_ppmDtc; }
|
||||
std::shared_ptr<ProjectDataManagement::Interface::Dtc> pdmDtc() const override { return m_pdmDtc; }
|
||||
|
||||
std::shared_ptr<SituationReplay::Interface::Dtc> srpDtc() const override { return m_srpDtc; }
|
||||
|
||||
std::shared_ptr<ParticipantManagement::ForeignParticipantInfoGuiInterface> ppmParticipantInfoIfc() const override { return m_ppmParticipantInfoIfc; }
|
||||
|
||||
//private:
|
||||
LtsSession::LtsSession *m_session;
|
||||
|
||||
private:
|
||||
std::shared_ptr<AdvancedSymbology::ForeignDataInterface> m_asbIfc; // optional
|
||||
std::shared_ptr<AudioVideoManagement::ForeignDataInterface> m_avmDataIfc;
|
||||
std::shared_ptr<Buildings::Interface::Dtc> m_bldDtc;
|
||||
std::shared_ptr<Buildings::ForeignInfoGuiInterface> m_bldInfoIfc; // optional
|
||||
mutable std::shared_ptr<InfrastructureManagement::Interface::Dtc> m_ismDtc;
|
||||
|
||||
mutable std::shared_ptr<InfrastructureManagement::ForeignDataInterface> m_ismDataIfc;
|
||||
std::shared_ptr<AreaEffectSimulation::Interface::Dtc> m_aesDtc; // optional
|
||||
std::shared_ptr<ParticipantManagement::Interface::Dtc> m_ppmDtc; // optional
|
||||
std::shared_ptr<SituationReplay::Interface::Dtc> m_srpDtc; // optional
|
||||
std::shared_ptr<ProjectDataManagement::Interface::Dtc> m_pdmDtc; //optional
|
||||
std::shared_ptr<ParticipantManagement::ForeignParticipantInfoGuiInterface> m_ppmParticipantInfoIfc; // optional
|
||||
|
||||
NGL::INGLLogger &m_logger;
|
||||
};
|
||||
|
||||
} // namespace BuildingViewer
|
||||
@@ -0,0 +1,142 @@
|
||||
/**
|
||||
* @RDE_HEADER@
|
||||
* HMI Plugin for MeteoDataManagement - Meteo Data Overview Dialog
|
||||
* $Id$
|
||||
* $HeadURL$
|
||||
* $Author$
|
||||
* Created by Patric Karwat, SLSE, 2016-10-05
|
||||
*/
|
||||
|
||||
#include "ui_bdv_viewer_settings.h"
|
||||
#include "bdv_viewer_settings.h"
|
||||
#include <Common/bdv_controller.h>
|
||||
|
||||
#include <LtsUtilsSettings/settings.h>
|
||||
|
||||
namespace BuildingViewer
|
||||
{
|
||||
static QVariant getSetting(const QString &key, const QVariant &def)
|
||||
{
|
||||
return LtsUtils::OperatorSettings::getInstance()->value(QStringLiteral("BgViewer"), key, def);
|
||||
}
|
||||
|
||||
static void setSetting(const QString &key, const QVariant &val)
|
||||
{
|
||||
LtsUtils::OperatorSettings::getInstance()->setValue(QStringLiteral("BgViewer"), key, val);
|
||||
}
|
||||
|
||||
BgViewerSettingsView::BgViewerSettingsView(BgViewerController *pBgvController,
|
||||
QWidget *parent)
|
||||
: LtsWidgets::LtsDialog(parent, LtsWidgets::ButtonCombination::OkApplyCancel)
|
||||
, m_ui(new Ui::BgViewerSettingsUI)
|
||||
, m_pBgvController(pBgvController)
|
||||
{
|
||||
m_ui->setupUi(this);
|
||||
resetChangeHelper();
|
||||
|
||||
m_ui->m_pSliderGlobalTransparency->setValue(getSetting(QStringLiteral("GlobalTransparency"), 75).toInt());
|
||||
m_ui->m_pCheckBoxGlobalIsoMode->setChecked(getSetting(QStringLiteral("UseIsoMode"), false).toBool());
|
||||
m_ui->m_pCheckBoxUseDotsMode->setChecked(getSetting(QStringLiteral("UseDotsMode"), false).toBool()) ;
|
||||
m_ui->m_pSliderPlayerSymbolSize->setValue(getSetting(QStringLiteral("PlayerSymbolSize"), 20).toInt());
|
||||
m_ui->m_slider_HitlineDuration->setValue(getSetting(QStringLiteral("maxHitlineDurationTime_s"), 10).toInt());
|
||||
m_ui->m_slider_SymbolFlashing->setValue(getSetting(QStringLiteral("GearFlashTime_s"), 10).toInt());
|
||||
|
||||
connect(m_ui->m_pCheckBoxGlobalIsoMode, &QCheckBox::clicked, this, &BgViewerSettingsView::onViewModeChanged);
|
||||
connect(m_ui->m_pCheckBoxUseDotsMode, &QCheckBox::clicked, this, &BgViewerSettingsView::onPlayerDisplayModeChanged);
|
||||
connect(m_ui->m_pSliderGlobalTransparency, &QSlider::valueChanged, this, &BgViewerSettingsView::onTransparencyChanged);
|
||||
connect(m_ui->m_pSliderPlayerSymbolSize, &QSlider::valueChanged, this, &BgViewerSettingsView::onSymbolSizeChanged);
|
||||
connect(m_ui->m_slider_SymbolFlashing, &QSlider::valueChanged, this, &BgViewerSettingsView::onSymbolFireEventFlashingChanged);
|
||||
connect(m_ui->m_slider_HitlineDuration, &QSlider::valueChanged, this, &BgViewerSettingsView::onHitLineDisplayLengthChanged);
|
||||
|
||||
setOnlineHelpFilename(QStringLiteral("Building_Viewer-Global_Settings"));
|
||||
}
|
||||
|
||||
|
||||
BgViewerSettingsView::~BgViewerSettingsView()
|
||||
{
|
||||
delete m_ui;
|
||||
}
|
||||
|
||||
|
||||
void BgViewerSettingsView::retranslate()
|
||||
{
|
||||
translate(m_ui, tr("Global Settings"));
|
||||
onSymbolFireEventFlashingChanged(m_ui->m_slider_SymbolFlashing->value());
|
||||
onHitLineDisplayLengthChanged(m_ui->m_slider_HitlineDuration->value());
|
||||
}
|
||||
|
||||
|
||||
bool BgViewerSettingsView::apply()
|
||||
{
|
||||
if (m_viewModeChange)
|
||||
m_pBgvController->excSetGlobalViewMode(m_ui->m_pCheckBoxGlobalIsoMode->isChecked());
|
||||
|
||||
if (m_playerDisplayModeChange)
|
||||
m_pBgvController->excSetGlobalDotsMode(m_ui->m_pCheckBoxUseDotsMode->isChecked());
|
||||
|
||||
if (m_transparencyChange)
|
||||
m_pBgvController->excSetGlobalTransparency(static_cast<double>(m_ui->m_pSliderGlobalTransparency->value()));
|
||||
|
||||
if (m_hitlineChange)
|
||||
m_pBgvController->excSetHitlineDuration(m_ui->m_slider_HitlineDuration->value());
|
||||
|
||||
if (m_symbolSizeChange)
|
||||
m_pBgvController->updatePlayerSymbols(m_ui->m_pSliderPlayerSymbolSize->value());
|
||||
|
||||
setSetting(QStringLiteral("GlobalTransparency"), m_ui->m_pSliderGlobalTransparency->value());
|
||||
setSetting(QStringLiteral("UseIsoMode"), m_ui->m_pCheckBoxGlobalIsoMode->isChecked());
|
||||
setSetting(QStringLiteral("UseDotsMode"), m_ui->m_pCheckBoxUseDotsMode->isChecked());
|
||||
setSetting(QStringLiteral("PlayerSymbolSize"), m_ui->m_pSliderPlayerSymbolSize->value());
|
||||
setSetting(QStringLiteral("maxHitlineDurationTime_s"), m_ui->m_slider_HitlineDuration->value());
|
||||
setSetting(QStringLiteral("GearFlashTime_s"), m_ui->m_slider_SymbolFlashing->value());
|
||||
setSetting(QStringLiteral("maxGearFlashTime_s"), m_ui->m_slider_SymbolFlashing->maximum());
|
||||
|
||||
resetChangeHelper();
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
void BgViewerSettingsView::resetChangeHelper()
|
||||
{
|
||||
m_transparencyChange = m_viewModeChange = m_playerDisplayModeChange = m_symbolSizeChange = m_gearFlashChange = m_hitlineChange = false;
|
||||
}
|
||||
|
||||
|
||||
void BgViewerSettingsView::onViewModeChanged()
|
||||
{
|
||||
m_viewModeChange = true;
|
||||
}
|
||||
|
||||
|
||||
void BgViewerSettingsView::onPlayerDisplayModeChanged()
|
||||
{
|
||||
m_playerDisplayModeChange = true;
|
||||
}
|
||||
|
||||
|
||||
void BgViewerSettingsView::onSymbolSizeChanged()
|
||||
{
|
||||
m_symbolSizeChange = true;
|
||||
}
|
||||
|
||||
|
||||
void BgViewerSettingsView::onTransparencyChanged()
|
||||
{
|
||||
m_transparencyChange = true;
|
||||
}
|
||||
|
||||
|
||||
void BgViewerSettingsView::onSymbolFireEventFlashingChanged(int val)
|
||||
{
|
||||
m_gearFlashChange = true;
|
||||
m_ui->m_label_durationSymbolFlashing->setText(tr("%1 sec").arg(val));
|
||||
}
|
||||
|
||||
|
||||
void BgViewerSettingsView::onHitLineDisplayLengthChanged(int val)
|
||||
{
|
||||
m_hitlineChange = true;
|
||||
m_ui->m_label_HitlineDuration->setText(tr("%1 sec").arg(val));
|
||||
}
|
||||
|
||||
} // namespace BuildingViewer
|
||||
@@ -0,0 +1,53 @@
|
||||
/**
|
||||
* @RDE_HEADER@
|
||||
* HMI Plugin for MeteoDataManagement - Meteo Data Overview Dialog
|
||||
* $Id$
|
||||
* $HeadURL$
|
||||
* $Author$
|
||||
* Created by Patric Karwat, SLSE, 2016-10-05
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <LtsWidgets/lts_dialog.h>
|
||||
|
||||
namespace Ui
|
||||
{
|
||||
class BgViewerSettingsUI;
|
||||
}
|
||||
|
||||
|
||||
namespace BuildingViewer
|
||||
{
|
||||
class BgViewerController;
|
||||
|
||||
class BgViewerSettingsView : public LtsWidgets::LtsDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit BgViewerSettingsView(BgViewerController *pBgvController,
|
||||
QWidget *parent = nullptr);
|
||||
~BgViewerSettingsView();
|
||||
|
||||
private slots:
|
||||
void onViewModeChanged();
|
||||
void onPlayerDisplayModeChanged();
|
||||
void onTransparencyChanged();
|
||||
void onSymbolSizeChanged();
|
||||
void onSymbolFireEventFlashingChanged(int val);
|
||||
void onHitLineDisplayLengthChanged(int val);
|
||||
|
||||
private:
|
||||
bool m_transparencyChange, m_viewModeChange, m_playerDisplayModeChange, m_symbolSizeChange, m_gearFlashChange, m_hitlineChange;
|
||||
void resetChangeHelper();
|
||||
|
||||
bool apply() override;
|
||||
void retranslate() override;
|
||||
|
||||
Ui::BgViewerSettingsUI *m_ui;
|
||||
|
||||
BgViewerController *m_pBgvController;
|
||||
};
|
||||
|
||||
} // namespace BuildingViewer
|
||||
@@ -0,0 +1,197 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>BgViewerSettingsUI</class>
|
||||
<widget class="QWidget" name="BgViewerSettingsUI">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>429</width>
|
||||
<height>200</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string notr="true">General Settings</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout_2" columnstretch="2,1">
|
||||
<item row="0" column="0">
|
||||
<layout class="QGridLayout" name="gridLayout">
|
||||
<item row="0" column="1">
|
||||
<widget class="QSlider" name="m_pSliderGlobalTransparency">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>150</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>100</number>
|
||||
</property>
|
||||
<property name="value">
|
||||
<number>75</number>
|
||||
</property>
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QCheckBox" name="m_pCheckBoxGlobalIsoMode">
|
||||
<property name="enabled">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Use orthographic view mode</string>
|
||||
</property>
|
||||
<property name="checked">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0">
|
||||
<widget class="QLabel" name="label_2">
|
||||
<property name="text">
|
||||
<string>Player symbol size:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="2">
|
||||
<widget class="QLabel" name="m_label_durationSymbolFlashing">
|
||||
<property name="text">
|
||||
<string>%1 sec</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="2">
|
||||
<widget class="QLabel" name="m_label_HitlineDuration">
|
||||
<property name="text">
|
||||
<string>%1 sec</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="0">
|
||||
<widget class="QLabel" name="label_3">
|
||||
<property name="text">
|
||||
<string>Symbol fire event flashing:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="1">
|
||||
<widget class="QSlider" name="m_pSliderPlayerSymbolSize">
|
||||
<property name="minimum">
|
||||
<number>10</number>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>45</number>
|
||||
</property>
|
||||
<property name="value">
|
||||
<number>20</number>
|
||||
</property>
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="text">
|
||||
<string>Transparency value:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="0">
|
||||
<widget class="QLabel" name="label_4">
|
||||
<property name="text">
|
||||
<string>Hit line display length:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="1">
|
||||
<widget class="QSlider" name="m_slider_HitlineDuration">
|
||||
<property name="maximum">
|
||||
<number>120</number>
|
||||
</property>
|
||||
<property name="singleStep">
|
||||
<number>5</number>
|
||||
</property>
|
||||
<property name="value">
|
||||
<number>10</number>
|
||||
</property>
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QCheckBox" name="m_pCheckBoxUseDotsMode">
|
||||
<property name="text">
|
||||
<string>Use dots mode</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="1">
|
||||
<widget class="QSlider" name="m_slider_SymbolFlashing">
|
||||
<property name="enabled">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>120</number>
|
||||
</property>
|
||||
<property name="singleStep">
|
||||
<number>5</number>
|
||||
</property>
|
||||
<property name="value">
|
||||
<number>10</number>
|
||||
</property>
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<spacer name="verticalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<spacer name="horizontalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<tabstops>
|
||||
<tabstop>m_pSliderGlobalTransparency</tabstop>
|
||||
<tabstop>m_pCheckBoxGlobalIsoMode</tabstop>
|
||||
<tabstop>m_pCheckBoxUseDotsMode</tabstop>
|
||||
<tabstop>m_pSliderPlayerSymbolSize</tabstop>
|
||||
<tabstop>m_slider_SymbolFlashing</tabstop>
|
||||
<tabstop>m_slider_HitlineDuration</tabstop>
|
||||
</tabstops>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
||||
@@ -0,0 +1,168 @@
|
||||
/**
|
||||
* @RDE_HEADER@
|
||||
* $Id$
|
||||
* $HeadURL$
|
||||
* $Author$
|
||||
* Created by Philipp Last, SLSY
|
||||
*/
|
||||
#include "ui_bdv_viewer_state.h"
|
||||
#include "bdv_viewer_state.h"
|
||||
#include <Common/bdv_controller.h>
|
||||
#include <LtsUtilsSettings/settings.h>
|
||||
#include <LtsSession/lts_session_manager.h>
|
||||
#include <PluginInterfaces/data_plugin_interface.h>
|
||||
|
||||
#include <QJsonArray>
|
||||
#include <QKeyEvent>
|
||||
#include <QFileDialog>
|
||||
|
||||
#include "bdv_viewer_state_model.h"
|
||||
#include <BuildingViewer/share/exccommands.h>
|
||||
|
||||
namespace BuildingViewer
|
||||
{
|
||||
BgViewerStateView::BgViewerStateView(BgViewerController *pBgViewerController, QWidget *parent)
|
||||
: LtsWidgets::LtsDialog(parent, LtsWidgets::ButtonCombination::CloseOnly)
|
||||
, m_ui(new Ui::BgViewerStateViewUI)
|
||||
, m_pBgViewerController(pBgViewerController)
|
||||
{
|
||||
m_ui->setupUi(this);
|
||||
|
||||
connect(m_ui->m_pushButton_SaveCurrentState, &QPushButton::clicked,
|
||||
this, &BgViewerStateView::onSaveCurrentState);
|
||||
connect(m_ui->m_pushButton_SelectModelFolder, &QPushButton::clicked,
|
||||
this, &BgViewerStateView::onSelectModelFolder);
|
||||
connect(m_ui->m_pushButton_AddModelsFromFolder, &QPushButton::clicked,
|
||||
this, &BgViewerStateView::onAddModelsFromFolder);
|
||||
connect(m_ui->m_pushButton_Record, &QPushButton::clicked,
|
||||
this, &BgViewerStateView::onStartStopRecord);
|
||||
connect(m_pBgViewerController, &BgViewerController::signalReceivedViewState,
|
||||
this, &BgViewerStateView::onHandleReceivedViewState);
|
||||
|
||||
m_ui->widget->setSelectionMode(QAbstractItemView::SingleSelection);
|
||||
|
||||
m_pModel = new BgViewerStateModel(this);
|
||||
m_ui->widget->setModel(m_pModel);
|
||||
|
||||
|
||||
//m_ui->widget->setMouseTracking(true); // Not working (see also eventFilter function)
|
||||
m_ui->widget->installEventFilter(this);
|
||||
m_ui->m_lineEdit_modelPath->setText(LtsUtils::OperatorSettings::getInstance()->value(QStringLiteral("BgViewer"), QStringLiteral("pathModelData"), QStringLiteral("/shd/CTC/TOOLS/TDS/GUEZ-buildings-SPD-ive/")).toString());
|
||||
}
|
||||
|
||||
|
||||
BgViewerStateView::~BgViewerStateView()
|
||||
{
|
||||
delete m_ui;
|
||||
}
|
||||
|
||||
|
||||
void BgViewerStateView::onSelectModelFolder()
|
||||
{
|
||||
QString pathToModelFolder = QFileDialog::getExistingDirectory(this, tr("Choose Building Model Data Path"), m_ui->m_lineEdit_modelPath->text(), QFileDialog::ReadOnly | QFileDialog::ShowDirsOnly);
|
||||
|
||||
if (pathToModelFolder.size())
|
||||
{
|
||||
m_ui->m_lineEdit_modelPath->setText(pathToModelFolder);
|
||||
LtsUtils::OperatorSettings::getInstance()->setValue(QStringLiteral("BgViewer"), QStringLiteral("pathModelData"), pathToModelFolder);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void BgViewerStateView::onAddModelsFromFolder()
|
||||
{
|
||||
m_pBgViewerController->excConnect({m_ui->m_lineEdit_modelPath->text().toStdString()});
|
||||
emit signalFetchBuildingList();
|
||||
}
|
||||
|
||||
|
||||
void BgViewerStateView::deleteSelectedState()
|
||||
{
|
||||
const QModelIndex idx = m_ui->widget->currentIndex();
|
||||
m_pModel->removeRow(idx.row());
|
||||
}
|
||||
|
||||
|
||||
bool BgViewerStateView::eventFilter(QObject *object, QEvent *event)
|
||||
{
|
||||
if (object == m_ui->widget)
|
||||
{
|
||||
if (event->type() == QEvent::MouseButtonDblClick)
|
||||
{
|
||||
restoreSelectedState(); // Not working, event never occurs
|
||||
}
|
||||
else if (event->type() == QEvent::KeyPress)
|
||||
{
|
||||
QKeyEvent *pKeyEvent = static_cast<QKeyEvent *>(event);
|
||||
|
||||
// Enter: Enter on numpad
|
||||
if (pKeyEvent->key() == Qt::Key_Return || pKeyEvent->key() == Qt::Key_Enter)
|
||||
restoreSelectedState();
|
||||
else if (pKeyEvent->key() == Qt::Key_Delete)
|
||||
deleteSelectedState();
|
||||
}
|
||||
}
|
||||
|
||||
return LtsWidgets::LtsDialog::eventFilter(object, event);
|
||||
}
|
||||
|
||||
|
||||
void BgViewerStateView::onSaveCurrentState()
|
||||
{
|
||||
m_ui->m_pushButton_SaveCurrentState->setEnabled(false);
|
||||
m_pBgViewerController->excGetViewState();
|
||||
}
|
||||
|
||||
|
||||
void BgViewerStateView::onStartStopRecord()
|
||||
{
|
||||
static bool isRecording = false;
|
||||
|
||||
if (!isRecording)
|
||||
{
|
||||
QString strPathToFolder = QFileDialog::getExistingDirectory(this, QStringLiteral("Open Directory"),
|
||||
QStringLiteral("/shd/CTC/TOOLS/TDS/export"),
|
||||
QFileDialog::ShowDirsOnly
|
||||
| QFileDialog::DontResolveSymlinks);
|
||||
m_pBgViewerController->excStartRecording(strPathToFolder + QLatin1Char('/'), QStringLiteral("all"));
|
||||
isRecording = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_pBgViewerController->excStopRecording(QStringLiteral("all"));
|
||||
isRecording = false;
|
||||
}
|
||||
|
||||
m_ui->m_pushButton_Record->setText(isRecording ? tr("Stop Recording") : tr("Start Recording"));
|
||||
}
|
||||
|
||||
|
||||
void BgViewerStateView::onHandleReceivedViewState(const QJsonValue &val)
|
||||
{
|
||||
// list.size() will also be 0 if there are no open ViewWidgets
|
||||
const auto arr = val.toArray();
|
||||
for (const auto &ele : arr)
|
||||
m_pModel->insertRow(ele);
|
||||
|
||||
m_ui->m_pushButton_SaveCurrentState->setEnabled(true);
|
||||
}
|
||||
|
||||
|
||||
void BgViewerStateView::restoreSelectedState()
|
||||
{
|
||||
if (m_pModel->rowCount())
|
||||
{
|
||||
const QModelIndex idx = m_ui->widget->currentIndex();
|
||||
m_pBgViewerController->excRestoreViewState(m_pModel->getRowData(idx.row()));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void BgViewerStateView::retranslate()
|
||||
{
|
||||
translate(m_ui, tr("View State (Debug)"));
|
||||
}
|
||||
|
||||
|
||||
} // namespace BuildingViewer
|
||||
|
||||
@@ -0,0 +1,56 @@
|
||||
/**
|
||||
* @RDE_HEADER@
|
||||
* HMI Plugin for MeteoDataManagement - Meteo Data Overview Dialog
|
||||
* $Id$
|
||||
* $HeadURL$
|
||||
* $Author$
|
||||
* Created by Patric Karwat, SLSE, 2016-10-05
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <LtsWidgets/lts_dialog.h>
|
||||
|
||||
namespace Ui
|
||||
{
|
||||
class BgViewerStateViewUI;
|
||||
}
|
||||
|
||||
|
||||
namespace BuildingViewer
|
||||
{
|
||||
class BgViewerController;
|
||||
class BgViewerStateModel;
|
||||
|
||||
class BgViewerStateView : public LtsWidgets::LtsDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit BgViewerStateView(BgViewerController *pBgViewerController, QWidget *parent = nullptr);
|
||||
~BgViewerStateView();
|
||||
|
||||
signals:
|
||||
void signalFetchBuildingList();
|
||||
|
||||
private slots:
|
||||
void onSaveCurrentState();
|
||||
void onSelectModelFolder();
|
||||
void onAddModelsFromFolder();
|
||||
void onStartStopRecord();
|
||||
void onHandleReceivedViewState(const QJsonValue &val);
|
||||
|
||||
private:
|
||||
void deleteSelectedState();
|
||||
void restoreSelectedState();
|
||||
bool eventFilter(QObject *object, QEvent *event) override;
|
||||
void retranslate() override;
|
||||
|
||||
Ui::BgViewerStateViewUI *m_ui;
|
||||
|
||||
BgViewerStateModel *m_pModel;
|
||||
|
||||
BgViewerController *m_pBgViewerController;
|
||||
};
|
||||
|
||||
} // namespace BuildingViewer
|
||||
@@ -0,0 +1,107 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>BgViewerStateViewUI</class>
|
||||
<widget class="QWidget" name="BgViewerStateViewUI">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>962</width>
|
||||
<height>433</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string notr="true"/>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<item>
|
||||
<widget class="QPushButton" name="m_pushButton_SaveCurrentState">
|
||||
<property name="enabled">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Save Current State</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLineEdit" name="m_lineEdit_modelPath">
|
||||
<property name="readOnly">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="m_pushButton_SelectModelFolder">
|
||||
<property name="text">
|
||||
<string>Select Model Folder</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="m_pushButton_AddModelsFromFolder">
|
||||
<property name="text">
|
||||
<string>Add Models From Folder</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="Line" name="line">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="m_pushButton_Record">
|
||||
<property name="text">
|
||||
<string>Start Recording</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="LtsDataView::LtsDataView" name="widget">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="MinimumExpanding" vsizetype="MinimumExpanding">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>250</height>
|
||||
</size>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<customwidgets>
|
||||
<customwidget>
|
||||
<class>LtsDataView::LtsDataView</class>
|
||||
<extends>QWidget</extends>
|
||||
<header>LtsDataView/lts_data_view.h</header>
|
||||
<container>1</container>
|
||||
</customwidget>
|
||||
</customwidgets>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
||||
@@ -0,0 +1,32 @@
|
||||
/**
|
||||
* @RDE_HEADER@
|
||||
* HMI Plugin for ParticipantManagement - Party Overview Model
|
||||
* $Id$
|
||||
* $HeadURL$
|
||||
* $Author$
|
||||
* Created by Philipp Last, SLSE, 2017-05-23
|
||||
*/
|
||||
|
||||
#include "bdv_viewer_state_model.h"
|
||||
|
||||
#include <LtsSession/lts_session_manager.h>
|
||||
|
||||
namespace BuildingViewer
|
||||
{
|
||||
BgViewerStateModel::BgViewerStateModel(QObject *parent)
|
||||
: LtsWidgets::LtsAbstractTableModel<QJsonValue>(
|
||||
{
|
||||
tr("Json")
|
||||
}, parent)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
QVariant BgViewerStateModel::data(const QModelIndex &index, int role) const
|
||||
{
|
||||
if (role != Qt::DisplayRole || !indexIsValid(index))
|
||||
return QVariant();
|
||||
|
||||
return m_vecData.at(index.row());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
/**
|
||||
* @RDE_HEADER@
|
||||
*
|
||||
* $Id$
|
||||
* $HeadURL$
|
||||
* $Author$
|
||||
* Created by Philipp Last, SLSE, 2017-05-23
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <LtsWidgets/lts_abstract_table_model.h>
|
||||
#include <QJsonValue>
|
||||
|
||||
namespace BuildingViewer
|
||||
{
|
||||
class BgViewerStateModel final : public LtsWidgets::LtsAbstractTableModel<QJsonValue>
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit BgViewerStateModel(QObject *parent = nullptr);
|
||||
|
||||
QVariant data(const QModelIndex &index, int role) const override;
|
||||
};
|
||||
}
|
||||
+9
@@ -0,0 +1,9 @@
|
||||
#
|
||||
# $Id$
|
||||
# $HeadURL$
|
||||
# $Author$
|
||||
#
|
||||
# Created by Mike Wille, SLSE, 2017-05-15
|
||||
#
|
||||
|
||||
ADD_SUBDIRECTORY(BuildingViewer)
|
||||
Reference in new issue
Block a user