3 Commits

19 changed files with 353 additions and 205 deletions

View File

@ -905,7 +905,7 @@ void HPPA::removeLayerByTreeIndex()
LayerTreeNode* node = static_cast<LayerTreeNode*>(currentIndexTmp.internalPointer());
if (!node || node->type() != LayerTreeNode::Type::Layer) return;
auto* layerNode = static_cast<LayerTreeLayerNode*>(node);
auto* layerNode = static_cast<LayerTreeLayer*>(node);
MapLayer* mapLayer = layerNode->mapLayer();
QWidget* layerWidget = nullptr;
@ -957,7 +957,7 @@ void HPPA::removeAllLayersInRasterGroup()
if (node->type() != LayerTreeNode::Type::Layer) continue;
auto* layerNode = static_cast<LayerTreeLayerNode*>(node);
auto* layerNode = static_cast<LayerTreeLayer*>(node);
MapLayer* mapLayer = layerNode->mapLayer();
QWidget* layerWidget = nullptr;
@ -1247,9 +1247,9 @@ void HPPA::onStartRecordStep1()
else
{
m_omc->stop();
m_RecordState -= 1;
m_RecordState -= 1;
ui.action_start_recording->setText(QString::fromLocal8Bit("采集"));
ui.action_start_recording->setText(QString::fromLocal8Bit("采集"));
ui.mainToolBar->widgetForAction(ui.action_start_recording)->setStyleSheet("QWidget{background-color:rgb(0,255,0);}");
}
return;
@ -1334,6 +1334,41 @@ void HPPA::onTabWidgetCurrentChanged(int index)//代码新建一个tab会调
{
canvas->setMapTool(activeTool);
}
// Sync layer tree view selection with the current tab
if (m_MapLayerStore && m_layerTreeView && m_LayerTreeModel && m_RasterGroup)
{
MapLayer* layer = m_MapLayerStore->layerForWidget(currentWidget);
if (layer)
{
// Find the LayerTreeLayer node in m_RasterGroup that matches this layer
for (int i = 0; i < m_RasterGroup->childCount(); ++i)
{
LayerTreeNode* child = m_RasterGroup->childAt(i);
if (child && child->type() == LayerTreeNode::Type::Layer)
{
auto* layerNode = static_cast<LayerTreeLayer*>(child);
if (layerNode->mapLayer() == layer)
{
QModelIndex nodeIndex = m_LayerTreeModel->index(i, 0,
m_LayerTreeModel->index(m_RasterGroup->rowInParent(), 0));
// Block signals to avoid infinite loop with onLayerTreeSelectionChanged
m_layerTreeView->selectionModel()->blockSignals(true);
m_layerTreeView->setCurrentIndex(nodeIndex);
m_layerTreeView->selectionModel()->blockSignals(false);
// Manually update ImageControl since we blocked the signal
RasterLayer* rl = qobject_cast<RasterLayer*>(layer);
if (rl)
{
m_ic->setActiveLayer(rl);
}
break;
}
}
}
}
}
}
void HPPA::onActionOpenDirectory()
@ -1570,16 +1605,7 @@ void HPPA::onOpenImg()
QFileInfo fi(uri);
QString baseName = fi.completeBaseName();
RasterLayer* rl = new RasterLayer(baseName, uri);
auto* layerNode = new LayerTreeLayerNode(rl);
m_LayerTreeModel->addLayer(m_RasterGroup, layerNode);
QWidget* mapcavasContainer = onCreateTab(baseName);
if (m_MapLayerStore) m_MapLayerStore->addLayer(rl, mapcavasContainer);
QList<Mapcavas*> mapcavas = mapcavasContainer->findChildren<Mapcavas*>();
mapcavas[0]->setLayers(rl);
mapcavas[0]->freshmap();
addLayer(baseName, uri, true);
}
void HPPA::onconnect()
@ -1722,26 +1748,6 @@ void HPPA::testImagerStatus()
m_TestImagerStausThread->start();
}
void HPPA::onImageFileSaved(QString path, int fileIndex)
{
// 该槽在 UI 线程中执行Qt 会使用 queued connection可以安全操作 model
QFileInfo fi(path);
QString base = fi.completeBaseName(); // 去掉路径与扩展名(例如 tmp_image_0
// 将新的 layer 添加到 Raster 分组
if (!m_LayerTreeModel || !m_RasterGroup) return;
// layer 名称可根据需要调整,这里用文件名作为图层名
{
auto* ln = new LayerTreeLayerNode(nullptr);
ln->setName(base);
m_LayerTreeModel->addLayer(m_RasterGroup, ln);
}
// 可选:展开 TOC 或者做其他 UI 更新(目前不做动画,仅打印日志)
qDebug() << "ImageFileSaved -> add layer:" << base << " index:" << fileIndex;
}
void HPPA::onAutoExposure()
{
double ReturnedExposureTime = m_Imager->auto_exposure();
@ -2045,23 +2051,26 @@ void WorkerThread3::run()
void HPPA::onLayerCreatedFromFile(const QString& baseName, const QString& filePath, int fileIndex)
{
if (!m_LayerTreeModel || !m_RasterGroup) return;
addLayer(baseName, filePath, false);
}
void HPPA::addLayer(const QString& baseName, const QString& filePath,bool refresh)
{
// Create MapLayer first and attach it to a LayerTreeLayerNode
RasterLayer* ml = new RasterLayer(baseName, filePath);
auto* layerNode = new LayerTreeLayer(ml);
LayerTreeNode* node = m_LayerTreeModel->addLayer(m_RasterGroup, layerNode);
QWidget* mapcavasContainer = onCreateTab(baseName);
// Create MapLayer first and attach it to a LayerTreeLayerNode
RasterLayer* ml = new RasterLayer(baseName, filePath);
if (m_MapLayerStore) m_MapLayerStore->addLayer(ml, mapcavasContainer);
QList<Mapcavas*> mapcavas = mapcavasContainer->findChildren<Mapcavas*>();
mapcavas[0]->setLayers(ml);
auto* layerNode = new LayerTreeLayerNode(ml);
LayerTreeNode* node = m_LayerTreeModel->addLayer(m_RasterGroup, layerNode);
LayerTreeLayerNode* lnode = dynamic_cast<LayerTreeLayerNode*>(node);
if (!lnode) return;
// layerNode already holds the MapLayer pointer from constructor
qDebug() << "LayerFileCreated -> created layer:" << baseName << "path:" << filePath << "index:" << fileIndex;
if (refresh)
{
mapcavas[0]->freshmap();
}
}
void HPPA::onLayerTreeSelectionChanged(const QItemSelection& selected, const QItemSelection& deselected)
@ -2085,7 +2094,7 @@ void HPPA::onLayerTreeSelectionChanged(const QItemSelection& selected, const QIt
return;
}
auto* layerNode = static_cast<LayerTreeLayerNode*>(node);
auto* layerNode = static_cast<LayerTreeLayer*>(node);
MapLayer* mapLayer = layerNode->mapLayer();
if (!mapLayer || mapLayer->layerType() != MapLayer::LayerType::Raster) {
m_ic->setActiveLayer(nullptr);

View File

@ -341,8 +341,7 @@ public Q_SLOTS:
void onCreated3DModelPlantPhenotype();
void onCreated3DModelOneMotor();
void onImageFileSaved(QString path, int fileIndex);
void addLayer(const QString& baseName, const QString& filePath, bool refresh);
void onLayerCreatedFromFile(const QString& baseName, const QString& filePath, int fileIndex);
void removeLayerByTreeIndex();
void removeAllLayersInRasterGroup();

View File

@ -103,6 +103,50 @@ bool Mapcavas::HasImage()
}
}
void Mapcavas::updateCrosshair(double sceneX, double sceneY)
{
QPen pen(Qt::red, 2.0);
pen.setCosmetic(true); // constant screen-width regardless of zoom
if (!m_hLine)
{
m_hLine = m_qtGraphicsScene->addLine(0, 0, 0, 0, pen);
m_hLine->setZValue(1e9);
}
if (!m_vLine)
{
m_vLine = m_qtGraphicsScene->addLine(0, 0, 0, 0, pen);
m_vLine->setZValue(1e9);
}
m_hLine->setPen(pen);
m_vLine->setPen(pen);
m_hLine->setLine(sceneX - m_CrosshairHalfLen, sceneY,
sceneX + m_CrosshairHalfLen, sceneY);
m_vLine->setLine(sceneX, sceneY - m_CrosshairHalfLen,
sceneX, sceneY + m_CrosshairHalfLen);
}
void Mapcavas::removeCrosshair()
{
if (m_hLine)
{
if (m_hLine->scene())
m_hLine->scene()->removeItem(m_hLine);
delete m_hLine;
m_hLine = nullptr;
}
if (m_vLine)
{
if (m_vLine->scene())
m_vLine->scene()->removeItem(m_vLine);
delete m_vLine;
m_vLine = nullptr;
}
}
void Mapcavas::wheelEvent(QWheelEvent *event)
{
// Always let the tool have a chance first

View File

@ -29,6 +29,9 @@ public:
bool HasImage();
void ensureSceneVisible();
void updateCrosshair(double sceneX, double sceneY);
void removeCrosshair();
void wheelEvent(QWheelEvent *event) Q_DECL_OVERRIDE;
void scaling(qreal scaleFactor);
@ -71,6 +74,10 @@ private:
QPoint m_lastMousePos; // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>µ<EFBFBD>λ<EFBFBD><CEBB>
qreal m_scale; // <20><><EFBFBD><EFBFBD>ֵ
double m_CrosshairHalfLen = 10.0;
QGraphicsLineItem* m_hLine = nullptr; // horizontal line
QGraphicsLineItem* m_vLine = nullptr; // vertical line
signals:
void leftMouseButtonPressed(int, int, QVector<double>, QVector<double>);

View File

@ -1,39 +1,13 @@
#include "LayerTree.h"
#include "LayerTreeGroupNode.h"
LayerTree::LayerTree(QObject* parent)
: QObject(parent)
: LayerTreeGroup("__root__", parent)
{
// root <20><>Ϊ<EFBFBD><CEAA><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> view <20><><EFBFBD><EFBFBD>ʾ
m_root = new LayerTreeGroupNode("__root__", this);
m_root->setVisible(Qt::Checked);
setVisible(Qt::Checked);
}
LayerTree::~LayerTree()
{
delete m_root;
m_root = nullptr;
}
LayerTreeNode* LayerTree::root() const
{
return m_root;
}
LayerTreeNode* LayerTree::insertNode(LayerTreeNode* parent, int row, LayerTreeNode* node)
{
if (!node) return nullptr;
if (!parent) parent = m_root;
if (row < 0) row = parent->childCount();
parent->insertChild(row, node);
return node;
}
LayerTreeNode* LayerTree::removeNode(LayerTreeNode* parent, int row)
{
if (!parent) parent = m_root;
return parent->takeChild(row);
}
void LayerTree::setChildrenVisible(LayerTreeNode* n, Qt::CheckState state)

View File

@ -1,18 +1,16 @@
#pragma once
#include <QObject>
#include "LayerTreeNode.h"
#include "LayerTreeGroupNode.h"
/**
* LayerTree<65><65><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ŀ¼<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
* - <20><><EFBFBD><EFBFBD> root
* - <20><EFBFBD><E1B9A9><EFBFBD><EFBFBD>/<2F>Ƴ<EFBFBD><C6B3>ڵ<EFBFBD><DAB5><EFBFBD> API
* LayerTree<65><65>ͼ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ڵ<EFBFBD>
* - <20>̳<EFBFBD><EFBFBD><EFBFBD> LayerTreeGroup<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ĸ<EFBFBD><EFBFBD>ڵ<EFBFBD>
* - <20><EFBFBD>ɼ<EFBFBD><C9BC>Լ<EFBFBD><D4BC><EFBFBD><EFBFBD><EFBFBD>ڵ<EFBFBD><DAB5><EFBFBD>̬<EFBFBD><CCAC><EFBFBD>µľ<C2B5>̬<EFBFBD><CCAC><EFBFBD><EFBFBD>
*
* ע<>⣺beginInsertRows/endInsertRows <20><> Qt Model <20><><EFBFBD><EFBFBD>֪ͨӦ<D6AA><D3A6> Model <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ã<EFBFBD>
* LayerTree ֻ<><D6BB><EFBFBD><EFBFBD>ά<EFBFBD><CEAC><EFBFBD><EFBFBD><EFBFBD>ݽṹ<DDBD><E1B9B9>ȷ<EFBFBD>ԡ<EFBFBD>
*/
class LayerTree : public QObject
class LayerTree : public LayerTreeGroup
{
Q_OBJECT
public:
@ -22,28 +20,7 @@ public:
LayerTree(const LayerTree&) = delete;
LayerTree& operator=(const LayerTree&) = delete;
LayerTreeNode* root() const;
// <20><><EFBFBD>룺parent Ϊ nullptr <20><>ʾ root<6F><74>row=-1 <20><>ʾ append
LayerTreeNode* insertNode(LayerTreeNode* parent, int row, LayerTreeNode* node);
// <20>Ƴ<EFBFBD><C6B3><EFBFBD><EFBFBD><EFBFBD> delete<74><65><EFBFBD><EFBFBD><EFBFBD>ر<EFBFBD><D8B1>Ƴ<EFBFBD><C6B3>ڵ㣨<DAB5><E3A3A8><EFBFBD><EFBFBD><EFBFBD>߸<EFBFBD><DFB8><EFBFBD> delete <20><><EFBFBD><EFBFBD><EFBFBD>²<EFBFBD><C2B2>
LayerTreeNode* removeNode(LayerTreeNode* parent, int row);
// <20>ɼ<EFBFBD><C9BC><EFBFBD><EFBFBD>߼<EFBFBD><DFBC><EFBFBD><EFBFBD><EFBFBD> Model <20><><EFBFBD>ã<EFBFBD>
static void setChildrenVisible(LayerTreeNode* n, Qt::CheckState state);
static void updateParentVisibleFromChildren(LayerTreeNode* parent);
static inline bool isLayer(LayerTreeNode* node)
{
return node && node->type() == LayerTreeNode::Type::Layer;
}
static inline bool isGroup(LayerTreeNode* node)
{
return node && node->type() == LayerTreeNode::Type::Group;
}
private:
LayerTreeNode* m_root = nullptr; // owned
};

View File

@ -1,6 +1,103 @@
#include "LayerTreeGroupNode.h"
#include "LayerTreeLayerNode.h"
LayerTreeGroupNode::LayerTreeGroupNode(const QString& name, QObject* parent)
LayerTreeGroup::LayerTreeGroup(const QString& name, QObject* parent)
: LayerTreeNode(name, parent)
{
}
LayerTreeGroup* LayerTreeGroup::insertGroup(int index, const QString& name)
{
auto* group = new LayerTreeGroup(name);
insertChildNode(index, group);
return group;
}
LayerTreeGroup* LayerTreeGroup::addGroup(const QString& name)
{
return insertGroup(childCount(), name);
}
LayerTreeLayer* LayerTreeGroup::insertLayer(int index, LayerTreeLayer* layer)
{
if (!layer) return nullptr;
insertChildNode(index, layer);
return layer;
}
LayerTreeLayer* LayerTreeGroup::addLayer(LayerTreeLayer* layer)
{
return insertLayer(childCount(), layer);
}
void LayerTreeGroup::insertChildNode(int index, LayerTreeNode* node)
{
insertChild(index, node);
}
void LayerTreeGroup::addChildNode(LayerTreeNode* node)
{
appendChild(node);
}
LayerTreeNode* LayerTreeGroup::removeChildNode(LayerTreeNode* node)
{
if (!node) return nullptr;
int row = -1;
for (int i = 0; i < childCount(); ++i)
{
if (childAt(i) == node)
{
row = i;
break;
}
}
if (row < 0) return nullptr;
removeChild(row, 1, false);
return node;
}
LayerTreeLayer* LayerTreeGroup::findLayer(const QString& name) const
{
const auto layers = findLayers();
for (auto* l : layers)
{
if (l->name() == name)
return l;
}
return nullptr;
}
QList<LayerTreeLayer*> LayerTreeGroup::findLayers() const
{
QList<LayerTreeLayer*> result;
for (int i = 0; i < childCount(); ++i)
{
LayerTreeNode* child = childAt(i);
if (LayerTreeNode::isLayer(child))
{
result.append(static_cast<LayerTreeLayer*>(child));
}
else if (LayerTreeNode::isGroup(child))
{
result.append(static_cast<LayerTreeGroup*>(child)->findLayers());
}
}
return result;
}
QList<LayerTreeGroup*> LayerTreeGroup::findGroups() const
{
QList<LayerTreeGroup*> result;
for (int i = 0; i < childCount(); ++i)
{
LayerTreeNode* child = childAt(i);
if (LayerTreeNode::isGroup(child))
{
auto* g = static_cast<LayerTreeGroup*>(child);
result.append(g);
result.append(g->findGroups());
}
}
return result;
}

View File

@ -1,15 +1,44 @@
#pragma once
#include "LayerTreeNode.h"
/** Group <20>ڵ<EFBFBD> */
class LayerTreeGroupNode : public LayerTreeNode
class LayerTreeLayer;
/**
* LayerTreeGroup<75><70>ͼ<EFBFBD><CDBC><EFBFBD><EFBFBD><EFBFBD>ڵ<EFBFBD>
* - <20><><EFBFBD><EFBFBD>Ϊ LayerTreeNode
* - <20><EFBFBD><E1B9A9><EFBFBD><EFBFBD>ͼ<EFBFBD><CDBC><EFBFBD>ڵ㣨LayerTreeLayer<65><72><EFBFBD><EFBFBD>ͼ<EFBFBD><CDBC><EFBFBD>飨LayerTreeGroup<75><70><EFBFBD>ı<EFBFBD><C4B1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
*/
class LayerTreeGroup : public LayerTreeNode
{
Q_OBJECT
public:
explicit LayerTreeGroupNode(const QString& name,
QObject* parent = nullptr);
explicit LayerTreeGroup(const QString& name = QString(),
QObject* parent = nullptr);
Type type() const override { return Type::Group; }
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
LayerTreeGroup* insertGroup(int index, const QString& name);
LayerTreeGroup* addGroup(const QString& name);
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͼ<EFBFBD><CDBC><EFBFBD>ڵ<EFBFBD>
LayerTreeLayer* insertLayer(int index, LayerTreeLayer* layer);
LayerTreeLayer* addLayer(LayerTreeLayer* layer);
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ڵ<EFBFBD>
void insertChildNode(int index, LayerTreeNode* node);
void addChildNode(LayerTreeNode* node);
// <20>Ƴ<EFBFBD><C6B3>ӽڵ㣨<DAB5><E3A3A8> delete<74><65><EFBFBD><EFBFBD><EFBFBD>ر<EFBFBD><D8B1>Ƴ<EFBFBD><C6B3>ڵ㣩
LayerTreeNode* removeChildNode(LayerTreeNode* node);
// <20><><EFBFBD><EFBFBD>
LayerTreeLayer* findLayer(const QString& name) const;
QList<LayerTreeLayer*> findLayers() const;
QList<LayerTreeGroup*> findGroups() const;
// <20>Ժ<EFBFBD><D4BA><EFBFBD><EFBFBD><EFBFBD>չ<EFBFBD><D5B9>collapsed / groupOpacity <20><>
};
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
using LayerTreeGroupNode = LayerTreeGroup;

View File

@ -1,22 +1,22 @@
#include "LayerTreeLayerNode.h"
LayerTreeLayerNode::LayerTreeLayerNode(MapLayer* layer, QObject* parent)
LayerTreeLayer::LayerTreeLayer(MapLayer* layer, QObject* parent)
: LayerTreeNode(layer ? layer->name() : QString(), parent), m_layer(layer)
{
}
LayerTreeNode::Type LayerTreeLayerNode::type() const
LayerTreeNode::Type LayerTreeLayer::type() const
{
return Type::Layer;
}
// <20><><EFBFBD><EFBFBD>һ<EFBFBD><D2BB> MapLayer ָ<><EFBFBD><EBA3A8>ӵ<EFBFBD>У<EFBFBD>
void LayerTreeLayerNode::setMapLayer(MapLayer* layer)
void LayerTreeLayer::setMapLayer(MapLayer* layer)
{
m_layer = layer;
}
MapLayer* LayerTreeLayerNode::mapLayer() const
MapLayer* LayerTreeLayer::mapLayer() const
{
return m_layer;
}

View File

@ -2,16 +2,19 @@
#include "LayerTreeNode.h"
#include "MapLayer.h"
/** Layer <20>ڵ<EFBFBD> */
class LayerTreeLayerNode : public LayerTreeNode
/**
* LayerTreeLayer<EFBFBD><EFBFBD>ͼ<EFBFBD><EFBFBD><EFBFBD>ڵ<EFBFBD>
* - <20><><EFBFBD><EFBFBD>Ϊ LayerTreeNode
* - <20><><EFBFBD><EFBFBD>һ<EFBFBD><D2BB> MapLayer ָ<><EFBFBD><EBA3A8>ӵ<EFBFBD>У<EFBFBD>
*/
class LayerTreeLayer : public LayerTreeNode
{
Q_OBJECT
public:
explicit LayerTreeLayerNode(MapLayer* layer, QObject* parent = nullptr);
explicit LayerTreeLayer(MapLayer* layer, QObject* parent = nullptr);
Type type() const override;
// <20><><EFBFBD><EFBFBD>һ<EFBFBD><D2BB> MapLayer ָ<><EFBFBD><EBA3A8>ӵ<EFBFBD>У<EFBFBD>
void setMapLayer(MapLayer* layer);
MapLayer* mapLayer() const;
@ -20,3 +23,6 @@ private:
// <20><><EFBFBD><EFBFBD>չ<EFBFBD><D5B9>layerId / pointer / legendItems <20><>
};
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
using LayerTreeLayerNode = LayerTreeLayer;

View File

@ -28,10 +28,10 @@ QModelIndex LayerTreeModel::index(int row, int column, const QModelIndex& parent
QModelIndex LayerTreeModel::parent(const QModelIndex& child) const
{
LayerTreeNode* node = nodeFromIndex(child);
if (!node || node == m_tree->root()) return {};
if (!node || node == m_tree) return {};
LayerTreeNode* p = node->parentNode();
if (!p || p == m_tree->root()) return {};
if (!p || p == m_tree) return {};
return createIndex(p->rowInParent(), 0, p);
}
@ -50,7 +50,7 @@ int LayerTreeModel::columnCount(const QModelIndex&) const
QVariant LayerTreeModel::data(const QModelIndex& index, int role) const
{
LayerTreeNode* n = nodeFromIndex(index);
if (!n || n == m_tree->root()) return {};
if (!n || n == m_tree) return {};
switch (role) {
case Qt::DisplayRole:
@ -59,9 +59,9 @@ QVariant LayerTreeModel::data(const QModelIndex& index, int role) const
case Qt::DecorationRole:
{
auto* tmp = nodeFromIndex(index);
if (LayerTree::isGroup(tmp))
if (LayerTreeNode::isGroup(tmp))
return QIcon();
else if (LayerTree::isLayer(tmp))
else if (LayerTreeNode::isLayer(tmp))
{
QString basePath = QCoreApplication::applicationDirPath();
return QIcon(basePath + "/icons/mIconRaster.svg");
@ -82,7 +82,7 @@ QVariant LayerTreeModel::data(const QModelIndex& index, int role) const
bool LayerTreeModel::setData(const QModelIndex& index, const QVariant& value, int role)
{
LayerTreeNode* n = nodeFromIndex(index);
if (!n || n == m_tree->root()) return false;
if (!n || n == m_tree) return false;
if (role == Qt::CheckStateRole) {
auto newState = static_cast<Qt::CheckState>(value.toInt());
@ -111,39 +111,39 @@ Qt::ItemFlags LayerTreeModel::flags(const QModelIndex& index) const
if (!index.isValid()) return Qt::NoItemFlags;
LayerTreeNode* n = nodeFromIndex(index);
if (!n || n == m_tree->root()) return Qt::NoItemFlags;
if (!n || n == m_tree) return Qt::NoItemFlags;
return Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsUserCheckable;
}
LayerTreeNode* LayerTreeModel::root() const
{
return m_tree->root();
return m_tree;
}
LayerTreeNode* LayerTreeModel::addGroup(LayerTreeNode* parent, const QString& name, const QIcon& icon)
{
if (!parent) parent = m_tree->root();
if (!parent) parent = m_tree;
const int row = parent->childCount();
beginInsertRows(indexFromNode(parent), row, row);
LayerTreeNode* g = m_tree->insertNode(parent, row, new LayerTreeGroupNode(name));
LayerTreeNode* g = m_tree->addGroup(name);
endInsertRows();
return g;
}
LayerTreeNode* LayerTreeModel::addLayer(LayerTreeNode* parent, LayerTreeLayerNode* layerNode, const QIcon& icon)
LayerTreeNode* LayerTreeModel::addLayer(LayerTreeNode* parent, LayerTreeLayer* layerNode, const QIcon& icon)
{
if (!parent) parent = m_tree->root();
if (!parent) parent = m_tree;
if (!layerNode) return nullptr;
const int row = parent->childCount();
beginInsertRows(indexFromNode(parent), row, row);
LayerTreeNode* l = m_tree->insertNode(parent, row, layerNode);
parent->insertChild(row, layerNode);
endInsertRows();
return l;
return layerNode;
}
void LayerTreeModel::setCascadeCheckEnabled(bool enabled)
@ -159,11 +159,12 @@ bool LayerTreeModel::cascadeCheckEnabled() const
// <20><><EFBFBD><EFBFBD>ʵ<EFBFBD>֣<EFBFBD><D6A3>Ƴ<EFBFBD><C6B3>ӽڵ㲢<DAB5><E3B2A2> model <20>Ϸ<EFBFBD><CFB7><EFBFBD> begin/endRemoveRows
LayerTreeNode* LayerTreeModel::removeNode(LayerTreeNode* parent, int row)
{
if (!parent) parent = m_tree->root();
if (!parent) parent = m_tree;
if (row < 0 || row >= parent->childCount()) return nullptr;
LayerTreeNode* removed = parent->childAt(row);
beginRemoveRows(indexFromNode(parent), row, row);
LayerTreeNode* removed = m_tree->removeNode(parent, row);
parent->removeChild(row, 1, false);
endRemoveRows();
return removed;
@ -171,12 +172,12 @@ LayerTreeNode* LayerTreeModel::removeNode(LayerTreeNode* parent, int row)
LayerTreeNode* LayerTreeModel::nodeFromIndex(const QModelIndex& index) const
{
if (!index.isValid()) return m_tree->root();
if (!index.isValid()) return m_tree;
return static_cast<LayerTreeNode*>(index.internalPointer());
}
QModelIndex LayerTreeModel::indexFromNode(LayerTreeNode* n) const
{
if (!n || n == m_tree->root()) return {};
if (!n || n == m_tree) return {};
return createIndex(n->rowInParent(), 0, n);
}

View File

@ -3,7 +3,7 @@
#include <QAbstractItemModel>
#include "LayerTree.h"
class LayerTreeLayerNode; // forward declare
class LayerTreeLayer; // forward declare
/**
* LayerTreeModel<65><6C>Qt <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><E3A3A8><EFBFBD>ٹ<EFBFBD><D9B9><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
@ -34,7 +34,7 @@ public:
LayerTreeNode* root() const;
LayerTreeNode* addGroup(LayerTreeNode* parent, const QString& name, const QIcon& icon = QIcon());
LayerTreeNode* addLayer(LayerTreeNode* parent, LayerTreeLayerNode* layerNode, const QIcon& icon = QIcon());
LayerTreeNode* addLayer(LayerTreeNode* parent, LayerTreeLayer* layerNode, const QIcon& icon = QIcon());
void setCascadeCheckEnabled(bool enabled);
bool cascadeCheckEnabled() const;

View File

@ -20,7 +20,11 @@ QString LayerTreeNode::name() const
void LayerTreeNode::setName(const QString& name)
{
m_name = name;
if (m_name != name)
{
m_name = name;
emit nameChanged(this, name);
}
}
QIcon LayerTreeNode::icon() const
@ -97,14 +101,35 @@ void LayerTreeNode::insertChild(int row, LayerTreeNode* child)
if (row < 0 || row > m_children.size())
row = m_children.size();
emit willAddChildren(this, row, row);
child->setParentNode(this);
m_children.insert(row, child);
emit addedChildren(this, row, row);
}
LayerTreeNode* LayerTreeNode::takeChild(int row)
void LayerTreeNode::removeChild(int from, int count, bool destroy)
{
if (row < 0 || row >= m_children.size()) return nullptr;
LayerTreeNode* taken = m_children.takeAt(row);
if (taken) taken->setParentNode(nullptr);
return taken;
if (from < 0 || count <= 0 || from + count > m_children.size()) return;
emit willRemoveChildren(this, from, from + count - 1);
QVector<LayerTreeNode*> removed;
removed.reserve(count);
for (int i = 0; i < count; ++i)
{
removed.append(m_children.at(from));
m_children.removeAt(from);
}
for (LayerTreeNode* node : removed)
{
node->setParentNode(nullptr);
}
emit removedChildren(this, from, from + count - 1);
if (destroy)
{
qDeleteAll(removed);
}
}

View File

@ -9,9 +9,10 @@
* LayerTreeNode<64><65><EFBFBD>ڵ<EFBFBD><DAB5><EFBFBD><EFBFBD><EFBFBD><E0A3A8><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
* - <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͨ<EFBFBD><CDA8><EFBFBD><EFBFBD><EFBFBD>ԣ<EFBFBD><D4A3><EFBFBD><EFBFBD><EFBFBD><><CDBC>/<2F>ɼ<EFBFBD><C9BC><EFBFBD>/<2F><><EFBFBD>ӹ<EFBFBD>ϵ
* - Group / Layer <20>ڵ<EFBFBD>ͨ<EFBFBD><CDA8><EFBFBD>̳<EFBFBD>ʵ<EFBFBD><CAB5>
* - <20><EFBFBD><E1B9A9><EFBFBD><EFBFBD><><C9BE><EFBFBD>ڵ<EFBFBD><DAB5><EFBFBD><EFBFBD>ź<EFBFBD>֪ͨ
*
* ˵<><CBB5><EFBFBD><EFBFBD>
* - <20><><EFBFBD><EFBFBD>ͬʱά<CAB1><CEAC><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ָ<EFBFBD><EFBFBD><EFBFBD>m_parentNode<EFBFBD><EFBFBD><EFBFBD><EFBFBD> QObject parent<6E><74><EFBFBD><EFBFBD>ѡ<EFBFBD><D1A1>
* - <20><><EFBFBD><EFBFBD>ͬʱά<CAB1><CEAC>"<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ָ<EFBFBD><EFBFBD>"<EFBFBD><EFBFBD>m_parentNode<EFBFBD><EFBFBD><EFBFBD><EFBFBD> QObject parent<6E><74><EFBFBD><EFBFBD>ѡ<EFBFBD><D1A1>
* - children <20>ɽڵ<C9BD><DAB5>Լ<EFBFBD><D4BC><EFBFBD><EFBFBD>в<EFBFBD><D0B2><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͷţ<CDB7><C5A3><EFBFBD><EFBFBD><EFBFBD>ʱ delete children<65><6E>
*/
class LayerTreeNode : public QObject
@ -50,7 +51,32 @@ public:
// ---- structure mutation (used by LayerTree / Model) ----
void appendChild(LayerTreeNode* child);
void insertChild(int row, LayerTreeNode* child);
LayerTreeNode* takeChild(int row); // remove but not delete
// <20><><EFBFBD><EFBFBD> QgsLayerTreeNode::removeChildrenPrivate <20>Ľ<EFBFBD>
// from: <20><>ʼ<EFBFBD><CABC><EFBFBD><EFBFBD>, count: <20>Ƴ<EFBFBD><C6B3><EFBFBD><EFBFBD><EFBFBD>, destroy: true <20><> delete <20><><EFBFBD>Ƴ<EFBFBD><C6B3>ڵ<EFBFBD>
void removeChild(int from, int count, bool destroy = true);
// ---- static type helpers ----
static inline bool isLayer(LayerTreeNode* node)
{
return node && node->type() == LayerTreeNode::Type::Layer;
}
static inline bool isGroup(LayerTreeNode* node)
{
return node && node->type() == LayerTreeNode::Type::Group;
}
signals:
// <20>ڲ<EFBFBD><DAB2><EFBFBD><EFBFBD>ӽڵ<D3BD>֮ǰ/֮<>󷢳<EFBFBD>
void willAddChildren(LayerTreeNode* node, int indexFrom, int indexTo);
void addedChildren(LayerTreeNode* node, int indexFrom, int indexTo);
// <20><><EFBFBD>Ƴ<EFBFBD><C6B3>ӽڵ<D3BD>֮ǰ/֮<>󷢳<EFBFBD>
void willRemoveChildren(LayerTreeNode* node, int indexFrom, int indexTo);
void removedChildren(LayerTreeNode* node, int indexFrom, int indexTo);
void nameChanged(LayerTreeNode* node, const QString& name);
protected:
void setParentNode(LayerTreeNode* p);

View File

@ -81,3 +81,12 @@ QWidget* MapLayerStore::widgetForLayer(const QString& absolutePath) const
}
return nullptr;
}
MapLayer* MapLayerStore::layerForWidget(QWidget* widget) const
{
if (!widget) return nullptr;
for (const auto& kv : m_layerWidgets) {
if (kv.second == widget) return kv.first;
}
return nullptr;
}

View File

@ -35,6 +35,9 @@ public slots:
// Get associated widget by layer absolute data path
QWidget* widgetForLayer(const QString& absolutePath) const;
// Reverse lookup: find the MapLayer associated with a given widget (or nullptr)
MapLayer* layerForWidget(QWidget* widget) const;
signals:
void layerAdded(MapLayer* layer);
// Emitted just before the layer is destroyed/removed from store

View File

@ -34,7 +34,7 @@ void MapTool::setMapcavas(Mapcavas* canvas)
if (m_isActive && m_canvas)
{
deactivate();
//deactivate();
}
m_canvas = canvas;

View File

@ -8,8 +8,6 @@
#include <QPen>
#include <cmath>
const double MapToolSpectral::CrosshairHalfLen = 10.0;
MapToolSpectral::MapToolSpectral(QObject* parent)
: MapTool(parent)
{
@ -18,7 +16,6 @@ MapToolSpectral::MapToolSpectral(QObject* parent)
MapToolSpectral::~MapToolSpectral()
{
//removeCrosshair();//不需要在析构函数中调用removeCrosshair()因为当MapToolSpectral被销毁时它的canvas()也会被销毁crosshair的scene也会被销毁所以crosshair会自动被删除不会造成内存泄漏。
}
void MapToolSpectral::activate()
@ -28,7 +25,7 @@ void MapToolSpectral::activate()
void MapToolSpectral::deactivate()
{
removeCrosshair();
canvas()->removeCrosshair();
MapTool::deactivate();
}
@ -48,7 +45,7 @@ void MapToolSpectral::canvasMousePressEvent(QMouseEvent* e)
if (rl && rl->isValidPixel(x, y))
{
// Place crosshair at pixel center
updateCrosshair(x + 0.5, y + 0.5);
canvas()->updateCrosshair(x + 0.5, y + 0.5);
QVector<double> wavelengths;
QVector<double> spectrum;
@ -58,51 +55,3 @@ void MapToolSpectral::canvasMousePressEvent(QMouseEvent* e)
}
}
}
void MapToolSpectral::updateCrosshair(double sceneX, double sceneY)
{
if (!canvas() || !canvas()->scene())
return;
QGraphicsScene* scene = canvas()->scene();
QPen pen(Qt::red, 2.0);
pen.setCosmetic(true); // constant screen-width regardless of zoom
if (!m_hLine)
{
m_hLine = scene->addLine(0, 0, 0, 0, pen);
m_hLine->setZValue(1e9);
}
if (!m_vLine)
{
m_vLine = scene->addLine(0, 0, 0, 0, pen);
m_vLine->setZValue(1e9);
}
m_hLine->setPen(pen);
m_vLine->setPen(pen);
m_hLine->setLine(sceneX - CrosshairHalfLen, sceneY,
sceneX + CrosshairHalfLen, sceneY);
m_vLine->setLine(sceneX, sceneY - CrosshairHalfLen,
sceneX, sceneY + CrosshairHalfLen);
}
void MapToolSpectral::removeCrosshair()
{
if (m_hLine)
{
if (m_hLine->scene())
m_hLine->scene()->removeItem(m_hLine);
delete m_hLine;
m_hLine = nullptr;
}
if (m_vLine)
{
if (m_vLine->scene())
m_vLine->scene()->removeItem(m_vLine);
delete m_vLine;
m_vLine = nullptr;
}
}

View File

@ -23,13 +23,6 @@ signals:
void spectralClicked(int x, int y, QVector<double> wavelengths, QVector<double> spectrum);
private:
void updateCrosshair(double sceneX, double sceneY);
void removeCrosshair();
QGraphicsLineItem* m_hLine = nullptr; // horizontal line
QGraphicsLineItem* m_vLine = nullptr; // vertical line
static const double CrosshairHalfLen;
};
#endif // MAPTOOLSPECTRAL_H