/** * @RDE_HEADER@ * Interface * $Id$ * $HeadURL$ * $Author$ */ // Own #include "layer_control_widget.h" #include #include #include // Qt #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include namespace SituationMap { const QLatin1String MIMETYPE("application/x-dndEsriLayerItemData"); //---------------------------------------------------------------------------- const char LayernameProperty[] = "layername"; //---------------------------------------------------------------------------- class DragableCheckBox : public QCheckBox { Q_OBJECT using BaseClass = QCheckBox; public: DragableCheckBox() = default; explicit DragableCheckBox(const QString &text) : QCheckBox(text) {} ~DragableCheckBox() = default; void mousePressEvent(QMouseEvent *event) override; void mouseMoveEvent(QMouseEvent *event) override; private: QPoint m_dragStartPos; }; // class LayerControlWidget::Private //----------------------------------------------------------------------------- void DragableCheckBox::mousePressEvent(QMouseEvent *event) { // qWarning() << LOGFUNCTION << " START"; if (event->button() == Qt::LeftButton) m_dragStartPos = event->pos(); BaseClass::mousePressEvent(event); // qWarning() << LOGFUNCTION << " END"; } void DragableCheckBox::mouseMoveEvent(QMouseEvent *event) { // qWarning() << LOGFUNCTION << " START"; if (!(event->buttons() & Qt::LeftButton)) return; if ((event->pos() - m_dragStartPos).manhattanLength() < QApplication::startDragDistance()) return; QByteArray itemData; QDataStream dataStream(&itemData, QIODevice::WriteOnly); dataStream << this->property(LayernameProperty).toString(); // == layername QMimeData *mimeData = new QMimeData; mimeData->setData(MIMETYPE, itemData); QDrag *drag = new QDrag(this); drag->setMimeData(mimeData); drag->exec(Qt::MoveAction); // qWarning() << LOGFUNCTION << " END"; } //----------------------------------------------------------------------------- struct SliderStruct { QCheckBox *cbOnOff = nullptr; QSlider *sl_opacity = nullptr; QSlider *sl_brightness = nullptr; QSlider *sl_contrast = nullptr; QSlider *sl_gamma = nullptr; }; class LayerControlWidget::Private { public: Private() = default; // OWN data: SituationMap::Map *m_map = nullptr; // Use INTERFACE QString m_debugInfo; bool m_zoomRotScaleEnabled = true; bool m_layerEnabled = true; bool m_basemapEnabled = true; QVBoxLayout *m_layout = nullptr; // MapLayer: QGridLayout *m_mapLayerLayout = nullptr; // BaseMapSelection: QHBoxLayout *m_baseMapSelectLayout = nullptr; QList m_baseMapSelectIcons; QLabel *m_lbBasemap = nullptr; QMap m_sliderMap; // Zoom and rotation QHBoxLayout *m_zoomLayout = nullptr; // will contain zoom and rotation elements QSlider *m_zoomSlider = nullptr; QSlider *m_rotationSlider = nullptr; QSlider *m_symbolSizeSlider = nullptr; // 10 ... 200 QTimer *m_symbolSizeTimer = nullptr; }; // class LayerControlWidget::Private //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- // class LayerControlWidget //----------------------------------------------------------------------------- LayerControlWidget::LayerControlWidget(QWidget *parent, Map *map, bool enableLayer, bool enableBasemap, const QString &debugInfo) : QWidget(parent) , d(new Private) , m_logger(getLogger("LayerControlWidget")) { TRACE_LOG(m_logger) << LOGFUNCTION << " START" << " debugInfo='" << debugInfo << "'"; d->m_debugInfo = debugInfo; d->m_map = map; d->m_layerEnabled = enableLayer; d->m_basemapEnabled = enableBasemap; d->m_layout = new QVBoxLayout(); this->setLayout(d->m_layout); setAcceptDrops(true); // use QueuedConnect to let dropEvent (and destroying of QDrag object) finish // BEFORE the panel is updated (and DragableCheckBox - parent of QDrag object - are deleted.) connect(d->m_map, &Map::layerOrderChanged, this, &LayerControlWidget::updatePanelLayer, Qt::ConnectionType::QueuedConnection); connect(d->m_map, &Map::layerParameterChanged, this, &LayerControlWidget::onLayerParamterChanged); connect(d->m_map, &Map::mapReady, this, &LayerControlWidget::onMapReady, Qt::ConnectionType::QueuedConnection); updatePanel(); TRACE_LOG(m_logger) << LOGFUNCTION << " debugInfo='" << d->m_debugInfo << "'" << " END"; } LayerControlWidget::~LayerControlWidget() { TRACE_LOG(m_logger) << LOGFUNCTION << " debugInfo='" << d->m_debugInfo << "'" << " START"; TRACE_LOG(m_logger) << LOGFUNCTION << " debugInfo='" << d->m_debugInfo << "'" << " END"; delete d; } bool LayerControlWidget::updatePanel() { TRACE_LOG(m_logger) << LOGFUNCTION << " debugInfo='" << d->m_debugInfo << "'" << " START"; updatePanelZoomRotationScales(); updatePanelLayer(); // updatePanelBasemap(); TRACE_LOG(m_logger) << LOGFUNCTION << " debugInfo='" << d->m_debugInfo << "'" << " END"; return true; } bool LayerControlWidget::updatePanelZoomRotationScales() { TRACE_LOG(m_logger) << LOGFUNCTION << " debugInfo='" << d->m_debugInfo << "'" << " START"; if (! d->m_zoomRotScaleEnabled) return false; if (d->m_zoomLayout) return true; d->m_zoomLayout = new QHBoxLayout(); d->m_layout->addLayout(d->m_zoomLayout); d->m_zoomSlider = generateZoomSlider(); d->m_zoomLayout->addWidget(d->m_zoomSlider); // problems around scale in 3D: d->m_zoomSlider->setEnabled(d->m_map->mode() == Mode::Mode_2D); QComboBox *cmbScale = new QComboBox(); d->m_zoomLayout->addWidget(cmbScale); cmbScale->addItem(tr("Presets")); cmbScale->insertSeparator(1); using scaleDataTyp = QPair; const auto scaleData = { scaleDataTyp(QLatin1String(" 1:25000"), 400000), scaleDataTyp(QLatin1String(" 1:50000"), 200000), scaleDataTyp(QLatin1String("1:100000"), 100000) }; for (const scaleDataTyp &item : scaleData) cmbScale->addItem(item.first, QVariant(item.second)); // stored in Qt::UserRole // c++11 -> lambda :-) connect(cmbScale, static_cast(&QComboBox::activated), this, [this, cmbScale](int index) { if (index <= 1) return; // 1 Damit 'Presets' + Separator ohne Auswirkung bleibt int selectedScale = cmbScale->currentData().toInt(); DEBUG_LOG(m_logger) << LOGFUNCTION << " debugInfo='" << d->m_debugInfo << "'" << " cmbScale selectedScale=" << selectedScale; d->m_map->setScale(selectedScale); cmbScale->setCurrentIndex(0); // Textausgabe auf 'Presets' setzen }); // // Rotation: // if (! d->m_rotationSlider) { d->m_rotationSlider = generateRotationSlider(); d->m_layout->addWidget(d->m_rotationSlider); } // // SymbolSize: // if (! d->m_symbolSizeSlider) { d->m_symbolSizeSlider = generateSymbolSizeSlider(); d->m_layout->addWidget(d->m_symbolSizeSlider); } TRACE_LOG(m_logger) << LOGFUNCTION << " debugInfo='" << d->m_debugInfo << "'" << " END"; return true; } bool LayerControlWidget::updatePanelLayer() { TRACE_LOG(m_logger) << LOGFUNCTION << " debugInfo='" << d->m_debugInfo << "'" << " START"; // // Layer: // // reNew the part of mapLayer : if (d->m_mapLayerLayout) { for (int row = 0; row < d->m_mapLayerLayout->rowCount(); ++row) { for (int col = 0; col < d->m_mapLayerLayout->columnCount(); ++col) { QLayoutItem *item = d->m_mapLayerLayout->itemAtPosition(row, col); if (item) { QWidget *w = item->widget(); delete w; // w->deleteLater() --> QCoreApplication::postEvent: Unexpected null receiver (ication/ngl_qt_msg_handler.inc:25) } } } } delete d->m_mapLayerLayout; d->m_mapLayerLayout = nullptr; d->m_sliderMap.clear(); if (! d->m_layerEnabled) return false; d->m_mapLayerLayout = new QGridLayout(); d->m_layout->addLayout(d->m_mapLayerLayout); int row = 0; QCheckBox *cbExpand = new QCheckBox(tr("Expand"), this); d->m_mapLayerLayout->addWidget(cbExpand, row++, 0); cbExpand->setChecked(false); connect(cbExpand, &QCheckBox::clicked, this, &LayerControlWidget::expandCollapse); // // Fill MapLayerLayout : // if (d->m_map) { int col = 0; const auto header = { tr("Layer"), tr("Opacity"), tr("Brightness"), tr("Contrast"), tr("Gamma") }; for (const QString &name : header) d->m_mapLayerLayout->addWidget(new QLabel(name), row, col++); const QStringList sl = d->m_map->layerFactory().layernames(); DEBUG_LOG(m_logger) << LOGFUNCTION << " debugInfo='" << d->m_debugInfo << "'" << " layers=" << sl.join(QLatin1Char(';')); row += sl.count(); for (const QString &layername : sl) { DEBUG_LOG(m_logger) << LOGFUNCTION << " debugInfo='" << d->m_debugInfo << "'" << " layerName=" << layername; int col = 0; const LayerParameter &lp = d->m_map->layerFactory().layerParameter(layername); const LayerType &layerType = d->m_map->layerFactory().layerType(layername); DragableCheckBox *cbOnOff = new DragableCheckBox(); if (lp.displayName.isEmpty()) cbOnOff->setText(layername); else cbOnOff->setText(lp.displayName); cbOnOff->setProperty(LayernameProperty, layername); d->m_sliderMap[layername].cbOnOff = cbOnOff; cbOnOff->setObjectName(QLatin1String("DragableCheckBox_") + layername); cbOnOff->setChecked(lp.visible); const QString &tooltip = generateToolTip(layername, lp); if (!tooltip.isEmpty()) cbOnOff->setToolTip(tooltip); connect(cbOnOff, &QCheckBox::stateChanged, this, &LayerControlWidget::layerOnOff); d->m_mapLayerLayout->addWidget(cbOnOff, row, col++); mySlider *sl_opac = new mySlider(layername, 0, 100); d->m_sliderMap[layername].sl_opacity = sl_opac; sl_opac->setObjectName(QLatin1String("sl_opac")); sl_opac->setValue(lp.opacity); connect(sl_opac, &mySlider::valueChanged, this, &LayerControlWidget::opacity); d->m_mapLayerLayout->addWidget(sl_opac, row, col++); if (layerType == SituationMap::LayerType::Basemap) { mySlider *sl_brightness = new mySlider(layername, -100, 100); d->m_sliderMap[layername].sl_brightness = sl_brightness; sl_brightness->setObjectName(QLatin1String("sl_brightness")); sl_brightness->setValue(lp.brightness); connect(sl_brightness, &mySlider::valueChanged, this, &LayerControlWidget::brightness); d->m_mapLayerLayout->addWidget(sl_brightness, row, col++); mySlider *sl_contrast = new mySlider(layername, -100, 100); d->m_sliderMap[layername].sl_contrast = sl_contrast; sl_contrast->setObjectName(QLatin1String("sl_contrast")); sl_contrast->setValue(lp.contrast); connect(sl_contrast, &mySlider::valueChanged, this, &LayerControlWidget::contrast); d->m_mapLayerLayout->addWidget(sl_contrast, row, col++); mySlider *sl_gamma = new mySlider(layername, -100, 100); d->m_sliderMap[layername].sl_gamma = sl_gamma; sl_gamma->setObjectName(QLatin1String("sl_gamma")); sl_gamma->setValue(lp.gamma); connect(sl_gamma, &mySlider::valueChanged, this, &LayerControlWidget::gamma); d->m_mapLayerLayout->addWidget(sl_gamma, row, col++); } --row; } #ifdef ONLY_FOR_TESTS QPushButton *pbAddBasemapLayer = new QPushButton(QLatin1String("add BasemapLayer")); d->m_mapLayerLayout->addWidget(pbAddBasemapLayer); QLatin1String newBasemapName("basemapAddedByBtn"); QLatin1String newBasemapUrl("http://192.168.133.88:6080/arcgis/rest/services/BremenGeoTiff/MapServer"); // QLatin1String newBasemap("http://192.168.133.88:6080/arcgis/rest/services/BremenGeoTiffUTM/MapServer"); pbAddBasemapLayer->setToolTip(newBasemapUrl); connect(pbAddBasemapLayer, &QPushButton::clicked, this, [this]() { bool success = d->m_map->layerFactory().addBasemap(newBasemapName, newBasemapUrl); INFO_LOG(m_logger) << LOGFUNCTION << " debugInfo='" << d->m_debugInfo << "'" << " adding basemapLayer, success=" << success; }); QPushButton *pbRemoveBasemapLayer = new QPushButton(QLatin1String("remove BasemapLayer")); d->m_mapLayerLayout->addWidget(pbRemoveBasemapLayer); pbRemoveBasemapLayer->setToolTip(newBasemapUrl); connect(pbRemoveBasemapLayer, &QPushButton::clicked, this, [this]() { bool success = d->m_map->layerFactory().removeBasemap(newBasemapName); INFO_LOG(m_logger) << LOGFUNCTION << " debugInfo='" << d->m_debugInfo << "'" << " removing basemapLayer, success=" << success; }); #endif expandCollapse(cbExpand->isChecked()); } else ERROR_LOG(m_logger) << LOGFUNCTION << " debugInfo='" << d->m_debugInfo << "'" << " no map !!!"; TRACE_LOG(m_logger) << LOGFUNCTION << " debugInfo='" << d->m_debugInfo << "'" << " END"; return true; } bool LayerControlWidget::updatePanelBasemap() { TRACE_LOG(m_logger) << LOGFUNCTION << " debugInfo='" << d->m_debugInfo << "'" << " START"; // clear old widgets: d->m_baseMapSelectIcons.clear(); if (d->m_baseMapSelectLayout) { QLayoutItem *item; while ((item = d->m_baseMapSelectLayout->takeAt(0))) { QWidget *w = item->widget(); delete w; delete item; } } delete d->m_baseMapSelectLayout; d->m_baseMapSelectLayout = nullptr; if (! d->m_basemapEnabled) return false; // create from scratch: if (! d->m_baseMapSelectLayout) { QVBoxLayout *vBox = new QVBoxLayout(); if (! d->m_lbBasemap) d->m_lbBasemap = new QLabel(tr("Basemaps:")); vBox->addWidget(d->m_lbBasemap); d->m_baseMapSelectLayout = new QHBoxLayout(); vBox->addLayout(d->m_baseMapSelectLayout); d->m_layout->addLayout(vBox); LayerFactory &layFac = d->m_map->layerFactory(); const QStringList &basemapLayernames = layFac.layernames(LayerType::Basemap); for (const QString &layername : basemapLayernames) { // baseMapProxy->setStyleSheet(QLatin1String("QPushButton {background-color: transparent; border: 1px solid transparent;}")); const LayerParameter &lp = d->m_map->layerFactory().layerParameter(layername); QToolButton *baseMapProxy = new QToolButton(this); baseMapProxy->setToolButtonStyle(Qt::ToolButtonTextBesideIcon); // eTextUnderIcon? baseMapProxy->setText(lp.displayName); baseMapProxy->setObjectName(d->m_debugInfo + layername); baseMapProxy->setProperty(LayernameProperty, layername); baseMapProxy->setIcon(QIcon(QPixmap::fromImage(lp.previewImage))); baseMapProxy->setIconSize(QSize(40,40)); baseMapProxy->setCheckable(true); baseMapProxy->setChecked(true); // Assume that all are enable by default const QString &tooltip = generateToolTip(layername, lp); if (!tooltip.isEmpty()) baseMapProxy->setToolTip(tooltip); d->m_baseMapSelectLayout->addWidget(baseMapProxy); d->m_baseMapSelectIcons.append(baseMapProxy); connect(baseMapProxy, &QToolButton::clicked, this, &LayerControlWidget::onBaseMapSelection); } // Q_FOREACH d->m_baseMapSelectLayout->addStretch(42); } TRACE_LOG(m_logger) << LOGFUNCTION << " debugInfo='" << d->m_debugInfo << "'" << " END"; return true; } void LayerControlWidget::expandCollapse(bool expanded) { TRACE_LOG(m_logger) << LOGFUNCTION << " debugInfo='" << d->m_debugInfo << "'" << " START"; for (int row = 1; row < d->m_mapLayerLayout->rowCount(); ++row) { for (int col = 2; col < d->m_mapLayerLayout->columnCount(); ++col) { QLayoutItem *item = d->m_mapLayerLayout->itemAtPosition(row, col); if (item) { QWidget *w = item->widget(); if (w) w->setVisible(expanded); } } } TRACE_LOG(m_logger) << LOGFUNCTION << " debugInfo='" << d->m_debugInfo << "'" << " END"; } QString LayerControlWidget::generateToolTip(const QString &layername, const LayerParameter &lp) { QString tooltip; tooltip.append(QStringLiteral("")); tooltip.append(QStringLiteral("

