Initial commit
This commit is contained in:
commit
b7d90b9afe
16245 files changed
+3396666
No files matched your search
+811
@@ -0,0 +1,811 @@
|
||||
/**
|
||||
* @RDE_HEADER@
|
||||
* The MountingPointListDialog shows how many assets are needed for a specific schedule, needed elsewhere,
|
||||
* totally possessed, free, and missing
|
||||
* Modified version using the checkStateProxyModel to allow setting via the checkboxes of the tree structure hjl 5/19
|
||||
* $Id$
|
||||
* $HeadURL$
|
||||
* $Author$
|
||||
* Created by Hannes Baeuerle, SLSE, 2016-11-03
|
||||
*/
|
||||
|
||||
#include "ism_mounting_point_list_dialog.h"
|
||||
#include "ui_ism_mounting_point_list_dialog.h"
|
||||
#include "ism_mounting_point_list_dialog_model.h"
|
||||
#include "ism_mounting_point_list_dialog_checkbox_proxy_model.h"
|
||||
#include "ism_mounting_point_list_dialog_checkbox_delegate.h"
|
||||
#include "ism_mounting_point_list_dialog_list_sort_model.h"
|
||||
|
||||
#include <LtsUtilsGuiDds/request_helper.h>
|
||||
#include <LtsUtilsCore/dds_vector.h>
|
||||
#include <InfrastructureManagement/ism_translation.h>
|
||||
#include <InfrastructureManagement/ism_operator_rights.h>
|
||||
#include <InfrastructureManagement/Shared/ism_mounting_point.h>
|
||||
#include <FilterManagement/flt_building_cmpnt_helper.h> // getVisibleTypesOfFilter
|
||||
#include <SituationMapPlugin/situation_map_gui_plugin_interface.h>
|
||||
#include <SituationMap/Map/map.h>
|
||||
#include <LtsSession/lts_session.h>
|
||||
#include <LtsSession/lts_session_data.h>
|
||||
#include <LtsPrinting/printing.h>
|
||||
|
||||
#include <QItemDelegate>
|
||||
#include <QTreeView>
|
||||
#include <QListWidget>
|
||||
#include <QMenu>
|
||||
#include <QHeaderView>
|
||||
#include <QScrollBar>
|
||||
#include <QTimer>
|
||||
|
||||
|
||||
using namespace LtsWidgets;
|
||||
|
||||
|
||||
namespace InfrastructureManagement
|
||||
{
|
||||
/// DummyLtsColumnFilterProxyModel
|
||||
class DummyLtsColumnFilterProxyModel : public LtsColumnFilterProxyModel
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
void setColumnStringFilter(const QString &, int ) override {}
|
||||
void setColumnDataFilter(const QVariant &newFilterData, int column) override
|
||||
{
|
||||
emit signalSetColumnDataFilter(newFilterData, column);
|
||||
}
|
||||
|
||||
bool filterAcceptsRow(int /*source_row*/, const QModelIndex &/*source_parent*/) const override
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
signals:
|
||||
void signalSetColumnDataFilter(const QVariant &newFilterData, int column);
|
||||
};
|
||||
|
||||
|
||||
|
||||
/// MountingPointListDialog
|
||||
MountingPointListDialog::MountingPointListDialog(const QString &menuGroup, QWidget *parent)
|
||||
: LtsWidgets::LtsDialog(parent, LtsWidgets::ButtonCombination::OkApplyCancel)
|
||||
, m_requestHelper(new LtsUtils::RequestHelper(this))
|
||||
, m_menuGroup(menuGroup)
|
||||
, m_ismGuiIfc(nullptr)
|
||||
, m_mapGuiInterface(nullptr)
|
||||
, m_typeFilterColumn(0)
|
||||
, m_typeFilterRow(0)
|
||||
, m_ddsSelector(nullptr)
|
||||
, m_scheduleId(-1)
|
||||
, m_ui(new Ui::MountingPointListDialog)
|
||||
, m_logger(getLogger("MountingPointListDialog"))
|
||||
{
|
||||
TRACE_LOG(m_logger) << LOGFUNCTION << " START";
|
||||
|
||||
m_ui->setupUi(this);
|
||||
setOnlineHelpFilename(QStringLiteral("Ressourcen-Mounting_Point_List"));
|
||||
m_buttonBox->connectButton(LtsWidgets::DialogButton::Print, this, &MountingPointListDialog::onPrint);
|
||||
TRACE_LOG(m_logger) << LOGFUNCTION << " END";
|
||||
}
|
||||
|
||||
MountingPointListDialog::~MountingPointListDialog()
|
||||
{
|
||||
TRACE_LOG(m_logger) << LOGFUNCTION << " START";
|
||||
m_mapGuiInterface->removeObjectIndicator();
|
||||
m_mapGuiInterface->setSkipMapObjectSelectionDialog(false);
|
||||
|
||||
if (m_ismGuiIfc)
|
||||
m_ismGuiIfc->setSelector(nullptr);
|
||||
|
||||
if (m_buildingComponentSettings)
|
||||
m_buildingComponentSettings->removeChangedCallback(this);
|
||||
|
||||
m_mapGuiInterface->setResourceManagerMode(m_oldResourceManagerMode);
|
||||
|
||||
delete m_ui;
|
||||
delete m_ddsSelector;
|
||||
delete m_requestHelper;
|
||||
TRACE_LOG(m_logger) << LOGFUNCTION << " END";
|
||||
}
|
||||
|
||||
void MountingPointListDialog::retranslate()
|
||||
{
|
||||
translate(m_ui, m_dtc->mainSchedule(m_scheduleId), tr("Mounting Point List"));
|
||||
m_buttonBox->getButton(LtsWidgets::DialogButton::Load)->setText(tr("Unmount"));
|
||||
}
|
||||
|
||||
bool MountingPointListDialog::init(LtsSession::LtsSession *session,
|
||||
const std::shared_ptr<Interface::Dtc> &dtc,
|
||||
const std::shared_ptr<Interface::Ftc> &ftc,
|
||||
const std::shared_ptr<ForeignDataInterface> &dataInterface,
|
||||
InfrastructureManagement::ForeignResourceManagementGuiInterface *ismGuiIfc,
|
||||
const std::shared_ptr<SituationMap::ForeignGuiInterface> &mapIfc,
|
||||
const std::shared_ptr<FilterManagement::ForeignFltBuildingComponentGuiInterface> fltBuildingComponentIfc)
|
||||
{
|
||||
TRACE_LOG(m_logger) << LOGFUNCTION << " START";
|
||||
m_dtc = dtc;
|
||||
m_ftc = ftc;
|
||||
m_dataIfc = dataInterface;
|
||||
m_session = session;
|
||||
m_mapGuiInterface = mapIfc;
|
||||
m_ismGuiIfc = ismGuiIfc;
|
||||
m_fltBuildingComponentIfc = fltBuildingComponentIfc;
|
||||
|
||||
disconnect(m_ui->mountingPointListView);
|
||||
disconnect(this);
|
||||
|
||||
if (!m_ftc->enableInstrumentationAssetModify())
|
||||
{
|
||||
ERROR_LOG(m_logger) << "Could not enable FT InstrumentationAssetModify of ISM";
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!m_ftc->enableInstrumentationAssetModify())
|
||||
{
|
||||
ERROR_LOG(m_logger) << "Could not enable FT enableInstrumentationAssetModify of ISM";
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!m_ftc->enableInstrumentationAssetRemove())
|
||||
{
|
||||
ERROR_LOG(m_logger) << "Could not enable FT enableInstrumentationAssetRemove of ISM";
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!m_ftc->enableInstrumentationAssetUnmount())
|
||||
{
|
||||
ERROR_LOG(m_logger) << "Could not enable FT enableInstrumentationAssetUnmount of ISM";
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!m_ftc->enableMountingPointAssetModify())
|
||||
{
|
||||
ERROR_LOG(m_logger) << "Could not enable FT MountingPointAssetModify of ISM";
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!m_ftc->enableMountingPointAssetRemove())
|
||||
{
|
||||
ERROR_LOG(m_logger) << "Could not enable FT MountingPointAssetRemove of ISM";
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!m_ftc->enableStructureElementModify())
|
||||
{
|
||||
ERROR_LOG(m_logger) << "Could not enable FT enableStructureElementModify of ISM";
|
||||
return false;
|
||||
}
|
||||
|
||||
delete m_sourceModel;
|
||||
m_sourceModel = new MountingPointListDialogModel(this);
|
||||
const QSet<MountingPointType> filters = { MountingPointType::BuildingSensorModule,
|
||||
MountingPointType::OutdoorCamera,
|
||||
// MountingPointType::BuildingControlUnit,
|
||||
MountingPointType::IndoorCamera,
|
||||
MountingPointType::OutdoorIPS,
|
||||
MountingPointType::IndoorIPS,
|
||||
MountingPointType::EffectGenerationControlUnit,
|
||||
#ifndef GUEZ_MODE
|
||||
MountingPointType::AnnouncementUnit,
|
||||
MountingPointType::BuildingNetworkSwitch
|
||||
#endif
|
||||
};
|
||||
m_sourceModel->setMntPointFilterTypes(filters);
|
||||
if (!m_sourceModel->initModel(m_dtc, m_dataIfc))
|
||||
{
|
||||
ERROR_LOG(m_logger) << "Could not init model";
|
||||
delete m_sourceModel;
|
||||
m_sourceModel = nullptr;
|
||||
return false;
|
||||
}
|
||||
|
||||
connect(m_sourceModel, &MountingPointListDialogModel::changesMade,
|
||||
this, &MountingPointListDialog::slotChangesMade); /*[this]
|
||||
{
|
||||
slotChangesMade();
|
||||
});*/
|
||||
|
||||
delete m_sortProxyModel;
|
||||
m_sortProxyModel = new MountingPointListSortModel(this);
|
||||
m_sortProxyModel->setTypeFilter(filters);
|
||||
m_sortProxyModel->setSourceModel(m_sourceModel);
|
||||
|
||||
delete m_checkboxProxyModel;
|
||||
m_checkboxProxyModel = new CheckboxProxyModel;
|
||||
|
||||
|
||||
|
||||
/* OKAY, get this...:
|
||||
* We need LtsDataView's filtering mechanism. But the CheckBoxProxyModel needs to be the *last* Proxy Model
|
||||
* because it checks which Checkbox state a leaf's parent and its parent's parents has. If the LtsDataView
|
||||
* does the filtering, then the CheckboxProxyModel doesn't know what lines were hidden, so the Checkbox
|
||||
* states don't match.
|
||||
* If LtsDataView is given an LtsColumnFilterProxyModel instead of an ItemModel, it will not create a
|
||||
* LtsColumnFilterProxyModel for filtering, but use the given one instead.
|
||||
* Here's the super hacky solution:
|
||||
* 1. First we need a barebones LtsColumnFilterProxyModel as the LAST model instance, for the LtsDataView,
|
||||
* which just sends a signa - when setColumnStringFilter was called - to ...
|
||||
* 2. the REAL LtsColumnFilterProxyModel, which does the real filtering. It needs to be put BEFORE
|
||||
* the CheckboxFilterProxy. So the CheckboxFilterProxy will see ALL rows that remain visible.
|
||||
*/
|
||||
|
||||
// Model => Sort => rcfpm => CheckboxProxy => dcfpm => View
|
||||
|
||||
m_sortProxyModel->setRecursiveFilteringEnabled(true); // non-leafs don't have a type to filter by, so tell LtsDataView's filter proxy model to ignore these and still show them if at least ONE child (recursive) of a non-leaf is visible
|
||||
|
||||
|
||||
LtsColumnFilterProxyModel *rcfpm = new LtsColumnFilterProxyModel; // the REAL filter, put before CheckboxFilterProxy.
|
||||
rcfpm->setSourceModel(m_sortProxyModel);
|
||||
rcfpm->setRecursiveFilteringEnabled(true); // non-leafs don't have a type to filter by, so tell LtsDataView's filter proxy model to ignore these and still show them if at least ONE child (recursive) of a non-leaf is visible
|
||||
|
||||
|
||||
m_checkboxProxyModel->setSourceModel(rcfpm);
|
||||
|
||||
|
||||
DummyLtsColumnFilterProxyModel *dcfpm = new DummyLtsColumnFilterProxyModel; // the fake filter, put as LAST instance. Source model is the CheckboxFilterProxy.
|
||||
dcfpm->setRecursiveFilteringEnabled(true); // non-leafs don't have a type to filter by, so tell LtsDataView's filter proxy model to ignore these and still show them if at least ONE child (recursive) of a non-leaf is visible
|
||||
connect(dcfpm, &DummyLtsColumnFilterProxyModel::signalSetColumnDataFilter,
|
||||
rcfpm, &LtsColumnFilterProxyModel::onSetColumnDataFilter);
|
||||
|
||||
dcfpm->setSourceModel(m_checkboxProxyModel);
|
||||
|
||||
m_ui->mountingPointListView->setModel(dcfpm);
|
||||
|
||||
// Needed as otherwise changes to the model do not affect the visibility of Rooms and Levels.
|
||||
connect(m_sourceModel, &MountingPointListDialogModel::dataChanged, m_sortProxyModel, &MountingPointListSortModel::invalidateFilter);
|
||||
|
||||
if (LtsSessionData::LtsSessionData::getInstance()->hasOperatorRight(OperatorRights::SystemConfiguration))
|
||||
{
|
||||
m_buttonBox->connectButton(LtsWidgets::DialogButton::Load, this, &MountingPointListDialog::onUnmountButtonClicked);
|
||||
m_buttonBox->setIcon(LtsWidgets::DialogButton::Load, QIcon(QLatin1String("icon:fixed_video_announcement.svg")));
|
||||
m_buttonBox->getButton(LtsWidgets::DialogButton::Load)->setEnabled(false);
|
||||
}
|
||||
// connect signals of TableView/CustomView: (for MapObjectIndicator
|
||||
connect(m_ui->mountingPointListView, &LtsDataView::LtsDataView::clicked, this, &MountingPointListDialog::onDataViewClicked);
|
||||
connect(m_ui->mountingPointListView, &LtsDataView::LtsDataView::signalEntered, this, &MountingPointListDialog::onDataViewEntered);
|
||||
|
||||
|
||||
//------------- Filter ----------------
|
||||
// SWPÄ 2/22 / GUEZE-1478:
|
||||
// Diese Filter werden ersetzt durch übergeordnete BuildingComponentnFilter (Extras | SituationMap | BuildingComponent)
|
||||
|
||||
// subscribe to Filter:
|
||||
if (m_fltBuildingComponentIfc)
|
||||
{
|
||||
const int operatorId = LtsSessionData::LtsSessionData::getInstance()->getOperatorId();
|
||||
m_buildingComponentSettings = m_fltBuildingComponentIfc->buildingComponentSettingsForOperator(operatorId, m_session->workspaceId());
|
||||
if (m_buildingComponentSettings)
|
||||
m_buildingComponentSettings->addChangedCallback(this); // will call onBuildingComponentSettingsChanged
|
||||
else
|
||||
{
|
||||
ERROR_LOG(m_logger) << LOGFUNCTION << " addChangedCallback fltBuildingComponentIfc failed";
|
||||
#ifdef LTS_DEBUG
|
||||
Q_ASSERT(false);
|
||||
#endif // LTS_DEBUG
|
||||
}
|
||||
// call on init:
|
||||
onBuildingComponentSettingsChanged();
|
||||
}else
|
||||
{
|
||||
ERROR_LOG(m_logger) << "No BuildingCOmponentIfc ";
|
||||
}
|
||||
|
||||
// honor visibilityChanged (dialog toogles between foreground/background)
|
||||
connect(this, &MountingPointListDialog::visibilityChanged, this, &MountingPointListDialog::onVisibilityChanged);
|
||||
|
||||
// show first tree level when activating the dialog
|
||||
m_ui->mountingPointListView->treeView()->expandToDepth(0);
|
||||
|
||||
delete m_ddsSelector;
|
||||
m_ddsSelector = nullptr;
|
||||
|
||||
m_ddsSelector = new DdsSelector(dtc, ftc, m_dataIfc, m_requestHelper);
|
||||
|
||||
// always select from the map when the dialog is visible
|
||||
m_ismGuiIfc->setSelector(m_ddsSelector);
|
||||
|
||||
|
||||
// SWPÄ GUEZE-1478 (?)
|
||||
// Mit Aufschalten des Dialog wird umgeschaltet auf Modus SituationMap::ResourceManagerMode::RMM_PlanDefinitionView
|
||||
// mit RMM_PlanDefinitionView sollte die Notification disabled werden...
|
||||
// bis Ende des Dialoges...
|
||||
m_oldResourceManagerMode = m_mapGuiInterface->resourceManagerMode();
|
||||
|
||||
// since switching _to_ RMM_PlanDefinitionView could be timeconsuming:
|
||||
// (and give the GlobalWaitDialog time being displayed)
|
||||
QTimer::singleShot(100, this, [this] () {
|
||||
m_mapGuiInterface->setResourceManagerMode(SituationMap::ResourceManagerMode::RMM_PlanDefinitionView);
|
||||
});
|
||||
|
||||
m_mapGuiInterface->setSkipMapObjectSelectionDialog(true);
|
||||
|
||||
|
||||
m_scheduleId = m_dataIfc->scheduleId();
|
||||
connect(m_dataIfc.get(), &ForeignDataInterface::scheduleIdChanged,
|
||||
this, &MountingPointListDialog::onScheduleIdChanged);
|
||||
|
||||
m_ui->mountingPointListView->setContextMenuPolicyPerView(LtsDataView::LtsDataView::Page::TABLE, Qt::CustomContextMenu);
|
||||
connect(m_ui->mountingPointListView->treeView(), &QTreeView::customContextMenuRequested,
|
||||
this, &MountingPointListDialog::onCustomContextMenu);
|
||||
|
||||
m_ui->mountingPointListView->treeView()->setColumnWidth(0, 500);
|
||||
m_ui->mountingPointListView->treeView()->setColumnWidth(1, 300);
|
||||
m_ui->mountingPointListView->treeView()->setColumnWidth(2, 300);
|
||||
m_ui->mountingPointListView->treeView()->header()->setSectionResizeMode(1, QHeaderView::Fixed);
|
||||
|
||||
|
||||
m_ui->mountingPointListView->searchView()->setColumnWidth(0, 500);
|
||||
m_ui->mountingPointListView->searchView()->setColumnWidth(1, 300);
|
||||
m_ui->mountingPointListView->searchView()->setColumnWidth(2, 300);
|
||||
m_ui->mountingPointListView->searchView()->header()->setSectionResizeMode(1, QHeaderView::Fixed);
|
||||
|
||||
connect(m_ui->mountingPointListView->searchView()->horizontalScrollBar(), &QScrollBar::rangeChanged,
|
||||
this, [this]()
|
||||
{
|
||||
m_ui->mountingPointListView->slotSetHorizontalRange(0,0);
|
||||
}, Qt::QueuedConnection);
|
||||
|
||||
connect(m_ui->mountingPointListView->treeView()->horizontalScrollBar(), &QScrollBar::rangeChanged,
|
||||
this, [this]()
|
||||
{
|
||||
m_ui->mountingPointListView->slotSetHorizontalRange(0,0);
|
||||
}, Qt::QueuedConnection);
|
||||
|
||||
m_ui->mountingPointListView->treeView()->setItemDelegateForColumn(MountingPointListDialogModel::Columns::NAME, new CheckboxDelegate);
|
||||
|
||||
// connect onEscapePressed of Map:
|
||||
if (m_mapGuiInterface && m_mapGuiInterface->map())
|
||||
connect(m_mapGuiInterface->map().data(), &SituationMap::Map::escapePressed,
|
||||
this, &MountingPointListDialog::onEscapePressed, Qt::UniqueConnection);
|
||||
|
||||
// InfoMountButton:
|
||||
connect(m_ui->tbMountMode, &QToolButton::clicked,
|
||||
this, &MountingPointListDialog::onInfoMountButtonClicked, Qt::UniqueConnection);
|
||||
onUpdateInfoMountButtonAndBehaviour();
|
||||
|
||||
TRACE_LOG(m_logger) << LOGFUNCTION << " END";
|
||||
return true;
|
||||
}
|
||||
|
||||
void MountingPointListDialog::getMountingPointPlanData(const QModelIndex &index, std::vector<MountingPointPlan>&modify, const QHash<int, MountingPointPlan> &mppMap)
|
||||
{
|
||||
NGLTreeItem *item = m_sourceModel->privateData(index);
|
||||
if (!item)
|
||||
return;
|
||||
if (item->data().canConvert<SimpleMountingPointData>())
|
||||
{
|
||||
const SimpleMountingPointData &data = item->data().value<SimpleMountingPointData>();
|
||||
DEBUG_LOG(m_logger) << "Item: " << m_sourceModel->data(index, Qt::DisplayRole).toString()
|
||||
<< ", Structure Element Id: " << data.id;
|
||||
|
||||
if (mppMap.contains(data.id))
|
||||
{
|
||||
if (data.aimState != mppMap[data.id].mountingPointState())
|
||||
modify.push_back(MountingPointPlan(data.id, data.aimState));
|
||||
}
|
||||
else if (data.aimState != MountingPointState_def::Idle)
|
||||
{
|
||||
DEBUG_LOG(m_logger) << "Not available in Map. Desired: " << data.aimState;
|
||||
modify.push_back(MountingPointPlan(data.id, data.aimState));
|
||||
}
|
||||
}
|
||||
for (int i =0 ; i< m_sourceModel->rowCount(index); i++ )
|
||||
getMountingPointPlanData(m_sourceModel->index(i, 0, index), modify, mppMap);
|
||||
}
|
||||
|
||||
bool MountingPointListDialog::hasMountingPointMountedAsset(const QModelIndex &index)
|
||||
{
|
||||
NGLTreeItem *treeItem = m_sourceModel->privateData(mapToSourciest(index));
|
||||
if (!treeItem)
|
||||
return false;
|
||||
QVariant v = treeItem->data();
|
||||
if (v.canConvert<SimpleMountingPointData>())
|
||||
{
|
||||
// MountingPoint:
|
||||
const SimpleMountingPointData itemData = v.value<SimpleMountingPointData>();
|
||||
int assetId = m_dtc->getMountedAssetId(itemData.id);
|
||||
return !(assetId == -1);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void MountingPointListDialog::onMountingPointPlanModifyReply(const Core::FunctionReplyObject &replyObject)
|
||||
{
|
||||
m_requestHelper->requestReply(replyObject);
|
||||
}
|
||||
|
||||
void MountingPointListDialog::onInstrumentationAssetModifyReply(const Core::FunctionReplyObject &replyObject)
|
||||
{
|
||||
m_requestHelper->requestReply(replyObject);
|
||||
}
|
||||
|
||||
void MountingPointListDialog::onInstrumentationAssetUnmountReply(const Core::FunctionReplyObject &replyObject)
|
||||
{
|
||||
m_requestHelper->requestReply(replyObject);
|
||||
}
|
||||
|
||||
void MountingPointListDialog::onStructureElementModifyReply(const Core::FunctionReplyObject &replyObject)
|
||||
{
|
||||
m_requestHelper->requestReply(replyObject);
|
||||
}
|
||||
|
||||
void MountingPointListDialog::onMountingPointAssetModifyReply(const Core::FunctionReplyObject &replyObject)
|
||||
{
|
||||
m_requestHelper->requestReply(replyObject);
|
||||
}
|
||||
|
||||
void MountingPointListDialog::onMountingPointAssetRemoveReply(const Core::FunctionReplyObject &replyObject)
|
||||
{
|
||||
m_requestHelper->requestReply(replyObject);
|
||||
}
|
||||
|
||||
void MountingPointListDialog::onBuildingComponentSettingsChanged()
|
||||
{
|
||||
DEBUG_LOG(m_logger) << LOGFUNCTION << " START";
|
||||
|
||||
// update view via m_sortProxyModel:
|
||||
|
||||
if (!m_buildingComponentSettings)
|
||||
return;
|
||||
const FilterManagement::BuildingComponentSettings::BldCmpSettings &bldCmpSettings =
|
||||
m_buildingComponentSettings->bldCmpSettings();
|
||||
|
||||
// 1) setTypeFilter:
|
||||
{
|
||||
const QSet<MountingPointType> visibleTypes = FilterManagement::getVisibleTypesOfFilter(bldCmpSettings);
|
||||
m_sortProxyModel->setTypeFilter(visibleTypes);
|
||||
}
|
||||
|
||||
// 2) floor:
|
||||
{
|
||||
// '-10' is floorId of Exterior / Outdoor
|
||||
// Filter has HIDDEN floorIds
|
||||
// (good reason: if filter not available (or nothing is checked), show all item on map...)
|
||||
// so translate here to visibleFloors:
|
||||
const QSet<int> &hiddenFloorIds = bldCmpSettings.buildingSettings.hiddenFloorIds;
|
||||
const QSet<int> &availableFloors = m_sourceModel->getAvailableFloors();
|
||||
QSet<int> visibleFloors;
|
||||
for (int floor : availableFloors)
|
||||
if (!hiddenFloorIds.contains(floor))
|
||||
visibleFloors.insert(floor);
|
||||
|
||||
// qCritical() << " hiddenFloorIds" << hiddenFloorIds;
|
||||
// qCritical() << " availableFloors" << availableFloors;
|
||||
// qCritical() << " visibleFloors" << visibleFloors;
|
||||
|
||||
m_sortProxyModel->setFloorFilter(visibleFloors);
|
||||
}
|
||||
DEBUG_LOG(m_logger) << LOGFUNCTION << " END";
|
||||
}
|
||||
|
||||
bool MountingPointListDialog::apply()
|
||||
{
|
||||
std::vector<MountingPointPlan> modify;
|
||||
const QModelIndex root = m_sourceModel->getIndexOfVisibleRootItem();
|
||||
if (!root.isValid())
|
||||
return false;
|
||||
|
||||
MainSchedule mainSchedule = m_dataIfc->mainSchedule(m_dataIfc->scheduleId());
|
||||
|
||||
QHash<int,MountingPointPlan> mppMap;
|
||||
for(const auto &elem : mainSchedule.elements())
|
||||
mppMap[elem.structureElementId()] = elem;
|
||||
|
||||
getMountingPointPlanData(root, modify, mppMap);
|
||||
|
||||
if (modify.empty())
|
||||
return true;
|
||||
|
||||
MountingPointPlanModifyRequest req(m_dataIfc->scheduleId(), modify);
|
||||
return m_requestHelper->startSingleRequest([req, this]()
|
||||
{
|
||||
return m_ftc->mountingPointPlanModifyRequest(req, this);
|
||||
});
|
||||
}
|
||||
|
||||
void MountingPointListDialog::onPrint()
|
||||
{
|
||||
MainSchedule ms = m_dtc->mainSchedule(m_dataIfc->scheduleId());
|
||||
QString header;
|
||||
header += QStringLiteral("<p>");
|
||||
header += tr("Instrumentation Plan: %1").arg(QString::fromStdString(ms.name()));
|
||||
header += QStringLiteral("<br/>");
|
||||
header += tr("Status: %1").arg(toString(ms.statusId()));
|
||||
header += QStringLiteral("<br/>");
|
||||
header += tr("Created: %1").arg(DTG::toStringMSec(ms.timeCreated()));
|
||||
header += QStringLiteral("<br/>");
|
||||
if (ms.timeStart().is_set())
|
||||
header += tr("START: %1").arg(DTG::toStringMSec(ms.timeStart().get()));
|
||||
else
|
||||
header += tr("START: %1").arg(tr("[N/A]"));
|
||||
header += QStringLiteral(" - ");
|
||||
if (ms.timeEnd().is_set())
|
||||
header += tr("END: %1").arg(DTG::toStringMSec(ms.timeEnd().get()));
|
||||
else
|
||||
header += tr("END: %1").arg(tr("[N/A]"));
|
||||
header += QStringLiteral("<br/>");
|
||||
header += QStringLiteral("</p>");
|
||||
|
||||
m_ui->mountingPointListView->expandAll();
|
||||
|
||||
LtsPrinting::printView(m_session, this, m_ui->mountingPointListView->treeView(), header);
|
||||
}
|
||||
|
||||
void MountingPointListDialog::onScheduleIdChanged(int32_t scheduleId)
|
||||
{
|
||||
if (scheduleId == m_scheduleId)
|
||||
return;
|
||||
|
||||
// scheduleId changed, data is maybe invalid -> close dialog:
|
||||
deleteLater();
|
||||
}
|
||||
|
||||
void MountingPointListDialog::onVisibilityChanged(bool visible)
|
||||
{
|
||||
Q_UNUSED(visible);
|
||||
// maybe dialog is put to background -> leave mount mode:
|
||||
onUpdateInfoMountButtonAndBehaviour();
|
||||
}
|
||||
|
||||
void MountingPointListDialog::onCustomContextMenu(QPoint pos)
|
||||
{
|
||||
QMenu *contextMenu = new QMenu(this);
|
||||
contextMenu->setAttribute(Qt::WA_DeleteOnClose);
|
||||
{
|
||||
QAction *action = new QAction(tr("Expand All"), this);
|
||||
action->setEnabled(true);
|
||||
connect(action, &QAction::triggered, this, [this]()
|
||||
{
|
||||
m_ui->mountingPointListView->expandAll();
|
||||
});
|
||||
contextMenu->addAction(action);
|
||||
}
|
||||
{
|
||||
QAction *action = new QAction(tr("Collapse All"), this);
|
||||
action->setEnabled(true);
|
||||
connect(action, &QAction::triggered, this, [this]()
|
||||
{
|
||||
m_ui->mountingPointListView->collapseAll();
|
||||
});
|
||||
contextMenu->addAction(action);
|
||||
}
|
||||
|
||||
contextMenu->addSeparator();
|
||||
QModelIndex index = m_ui->mountingPointListView->treeView()->indexAt(pos);
|
||||
bool hasChildren = m_ui->mountingPointListView->treeView()->model()->rowCount(index) > 0;
|
||||
|
||||
{
|
||||
QAction *action = new QAction(tr("Expand"), this);
|
||||
action->setEnabled(hasChildren);
|
||||
connect(action, &QAction::triggered, this, [this, index]()
|
||||
{
|
||||
#if QT_VERSION < QT_VERSION_CHECK(5,13,0)
|
||||
m_ui->mountingPointListView->treeView()->expand(index);
|
||||
#else
|
||||
m_ui->mountingPointListView->treeView()->expandRecursively(index);
|
||||
#endif
|
||||
});
|
||||
contextMenu->addAction(action);
|
||||
}
|
||||
|
||||
{
|
||||
QAction *action = new QAction(tr("Collapse"), this);
|
||||
action->setEnabled(hasChildren);
|
||||
connect(action, &QAction::triggered, this, [this, index]()
|
||||
{
|
||||
m_ui->mountingPointListView->treeView()->collapse(index);
|
||||
});
|
||||
contextMenu->addAction(action);
|
||||
}
|
||||
|
||||
contextMenu->popup(m_ui->mountingPointListView->treeView()->mapToGlobal(pos));
|
||||
}
|
||||
|
||||
void MountingPointListDialog::onDataViewClicked(const QModelIndex &mi)
|
||||
{
|
||||
m_clickedObjectStore.reset();
|
||||
onDataViewEntered(mi);
|
||||
|
||||
// suppress Entered for a while:
|
||||
m_clickedObjectStore.timestampMsec = QDateTime::currentMSecsSinceEpoch();
|
||||
|
||||
bool enabled = LtsSessionData::LtsSessionData::getInstance()->hasOperatorRight(OperatorRights::SystemConfiguration);
|
||||
m_buttonBox->getButton(LtsWidgets::DialogButton::Load)->setEnabled(hasMountingPointMountedAsset(mi) && enabled);
|
||||
}
|
||||
|
||||
QModelIndex MountingPointListDialog::mapToSourciest(const QModelIndex &index)
|
||||
{
|
||||
QModelIndex currentIndex = index;
|
||||
const QAbstractItemModel *model = index.model();
|
||||
//qWarning() << "start" << model << currentIndex;
|
||||
|
||||
while (true)
|
||||
{
|
||||
const QAbstractProxyModel *proxyModel = qobject_cast<const QAbstractProxyModel *>(model);
|
||||
|
||||
if (proxyModel == nullptr)
|
||||
break;
|
||||
|
||||
model = proxyModel->sourceModel();
|
||||
currentIndex = proxyModel->mapToSource(currentIndex);
|
||||
//qWarning() << "new" << model << currentIndex;
|
||||
}
|
||||
|
||||
//qWarning() << "done" << model << currentIndex;
|
||||
return currentIndex;
|
||||
}
|
||||
|
||||
void MountingPointListDialog::onDataViewEntered(const QModelIndex & mi)
|
||||
{
|
||||
if ( (QDateTime::currentMSecsSinceEpoch() - m_clickedObjectStore.timestampMsec) < 500)
|
||||
return;
|
||||
|
||||
const QModelIndex &theIndex(mapToSourciest(mi));
|
||||
NGLTreeItem *treeItem = m_sourceModel->privateData(theIndex);
|
||||
if (!treeItem)
|
||||
return;
|
||||
|
||||
const QVariant v(treeItem->data());
|
||||
if (v.canConvert<SimpleStructureElementData>())
|
||||
{
|
||||
// Building:
|
||||
const SimpleStructureElementData itemData = v.value<SimpleStructureElementData>();
|
||||
m_clickedObjectStore.mot = SituationMap::MapObjectType::MOT_Building;
|
||||
m_clickedObjectStore.entityId = itemData.mseId;
|
||||
|
||||
}
|
||||
else if (v.canConvert<SimpleMountingPointData>())
|
||||
{
|
||||
// MountingPoint:
|
||||
const SimpleMountingPointData itemData = v.value<SimpleMountingPointData>();
|
||||
m_clickedObjectStore.mot = SituationMap::MapObjectType::MOT_MountingPoint;
|
||||
m_clickedObjectStore.entityId = itemData.id;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_clickedObjectStore.reset();
|
||||
}
|
||||
|
||||
if (m_clickedObjectStore.entityId>=0)
|
||||
{
|
||||
m_mapGuiInterface->objectIndicatorToMapObject(m_clickedObjectStore.mot, m_clickedObjectStore.entityId, true);
|
||||
if (QGuiApplication::keyboardModifiers().testFlag(Qt::KeyboardModifier::ShiftModifier))
|
||||
m_mapGuiInterface->centerMapToMapObject(m_clickedObjectStore.mot, m_clickedObjectStore.entityId);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void MountingPointListDialog::onEscapePressed()
|
||||
{
|
||||
if (!m_mapGuiInterface)
|
||||
return;
|
||||
m_mapGuiInterface->removeObjectIndicator();
|
||||
}
|
||||
|
||||
void MountingPointListDialog::onUnmountButtonClicked()
|
||||
{
|
||||
if (m_ui->mountingPointListView->selectionModel()->selectedRows().size() < 1)
|
||||
return;
|
||||
|
||||
NGLTreeItem *treeItem = m_sourceModel->privateData(mapToSourciest(m_ui->mountingPointListView->currentIndex()));
|
||||
if (!treeItem)
|
||||
return;
|
||||
|
||||
const QVariant v = treeItem->data();
|
||||
if (v.canConvert<SimpleMountingPointData>())
|
||||
{
|
||||
const SimpleMountingPointData itemData = v.value<SimpleMountingPointData>();
|
||||
|
||||
LtsWidgets::Button button = LtsWidgets::LtsMessageDialog::showMessage(
|
||||
this, tr("Do you really want to unmount asset on selected mounting point?"), tr("Unmount Assets"), LtsWidgets::Behaviour::Modal,
|
||||
{ LtsWidgets::Button::Yes, LtsWidgets::Button::No });
|
||||
if (button == LtsWidgets::Button::Yes)
|
||||
{
|
||||
const int assetId = m_dtc->getMountedAssetId(itemData.id);
|
||||
if (assetId > 0)
|
||||
{
|
||||
InstrumentationAssetUnmountRequest req(assetId);
|
||||
bool ret = m_requestHelper->startSingleRequest([req, this]()
|
||||
{
|
||||
return m_ftc->instrumentationAssetUnmountRequest(req, this);
|
||||
});
|
||||
|
||||
if (!ret)
|
||||
WARNING_LOG(m_logger)<<" couldn't unmount asset on MountingPoinAsset id: "<<req.id();
|
||||
else
|
||||
m_buttonBox->setButtonEnabled(LtsWidgets::DialogButton::Load,false);
|
||||
}
|
||||
else // mounted asset id not found
|
||||
{
|
||||
LtsWidgets::LtsMessageDialog::showMessage(
|
||||
this, tr("No mounted asset found on this mounting point"), tr("Unmount Assets"), LtsWidgets::Behaviour::Modal, LtsWidgets::Button::Ok);
|
||||
|
||||
m_buttonBox->setButtonEnabled(LtsWidgets::DialogButton::Load,false);
|
||||
}
|
||||
} // end if allow unmount asset
|
||||
}
|
||||
else
|
||||
{
|
||||
ERROR_LOG(m_logger)<<" Couldn't convert to SimpleMountingPointData: ";
|
||||
}
|
||||
}
|
||||
|
||||
void MountingPointListDialog::onInfoMountButtonClicked(bool)
|
||||
{
|
||||
// toggle btn and sitMap behaviour, but keep visibility in mind:
|
||||
|
||||
switch (m_infoMount) {
|
||||
case InfoMount::IM_INFO:
|
||||
m_infoMount = InfoMount::IM_MOUNT;
|
||||
break;
|
||||
case InfoMount::IM_MOUNT:
|
||||
m_infoMount = InfoMount::IM_INFO;
|
||||
break;
|
||||
default:
|
||||
// empty
|
||||
break;
|
||||
} // switch
|
||||
|
||||
onUpdateInfoMountButtonAndBehaviour();
|
||||
}
|
||||
|
||||
void MountingPointListDialog::onUpdateInfoMountButtonAndBehaviour()
|
||||
{
|
||||
// // maybe dialog is put to background and is hidden now -> leave mount mode:
|
||||
// // in that case switch to 'IM_INFO' tempoary:
|
||||
InfoMount infoMountTemp = m_infoMount;
|
||||
const bool bDialogIsVisi = this->isVisible();
|
||||
if (!bDialogIsVisi)
|
||||
infoMountTemp = InfoMount::IM_INFO;
|
||||
|
||||
switch (infoMountTemp) {
|
||||
case InfoMount::IM_INFO:
|
||||
{
|
||||
QColor backgroundColor = QToolButton().palette().window().color();
|
||||
QColor textColor = QGuiApplication::palette().color(QPalette::Text);
|
||||
QString style = QStringLiteral("QToolButton { background-color: rgb(%1,%2,%3); color: rgb(%4,%5,%6) }")
|
||||
.arg(backgroundColor.red()).arg(backgroundColor.green()).arg(backgroundColor.blue())
|
||||
.arg(textColor.red()).arg(textColor.green()).arg(textColor.blue());
|
||||
m_ui->tbMountMode->setText(tr("Info"));
|
||||
m_ui->tbMountMode->setStyleSheet(style);
|
||||
m_ui->tbMountMode->setToolTip(tr("Click on map object opens info dialog"));
|
||||
|
||||
m_ismGuiIfc->setSelector(nullptr);
|
||||
m_mapGuiInterface->setSkipMapObjectSelectionDialog(false);
|
||||
}
|
||||
break;
|
||||
case InfoMount::IM_MOUNT:
|
||||
{
|
||||
QColor color = QGuiApplication::palette().color(QPalette::Link);
|
||||
QString style = QStringLiteral("QToolButton { background-color: rgb(%1,%2,%3); color: white }").arg(
|
||||
QString::number(color.red()), QString::number(color.green()), QString::number(color.blue())
|
||||
);
|
||||
m_ui->tbMountMode->setStyleSheet(style);
|
||||
m_ui->tbMountMode->setText(tr("Map Selection"));
|
||||
m_ui->tbMountMode->setToolTip(tr("Click on map object toogles aim state"));
|
||||
|
||||
m_ismGuiIfc->setSelector(m_ddsSelector);
|
||||
m_mapGuiInterface->setSkipMapObjectSelectionDialog(true);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
// empty
|
||||
break;
|
||||
} // switch
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
//( class ClickedObjectStore
|
||||
//------------------------------------------------------------------------------
|
||||
void MountingPointListDialog::ClickedObjectStore::reset()
|
||||
{
|
||||
mot = SituationMap::MapObjectType::MOT_Undefined;
|
||||
entityId = -1;
|
||||
timestampMsec = 0;
|
||||
}
|
||||
|
||||
} // namespace InfrastructureManagement
|
||||
|
||||
|
||||
|
||||
#include "ism_mounting_point_list_dialog.moc"
|
||||
+167
@@ -0,0 +1,167 @@
|
||||
/**
|
||||
* @RDE_HEADER@
|
||||
* The MountingPointListDialog shows how many assets are needed for a specific schedule, needed elsewhere,
|
||||
* totally possessed, free, and missing
|
||||
* Modified version using the checkStateProxyModel to allow setting via the checkboxes of the tree structure hjl 5/19
|
||||
* $Id$
|
||||
* $HeadURL$
|
||||
* $Author$
|
||||
* Created by Hannes Baeuerle, SLSE, 2016-11-03
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <InfrastructureManagement/ism_dtc.h>
|
||||
#include <InfrastructureManagement/ism_ftc.h>
|
||||
#include <InfrastructureManagement/logger.h>
|
||||
#include <InfrastructureManagement/ism_data_plugin_interface.h>
|
||||
#include <SituationMapPlugin/situation_map_gui_plugin_interface.h>
|
||||
#include <InfrastructureManagement/ism_resource_management_gui_plugin_interface.h>
|
||||
#include <InfrastructureManagement/Gui/ResourceManagement/MountingPointMapSelection/ism_dds_selector.h>
|
||||
#include <InfrastructureManagement/Gui/ResourceManagement/MountingPointMapSelection/ism_selector.h>
|
||||
#include <FilterManagement/flt_building_cmpnt_plugin_interface.h> // honor current filter settings (menue SituationMap)
|
||||
#include <FilterManagement/flt_building_cmpnt_settings.h> // hold current filter settings (and for addCSubscriberCallback)
|
||||
#include <LtsWidgets/lts_dialog.h>
|
||||
#include <LtsDataView/check_state_proxy_model.h>
|
||||
#include <LtsWidgets/lts_abstract_table_model.h>
|
||||
|
||||
#include <QItemDelegate>
|
||||
|
||||
|
||||
class QCheckBox;
|
||||
|
||||
namespace Ui
|
||||
{
|
||||
class MountingPointListDialog;
|
||||
}
|
||||
|
||||
namespace LtsSession
|
||||
{
|
||||
class LtsSession;
|
||||
}
|
||||
|
||||
namespace LtsUtils
|
||||
{
|
||||
class RequestHelper;
|
||||
}
|
||||
|
||||
namespace SituationMap
|
||||
{
|
||||
enum class MapObjectType;
|
||||
}
|
||||
|
||||
|
||||
|
||||
namespace InfrastructureManagement
|
||||
{
|
||||
class MountingPointListDialogModel;
|
||||
class MountingPointListSortModel;
|
||||
class CheckboxProxyModel;
|
||||
|
||||
|
||||
|
||||
class MountingPointListDialog final
|
||||
: public LtsWidgets::LtsDialog
|
||||
, protected Interface::Ftc::MountingPointPlanModifyReplyHandler
|
||||
, protected Interface::Ftc::InstrumentationAssetUnmountReplyHandler
|
||||
, protected Interface::Ftc::StructureElementModifyReplyHandler
|
||||
, protected Interface::Ftc::InstrumentationAssetModifyReplyHandler
|
||||
, protected Interface::Ftc::MountingPointAssetModifyReplyHandler
|
||||
, protected Interface::Ftc::MountingPointAssetRemoveReplyHandler
|
||||
, protected FilterManagement::BuildingComponentSettings::SettingsChangedCallback
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit MountingPointListDialog(const QString &menuGroup, QWidget *parent = nullptr);
|
||||
~MountingPointListDialog();
|
||||
|
||||
bool init(LtsSession::LtsSession *session,
|
||||
const std::shared_ptr<Interface::Dtc> &dtc,
|
||||
const std::shared_ptr<Interface::Ftc> &ftc,
|
||||
const std::shared_ptr<ForeignDataInterface> &dataInterface,
|
||||
InfrastructureManagement::ForeignResourceManagementGuiInterface *ismGuiIfc,
|
||||
const std::shared_ptr<SituationMap::ForeignGuiInterface> &mapIfc,
|
||||
const std::shared_ptr<FilterManagement::ForeignFltBuildingComponentGuiInterface> fltBuildingComponentIfc
|
||||
);
|
||||
|
||||
void onMountingPointPlanModifyReply(const Core::FunctionReplyObject &replyObject) override final;
|
||||
|
||||
void onInstrumentationAssetModifyReply(const Core::FunctionReplyObject &replyObject) override final;
|
||||
void onInstrumentationAssetUnmountReply(const Core::FunctionReplyObject &replyObject) override final;
|
||||
|
||||
void onStructureElementModifyReply(const Core::FunctionReplyObject &replyObject) override final;
|
||||
|
||||
void onMountingPointAssetModifyReply(const Core::FunctionReplyObject &replyObject) override final;
|
||||
void onMountingPointAssetRemoveReply(const Core::FunctionReplyObject &replyObject) override final;
|
||||
|
||||
void onBuildingComponentSettingsChanged() override final;
|
||||
|
||||
void getMountingPointPlanData(const QModelIndex &index, std::vector<MountingPointPlan> &add, const QHash<int, MountingPointPlan> &mppMap);
|
||||
bool hasMountingPointMountedAsset(const QModelIndex &index);
|
||||
friend class MountingPointSelector;
|
||||
|
||||
private slots:
|
||||
void onVisibilityChanged(bool visible);
|
||||
void onPrint();
|
||||
void onScheduleIdChanged(int32_t scheduleId);
|
||||
void onCustomContextMenu(QPoint pos);
|
||||
|
||||
void onDataViewClicked(const QModelIndex &mi);
|
||||
void onDataViewEntered(const QModelIndex &mi);
|
||||
void onEscapePressed();
|
||||
void onUnmountButtonClicked();
|
||||
|
||||
void onInfoMountButtonClicked(bool);
|
||||
void onUpdateInfoMountButtonAndBehaviour();
|
||||
|
||||
private: // methods
|
||||
void retranslate() override;
|
||||
bool apply() override final;
|
||||
bool isIncludedId(int32_t mountingPointId) const;
|
||||
QModelIndex mapToSourciest(const QModelIndex &index);
|
||||
|
||||
private: // attributes
|
||||
MountingPointListDialogModel *m_sourceModel{nullptr};
|
||||
MountingPointListSortModel *m_sortProxyModel{nullptr};
|
||||
CheckboxProxyModel *m_checkboxProxyModel{nullptr};
|
||||
std::shared_ptr<Interface::Dtc> m_dtc;
|
||||
std::shared_ptr<Interface::Ftc> m_ftc;
|
||||
std::shared_ptr<ForeignDataInterface> m_dataIfc;
|
||||
LtsUtils::RequestHelper *m_requestHelper{nullptr};
|
||||
QString m_menuGroup;
|
||||
|
||||
LtsSession::LtsSession *m_session{nullptr};
|
||||
ForeignResourceManagementGuiInterface *m_ismGuiIfc{nullptr};
|
||||
std::shared_ptr<SituationMap::ForeignGuiInterface> m_mapGuiInterface;
|
||||
|
||||
struct ClickedObjectStore
|
||||
{
|
||||
SituationMap::MapObjectType mot {SituationMap::MapObjectType::MOT_Undefined};
|
||||
int entityId {-1};
|
||||
qint64 timestampMsec {-1};
|
||||
void reset();
|
||||
} m_clickedObjectStore;
|
||||
|
||||
unsigned int m_typeFilterColumn;
|
||||
unsigned int m_typeFilterRow;
|
||||
DdsSelector *m_ddsSelector{nullptr};
|
||||
int32_t m_scheduleId;
|
||||
|
||||
// click leads to a) InfoDialog or b) mounting/changing aimState (Idle, Equipped, Empty)
|
||||
enum class InfoMount
|
||||
{
|
||||
IM_INFO, ///! on Click on MapObject, normal map behaviour: info dialog
|
||||
IM_MOUNT ///! on Click on MapObject, change aim state
|
||||
}
|
||||
m_infoMount{InfoMount::IM_INFO};
|
||||
|
||||
SituationMap::ResourceManagerMode m_oldResourceManagerMode{SituationMap::ResourceManagerMode::Undefined};
|
||||
std::shared_ptr<FilterManagement::ForeignFltBuildingComponentGuiInterface> m_fltBuildingComponentIfc;
|
||||
std::shared_ptr<FilterManagement::BuildingComponentSettings> m_buildingComponentSettings;
|
||||
|
||||
|
||||
Ui::MountingPointListDialog *m_ui{nullptr};
|
||||
LOGGER_T m_logger;
|
||||
|
||||
}; // class MountingPointListDialog
|
||||
} // namespace InfrastructureManagement
|
||||
+74
@@ -0,0 +1,74 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>MountingPointListDialog</class>
|
||||
<widget class="QWidget" name="MountingPointListDialog">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>833</width>
|
||||
<height>478</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string notr="true">Asset Stocks</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout">
|
||||
<item row="2" column="1" colspan="2">
|
||||
<widget class="LtsDataView::LtsDataView" name="mountingPointListView" native="true">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="rootIsDecorated" stdset="0">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="showColumnCount" stdset="0">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="toolButtonsVisible" stdset="0">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="1">
|
||||
<spacer name="horizontalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>439</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item row="1" column="0" colspan="2">
|
||||
<widget class="QToolButton" name="tbMountMode">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>150</width>
|
||||
<height>50</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string notr="true">mountMode</string>
|
||||
</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>
|
||||
+52
@@ -0,0 +1,52 @@
|
||||
#include "ism_mounting_point_list_dialog_checkbox_delegate.h"
|
||||
#include "ism_mounting_point_list_dialog_model.h"
|
||||
|
||||
#include <QPainter>
|
||||
|
||||
|
||||
namespace InfrastructureManagement
|
||||
{
|
||||
CheckboxDelegate::CheckboxDelegate(QObject *parent)
|
||||
: QItemDelegate(parent)
|
||||
{}
|
||||
|
||||
|
||||
void CheckboxDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const
|
||||
{
|
||||
QItemDelegate::paint(painter, option, index);
|
||||
|
||||
if (index.column() != MountingPointListDialogModel::Columns::NAME)
|
||||
return;
|
||||
|
||||
painter->save();
|
||||
painter->setClipRect(option.rect);
|
||||
painter->setClipping(true);
|
||||
|
||||
const QVariant value(index.data(Qt::UserRole + 1));
|
||||
if (value.isValid() && value.canConvert<int>())
|
||||
{
|
||||
QPixmap x(QStringLiteral(":/style/checkbox-multi-state.svg"));
|
||||
|
||||
switch (value.toInt())
|
||||
{
|
||||
case MountingPointState::Equipped:
|
||||
x = QPixmap(QStringLiteral(":/style/checkbox-true.svg"));
|
||||
break;
|
||||
case MountingPointState::Idle:
|
||||
x = QPixmap(QStringLiteral(":/style/checkbox-empty.svg"));
|
||||
break;
|
||||
case MountingPointState::Empty:
|
||||
x = QPixmap(QStringLiteral(":/style/checkbox-false.svg"));
|
||||
break;
|
||||
}
|
||||
|
||||
const QStyleOptionViewItem opt = setOptions(index, option);
|
||||
const QRect checkRect(QItemDelegate::doCheck(opt, opt.rect, /*value*/1));
|
||||
|
||||
painter->drawPixmap(checkRect.adjusted(3,0,3,0), x, QRect());
|
||||
//QItemDelegate::drawCheck(painter, opt, checkRect, Qt::CheckState::Checked); // test
|
||||
}
|
||||
|
||||
painter->restore();
|
||||
}
|
||||
} // namespace InfrastructureManagement
|
||||
+18
@@ -0,0 +1,18 @@
|
||||
#pragma once
|
||||
|
||||
#include "ism_mounting_point_list_dialog_checkbox_delegate.h"
|
||||
|
||||
#include <QItemDelegate>
|
||||
|
||||
|
||||
namespace InfrastructureManagement
|
||||
{
|
||||
class CheckboxDelegate : public QItemDelegate
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
CheckboxDelegate(QObject *parent = nullptr);
|
||||
void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const;
|
||||
};
|
||||
} // namespace InfrastructureManagement
|
||||
+168
@@ -0,0 +1,168 @@
|
||||
#include "ism_mounting_point_list_dialog_checkbox_proxy_model.h"
|
||||
#include "ism_mounting_point_list_dialog_model.h"
|
||||
|
||||
|
||||
namespace InfrastructureManagement
|
||||
{
|
||||
Qt::ItemFlags CheckboxProxyModel::flags(const QModelIndex &index) const
|
||||
{
|
||||
if (!index.isValid())
|
||||
return sourceModel()->flags(index); // delegate to source model for further processing if necessary
|
||||
|
||||
// Sets only the checkbox nodes on user checkable,
|
||||
// checkbox leaves must be handled in source model.
|
||||
QModelIndex sourceIndex = mapToSource(index);
|
||||
Qt::ItemFlags fl = sourceModel()->flags(sourceIndex);
|
||||
if (index.column() == 0)
|
||||
return fl | Qt::ItemIsUserCheckable;
|
||||
return fl;
|
||||
}
|
||||
|
||||
|
||||
QVariant CheckboxProxyModel::data(const QModelIndex &index, int role) const
|
||||
{
|
||||
if (!index.isValid())
|
||||
return {};
|
||||
|
||||
const QModelIndex sourceIndex(mapToSource(index));
|
||||
|
||||
// delegate everything except CheckStateRole to source model
|
||||
if (role != (Qt::UserRole + 1))
|
||||
return sourceModel()->data(sourceIndex, role);
|
||||
|
||||
// delegate a leaf too with CheckStateRole to source model
|
||||
if (isLeaf(index))
|
||||
return sourceModel()->data(sourceIndex, role);
|
||||
|
||||
// delegate to source model for further processing of further columns if necessary
|
||||
if (index.column() != MountingPointListDialogModel::Columns::NAME)
|
||||
return sourceModel()->data(sourceIndex, role);
|
||||
|
||||
// sets the node checkboxes and decoration depending on the entries in the tree structure
|
||||
bool lastMpsSet = false; // std::optional >_>
|
||||
int lastMps = -2;
|
||||
int childCount = rowCount(index);
|
||||
for (int childRow = 0; childRow < childCount; ++childRow)
|
||||
{
|
||||
const QModelIndex childIndex(this->index(childRow, 0, index));
|
||||
|
||||
const QVariant value(data(childIndex, (Qt::UserRole + 1)));
|
||||
if (value.isValid() && value.canConvert<int>())
|
||||
{
|
||||
int state = value.toInt();
|
||||
|
||||
if (!lastMpsSet)
|
||||
{
|
||||
lastMpsSet = true;
|
||||
lastMps = state;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (lastMps != state) // if at one point there is a different status inside one parent, show the 'partial' checkbox state as there are mixed states
|
||||
return -2;
|
||||
}
|
||||
}
|
||||
|
||||
return lastMps;
|
||||
}
|
||||
|
||||
|
||||
QString mpsToString(const int mps)
|
||||
{
|
||||
switch ((int)mps)
|
||||
{
|
||||
case -2:
|
||||
return QStringLiteral("PARTIALLY");
|
||||
case -1:
|
||||
return QStringLiteral("EMPTY");
|
||||
case 0:
|
||||
return QStringLiteral("IDLE");
|
||||
case 1:
|
||||
return QStringLiteral("EQUIPPED");
|
||||
default:
|
||||
return QStringLiteral("( !UNKNOWN! )");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
QString mpsToString(const MountingPointState_def::type mps)
|
||||
{
|
||||
return mpsToString((int)mps);
|
||||
}
|
||||
|
||||
|
||||
bool CheckboxProxyModel::setData(const QModelIndex &index, const QVariant &value, int role)
|
||||
{
|
||||
/* this setData is called if the user clicks on a checkbox
|
||||
* then this setData calls the sourceModel's setData to finally
|
||||
* set the underlying checkboxes */
|
||||
|
||||
if (!index.isValid())
|
||||
return false;
|
||||
|
||||
const QModelIndex sourceIndex(mapToSource(index));
|
||||
|
||||
// delegate to source model for further processing of further columns if necessary
|
||||
if (index.column() != MountingPointListDialogModel::Columns::NAME)
|
||||
return sourceModel()->setData(sourceIndex, value, role);
|
||||
|
||||
|
||||
/* Qt calls setData with role == Qt::CheckStateRole if the user clicks on a checkbox.
|
||||
* We need to know at this point if wither the call to this method was called by Qt,
|
||||
* or if this method called setData recursively. If this is the first call, the new
|
||||
* checkbox state has to be determined at this point. To determine if the call to
|
||||
* setData is a recursive call, we set role to Qt::UserRole+1. Kind of a hack. */
|
||||
|
||||
int newMps = value.toInt();
|
||||
|
||||
if (role == Qt::CheckStateRole)
|
||||
{
|
||||
//newMps = (int)MountingPointState_def::Idle;
|
||||
int mps = index.data(Qt::UserRole + 1).toInt();
|
||||
switch (mps)
|
||||
{
|
||||
case -2: // SPECIAL CASE, not a real MPS, but the indicator that there are mixed states on the underlying children
|
||||
newMps = (int)MountingPointState_def::Idle;
|
||||
break;
|
||||
case (int)MountingPointState_def::Idle:
|
||||
newMps = (int)MountingPointState_def::Equipped;
|
||||
break;
|
||||
case (int)MountingPointState_def::Equipped:
|
||||
newMps = (int)MountingPointState_def::Empty;
|
||||
break;
|
||||
case (int)MountingPointState_def::Empty:
|
||||
newMps = (int)MountingPointState_def::Idle;
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (isLeaf(index))
|
||||
{
|
||||
// delegate a leaf to source model
|
||||
sourceModel()->setData(sourceIndex, newMps, role);
|
||||
}
|
||||
else
|
||||
{
|
||||
// update underlying children recursively (Additional nodes with leaves may also exist)
|
||||
const int childCount = rowCount(index);
|
||||
for (int childRow = 0; childRow < childCount; ++childRow)
|
||||
{
|
||||
const QModelIndex childIndex(this->index(childRow, 0, index));
|
||||
setData(childIndex, newMps, (Qt::UserRole + 1));
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool CheckboxProxyModel::isLeaf(const QModelIndex &index) const
|
||||
{
|
||||
const QModelIndex sourceIndex(mapToSource(index));
|
||||
return sourceModel()->flags(sourceIndex).testFlag(Qt::ItemIsUserCheckable);
|
||||
}
|
||||
} // namespace InfrastructureManagement
|
||||
|
||||
|
||||
+19
@@ -0,0 +1,19 @@
|
||||
#pragma once
|
||||
|
||||
#include <QIdentityProxyModel>
|
||||
|
||||
|
||||
namespace InfrastructureManagement
|
||||
{
|
||||
class CheckboxProxyModel : public QIdentityProxyModel
|
||||
{
|
||||
public:
|
||||
using QIdentityProxyModel::QIdentityProxyModel;
|
||||
Qt::ItemFlags flags(const QModelIndex &index) const override;
|
||||
QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
|
||||
bool setData(const QModelIndex &index, const QVariant &value, int role = Qt::EditRole) override;
|
||||
|
||||
private:
|
||||
bool isLeaf(const QModelIndex &index) const;
|
||||
};
|
||||
} // namespace InfrastructureManagement
|
||||
+120
@@ -0,0 +1,120 @@
|
||||
#include "ism_mounting_point_list_dialog_list_sort_model.h"
|
||||
|
||||
#include <Plugins/InfrastructureManagement/Shared/ism_mounting_point.h>
|
||||
|
||||
namespace InfrastructureManagement
|
||||
{
|
||||
|
||||
void MountingPointListSortModel::setSourceModel(QAbstractItemModel *sourceModel)
|
||||
{
|
||||
m_sourceModel = qobject_cast<MountingPointListDialogModel*>(sourceModel);
|
||||
LtsWidgets::LtsColumnFilterProxyModel::setSourceModel(m_sourceModel);
|
||||
}
|
||||
|
||||
void MountingPointListSortModel::setTypeFilter(const QSet<MountingPointType> &visibleTypes)
|
||||
{
|
||||
if (m_visibleTypes == visibleTypes)
|
||||
return;
|
||||
m_visibleTypes = visibleTypes;
|
||||
invalidateFilter();
|
||||
}
|
||||
|
||||
void MountingPointListSortModel::addToTypeFilter(MountingPointType mpt, bool bAdd)
|
||||
{
|
||||
auto visibleTypes = m_visibleTypes;
|
||||
if (bAdd)
|
||||
{
|
||||
if(mpt == MountingPointType::IndoorIPS)
|
||||
{
|
||||
visibleTypes.insert(MountingPointType::OutdoorIPS);
|
||||
}
|
||||
visibleTypes.insert(mpt);
|
||||
}
|
||||
else
|
||||
{
|
||||
if(mpt == MountingPointType::IndoorIPS)
|
||||
{
|
||||
visibleTypes.remove(MountingPointType::OutdoorIPS);
|
||||
}
|
||||
visibleTypes.remove(mpt);
|
||||
}
|
||||
setTypeFilter(visibleTypes);
|
||||
}
|
||||
|
||||
void MountingPointListSortModel::setFloorFilter(const QSet<int> &visibleFloors)
|
||||
{
|
||||
if (m_visibleFloors == visibleFloors)
|
||||
return;
|
||||
m_visibleFloors = visibleFloors;
|
||||
invalidateFilter();
|
||||
}
|
||||
|
||||
void MountingPointListSortModel::addToFloorFilter(int floor, bool bAdd)
|
||||
{
|
||||
auto visibleFloors = m_visibleFloors;
|
||||
if (bAdd)
|
||||
visibleFloors.insert(floor);
|
||||
else
|
||||
visibleFloors.remove(floor);
|
||||
setFloorFilter(visibleFloors);
|
||||
}
|
||||
|
||||
bool MountingPointListSortModel::filterAcceptsRow(int source_row, const QModelIndex &source_parent) const
|
||||
{
|
||||
if (!m_sourceModel)
|
||||
return true;
|
||||
|
||||
bool isRootItem = !source_parent.isValid();
|
||||
if (isRootItem)
|
||||
{
|
||||
Q_ASSERT(source_row == 0);
|
||||
return true; // root item shall always be visible
|
||||
}
|
||||
|
||||
const QModelIndex childIdx = m_sourceModel->index(source_row, 0, source_parent);
|
||||
const NGLTreeItem *itemChild = m_sourceModel->privateData(childIdx);
|
||||
Q_ASSERT(itemChild);
|
||||
|
||||
bool isLeaf = itemChild->data().canConvert<SimpleMountingPointData>();
|
||||
if (isLeaf)
|
||||
{
|
||||
const SimpleMountingPointData data = itemChild->data().value<SimpleMountingPointData>();
|
||||
Q_ASSERT(data.isMountingPoint());
|
||||
|
||||
return m_visibleTypes.contains(data.mpType) && m_visibleFloors.contains(data.floor);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!itemChild->data().canConvert<SimpleStructureElementData>())
|
||||
return true;
|
||||
const SimpleStructureElementData ssed = itemChild->data().value<SimpleStructureElementData>();
|
||||
if (ssed.floor != -20 && !m_visibleFloors.contains(ssed.floor))
|
||||
return false;
|
||||
}
|
||||
|
||||
// Qt5.11: setRecursiveFilteringEnabled(true);
|
||||
for (int i = 0; i < itemChild->childCount(); ++i)
|
||||
{
|
||||
if (filterAcceptsRow(i, childIdx))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool MountingPointListSortModel::lessThan(const QModelIndex &source_left, const QModelIndex &source_right) const
|
||||
{
|
||||
if (!m_sourceModel || source_left.column() != source_right.column())
|
||||
return BaseClass::lessThan(source_left, source_right);
|
||||
|
||||
const NGLTreeItem *itemLeft = m_sourceModel->privateData(source_left);
|
||||
const NGLTreeItem *itemRight = m_sourceModel->privateData(source_right);
|
||||
if (!itemLeft || !itemRight)
|
||||
return BaseClass::lessThan(source_left, source_right);
|
||||
|
||||
const SimpleMountingPointData left = itemLeft->data().value<SimpleMountingPointData>();
|
||||
const SimpleMountingPointData right = itemRight->data().value<SimpleMountingPointData>();
|
||||
if (left.name != right.name)
|
||||
return left.name < right.name;
|
||||
return left.id < right.id;
|
||||
}
|
||||
} // namespace InfrastructureManagement
|
||||
+38
@@ -0,0 +1,38 @@
|
||||
#pragma once
|
||||
|
||||
#include "ism_mounting_point_list_dialog_model.h"
|
||||
|
||||
#include <LtsWidgets/lts_column_filter_proxy_model.h>
|
||||
|
||||
#include <QSet>
|
||||
|
||||
|
||||
namespace InfrastructureManagement
|
||||
{
|
||||
class MountingPointListSortModel final : public LtsWidgets::LtsColumnFilterProxyModel
|
||||
{
|
||||
using BaseClass = LtsWidgets::LtsColumnFilterProxyModel;
|
||||
|
||||
Q_OBJECT
|
||||
public:
|
||||
using LtsWidgets::LtsColumnFilterProxyModel::LtsColumnFilterProxyModel;
|
||||
|
||||
void setSourceModel(QAbstractItemModel *sourceModel) override;
|
||||
|
||||
void setTypeFilter(const QSet<MountingPointType> &visibleTypes);
|
||||
void addToTypeFilter(MountingPointType mpt, bool bAdd);
|
||||
|
||||
void setFloorFilter(const QSet<int> &visibleFloors);
|
||||
void addToFloorFilter(int floor, bool bAdd);
|
||||
|
||||
bool filterAcceptsRow(int source_row, const QModelIndex &source_parent) const override;
|
||||
bool lessThan(const QModelIndex &source_left, const QModelIndex &source_right) const override;
|
||||
|
||||
using LtsWidgets::LtsColumnFilterProxyModel::invalidateFilter;
|
||||
|
||||
private:
|
||||
MountingPointListDialogModel *m_sourceModel = nullptr;
|
||||
QSet<MountingPointType> m_visibleTypes;
|
||||
QSet<int> m_visibleFloors;
|
||||
};
|
||||
} // namespace InfrastructureManagement
|
||||
+478
@@ -0,0 +1,478 @@
|
||||
/**
|
||||
* @RDE_HEADER@
|
||||
* The MountingPointListDialogModel provices data for MountingPointListDialog
|
||||
* Modified version using the checkStateProxyModel to allow setting via the checkboxes of the tree structure hjl 5/19
|
||||
* $Id$
|
||||
* $HeadURL$
|
||||
* $Author$
|
||||
* Created by Hannes Baeuerle, SLSE, 2016-11-03
|
||||
*/
|
||||
|
||||
#include "ism_mounting_point_list_dialog_model.h"
|
||||
#include "ism_mounting_point_list_dialog_list_sort_model.h"
|
||||
|
||||
#include <InfrastructureManagement/ism_translation.h>
|
||||
#include <Plugins/InfrastructureManagement/Shared/ism_mounting_point.h>
|
||||
|
||||
#include <QTimer>
|
||||
|
||||
// #define BENCHMARK
|
||||
|
||||
#ifdef BENCHMARK
|
||||
# include <QElapsedTimer>
|
||||
# include <QDebug>
|
||||
#endif
|
||||
|
||||
|
||||
namespace InfrastructureManagement
|
||||
{
|
||||
|
||||
MountingPointListDialogModel::MountingPointListDialogModel(QObject *parent)
|
||||
: NGLTreeModel(parent, new NGLTreeItem(QVariant()), { tr("Name"), tr("Type"), tr("Asset"), tr("Aim State") })
|
||||
, m_visRoot(new NGLTreeItem(tr("Mounting Points")))
|
||||
, m_dtc(nullptr)
|
||||
, m_scheduleId(-1)
|
||||
, m_dataChangedTimer(new QTimer(this))
|
||||
, m_logger(getLogger("MountingPointListDialogModel"))
|
||||
{
|
||||
TRACE_LOG(m_logger) << LOGFUNCTION << " START";
|
||||
m_dataChangedTimer->setSingleShot(true);
|
||||
m_dataChangedTimer->setInterval(100);
|
||||
connect(m_dataChangedTimer, &QTimer::timeout, this, &MountingPointListDialogModel::emitDataChanged);
|
||||
TRACE_LOG(m_logger) << LOGFUNCTION << " END";
|
||||
}
|
||||
|
||||
|
||||
QVariant MountingPointListDialogModel::data(const QModelIndex &index, int role) const
|
||||
{
|
||||
if (!index.isValid())
|
||||
return QVariant();
|
||||
|
||||
NGLTreeItem *item = privateData(index);
|
||||
|
||||
const int indexColumn = index.column();
|
||||
|
||||
if (role == Qt::DisplayRole)
|
||||
{
|
||||
if (indexColumn != NAME && !item->data().canConvert<SimpleMountingPointData>())
|
||||
return QVariant();
|
||||
|
||||
const SimpleMountingPointData itemData = item->data().value<SimpleMountingPointData>();
|
||||
|
||||
switch (indexColumn)
|
||||
{
|
||||
case NAME:
|
||||
if (item->data().canConvert<SimpleMountingPointData>())
|
||||
return item->data().value<SimpleMountingPointData>().name;
|
||||
if (item->data().canConvert<SimpleStructureElementData>())
|
||||
return item->data().value<SimpleStructureElementData>().name;
|
||||
if (item->data().canConvert<SimpleBuildingGroupData>())
|
||||
return item->data().value<SimpleBuildingGroupData>().name;
|
||||
return tr("all");
|
||||
case STATE:
|
||||
if (itemData.seType == StructureElementType::MountingPoint)
|
||||
return toString(itemData.aimState);
|
||||
break;
|
||||
case ASSET_BARCODE:
|
||||
if (item->data().canConvert<SimpleMountingPointData>())
|
||||
return item->data().value<SimpleMountingPointData>().assetBarcode;
|
||||
break;
|
||||
case TYPE:
|
||||
if (itemData.seType == StructureElementType::MountingPoint)
|
||||
{
|
||||
if(itemData.mpType == MountingPointType::OutdoorIPS)
|
||||
return toString(MountingPointType::IndoorIPS);
|
||||
return toString(itemData.mpType);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (role == LtsWidgets::LtsColumnFilterProxyModel::ComboboxFilterRole
|
||||
&& indexColumn == TYPE)
|
||||
{
|
||||
const SimpleMountingPointData itemData = item->data().value<SimpleMountingPointData>();
|
||||
if (itemData.mpType.underlying() == MountingPointType::Unknown)
|
||||
{
|
||||
ERROR_LOG(m_logger) << "unknown!!!";
|
||||
return QVariant(); // return INVALID QVariant to let LtsDataView's proxy filter model ignore this row while filtering / aka. don't hide it when filtering
|
||||
}
|
||||
|
||||
ERROR_LOG(m_logger) << "mpType = " << itemData.mpType.underlying();
|
||||
if(itemData.mpType == MountingPointType::OutdoorIPS)
|
||||
return MountingPointType::IndoorIPS;
|
||||
|
||||
return itemData.mpType.underlying();
|
||||
}
|
||||
|
||||
if (role == Qt::CheckStateRole && index.column() == NAME)
|
||||
return Qt::Unchecked; // dummy
|
||||
|
||||
if (role == Qt::UserRole && item->data().canConvert<SimpleMountingPointData>())
|
||||
return item->data().value<SimpleMountingPointData>().id;
|
||||
|
||||
if (role == (Qt::UserRole + 1) && item->data().canConvert<SimpleMountingPointData>())
|
||||
return item->data().value<SimpleMountingPointData>().aimState.underlying();
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
|
||||
bool MountingPointListDialogModel::initModel(const std::shared_ptr<Interface::Dtc> &dtc, const std::shared_ptr<ForeignDataInterface> &dataInterface)
|
||||
{
|
||||
TRACE_LOG(m_logger) << LOGFUNCTION << " START";
|
||||
if (m_dtc == dtc)
|
||||
return true;
|
||||
|
||||
if (!(dtc->enableMainStructureElement() &&
|
||||
dtc->enableMountingPointAsset()))
|
||||
{
|
||||
ERROR_LOG(m_logger) << "Could not enable Datatopics";
|
||||
return false;
|
||||
}
|
||||
m_dtc = dtc;
|
||||
|
||||
m_dataInterface = dataInterface;
|
||||
m_scheduleId = m_dataInterface->scheduleId();
|
||||
|
||||
connect(m_dataInterface.get(), &ForeignDataInterface::mountingPointChanged,
|
||||
this, &MountingPointListDialogModel::onMountingPointChanged);
|
||||
|
||||
DEBUG_LOG(m_logger) << "initModel successful";
|
||||
|
||||
initData();
|
||||
|
||||
beginResetModel();
|
||||
endResetModel();
|
||||
|
||||
TRACE_LOG(m_logger) << LOGFUNCTION << " START";
|
||||
return true;
|
||||
}
|
||||
|
||||
QModelIndex MountingPointListDialogModel::getIndexOfVisibleRootItem() const
|
||||
{
|
||||
return indexFromItem(m_visRoot);
|
||||
}
|
||||
|
||||
void MountingPointListDialogModel::initData()
|
||||
{
|
||||
TRACE_LOG(m_logger) << LOGFUNCTION << " START";
|
||||
|
||||
#ifdef BENCHMARK
|
||||
QElapsedTimer elapsedTimer1;
|
||||
elapsedTimer1.start();
|
||||
#endif // BENCHMARK
|
||||
|
||||
|
||||
NGLTreeModel::resetModel();
|
||||
|
||||
m_rootItem->appendChild(m_visRoot);
|
||||
|
||||
// const InfrastructureManagement::MainSchedule ¤tSchedule = m_dtc->mainSchedule(m_scheduleId);
|
||||
const QMap<int, InfrastructureManagement::MainStructureElement> &mainStructEles = m_dtc->mainStructureElements();
|
||||
|
||||
|
||||
// cfroebel 2018-11-07:
|
||||
// The algorithm of building the tree structure assumes that
|
||||
// the StructureElements are hierarchically ordered, i.e. that the
|
||||
// MountingPoint comes after its Room, Level and Building.
|
||||
// Is that guaranteed by the service?
|
||||
m_mountingPointIndexes.reserve(mainStructEles.size());
|
||||
m_availableBuildingGroups.reserve(mainStructEles.size());
|
||||
|
||||
for (const MainStructureElement &mse : mainStructEles)
|
||||
{
|
||||
// only consider buildings
|
||||
if (mse.structureElementTypeId() != StructureElementType::Building)
|
||||
continue;
|
||||
|
||||
// 1- if a buildingGroup modelIndex for current building dosen't exist
|
||||
// a new one will be first added and used as parentIndex for the blg_Index.
|
||||
QModelIndex groupIndex;
|
||||
const StructureElement bse= setBuildingGroup(mse.groupId());
|
||||
// Outdoor camera will not be displayed
|
||||
if (mse.groupId() != BuildingGroup::OutdoorCameras)
|
||||
{
|
||||
if (m_availableBuildingGroups.contains(bse.id()) == false)
|
||||
{
|
||||
SimpleBuildingGroupData buildingGroup;
|
||||
buildingGroup.name = QString::fromStdString(bse.displayName());
|
||||
NGLTreeItem *groupItem = new NGLTreeItem(QVariant::fromValue(buildingGroup));
|
||||
QModelIndex groupParentIndex;
|
||||
groupParentIndex = indexFromItem(m_visRoot);
|
||||
insertRow(rowCount(groupParentIndex), groupParentIndex, groupItem);
|
||||
groupIndex = index(groupItem->row(), 0, groupParentIndex);
|
||||
m_mountingPointIndexes.insert(bse.id(), groupIndex);
|
||||
m_availableBuildingGroups.insert(bse.id());
|
||||
}
|
||||
else
|
||||
{
|
||||
groupIndex = m_mountingPointIndexes.value(bse.id(), indexFromItem(m_visRoot));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
for (const StructureElement ¤tElement : mse.elements())
|
||||
{
|
||||
NGLTreeItem *item;
|
||||
|
||||
if (currentElement.structureElementTypeId() == StructureElementType::MountingPoint)
|
||||
{
|
||||
const MountingPoint &mountingPoint = m_dataInterface->mountingPoint(currentElement.id());
|
||||
|
||||
if (!mountingPoint.isValid())
|
||||
continue;
|
||||
|
||||
if (mountingPoint.type() == MountingPointType::Unknown ||
|
||||
mountingPoint.type() == MountingPointType::BuildingControlUnit ||
|
||||
mountingPoint.type() == MountingPointType::VirtualIPS ||
|
||||
mountingPoint.type() == MountingPointType::MeteoDataUnit ||
|
||||
mountingPoint.type() == MountingPointType::BuildingNetworkSwitch ||
|
||||
mountingPoint.type() == MountingPointType::OutdoorCamera)
|
||||
continue;
|
||||
|
||||
SimpleMountingPointData mpData;
|
||||
mpData.seType = currentElement.structureElementTypeId();
|
||||
mpData.id = mountingPoint.id();
|
||||
mpData.name = mountingPoint.name();
|
||||
mpData.aimState = mountingPoint.aimState();
|
||||
mpData.mpType = mountingPoint.type();
|
||||
mpData.floor = mountingPoint.floor();
|
||||
|
||||
// attention: getMountedAssetId could be expensive
|
||||
// const int assetId = m_dtc->getMountedAssetId(mountingPoint.data().id());
|
||||
// use already available mountingPoint instead: :-)
|
||||
const int assetId = mountingPoint.associatedAssetId();
|
||||
mpData.assetBarcode = QStringLiteral("-");
|
||||
if(assetId != -1)
|
||||
{
|
||||
mpData.assetBarcode = QString::fromStdString(m_dtc->instrumentationAsset(assetId).barcode());
|
||||
}
|
||||
|
||||
item = new NGLTreeItem(QVariant::fromValue(mpData));
|
||||
}
|
||||
else
|
||||
{
|
||||
SimpleStructureElementData ssed;
|
||||
ssed.mseId = mse.id();
|
||||
if (currentElement.structureElementTypeId() == StructureElementType::Floor)
|
||||
ssed.floor = QString::fromStdString(currentElement.name()).split(QLatin1Literal("_")).value(1, QLatin1String("-10")).toInt();
|
||||
else
|
||||
ssed.floor = -20;
|
||||
ssed.name = currentElement.displayName().empty() ? QString::fromStdString(currentElement.name()) : QString::fromStdString(currentElement.displayName());
|
||||
item = new NGLTreeItem(QVariant::fromValue(ssed));
|
||||
m_availableFloors << ssed.floor;
|
||||
}
|
||||
|
||||
const auto &path = currentElement.path();
|
||||
|
||||
QModelIndex parentIndex;
|
||||
if (path.size() > 1)
|
||||
{
|
||||
parentIndex = m_mountingPointIndexes.value(path.at(path.size() - 2), indexFromItem(m_visRoot)); //default sollte nie erreicht werden
|
||||
if (!parentIndex.isValid())
|
||||
{
|
||||
ERROR_LOG(m_logger) << "Did not find parent for structure element with id " << currentElement.id() << " mseid: " << mse.id();
|
||||
for (const StructureElement &se : mse.elements())
|
||||
ERROR_LOG(m_logger) << " se: " << se.id() << ", " << se.displayName() << ", " << se.name();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// 2- Append building to it section index
|
||||
if(groupIndex.isValid() == false)
|
||||
{
|
||||
parentIndex = indexFromItem(m_visRoot);
|
||||
}
|
||||
else
|
||||
{
|
||||
parentIndex = groupIndex;
|
||||
}
|
||||
}
|
||||
insertRow(rowCount(parentIndex), parentIndex, item);
|
||||
|
||||
m_mountingPointIndexes.insert(currentElement.id(), index(item->row(), 0, parentIndex));
|
||||
}
|
||||
}
|
||||
|
||||
m_availableFloors << -10;
|
||||
|
||||
#ifdef BENCHMARK
|
||||
qCritical() << " MountingPointListDialogModel::init-BENCHMARK: took " << elapsedTimer1.elapsed() << " [ms]";
|
||||
#endif // BENCHMARK
|
||||
|
||||
TRACE_LOG(m_logger) << LOGFUNCTION << " END";
|
||||
}
|
||||
|
||||
QSet<int> MountingPointListDialogModel::getAvailableFloors() const
|
||||
{
|
||||
return m_availableFloors;
|
||||
}
|
||||
|
||||
StructureElement MountingPointListDialogModel::setBuildingGroup(int groupId)
|
||||
{
|
||||
StructureElement se{};
|
||||
InfrastructureManagement::BuildingGroup_def::type buildingGroup = static_cast<InfrastructureManagement::BuildingGroup_def::type>(groupId);
|
||||
if(buildingGroup == 0)
|
||||
{
|
||||
buildingGroup = InfrastructureManagement::BuildingGroup_def::UnknownGroup;
|
||||
}
|
||||
|
||||
se.id() = maxIntValue - static_cast<int>(buildingGroup);
|
||||
se.name() = InfrastructureManagement::toString(buildingGroup).toStdString();
|
||||
se.displayName() = InfrastructureManagement::toString(buildingGroup).toStdString();
|
||||
se.structureElementTypeId() = InfrastructureManagement::StructureElementType::Section;
|
||||
return se;
|
||||
}
|
||||
|
||||
Qt::ItemFlags MountingPointListDialogModel::flags(const QModelIndex &index) const
|
||||
{
|
||||
Qt::ItemFlags fl = NGLTreeModel::flags(index);
|
||||
if (!index.isValid())
|
||||
return fl;
|
||||
|
||||
NGLTreeItem *item = privateData(index);
|
||||
bool isLeaf = item->data().canConvert<SimpleMountingPointData>();
|
||||
if (isLeaf && index.column() == Columns::NAME)
|
||||
return fl | Qt::ItemIsUserCheckable | Qt::ItemIsUserTristate;
|
||||
return fl;
|
||||
}
|
||||
|
||||
bool MountingPointListDialogModel::setData(const QModelIndex &index, const QVariant &value, int role)
|
||||
{
|
||||
// is called by the CheckboxProxyModel's setData method
|
||||
|
||||
if (index.column() != NAME || !index.isValid())
|
||||
return NGLTreeModel::/**/setData(index, value, role);
|
||||
|
||||
auto lambda = [this, &value](const QModelIndex &idx)
|
||||
{
|
||||
NGLTreeItem *item = privateData(idx);
|
||||
|
||||
if (!item->data().canConvert<SimpleMountingPointData>()) // not a leaf?
|
||||
{
|
||||
Q_ASSERT(false); // CheckboxProxyModel never calls this model's setData if the index is not a leaf
|
||||
|
||||
/* we don't know what state the parent is, wo don't know how many children there REALLY are.
|
||||
* all this is hidden behind multiple proxy models. so send a signal to the dialog,
|
||||
* get the clicked parent's state and set all its (visible!) children.
|
||||
* at least that's the plan .... */
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
SimpleMountingPointData smpd = item->data().value<SimpleMountingPointData>();
|
||||
smpd.aimState = (MountingPointState::inner_enum)value.toInt();
|
||||
|
||||
item->setData(QVariant::fromValue(smpd));
|
||||
|
||||
emit changesMade();
|
||||
};
|
||||
|
||||
if (index.parent().isValid())
|
||||
{
|
||||
lambda(index);
|
||||
}
|
||||
else
|
||||
{
|
||||
for (const QModelIndex &idx : qAsConst(m_mountingPointIndexes))
|
||||
lambda(idx);
|
||||
}
|
||||
|
||||
m_dataChangedTimer->start(); // ugly hack
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
QVariant MountingPointListDialogModel::headerData(int section, Qt::Orientation orientation, int role) const
|
||||
{
|
||||
if (orientation == Qt::Horizontal
|
||||
&& role == LtsWidgets::LtsColumnFilterProxyModel::ComboboxFilterRole
|
||||
&& section == TYPE)
|
||||
return m_cbxFilterType;
|
||||
return BaseClass::headerData(section, orientation, role);
|
||||
}
|
||||
|
||||
|
||||
void MountingPointListDialogModel::setMntPointFilterTypes(QSet<MountingPointType> types)
|
||||
{
|
||||
LtsWidgets::ComboboxFilterContent cfc;
|
||||
LtsWidgets::ComboboxFilterData cfd;
|
||||
for (const auto es : qAsConst(types))
|
||||
{
|
||||
if (es == MountingPointType::OutdoorIPS)
|
||||
continue;
|
||||
cfd.data = es.underlying();
|
||||
cfd.text = toString(es);
|
||||
cfc.data.push_back(cfd);
|
||||
|
||||
// DEBUG_LOG(m_logger)<<" cfd.text: "<<cfd.text;
|
||||
}
|
||||
cfc.sortItems = true;
|
||||
m_cbxFilterType = cfc.toVariant();
|
||||
}
|
||||
|
||||
void MountingPointListDialogModel::onMountingPointChanged(const MountingPoint &mountingPoint, DataModification modType)
|
||||
{
|
||||
if (modType != DataModification::eModified)
|
||||
return;
|
||||
|
||||
QModelIndex index = m_mountingPointIndexes.value(mountingPoint.id());
|
||||
if (!index.isValid())
|
||||
return;
|
||||
|
||||
NGLTreeItem *item = privateData(index);
|
||||
|
||||
if (!(item && item->data().canConvert<SimpleMountingPointData>()))
|
||||
return;
|
||||
|
||||
SimpleMountingPointData mpData = item->data().value<SimpleMountingPointData>();
|
||||
|
||||
mpData.name = mountingPoint.name();
|
||||
mpData.aimState = mountingPoint.aimState();
|
||||
const int assetId = mountingPoint.associatedAssetId(); // (m_dtc->getMountedAssetId(mountingPoint.data().id());
|
||||
mpData.assetBarcode = QStringLiteral("-");
|
||||
mpData.floor = mountingPoint.floor();
|
||||
|
||||
if(assetId != -1)
|
||||
{
|
||||
mpData.assetBarcode = QString::fromStdString(m_dtc->instrumentationAsset(assetId).barcode());
|
||||
}
|
||||
item->setData(QVariant::fromValue(mpData));
|
||||
m_dataChangedTimer->start();
|
||||
}
|
||||
|
||||
void MountingPointListDialogModel::onScheduleIdChanged(int32_t scheduleId)
|
||||
{
|
||||
// is this unreachable code?
|
||||
|
||||
if (scheduleId == m_scheduleId)
|
||||
return;
|
||||
|
||||
DEBUG_LOG(m_logger) << "onScheduleIdChanged: " << scheduleId;
|
||||
|
||||
m_scheduleId = scheduleId;
|
||||
|
||||
// !!! Maybe this is critical !!!
|
||||
// !!! Maybe this is critical !!!
|
||||
// !!! Maybe this is critical !!!
|
||||
// m_dataInterface::setScheduleId will update the MountingPoints (aimState) according schedule!!!
|
||||
m_dataInterface->setScheduleId(m_scheduleId);
|
||||
initData();
|
||||
}
|
||||
|
||||
void MountingPointListDialogModel::emitDataChanged()
|
||||
{
|
||||
QModelIndex vri = getIndexOfVisibleRootItem();
|
||||
emit dataChanged(vri, index(rowCount(vri) -1, Columns::STATE, vri), {Qt::DisplayRole, Qt::CheckStateRole});
|
||||
}
|
||||
|
||||
|
||||
|
||||
//
|
||||
// MountingPointListSortModel
|
||||
//
|
||||
|
||||
|
||||
} // namespace InfrastructureManagement
|
||||
+137
@@ -0,0 +1,137 @@
|
||||
/**
|
||||
* @RDE_HEADER@
|
||||
* The MountingPointListDialogModel provices data for MountingPointListDialog
|
||||
* Modified version using the checkStateProxyModel to allow setting via the checkboxes of the tree structure hjl 5/19
|
||||
* $Id$
|
||||
* $HeadURL$
|
||||
* $Author$
|
||||
* Created by Hannes Baeuerle, SLSE, 2016-11-03
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <InfrastructureManagement/ism_dtc.h>
|
||||
#include <InfrastructureManagement/logger.h>
|
||||
|
||||
#include <QSet>
|
||||
|
||||
#include <nglwidgets/ngltreemodel.h>
|
||||
#include <nglwidgets/ngltreeitem.h>
|
||||
|
||||
#include <Plugins/InfrastructureManagement/ism_data_plugin_interface.h>
|
||||
|
||||
#include <LtsWidgets/lts_column_filter_proxy_model.h>
|
||||
#include <LtsDataView/check_state_proxy_model.h>
|
||||
|
||||
|
||||
namespace InfrastructureManagement
|
||||
{
|
||||
struct SimpleMountingPointData
|
||||
{
|
||||
QString name;
|
||||
int32_t id = 0; // StructureElementId
|
||||
StructureElementType seType;
|
||||
MountingPointType mpType;
|
||||
MountingPointState aimState;
|
||||
// int assetId; Chance to only reload assetBarcode, if assetId changes...
|
||||
QString assetBarcode;
|
||||
int32_t floor;
|
||||
|
||||
bool isMountingPoint() const { return seType == StructureElementType::MountingPoint; }
|
||||
};
|
||||
|
||||
struct SimpleStructureElementData
|
||||
{
|
||||
int mseId;
|
||||
QString name;
|
||||
int floor;
|
||||
};
|
||||
|
||||
struct SimpleBuildingGroupData
|
||||
{
|
||||
QString name;
|
||||
};
|
||||
|
||||
class MountingPointListDialogModel final : public NGLTreeModel
|
||||
{
|
||||
Q_OBJECT
|
||||
using BaseClass = NGLTreeModel;
|
||||
|
||||
public:
|
||||
enum Columns
|
||||
{
|
||||
NAME,
|
||||
TYPE,
|
||||
ASSET_BARCODE,
|
||||
STATE
|
||||
};
|
||||
explicit MountingPointListDialogModel(QObject *parent = nullptr);
|
||||
|
||||
QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const override;
|
||||
/**
|
||||
* Handles the representation of data.
|
||||
* In case of CheckStateRole only leafs will be handled.
|
||||
* Nodes are handled in the upstream CheckStateProxyModel class.
|
||||
* @param[in] index item index to be handled
|
||||
* @param[in] role role to which the data relates
|
||||
*
|
||||
*/
|
||||
QVariant data(const QModelIndex &index, int role) const override final;
|
||||
|
||||
bool initModel(const std::shared_ptr<Interface::Dtc> &dtc, const std::shared_ptr<ForeignDataInterface> &dataInterface);
|
||||
|
||||
QModelIndex getIndexOfVisibleRootItem() const;
|
||||
|
||||
/**
|
||||
* Sets only the leafs of the tree view to Qt::ItemIsUserCheckable.
|
||||
* Nodes are handled in the upstream CheckStateProxyModel class.
|
||||
* @param[in] index item index to be handled
|
||||
*
|
||||
*/
|
||||
Qt::ItemFlags flags(const QModelIndex &index) const override final;
|
||||
|
||||
/**
|
||||
* Sets the check state data according to their check box in the internal model.
|
||||
* CheckState data can be set for leafs only.
|
||||
* Nodes are handled in the upstream CheckStateProxyModel class.
|
||||
* @param[in] index item index to be handled
|
||||
* @param[in] value value to be set
|
||||
* @param[in] role role to which the data relates (here especially Qt::CheckStateRole)
|
||||
*
|
||||
*/
|
||||
bool setData(const QModelIndex &index, const QVariant &value, int role) override;
|
||||
void setMntPointFilterTypes(QSet<InfrastructureManagement::MountingPointType> types);
|
||||
QSet<int> getAvailableFloors() const;
|
||||
StructureElement setBuildingGroup(int groupId);
|
||||
static const int maxIntValue = std::numeric_limits<int>::max();
|
||||
|
||||
signals:
|
||||
void changesMade();
|
||||
|
||||
public slots:
|
||||
void onMountingPointChanged(const MountingPoint &mountingPoint, DataModification modType);
|
||||
|
||||
private slots:
|
||||
void onScheduleIdChanged(int32_t scheduleId);
|
||||
void emitDataChanged();
|
||||
|
||||
private:
|
||||
void initData();
|
||||
friend class MountingPointListSortModel;
|
||||
|
||||
NGLTreeItem *m_visRoot;
|
||||
std::shared_ptr<Interface::Dtc> m_dtc;
|
||||
std::shared_ptr<InfrastructureManagement::ForeignDataInterface> m_dataInterface;
|
||||
int32_t m_scheduleId;
|
||||
QHash<int, QModelIndex> m_mountingPointIndexes;
|
||||
QTimer *m_dataChangedTimer{nullptr};
|
||||
QSet<int> m_availableFloors;
|
||||
QSet<int> m_availableBuildingGroups;
|
||||
QVariant m_cbxFilterType;
|
||||
LOGGER_T m_logger;
|
||||
}; // class MountingPointListDialogModel
|
||||
|
||||
} // namespace InfrastructureManagement
|
||||
Q_DECLARE_METATYPE(InfrastructureManagement::SimpleMountingPointData)
|
||||
Q_DECLARE_METATYPE(InfrastructureManagement::SimpleStructureElementData)
|
||||
Q_DECLARE_METATYPE(InfrastructureManagement::SimpleBuildingGroupData)
|
||||
Reference in new issue
Block a user