/** ** ** @RDE_HEADER@ ** Handles aggregation of participant layer ** $Id$ ** $HeadURL$ ** $Author$ ** ** ----------------------------------------------------------------------------------------------- ** ** Hardware-Environment: Intel-PC ** Software-Environment: Windows 7, Qt 5.4. ArcGIS 10.2.5 ** ** Language ........: C++ 11 ** ** ----------------------------------------------------------------------------------------------- ** ** Author ...........: Jörg Turla, SPD G, Tel. 3132 ** ** ----------------------------------------------------------------------------------------------- ** ** Notes .........: ** ** 16.08.2017, JT : first edition ** ** ----------------------------------------------------------------------------------------------- */ #include "layer_aggregation_widget.h" #include #include #include #include #include #include #include #include #include #include #include #include #include using namespace SituationMap; struct AggregationData { QString layerName; QString displayName; double minScale = LayerParameter::UNDEFINED_SCALE; // 0 double maxScale = LayerParameter::UNDEFINED_SCALE; // 0 bool minScaleValid = false; bool maxScaleValid = false; }; // AggregationData struct AggregationWidgets { QCheckBox *cbMinScaleValid = nullptr; QPushButton *pbMinScale = nullptr; QPushButton *pbMinScaleTo = nullptr; QCheckBox *cbMaxScaleValid = nullptr; QPushButton *pbMaxScale = nullptr; QPushButton *pbMaxScaleTo = nullptr; QPushButton *pbReset = nullptr; QPushButton *pbApply = nullptr; }; class LayerAggregationWidget::InternalData { public: Map *m_map = nullptr; bool m_valid = false; LayerType m_layerType; QVector m_aggregationList; QMap m_aggregationReset; QMap m_aggregationWidgets; LOGGER_T m_logger; explicit InternalData(Map *map,LayerType layerType) : m_map(map) , m_layerType(layerType) , m_logger(getLogger("LayerAggregation")) {} }; // LayerAggregationWidget::InternalData //------------------------------------------------------------------------------ QString LayerAggregationWidget::scaleText(double scale) { return (scale >= 1) ? QStringLiteral("1:%1").arg(int(scale)) : tr("undefined"); } // QString LayerAggregationWidget::scaleText(double scale) void LayerAggregationWidget::setMinScaleLabel(QPushButton *btn, double scale) { btn->setText(tr("Min. Scale from Map\n%1").arg(scaleText(scale))); } // void LayerAggregationWidget::setMinScaleLabel(QPushButton * btn, double scale) void LayerAggregationWidget::setMaxScaleLabel(QPushButton *btn, double scale) { btn->setText(tr("Max. Scale from Map\n%1").arg(scaleText(scale))); } // void LayerAggregationWidget::setMaxScaleLabel(QPushButton * btn, double scale) LayerAggregationWidget::LayerAggregationWidget(Map *map, LayerType layerType, const QRegularExpression &nameCondition, QWidget *parent) : QWidget(parent), m_internal(new InternalData(map,layerType)) { if (!nameCondition.isValid()) { ERROR_LOG(m_internal->m_logger) << LOGFUNCTION << " Illegal regular expression in nameCondition."; return; } if (map == nullptr) { ERROR_LOG(m_internal->m_logger) << LOGFUNCTION << " Invalid situation map, cannot initialize dialog"; return; } QGridLayout *layout = new QGridLayout(this); layout->setSpacing(10); const LayerFactory &layerFactory = map->layerFactory(); QIcon scaleToIcon(QStringLiteral("icon:search.svg")); const auto ln = layerFactory.layernames(layerType); for (const QString &layerName : ln) { if (nameCondition.match(layerName).hasMatch()) { // get layer AggregationData data; AggregationWidgets &widgets = m_internal->m_aggregationWidgets[layerName]; const LayerParameter &layerPara = layerFactory.layerParameter(layerName); data.layerName = layerName; data.minScale = layerPara.minScale; data.maxScale = layerPara.maxScale; data.minScaleValid = layerPara.minScaleValid(); data.maxScaleValid = layerPara.maxScaleValid(); data.displayName = layerPara.displayName; int row = m_internal->m_aggregationList.size(); QLabel *laName = new QLabel(layerPara.displayName.isEmpty() ? layerName : layerPara.displayName, this); widgets.pbReset = new QPushButton(this); widgets.pbApply = new QPushButton(this); widgets.pbReset->setSizePolicy(QSizePolicy(QSizePolicy::Minimum, QSizePolicy::Expanding)); widgets.pbApply->setSizePolicy(QSizePolicy(QSizePolicy::Minimum, QSizePolicy::Expanding)); QHBoxLayout *minLayout = new QHBoxLayout(); minLayout->addSpacing(20); minLayout->addWidget(widgets.cbMinScaleValid = new QCheckBox(QString(), this)); minLayout->addWidget(widgets.pbMinScale = new QPushButton(QString(), this)); minLayout->addWidget(widgets.pbMinScaleTo = new QPushButton(scaleToIcon, QString(), this)); minLayout->addSpacing(20); setMinScaleLabel(widgets.pbMinScale, layerPara.minScale); QHBoxLayout *maxLayout = new QHBoxLayout(); maxLayout->addWidget(widgets.cbMaxScaleValid = new QCheckBox(QString(), this)); maxLayout->addWidget(widgets.pbMaxScale = new QPushButton(QString(), this)); maxLayout->addWidget(widgets.pbMaxScaleTo = new QPushButton(scaleToIcon, QString(), this)); maxLayout->addSpacing(20); setMaxScaleLabel(widgets.pbMaxScale, layerPara.maxScale); widgets.pbMinScale->setSizePolicy(QSizePolicy(QSizePolicy::Minimum, QSizePolicy::Expanding)); widgets.pbMaxScale->setSizePolicy(QSizePolicy(QSizePolicy::Minimum, QSizePolicy::Expanding)); layout->addWidget(laName, row, 0); layout->addLayout(minLayout, row, 1); layout->addLayout(maxLayout, row, 2); layout->addWidget(widgets.pbReset, row, 3); layout->addWidget(widgets.pbApply, row, 4); m_internal->m_aggregationList << data; m_internal->m_aggregationReset[layerName] = data; widgets.pbMinScale->setProperty("row", row); widgets.pbMaxScale->setProperty("row", row); widgets.cbMinScaleValid->setProperty("row", row); widgets.cbMaxScaleValid->setProperty("row", row); widgets.pbMinScaleTo->setProperty("row", row); widgets.pbMaxScaleTo->setProperty("row", row); widgets.pbReset->setProperty("row", row); widgets.pbApply->setProperty("row", row); connect(widgets.cbMinScaleValid, &QCheckBox::clicked, this, &LayerAggregationWidget::onSetValid); connect(widgets.cbMaxScaleValid, &QCheckBox::clicked, this, &LayerAggregationWidget::onSetValid); connect(widgets.pbMinScale, &QPushButton::clicked, this, &LayerAggregationWidget::onGetMinScale); connect(widgets.pbMaxScale, &QPushButton::clicked, this, &LayerAggregationWidget::onGetMaxScale); connect(widgets.pbMinScaleTo, &QPushButton::clicked, this, &LayerAggregationWidget::onZoomTo); connect(widgets.pbMaxScaleTo, &QPushButton::clicked, this, &LayerAggregationWidget::onZoomTo); connect(widgets.pbReset, &QPushButton::clicked, this, &LayerAggregationWidget::onReset); connect(widgets.pbApply, &QPushButton::clicked, this, &LayerAggregationWidget::onApply); widgets.cbMinScaleValid->setChecked(data.minScaleValid); widgets.cbMinScaleValid->setEnabled(data.minScaleValid); widgets.cbMaxScaleValid->setChecked(data.maxScaleValid); widgets.cbMaxScaleValid->setEnabled(data.maxScaleValid); widgets.pbMinScaleTo->setEnabled(data.minScaleValid); widgets.pbMaxScaleTo->setEnabled(data.maxScaleValid); widgets.pbReset->setEnabled(false); widgets.pbApply->setEnabled(false); } } retranslate(); if (m_internal->m_aggregationList.isEmpty()) { QLabel *lbEmpty = new QLabel(tr("Can't find any layer"), this); QPixmap icon(QStringLiteral("icon:overlays.svg")); lbEmpty->setWindowIcon(icon); layout->addWidget(lbEmpty, 0, 0, Qt::AlignCenter); return; } } // LayerAggregation::LayerAggregation( Map * map, QObject * parent ) void LayerAggregationWidget::retranslate() { if (m_internal->m_map == nullptr) return; const LayerFactory &layerFactory = m_internal->m_map->layerFactory(); const auto ln = layerFactory.layernames(m_internal->m_layerType); for (const QString &layerName : ln) { if (!m_internal->m_aggregationWidgets.contains(layerName)) continue; AggregationWidgets &widgets = m_internal->m_aggregationWidgets[layerName]; widgets.pbReset->setText(tr("Reset")); widgets.pbApply->setText(tr("Apply to Map")); widgets.pbReset->setToolTip(tr("Restore initial scales of this level")); widgets.pbApply->setToolTip(tr("Set scales to corresponding map layer temporarily")); widgets.cbMinScaleValid->setToolTip(tr("Activate or deactivate this scale value")); widgets.pbMinScale ->setToolTip(tr("Get current map scale of map view")); widgets.pbMinScaleTo ->setToolTip(tr("Set this scale value to map view as current scale")); widgets.cbMaxScaleValid->setToolTip(tr("Activate or deactivate this scale value")); widgets.pbMaxScale ->setToolTip(tr("Get current map scale of map view")); widgets.pbMaxScaleTo ->setToolTip(tr("Set this scale value to map view as current scale")); } } // void LayerAggregationWidget::retranslate() LayerAggregationWidget::~LayerAggregationWidget() { delete m_internal; m_internal = nullptr; } // LayerAggregationWidget::~LayerAggregationWidget() void LayerAggregationWidget::onZoomTo() { QPushButton *senderButton = qobject_cast(sender()); if (nullptr == senderButton) return; int row = senderButton->property("row").toInt(); if ((row < 0) || (row >= m_internal->m_aggregationList.size())) return; const AggregationData &data = m_internal->m_aggregationList[row]; const AggregationWidgets &widgets = m_internal->m_aggregationWidgets[data.layerName]; double scale = 0.0; if ((widgets.pbMinScaleTo == senderButton) && (data.minScaleValid)) scale = data.minScale; if ((widgets.pbMaxScaleTo == senderButton) && (data.maxScaleValid)) scale = data.maxScale; if (scale < 1) return; m_internal->m_map->setScale(scale); } // void LayerAggregationWidget::onZoomTo() void LayerAggregationWidget::onGetMinScale() { QPushButton *senderButton = qobject_cast(sender()); if (nullptr == senderButton) return; int row = senderButton->property("row").toInt(); if ((row < 0) || (row >= m_internal->m_aggregationList.size())) return; double scale = m_internal->m_map->scale(); AggregationData &data = m_internal->m_aggregationList[row]; if (data.maxScaleValid && (data.maxScale >= scale)) { const QString &msg = tr("Chosen scale is too small"); LtsWidgets::LtsMessageDialog::showMessage(this, msg, tr("Layer Aggregation")); return; } data.minScale = scale; data.minScaleValid = true; setMinScaleLabel(senderButton, data.minScale); const AggregationWidgets &widgets = m_internal->m_aggregationWidgets[data.layerName]; widgets.cbMinScaleValid->setChecked(true); widgets.cbMinScaleValid->setEnabled(true); widgets.pbMinScaleTo->setEnabled(true); widgets.pbReset->setEnabled(true); widgets.pbApply->setEnabled(true); emit changesMade(); } // void LayerAggregationWidget::onGetMinScale() void LayerAggregationWidget::onGetMaxScale() { QPushButton *senderButton = qobject_cast(sender()); if (nullptr == senderButton) return; int row = senderButton->property("row").toInt(); if ((row < 0) || (row >= m_internal->m_aggregationList.size())) return; double scale = m_internal->m_map->scale(); AggregationData &data = m_internal->m_aggregationList[row]; if (data.minScaleValid && (data.minScale <= scale)) { const QString &msg = tr("Chosen scale is too large"); LtsWidgets::LtsMessageDialog::showMessage(this, msg, tr("Layer Aggregation")); return; } data.maxScale = scale; data.maxScaleValid = true; setMaxScaleLabel(senderButton, data.maxScale); const AggregationWidgets &widgets = m_internal->m_aggregationWidgets[data.layerName]; widgets.cbMaxScaleValid->setChecked(true); widgets.cbMaxScaleValid->setEnabled(true); widgets.pbMaxScaleTo->setEnabled(true); widgets.pbReset->setEnabled(true); widgets.pbApply->setEnabled(true); emit changesMade(); } // void LayerAggregationWidget::onGetMaxScale() void LayerAggregationWidget::onSetValid(bool value) { QCheckBox *senderButton = qobject_cast(sender()); if (nullptr == senderButton) return; int row = senderButton->property("row").toInt(); if ((row < 0) || (row >= m_internal->m_aggregationList.size())) return; AggregationData &data = m_internal->m_aggregationList[row]; const AggregationWidgets &widgets = m_internal->m_aggregationWidgets[data.layerName]; if (senderButton == widgets.cbMinScaleValid) { if (data.maxScaleValid && value && (data.maxScale >= data.minScale)) { senderButton->setChecked(false); const QString &msg = tr("Minimum scale is too small"); LtsWidgets::LtsMessageDialog::showMessage(this, msg, tr("Layer Aggregation")); return; } data.minScaleValid = value; } if (senderButton == widgets.cbMaxScaleValid) { if (data.minScaleValid && value && (data.minScale <= data.maxScale)) { senderButton->setChecked(false); const QString &msg = tr("Maximum scale is too large"); LtsWidgets::LtsMessageDialog::showMessage(this, msg, tr("Layer Aggregation")); return; } data.maxScaleValid = value; } widgets.pbMinScaleTo->setEnabled(data.minScaleValid); widgets.pbMaxScaleTo->setEnabled(data.maxScaleValid); widgets.pbReset->setEnabled(true); widgets.pbApply->setEnabled(true); emit changesMade(); } // void LayerAggregationWidget::onSetValid(bool value) void LayerAggregationWidget::doReset(int row) { if ((row < 0) || (row >= m_internal->m_aggregationList.size())) return; AggregationData &data = m_internal->m_aggregationList[row]; data = m_internal->m_aggregationReset[data.layerName]; const AggregationWidgets &widgets = m_internal->m_aggregationWidgets[data.layerName]; setMinScaleLabel(widgets.pbMinScale, data.minScale); setMaxScaleLabel(widgets.pbMaxScale, data.maxScale); widgets.cbMinScaleValid->setChecked(data.minScaleValid); widgets.cbMinScaleValid->setEnabled(data.minScaleValid); widgets.cbMaxScaleValid->setChecked(data.maxScaleValid); widgets.cbMaxScaleValid->setEnabled(data.maxScaleValid); widgets.pbMinScaleTo->setEnabled(data.minScaleValid); widgets.pbMaxScaleTo->setEnabled(data.maxScaleValid); widgets.pbReset->setEnabled(false); widgets.pbApply->setEnabled(!widgets.pbApply->isEnabled()); } // void doReset(SituationMap::Map * map, const AggregationData & data) void LayerAggregationWidget::onReset() { QObject *senderObj = sender(); if (nullptr == senderObj) return; int row = senderObj->property("row").toInt(); if ((row < 0) || (row >= m_internal->m_aggregationList.size())) return; doReset(row); } // void LayerAggregationWidget::onReset() static void doApply(SituationMap::Map *map, const AggregationData &data) { LayerFactory &layerFactory = map->layerFactory(); LayerParameter layerParamter = layerFactory.layerParameter(data.layerName); layerParamter.minScale = data.minScaleValid ? data.minScale : LayerParameter::UNDEFINED_SCALE; // 0; layerParamter.maxScale = data.maxScaleValid ? data.maxScale : LayerParameter::UNDEFINED_SCALE; // 0; layerFactory.setLayerParameter(data.layerName, layerParamter); } // void doApply(SituationMap::Map * map, const AggregationData & data) void LayerAggregationWidget::onApply() { QObject *senderObj = sender(); if (!senderObj) return; int row = senderObj->property("row").toInt(); if ((row < 0) || (row >= m_internal->m_aggregationList.size())) return; const AggregationData &data = m_internal->m_aggregationList[row]; doApply(m_internal->m_map, data); const AggregationWidgets &widgets = m_internal->m_aggregationWidgets[data.layerName]; widgets.pbApply->setEnabled(false); } // void LayerAggregationWidget::onApply() void LayerAggregationWidget::onApplyAll() { for (const AggregationData &data : qAsConst(m_internal->m_aggregationList)) { const AggregationWidgets &widgets = m_internal->m_aggregationWidgets[data.layerName]; if (widgets.pbApply->isEnabled()) { doApply(m_internal->m_map, data); widgets.pbApply->setEnabled(false); } } } // void LayerAggregationWidget::onApplyAll() void LayerAggregationWidget::onResetAll() { for (const auto &aggData : qAsConst(m_internal->m_aggregationList)) { const AggregationWidgets &widgets = m_internal->m_aggregationWidgets[aggData.layerName]; doReset(widgets.pbApply->property("row").toInt()); doApply(m_internal->m_map, aggData); widgets.pbApply->setEnabled(false); } } // void LayerAggregationWidget::onResetAll() void LayerAggregationWidget::onSetDefaultScales() { if (m_internal->m_aggregationList.isEmpty()) return; // Calculate scale defaults here ... double mapMinScaleSQRT = sqrt(m_internal->m_map->minScale()); double mapMaxScaleSQRT = sqrt(m_internal->m_map->maxScale()); const int aggregationListCount = m_internal->m_aggregationList.size(); double stepScaleSQRT = (mapMinScaleSQRT - mapMaxScaleSQRT) / static_cast(aggregationListCount); unsigned int step = 0; for (auto &aggData : m_internal->m_aggregationList) { double dScaleSQRT = mapMaxScaleSQRT + (step * stepScaleSQRT); aggData.maxScaleValid = true; aggData.maxScale = dScaleSQRT * dScaleSQRT; dScaleSQRT = mapMaxScaleSQRT + ((step + 1) * stepScaleSQRT); aggData.minScaleValid = true; aggData.minScale = dScaleSQRT * dScaleSQRT; } // for // disable start and end if (aggregationListCount > 0) { // front -> max m_internal->m_aggregationList.front().maxScale = 0; m_internal->m_aggregationList.front().maxScaleValid = false; // back -> min m_internal->m_aggregationList.back().minScale = 0; m_internal->m_aggregationList.back().minScaleValid = false; } // if // update ui to m_aggregationList: for (const auto &aggData : qAsConst(m_internal->m_aggregationList)) { const AggregationWidgets &widgets = m_internal->m_aggregationWidgets[aggData.layerName]; widgets.cbMinScaleValid->setEnabled(aggData.minScaleValid); widgets.cbMinScaleValid->setChecked(aggData.minScaleValid); widgets.pbMinScaleTo->setEnabled(aggData.minScaleValid); widgets.cbMaxScaleValid->setEnabled(aggData.maxScaleValid); widgets.cbMaxScaleValid->setChecked(aggData.maxScaleValid); widgets.pbMaxScaleTo->setEnabled(aggData.maxScaleValid); widgets.pbApply->setEnabled(true); widgets.pbReset->setEnabled(true); setMinScaleLabel(widgets.pbMinScale, aggData.minScale); setMaxScaleLabel(widgets.pbMaxScale, aggData.maxScale); } // for emit changesMade(); } // void LayerAggregationWidget::onSetDefaultScales()