displayName=%1

").arg(lp.displayName)); if (! lp.previewImage.isNull()) { // without a temporary file: QByteArray data; QBuffer buffer(&data); lp.previewImage.save(&buffer, "PNG", 100); QString html(QLatin1String("
")); html.append(QStringLiteral("").arg(QString::fromLatin1(data.toBase64()))); tooltip.append(html); } if (lp.basemapType != BasemapType::Undefined) tooltip.append(QStringLiteral("

BasemapType=%1

").arg(toDisplayString(lp.basemapType))); tooltip.append(QStringLiteral("

layername=%1

").arg(layername)); tooltip.append(QStringLiteral("

description=%1

").arg(lp.description)); tooltip.append(QStringLiteral("

svcDescription=%1

").arg(lp.svcDescription)); tooltip.append(QStringLiteral("

url=%1

").arg(lp.url.toString())); tooltip.append(QStringLiteral("

minScale=%1 - maxScale=%2

").arg((int)lp.minScale).arg((int)lp.maxScale)); tooltip.append(QStringLiteral("")); return tooltip; } QSlider *LayerControlWidget::generateZoomSlider() { TRACE_LOG(m_logger) << LOGFUNCTION << " debugInfo='" << d->m_debugInfo << "'" << " START"; QSlider *slider = new QSlider(Qt::Orientation::Horizontal); // 1. Init if (d->m_map->isReady()) { // This branch is taken in case of FunctionDialog: onZoomSliderInit(slider); } // 2. extentChanged // Attention: use identical signal at any other zoom/scale-Slider!!! connect(d->m_map, &Map::extentChangedDelayed, this, &LayerControlWidget::onMapExtentChanged); // 3. valueChanged connect(slider, &QSlider::valueChanged, this, &LayerControlWidget::onZoomSliderValueChanged); TRACE_LOG(m_logger) << LOGFUNCTION << " debugInfo='" << d->m_debugInfo << "'" << " END"; return slider; } QSlider *LayerControlWidget::generateRotationSlider() { TRACE_LOG(m_logger) << LOGFUNCTION << " debugInfo='" << d->m_debugInfo << "'" << " START"; QSlider *slider = new QSlider(); slider->setToolTip(tr("Rotation")); slider->setOrientation(Qt::Orientation::Horizontal); slider->setTickPosition(QSlider::TicksBelow); slider->setTickInterval(10); slider->setSingleStep(10); slider->setMinimum(0); slider->setMaximum(359); slider->setValue(0); if (d->m_map->isReady()) slider->setValue(d->m_map->rotation()); connect(slider, &QSlider::valueChanged, this, &LayerControlWidget::onRotationSliderValueChanged); connect(d->m_map, &Map::rotationChanged, this, &LayerControlWidget::onRotationOfMapChanged); TRACE_LOG(m_logger) << LOGFUNCTION << " debugInfo='" << d->m_debugInfo << "'" << " END"; return slider; } QSlider *LayerControlWidget::generateSymbolSizeSlider() { TRACE_LOG(m_logger) << LOGFUNCTION << " debugInfo='" << d->m_debugInfo << "'" << " START"; QSlider *slider = new QSlider(); slider->setToolTip(tr("Symbol Size")); slider->setOrientation(Qt::Orientation::Horizontal); slider->setTickPosition(QSlider::TicksBelow); slider->setTickInterval(10); // 10% slider->setMinimum(SituationMap::symbolScaleMinimum * 100); // 10% slider->setMaximum(SituationMap::symbolScaleMaximum * 100); // 200% slider->setSingleStep(10); // 10% if (d->m_map->isReady()) slider->setValue(d->m_map->symbolScale() * 100); connect(slider, &QSlider::valueChanged, this, &LayerControlWidget::onSymbolSizeSliderValueChanged); connect(d->m_map, &Map::symbolScaleChanged, this, &LayerControlWidget::onSymbolSizeOfMapChanged); TRACE_LOG(m_logger) << LOGFUNCTION << " debugInfo='" << d->m_debugInfo << "'" << " END"; return slider; } void LayerControlWidget::onZoomSliderInit(QSlider *slider) { TRACE_LOG(m_logger) << LOGFUNCTION << " debugInfo='" << d->m_debugInfo << "'" << " START"; if (! slider) return; const QSignalBlocker blocker(slider); slider->setToolTip(tr("Zoom")); slider->setMinimum(sqrt(d->m_map->maxScale())); slider->setMaximum(sqrt(d->m_map->minScale())); onMapExtentChanged(); if (slider->minimum() == slider->maximum()) { WARNING_LOG(m_logger) << LOGFUNCTION << " min/max value are identical, debugInfo='" << d->m_debugInfo << "'" << " minimum=" << slider->minimum() << " maximum=" << slider->maximum() << " value=" << slider->value(); slider->setMinimum(sqrt(500)); slider->setMaximum(sqrt(100000)); WARNING_LOG(m_logger) << LOGFUNCTION << " min/max value are identical, debugInfo='" << d->m_debugInfo << "'" << " minimum=" << slider->minimum() << " maximum=" << slider->maximum() << " value=" << slider->value(); } DEBUG_LOG(m_logger) << LOGFUNCTION << " debugInfo='" << d->m_debugInfo << "'" << " minimum=" << slider->minimum() << " maximum=" << slider->maximum() << " value=" << slider->value(); TRACE_LOG(m_logger) << LOGFUNCTION << " debugInfo='" << d->m_debugInfo << "'" << " END"; } void LayerControlWidget::onZoomSliderValueChanged() { TRACE_LOG(m_logger) << LOGFUNCTION << " debugInfo='" << d->m_debugInfo << "'" << " START"; QSlider *slider = qobject_cast(sender()); if (! slider) return; if (d->m_map->isReady()) d->m_map->setScale(slider->value() * slider->value()); DEBUG_LOG(m_logger) << LOGFUNCTION << " debugInfo='" << d->m_debugInfo << "'" << " new target value: " << slider->value() * slider->value(); TRACE_LOG(m_logger) << LOGFUNCTION << " debugInfo='" << d->m_debugInfo << "'" << " END"; } void LayerControlWidget::onRotationSliderValueChanged() { TRACE_LOG(m_logger) << LOGFUNCTION << " debugInfo='" << d->m_debugInfo << "'" << " START" << " rawValue = " << d->m_rotationSlider->value(); if (d->m_map->isReady() // && slider->isSliderDown() ) { // ERROR_LOG(m_logger) << LOGFUNCTION << " debugInfo='" << d->m_debugInfo << "'" << " push new value " // << " slider= " << slider // << slider->value(); d->m_map->setRotation(d->m_rotationSlider->value()); } TRACE_LOG(m_logger) << LOGFUNCTION << " debugInfo='" << d->m_debugInfo << "'" << " END"; } void LayerControlWidget::onRotationOfMapChanged(double rotation) { TRACE_LOG(m_logger) << LOGFUNCTION << " debugInfo='" << d->m_debugInfo << "'" << " START" << " rotation " << rotation; if (! d->m_rotationSlider) return; if (d->m_map->isReady() && !d->m_rotationSlider->isSliderDown()) { const QSignalBlocker blocker(d->m_rotationSlider); d->m_rotationSlider->setValue(rotation); } TRACE_LOG(m_logger) << LOGFUNCTION << " debugInfo='" << d->m_debugInfo << "'" << " END"; } void LayerControlWidget::onSymbolSizeSliderValueChanged() { TRACE_LOG(m_logger) << LOGFUNCTION << " debugInfo='" << d->m_debugInfo << "'" << " START" << " rawValue = " << d->m_symbolSizeSlider->value(); if (!d->m_symbolSizeTimer) { d->m_symbolSizeTimer = new QTimer(this); d->m_symbolSizeTimer->setSingleShot(true); d->m_symbolSizeTimer->setInterval(500); // msec connect(d->m_symbolSizeTimer, &QTimer::timeout, this, &LayerControlWidget::onSymbolSizeSliderValueChangedTimeout); } d->m_symbolSizeTimer->start(); // start -> restart TRACE_LOG(m_logger) << LOGFUNCTION << " debugInfo='" << d->m_debugInfo << "'" << " END"; } void LayerControlWidget::onSymbolSizeSliderValueChangedTimeout() { TRACE_LOG(m_logger) << LOGFUNCTION << " debugInfo='" << d->m_debugInfo << "'" << " START" << " rawValue = " << d->m_symbolSizeSlider->value(); double symSize = d->m_symbolSizeSlider->value() / 100.0; d->m_map->setSymbolScale(symSize); TRACE_LOG(m_logger) << LOGFUNCTION << " debugInfo='" << d->m_debugInfo << "'" << " END"; } void LayerControlWidget::onSymbolSizeOfMapChanged(double symbolSize) { TRACE_LOG(m_logger) << LOGFUNCTION << " debugInfo='" << d->m_debugInfo << "'" << " START" << " symbolSize " << symbolSize; if (! d->m_symbolSizeSlider) return; int symSizeInt = symbolSize * 100; const QSignalBlocker blocker(d->m_symbolSizeSlider); d->m_symbolSizeSlider->setValue(symSizeInt); TRACE_LOG(m_logger) << LOGFUNCTION << " debugInfo='" << d->m_debugInfo << "'" << " END"; } void LayerControlWidget::onBaseMapSelection() { TRACE_LOG(m_logger) << LOGFUNCTION << " debugInfo='" << d->m_debugInfo << "'" << " START"; QObject *pb = qobject_cast(sender()); if (! pb) { DEBUG_LOG(m_logger) << LOGFUNCTION << " debugInfo='" << d->m_debugInfo << "'" << " cast failed"; return; } // check/uncheck all: for (auto widget : qAsConst(d->m_baseMapSelectIcons)) widget->setChecked(widget == pb); LayerFactory &layFac = d->m_map->layerFactory(); const QStringList &basemapLayernames = layFac.layernames(LayerType::Basemap); const QString &curName = pb->property(LayernameProperty).toString(); DEBUG_LOG(m_logger) << LOGFUNCTION << " debugInfo='" << d->m_debugInfo << "'" << " sender=" << curName; for (const QString &name : basemapLayernames) { bool isCur = name.compare(curName) == 0; LayerParameter lp = layFac.layerParameter(name); if (isCur) lp.resetView(); lp.visible = isCur; layFac.setLayerParameter(name, lp); } TRACE_LOG(m_logger) << LOGFUNCTION << " debugInfo='" << d->m_debugInfo << "'" << " END"; } void LayerControlWidget::onMapReady() { TRACE_LOG(m_logger) << LOGFUNCTION << " debugInfo='" << d->m_debugInfo << "'" << " START"; onZoomSliderInit(d->m_zoomSlider); onRotationOfMapChanged(d->m_map->rotation()); onSymbolSizeOfMapChanged(d->m_map->symbolScale()); TRACE_LOG(m_logger) << LOGFUNCTION << " debugInfo='" << d->m_debugInfo << "'" << " END"; } void LayerControlWidget::onMapExtentChanged() { TRACE_LOG(m_logger) << LOGFUNCTION << " debugInfo='" << d->m_debugInfo << "'" << " START"; if (d->m_zoomSlider && d->m_zoomSlider->isEnabled() && d->m_map->isReady() && (!d->m_zoomSlider->isSliderDown())) { const QSignalBlocker blocker(d->m_zoomSlider); float newVal = sqrt(d->m_map->scale()); d->m_zoomSlider->setValue(newVal); DEBUG_LOG(m_logger) << LOGFUNCTION << " debugInfo='" << d->m_debugInfo << "'" << " d->m_map->scale(): " << d->m_map->scale() << "; newVal: " << newVal << "; value set to: " << d->m_zoomSlider->value(); } TRACE_LOG(m_logger) << LOGFUNCTION << " debugInfo='" << d->m_debugInfo << "'" << " END"; } void LayerControlWidget::layerOnOff() { QCheckBox *cb = qobject_cast(sender()); if (!cb) return; QString layername = cb->property(LayernameProperty).toString(); // get LayerParameter, update data and set: LayerParameter lp = d->m_map->layerFactory().layerParameter(layername); lp.visible = cb->isChecked(); d->m_map->layerFactory().setLayerParameter(layername, lp); } void LayerControlWidget::opacity(int) { mySlider *sl = qobject_cast(sender()); if (!sl) return; QString layername = sl->m_layername; LayerParameter lp = d->m_map->layerFactory().layerParameter(layername); lp.opacity = sl->value(); d->m_map->layerFactory().setLayerParameter(layername, lp); } void LayerControlWidget::brightness(int) { mySlider *sl = qobject_cast(sender()); if (!sl) return; QString layername = sl->m_layername; LayerParameter lp = d->m_map->layerFactory().layerParameter(layername); lp.brightness = sl->value(); d->m_map->layerFactory().setLayerParameter(layername, lp); } void LayerControlWidget::contrast(int) { mySlider *sl = qobject_cast(sender()); if (!sl) return; QString layername = sl->m_layername; LayerParameter lp = d->m_map->layerFactory().layerParameter(layername); lp.contrast = sl->value(); d->m_map->layerFactory().setLayerParameter(layername, lp); } void LayerControlWidget::gamma(int) { mySlider *sl = qobject_cast(sender()); if (!sl) return; QString layername = sl->m_layername; LayerParameter lp = d->m_map->layerFactory().layerParameter(layername); lp.gamma = sl->value(); d->m_map->layerFactory().setLayerParameter(layername, lp); } void LayerControlWidget::onLayerParamterChanged(const QString &layername, const LayerParameter &newLayerParameter) { TRACE_LOG(m_logger) << LOGFUNCTION << " debugInfo='" << d->m_debugInfo << "'" << " START" << " layername= '" << layername << "'"; // INFO_LOG(m_logger) << LOGFUNCTION << " debugInfo='" << d->m_debugInfo << "'" // << " layername=" << layername // << " lp=" << newLayerParameter; if (! d->m_sliderMap.contains(layername)) { DEBUG_LOG(m_logger) << LOGFUNCTION << " debugInfo='" << d->m_debugInfo << "'" << " layername='" << layername << "' is new -> updatePanel"; updatePanelLayer(); return; } // refresh GUI: if (d->m_sliderMap.contains(layername)) { SliderStruct &data = d->m_sliderMap[layername]; if (data.cbOnOff) data.cbOnOff ->setChecked(newLayerParameter.visible); if (data.sl_opacity) data.sl_opacity ->setValue(newLayerParameter.opacity); if (data.sl_brightness) data.sl_brightness->setValue(newLayerParameter.brightness); if (data.sl_contrast) data.sl_contrast ->setValue(newLayerParameter.contrast); if (data.sl_gamma) data.sl_gamma ->setValue(newLayerParameter.gamma); } TRACE_LOG(m_logger) << LOGFUNCTION << " debugInfo='" << d->m_debugInfo << "'" << " END"; } QString LayerControlWidget::layernameAt(const QPoint &pos) const { TRACE_LOG(m_logger) << LOGFUNCTION << " debugInfo='" << d->m_debugInfo << "'" << " START"; QWidget *child = childAt(pos); if (!child) { DEBUG_LOG(m_logger) << LOGFUNCTION << " debugInfo='" << d->m_debugInfo << "'" << " no child"; return QString(); } DragableCheckBox *cb = dynamic_cast(child); if (!cb) { DEBUG_LOG(m_logger) << LOGFUNCTION << " debugInfo='" << d->m_debugInfo << "'" << " dynacast failed"; return QString(); } const QString &childLayername = cb->property(LayernameProperty).toString(); DEBUG_LOG(m_logger) << LOGFUNCTION << " debugInfo='" << d->m_debugInfo << "'" << " childLayername=" << childLayername; TRACE_LOG(m_logger) << LOGFUNCTION << " debugInfo='" << d->m_debugInfo << "'" << " END"; return childLayername; } QStringList LayerControlWidget::newLayerOrder(const QString &draggedLayername, const QString &childLayername) { TRACE_LOG(m_logger) << LOGFUNCTION << " debugInfo='" << d->m_debugInfo << "'" << " START"; // get current order: QStringList sl = d->m_map->layerFactory().layernames(); if (draggedLayername == childLayername) return sl; // remove sl.removeOne(draggedLayername); // find new position: int idx = sl.indexOf(childLayername); // insert AFTER; sl.insert(++idx, draggedLayername); TRACE_LOG(m_logger) << LOGFUNCTION << " debugInfo='" << d->m_debugInfo << "'" << " END"; return sl; } void LayerControlWidget::dragMoveEvent(QDragMoveEvent *event) { TRACE_LOG(m_logger) << LOGFUNCTION << " debugInfo='" << d->m_debugInfo << "'" << " START"; if (event->mimeData()->hasFormat(MIMETYPE)) { if (event->source() == this) { event->setDropAction(Qt::MoveAction); event->accept(); } else { QByteArray itemData = event->mimeData()->data(MIMETYPE); QDataStream dataStream(&itemData, QIODevice::ReadOnly); QString draggedLayername; dataStream >> draggedLayername; DEBUG_LOG(m_logger) << LOGFUNCTION << " debugInfo='" << d->m_debugInfo << "'" << " draggedLayername=" << draggedLayername; const QString &childLayername = layernameAt(event->pos()); DEBUG_LOG(m_logger) << LOGFUNCTION << " debugInfo='" << d->m_debugInfo << "'" << " childLayername=" << childLayername; if (childLayername.isEmpty() || (draggedLayername == childLayername)) event->ignore(); else { const QStringList &newOrder = newLayerOrder(draggedLayername, childLayername); bool ok = d->m_map->layerFactory().checkLayerOrder(newOrder); DEBUG_LOG(m_logger) << LOGFUNCTION << " debugInfo='" << d->m_debugInfo << "'" << " layerOrder ok: " << ok; if (ok) event->acceptProposedAction(); else event->ignore(); } } } else event->ignore(); TRACE_LOG(m_logger) << LOGFUNCTION << " debugInfo='" << d->m_debugInfo << "'" << " END"; } void LayerControlWidget::dragEnterEvent(QDragEnterEvent *event) { TRACE_LOG(m_logger) << LOGFUNCTION << " debugInfo='" << d->m_debugInfo << "'" << " START"; if (event->mimeData()->hasFormat(MIMETYPE)) { event->acceptProposedAction(); // if (event->source() != this) { //// event->setDropAction(Qt::MoveAction); // event->accept(); // } else { // event->acceptProposedAction(); // } } else event->ignore(); TRACE_LOG(m_logger) << LOGFUNCTION << " debugInfo='" << d->m_debugInfo << "'" << " END"; } void LayerControlWidget::dropEvent(QDropEvent *event) { TRACE_LOG(m_logger) << LOGFUNCTION << " debugInfo='" << d->m_debugInfo << "'" << " START"; if (event->mimeData()->hasFormat(MIMETYPE)) { QByteArray itemData = event->mimeData()->data(MIMETYPE); QDataStream dataStream(&itemData, QIODevice::ReadOnly); QString draggedLayername; dataStream >> draggedLayername; DEBUG_LOG(m_logger) << LOGFUNCTION << " debugInfo='" << d->m_debugInfo << "'" << " draggedLayername=" << draggedLayername; if (event->source() == this) { event->setDropAction(Qt::MoveAction); event->accept(); } else { event->acceptProposedAction(); const QString &childLayername = layernameAt(event->pos()); DEBUG_LOG(m_logger) << LOGFUNCTION << " debugInfo='" << d->m_debugInfo << "'" << " childLayername=" << childLayername; if (draggedLayername == childLayername) return; const QStringList &newOrder = newLayerOrder(draggedLayername, childLayername); bool ok = d->m_map->layerFactory().orderLayerTo(newOrder); DEBUG_LOG(m_logger) << LOGFUNCTION << " debugInfo='" << d->m_debugInfo << "'" << " layerOrder ok: " << ok; } } else event->ignore(); TRACE_LOG(m_logger) << LOGFUNCTION << " debugInfo='" << d->m_debugInfo << "'" << " END"; } } // namespace SituationMap #include "layer_control_widget.moc"