#include "treeviewmanager.h" #include "OriginalWnd.h" // 包含 OriginalWnd 的定义 // 构造函数 TreeViewManager::TreeViewManager(OriginalWnd* originalWnd, QWidget *widget2, QWidget *parent) : QWidget(parent), m_originalWnd(originalWnd), widget2(widget2), treeViewDown(new QTreeView(widget2)), navigationWidget(nullptr), buttonOpenFile(nullptr), buttonUp(nullptr), buttonDown(nullptr), buttonLeft(nullptr), buttonRight(nullptr), restoring(false) { if (!widget2) { qWarning() << "TreeViewManager: widget2 未初始化"; return; } // 初始化目录树模型 downModel = new QStandardItemModel(this); treeViewDown->setModel(downModel); // 给 viewport() 安装事件过滤器,以便拦截其 Paint 事件 treeViewDown->viewport()->installEventFilter(this); // 应用样式表 applyCustomStyles(); treeViewDown->setHeaderHidden(true); // 显示头部 treeViewDown->setGeometry(16, 106, widget2->width()-16, widget2->height() - 106); treeViewDown->setEditTriggers(QAbstractItemView::NoEditTriggers); treeViewDown->show(); //分割线 QFrame *lineFrame = new QFrame(widget2); lineFrame->setGeometry(16, 89, 428, 2); // 高度设 2 像素 lineFrame->setFrameShape(QFrame::HLine); lineFrame->setFrameShadow(QFrame::Plain); lineFrame->setLineWidth(2); lineFrame->setStyleSheet("color: #C7CAEB;"); lineFrame->show(); qDebug() << "widget2 geometry:" << widget2->geometry(); qDebug() << "treeViewDown geometry:" << treeViewDown->geometry(); // 加载 JSON 数据 loadJsonFromFile(":/config/menu_config.json"); // 创建按钮并设置布局 setupButton(); // 创建导航栏 navigationWidget = new QWidget(widget2); navigationWidget->setGeometry(15, 15, 300, 74); navigationLayout = new QVBoxLayout(navigationWidget); navigationLayout->setContentsMargins(0, 0, 0, 0); navigationLayout->setSpacing(0); navigationWidget->show(); // 更新导航栏位置 updateNavigationWidgetGeometry(); connect(treeViewDown, &QTreeView::clicked, this, [=](const QModelIndex &index) { QStandardItem *item = downModel->itemFromIndex(index); if (!item) return; QVariant data = item->data(Qt::UserRole); if (data.canConvert()) { QJsonObject fields = data.toJsonObject(); displayThirdLevelFields(fields); // 显示三级目录字段 } }); // 连接点击信号 connect(treeViewDown, &QTreeView::clicked, this, [=](const QModelIndex &index) { QStandardItem *item = downModel->itemFromIndex(index); if (!item) return; // 仅在非恢复状态下记录选中路径 if (!restoring) { QStringList path = buildItemPath(item); addVisitedPath(path); } QVariant data = item->data(Qt::UserRole); if (data.canConvert()) { QJsonObject fields = data.toJsonObject(); if (fields.contains("isThirdLevel") && fields["isThirdLevel"].toBool()) { qDebug() << "加载三级目录字段内容:" << fields; // 更新导航栏 updateNavigationBar(index); // 显示三级目录字段内容 displayThirdLevelFields(fields); treeViewDown->hide(); // 隐藏 treeViewDown return; } } // 即使是非三级目录,也更新导航栏 updateNavigationBar(index); qDebug() << "更新导航栏,目录项:" << item->text(); }); // 连接 expanded 和 collapsed 信号 connect(treeViewDown, &QTreeView::expanded, this, [=](const QModelIndex &index) { QStandardItem *item = downModel->itemFromIndex(index); if (!item) return; QStringList path = buildItemPath(item); addExpandedPath(path); }); connect(treeViewDown, &QTreeView::collapsed, this, [=](const QModelIndex &index) { QStandardItem *item = downModel->itemFromIndex(index); if (!item) return; QStringList path = buildItemPath(item); removeExpandedPath(path); }); // 加载并展开上次访问过的路径 loadVisitedPaths(); // 启动时加载第一个三级目录的按钮 // 假设第一个三级目录是第一个子项的第一个子项的第一个子项 QStandardItem *rootItem = downModel->invisibleRootItem(); if (rootItem->rowCount() > 0) { QStandardItem *firstFirstLevel = rootItem->child(0); if (firstFirstLevel && firstFirstLevel->rowCount() > 0) { QStandardItem *firstSecondLevel = firstFirstLevel->child(0); if (firstSecondLevel && firstSecondLevel->rowCount() > 0) { QStandardItem *firstThirdLevel = firstSecondLevel->child(0); QVariant data = firstThirdLevel->data(Qt::UserRole); if (data.canConvert()) { QJsonObject thirdLevelObj = data.toJsonObject(); if (thirdLevelObj.contains("isThirdLevel") && thirdLevelObj["isThirdLevel"].toBool()) { loadButtonConfigForThirdLevel(thirdLevelObj); } } } } } connect(buttonOpenFile, &QPushButton::clicked, this, &TreeViewManager::onButtonOpenFileClicked); connect(buttonUp, &QPushButton::clicked, this, &TreeViewManager::onButtonUpClicked); connect(buttonDown, &QPushButton::clicked, this, &TreeViewManager::onButtonDownClicked); connect(buttonLeft, &QPushButton::clicked, this, &TreeViewManager::onButtonLeftClicked); connect(buttonRight, &QPushButton::clicked, this, &TreeViewManager::onButtonRightClicked); } TreeViewManager::~TreeViewManager() { // 在析构时,保存当前状态(展开/选中) saveVisitedPaths(); } /** * @brief 保存当前选中路径和展开路径到 QSettings */ void TreeViewManager::saveVisitedPaths() { QSettings settings("RunCloudTech", "David"); settings.beginGroup("TreeViewState"); QStringList visitedList(visitedPaths.begin(), visitedPaths.end()); QStringList expandedList(expandedPaths.begin(), expandedPaths.end()); // 显式构造 QVariant QVariant visitedVar(visitedList); QVariant expandedVar(expandedList); // 保存到 QSettings settings.setValue("visitedPaths", visitedVar); settings.setValue("expandedPaths", expandedVar); settings.endGroup(); qDebug() << "保存选中路径:" << visitedList; qDebug() << "保存展开路径:" << expandedList; } /** * @brief 从 QSettings 恢复选中路径和展开路径 */ void TreeViewManager::loadVisitedPaths() { QSettings settings("RunCloudTech", "David"); settings.beginGroup("TreeViewState"); // 读取保存的数据 QStringList loadedVisited = settings.value("visitedPaths").toStringList(); QStringList loadedExpanded = settings.value("expandedPaths").toStringList(); settings.endGroup(); qDebug() << "加载选中路径:" << loadedVisited; qDebug() << "加载展开路径:" << loadedExpanded; restoring = true; // 进入恢复模式 // 恢复展开路径 for (const QString &p : loadedExpanded) { QStringList path = p.split("/"); QModelIndex idx = findItemByPath(path); if (idx.isValid()) { treeViewDown->expand(idx); expandedPaths.insert(p); // 重新插入 } } // 恢复选中路径(选中最后一个路径) if (!loadedVisited.isEmpty()) { QString lastPathStr = loadedVisited.last(); QStringList lastPath = lastPathStr.split("/"); QModelIndex lastIdx = findItemByPath(lastPath); if (lastIdx.isValid()) { treeViewDown->setCurrentIndex(lastIdx); visitedPaths.insert(lastPathStr); } } restoring = false; // 退出恢复模式 // ===== 在此处调用导航栏恢复 ===== updateNavigationBar(QModelIndex()); // 让它自动从 QSettings 里读 navPath } /** * @brief 记录选中的路径 * @param path 节点路径列表 */ void TreeViewManager::addVisitedPath(const QStringList &path) { QString joined = path.join("/"); if (!visitedPaths.contains(joined)) { visitedPaths.insert(joined); qDebug() << "记录[选中]路径:" << joined; } } /** * @brief 记录展开的路径 * @param path 节点路径列表 */ void TreeViewManager::addExpandedPath(const QStringList &path) { QString joined = path.join("/"); if (!expandedPaths.contains(joined)) { expandedPaths.insert(joined); qDebug() << "记录[展开]路径:" << joined; } } /** * @brief 移除展开的路径 * @param path 节点路径列表 */ void TreeViewManager::removeExpandedPath(const QStringList &path) { QString joinedPath = path.join("/"); if (expandedPaths.contains(joinedPath)) { expandedPaths.remove(joinedPath); qDebug() << "移除展开路径:" << joinedPath; } } /** * @brief 构建节点的完整路径 * @param item 当前节点 * @return 节点路径列表 */ QStringList TreeViewManager::buildItemPath(QStandardItem *item) { QStringList path; QStandardItem *currentItem = item; while (currentItem) { path.prepend(currentItem->text()); currentItem = currentItem->parent(); } return path; } /** * @brief 根据路径查找对应的节点 * @param path 节点路径列表 * @return 节点的 QModelIndex */ QModelIndex TreeViewManager::findItemByPath(const QStringList &path) { if (path.isEmpty()) return QModelIndex(); QStandardItem *currentItem = downModel->invisibleRootItem(); QModelIndex currentIndex; for (const QString &part : path) { bool found = false; for (int i = 0; i < currentItem->rowCount(); ++i) { QStandardItem *child = currentItem->child(i); if (child->text() == part) { currentIndex = downModel->indexFromItem(child); currentItem = child; found = true; break; } } if (!found) { qWarning() << "未找到路径部分:" << part; return QModelIndex(); } } return currentIndex; } bool TreeViewManager::eventFilter(QObject *watched, QEvent *event) { // 只拦截 treeViewDown->viewport() 的 Paint 事件 if (watched == treeViewDown->viewport() && event->type() == QEvent::Paint) { // 第1步:让 QTreeView 先进行默认绘制 (文字、图标等) // 这样可以把“树节点”都画出来 bool handled = QWidget::eventFilter(watched, event); // 第2步:在同一个绘制周期里,使用 QPainter 叠加画“拐角线” QPainter painter(treeViewDown->viewport()); if (!painter.isActive()) { qWarning() << "Painter not active"; return handled; } painter.save(); painter.setPen(QPen(Qt::gray, 1, Qt::DashLine)); // 灰色、1px 宽、虚线 // 调用一个递归或遍历函数,把所有节点的父->子线、兄弟延续竖线都画上 paintAllBranches(QModelIndex(), painter); painter.restore(); // 返回 handled 或 true 均可,通常返回 handled 即可 return handled; } // 其余事件交给父类默认处理 return QWidget::eventFilter(watched, event); } void TreeViewManager::paintAllBranches(const QModelIndex &parentIndex, QPainter &painter) { int rowCount = downModel->rowCount(parentIndex); for(int i = 0; i < rowCount; ++i) { // 当前子节点 QModelIndex childIndex = downModel->index(i, 0, parentIndex); if (!childIndex.isValid()) continue; // 1) 父->子拐角线 drawParentChildLine(childIndex, painter); // 2) 兄弟延续竖线(如果本节点不是最后一个兄弟,就在拐点列画条向下的线) if (i < rowCount - 1) { drawSiblingLine(childIndex, painter); } // 3) 递归处理子节点 paintAllBranches(childIndex, painter); } } /** * @brief 在“父节点 -> 子节点”间画一条“L”型拐角线,仅调整横向线段的长度 */ void TreeViewManager::drawParentChildLine(const QModelIndex &childIndex, QPainter &painter) { QModelIndex parentIndex = childIndex.parent(); if (!parentIndex.isValid()) { // 说明是“顶层节点” // 定义一个固定的起点 (rootX, rootY) int indent = treeViewDown->indentation(); int depth = 0; // 顶层节点深度为0 int branchX = (depth + 1) * indent - indent / 2; // 计算 branchX 基于缩进和深度 // 定义 rootY 为节点中心 Y QRect childRect = treeViewDown->visualRect(childIndex); if (!childRect.isValid()) return; int rootY = childRect.center().y(); // 定义横向偏移量 const int hOffset = -20; // 根据需求调整 // 绘制竖线: 从 (branchX, rootY) 到 (branchX, childRect.center().y()) painter.drawLine(QPoint(branchX, rootY), QPoint(branchX, childRect.center().y())); // 计算新的横线终点 int newX = childRect.left() + hOffset; // 绘制横线: 从 (branchX, childRect.center().y()) 到 (newX, childRect.center().y()) painter.drawLine(QPoint(branchX, childRect.center().y()), QPoint(newX, childRect.center().y())); return; } QRect parentRect = treeViewDown->visualRect(parentIndex); QRect childRect = treeViewDown->visualRect(childIndex); if (!parentRect.isValid() || !childRect.isValid()) { // 父或子可能超出可视区域 return; } int pMidY = parentRect.center().y(); int cMidY = childRect.center().y(); // 计算节点深度 int depth = 0; QModelIndex p = parentIndex; while (p.isValid()) { depth++; p = p.parent(); } int indent = treeViewDown->indentation(); int branchX = depth * indent - indent / 2; // 确保 branchX 不超出视图范围 branchX = std::max(branchX, 0); // 定义横向偏移量 const int hOffset = -15; // 根据需求调整 // 绘制竖线: 从 (branchX, pMidY) 到 (branchX, cMidY) painter.drawLine(QPoint(branchX, pMidY), QPoint(branchX, cMidY)); // 计算新的横线终点 int newX = childRect.left() + hOffset; // 绘制横线: 从 (branchX, cMidY) 到 (newX, cMidY) painter.drawLine(QPoint(branchX, cMidY), QPoint(newX, cMidY)); } /** * @brief 若本节点下面还有兄弟,则在拐点列那里继续往下画竖线 */ void TreeViewManager::drawSiblingLine(const QModelIndex &childIndex, QPainter &painter) { QModelIndex parentIndex = childIndex.parent(); if (!parentIndex.isValid()) { return; // 没有父节点 } // 下一个兄弟 int row = childIndex.row(); int lastRow = downModel->rowCount(parentIndex) - 1; if (row >= lastRow) { return; // 说明是最后一个兄弟,不用画延伸线 } QModelIndex nextSibling = downModel->index(row + 1, 0, parentIndex); QRect currRect = treeViewDown->visualRect(childIndex); QRect nextRect = treeViewDown->visualRect(nextSibling); if (!currRect.isValid() || !nextRect.isValid()) { return; } // 计算节点深度 int depth = 0; QModelIndex p = parentIndex; while (p.isValid()) { depth++; p = p.parent(); } int indent = treeViewDown->indentation(); int branchX = depth * indent - indent / 2; // 确保 branchX 不超出视图范围 branchX = std::max(branchX, 0); // 从当前节点底部向下延伸到下一个兄弟节点顶部 int startY = currRect.bottom(); int endY = nextRect.top(); painter.drawLine(QPoint(branchX, startY), QPoint(branchX, endY)); } void TreeViewManager::loadJsonFromFile(const QString &filePath) { QFile jsonFile(filePath); if (!jsonFile.exists()) { qWarning() << "JSON 文件不存在:" << filePath; return; } if (!jsonFile.open(QIODevice::ReadOnly)) { qWarning() << "无法打开 JSON 文件:" << filePath; return; } QByteArray fileData = jsonFile.readAll(); jsonFile.close(); QJsonDocument jsonDoc = QJsonDocument::fromJson(fileData); if (jsonDoc.isNull() || !jsonDoc.isObject()) { qWarning() << "JSON 文件格式错误:" << filePath; return; } // 存储加载的 JSON 文档 m_jsonDoc = jsonDoc; // 直接传递解析好的 JSON 文档 loadTreeData(jsonDoc); qDebug() << "JSON 数据加载完成"; } void TreeViewManager::applyCustomStyles() { treeViewDown->setStyleSheet(R"( /* 设置分支图标 */ QTreeView::branch:closed:has-children { border-image: none; image: url(:/images/home_add.png); } QTreeView::branch:open:has-children { border-image: none; image: url(:/images/home_minus.png); } /* 设置多选框 */ QTreeView::indicator:unchecked { image: url(:/images/home_NotSelecte.png); } QTreeView::indicator:checked { image: url(:/images/home_selected.png); } /* 背景透明 */ QTreeView { background: transparent; border: none; } )"); } void TreeViewManager::loadTreeData(const QJsonDocument &doc) { if (!doc.isObject()) { qWarning() << "无效的 JSON 结构"; return; } qDebug() << "加载的 JSON 数据:" << doc.toJson(); buildTree(doc.object(), downModel->invisibleRootItem()); } void TreeViewManager::buildTree(const QJsonObject &jsonObj, QStandardItem *parent) { for (auto it = jsonObj.begin(); it != jsonObj.end(); ++it) { if (it.key() == "isThirdLevel") { qDebug() << "跳过 'isThirdLevel' 字段:" << it.key(); continue; // 跳过 "isThirdLevel" 字段 } QStandardItem *item = new QStandardItem(it.key()); item->setCheckable(true); // 添加多选框 parent->appendRow(item); if (it.value().isObject()) { QJsonObject childObj = it.value().toObject(); if (childObj.contains("isThirdLevel") && childObj["isThirdLevel"].toBool()) { // 是三级目录,存储整个对象到 UserRole item->setData(childObj, Qt::UserRole); qDebug() << "识别为三级目录:" << it.key(); } else { // 递归处理子目录 buildTree(childObj, item); } } } } // 更新导航栏位置和大小 void TreeViewManager::updateNavigationWidgetGeometry() { // 设置导航栏的宽度和高度 int navWidth = 300; // 固定宽度为 300 像素 int navHeight = 74; // 固定高度为 74 像素 // 设置导航栏的左上角位置 int navLeft = 15; // 距离 widget2 左边 15 像素 int navTop = 15; // 距离 widget2 顶部 15 像素 // 设置导航栏的几何位置 navigationWidget->setGeometry(navLeft, navTop, navWidth, navHeight); // 如果需要,刷新组件 navigationWidget->update(); qDebug() << "Updated navigationWidget geometry:" << navigationWidget->geometry(); } void TreeViewManager::updateNavigationBar(const QModelIndex &index) { // 0) 如果当前 index 无效,尝试从 QSettings 读取“上次导航路径”并恢复 if (!index.isValid()) { qWarning() << "updateNavigationBar(): 当前 index 无效,尝试从 QSettings 恢复上次导航"; QSettings settings("RunCloudTech", "David"); settings.beginGroup("TreeViewNav"); QStringList lastNavPath = settings.value("lastNavPath").toStringList(); settings.endGroup(); if (!lastNavPath.isEmpty()) { // 找到对应的节点索引 QModelIndex savedIndex = findItemByPath(lastNavPath); if (savedIndex.isValid()) { qDebug() << "成功从 QSettings 恢复导航路径:" << lastNavPath << ",对应项:" << downModel->itemFromIndex(savedIndex)->text(); // 再次调用本函数,更新导航栏 updateNavigationBar(savedIndex); } else { qWarning() << "QSettings 里存的路径无法找到对应节点,无法恢复。"; } } else { qWarning() << "QSettings 里没有存任何导航路径,或为空。"; } return; } QStandardItem *item = downModel->itemFromIndex(index); if (!item) { qWarning() << "导航栏更新失败:未找到对应项"; return; } qDebug() << "导航栏更新,目录项:" << item->text(); // 如果导航栏已有布局,先清理 if (navigationWidget->layout()) { QLayoutItem *child; while ((child = navigationWidget->layout()->takeAt(0)) != nullptr) { if (child->widget()) { child->widget()->deleteLater(); } delete child; } delete navigationWidget->layout(); } // 构建路径列表,从当前项回溯到根节点 QList path; QStandardItem *temp = item; while (temp) { if (temp->text() != "isThirdLevel") { // 排除 "isThirdLevel" 标识 path.prepend(temp); // 从根节点开始 } temp = temp->parent(); } qDebug() << "导航路径:" << [path]() { QStringList pathNames; for (QStandardItem *p : path) { pathNames.append(p->text()); } return pathNames.join(" -> "); }(); // 创建新的导航栏布局 QVBoxLayout *newLayout = new QVBoxLayout; newLayout->setContentsMargins(0, 0, 0, 0); newLayout->setSpacing(0); // 确保始终显示三行 for (int i = 0; i < 3; ++i) { QLabel *label = new QLabel; if (i < path.size()) { QString text = path[i]->text(); if (i == 1) text = " " + text; // 一级目录缩进 if (i == 2) text = " " + text; // 二级/三级目录缩进 label->setText(text); } else { label->setText(""); // 填充空白行 } // 设置字体和样式 QFont font = label->font(); font.setPointSize(12); label->setFont(font); label->setAlignment(Qt::AlignLeft | Qt::AlignVCenter); label->setFixedHeight(navigationWidget->height() / 3); newLayout->addWidget(label); } // 设置布局并更新导航栏 navigationWidget->setLayout(newLayout); navigationWidget->update(); qDebug() << "导航栏更新完成:" << path.size() << "项"; //当前路径存到 QSettings,供下次启动恢复 QStringList pathStrings; for (QStandardItem *p : path) { pathStrings << p->text(); } QSettings settings("RunCloudTech", "David"); settings.beginGroup("TreeViewNav"); settings.setValue("lastNavPath", pathStrings); settings.endGroup(); qDebug() << "已将当前导航路径写入 QSettings:" << pathStrings; } /** * @brief 加载并显示三级目录的按钮配置信息 * @param thirdLevelObj 三级目录的 JSON 对象 */ void TreeViewManager::loadButtonConfigForThirdLevel(const QJsonObject &thirdLevelObj) { if (!m_originalWnd) { qWarning() << "OriginalWnd 指针为空,无法加载按钮配置"; return; } if (!thirdLevelObj.contains("buttons")) { qWarning() << "三级目录配置中不包含 'buttons' 字段"; return; } QJsonArray buttonsArray = thirdLevelObj.value("buttons").toArray(); if (buttonsArray.size() != 12) { qWarning() << "按钮数量不是12个,实际数量:" << buttonsArray.size(); // 根据需求选择是否继续处理 } // 获取 widget_left QWidget* widgetLeft = m_originalWnd->getWidgetLeft(); if (!widgetLeft) { qWarning() << "无法访问 widget_left"; return; } // 设置 widget_left 的固定大小 widgetLeft->setFixedSize(190, 988); // 使用绝对定位创建按钮 for (int i = 0; i < buttonsArray.size() && i < 12; ++i) { QJsonObject buttonObj = buttonsArray[i].toObject(); QString buttonId = buttonObj.value("id").toString(); QString buttonIcon = buttonObj.value("icon").toString(); QString buttonText = buttonObj.value("text").toString(); bool isEnabled = buttonObj.value("enabled").toBool(); // 创建按钮 QPushButton *button = new QPushButton(widgetLeft); button->setObjectName(buttonId); button->setText(buttonText); button->setIcon(QIcon(buttonIcon)); button->setIconSize(QSize(24, 24)); // 根据需要调整图标大小 button->setStyleSheet(R"( QPushButton { position: absolute; width: 158px; height: 48px; border-radius: 6px; opacity: 1; background: #CBD0FF; text-align: center; } QPushButton:hover { background: #A9B4FF; /* 鼠标悬停效果 */ } )"); // 设置按钮的位置 int x = 16; int y = 245 + i * (48 + 13); // 第一个按钮 y=245,后续每个按钮间隔13px button->setGeometry(x, y, 158, 48); // 设置按钮的可见性 button->setVisible(isEnabled); // 如果按钮不启用,可以选择禁用它 if (!isEnabled) { button->setEnabled(false); } button->show(); qDebug() << "创建按钮:" << buttonId << ", 文本:" << buttonText << ", 图标:" << buttonIcon << ", 启用:" << isEnabled; } } void TreeViewManager::displayThirdLevelFields(const QJsonObject &fields) { if (fields.isEmpty()) { qWarning() << "字段数据为空,无法显示"; return; } qDebug() << "显示的字段数据:" << fields; // 检查是否为三级目录 if (!fields.contains("isThirdLevel") || !fields["isThirdLevel"].toBool()) { qWarning() << "不是三级目录,跳过按钮加载"; return; } // 调用新函数加载按钮配置 loadButtonConfigForThirdLevel(fields); // 1. 检查是否已存在字段窗口,防止重复创建 foreach (QObject *child, widget2->children()) { QWidget *childWidget = qobject_cast(child); if (childWidget && childWidget->windowTitle() == "字段展示") { qDebug() << "字段窗口已存在,关闭旧窗口"; childWidget->close(); } } // 2. 创建一个新的 “字段展示” 窗口 QWidget *fieldWindow = new QWidget(widget2); fieldWindow->setWindowTitle("字段展示"); fieldWindow->setGeometry(treeViewDown->geometry()); // -- 2.1 创建一个滚动区域 QScrollArea QScrollArea *scrollArea = new QScrollArea(fieldWindow); scrollArea->setWidgetResizable(true); // 内容自适应大小 scrollArea->setHorizontalScrollBarPolicy(Qt::ScrollBarAsNeeded); // 保留水平滚动条 qDebug() << "QScrollArea 已创建,水平滚动条策略设置为 ScrollBarAsNeeded"; // -- 2.2 创建滚动容器 scrollWidget,并设置垂直布局 QWidget *scrollWidget = new QWidget; scrollWidget->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred); // 宽度跟随父窗口 QVBoxLayout *scrollLayout = new QVBoxLayout(scrollWidget); scrollLayout->setSpacing(18); // 字段的垂直间距 scrollLayout->setContentsMargins(10, 10, 10, 10); // 减少边距 qDebug() << "滚动容器和垂直布局已创建,垂直间距和边距已减少"; // 3. 遍历 JSON 中的字段,生成控件 for (auto it = fields.begin(); it != fields.end(); ++it) { QString fieldName = it.key(); if (fieldName == "isThirdLevel") { continue; // 跳过 isThirdLevel 字段 } QJsonObject fieldConfig = it.value().toObject(); QString fieldType = fieldConfig["type"].toString(); qDebug() << "处理字段:" << fieldName << "类型:" << fieldType; // 每个字段一行:Label在左,控件在右 QHBoxLayout *fieldLayout = new QHBoxLayout; fieldLayout->setSpacing(5); // 减少每行的水平间距 // (1)左侧:字段名 (最小宽度,固定高度24px,左对齐) QLabel *label = new QLabel(fieldName); label->setAlignment(Qt::AlignVCenter | Qt::AlignLeft); label->setFixedHeight(24); // 高度为24px label->setMinimumWidth(120); // 减少最小宽度,允许根据内容自动调整 fieldLayout->addWidget(label); // 在中间插入弹性伸缩,使后面的控件靠右 fieldLayout->addStretch(1); // (2)右侧:根据 fieldType 创建相应控件 QWidget *rightWidget = new QWidget; QHBoxLayout *rightLayout = new QHBoxLayout(rightWidget); rightLayout->setContentsMargins(0, 0, 0, 0); // 移除右侧边距 rightLayout->setSpacing(5); // 减少控件之间的间距 if (fieldType == "input") { // 创建 QLineEdit 输入框 QLineEdit *lineEdit = new QLineEdit(fieldConfig["value"].toString()); lineEdit->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed); // 水平方向扩展 lineEdit->setFixedHeight(28); // 减少高度 lineEdit->setAlignment(Qt::AlignLeft); // 输入框左对齐 lineEdit->setStyleSheet(R"( QLineEdit { background: #FFFFFF; border: 1px solid #BABBDC; border-radius: 6px; padding: 2px 5px; } )"); rightLayout->addWidget(lineEdit); qDebug() << "添加输入框:" << fieldName; } else if (fieldType == "radio") { // 创建一组 QRadioButton 单选框 QHBoxLayout *radioLayout = new QHBoxLayout; radioLayout->setSpacing(5); // 减少单选按钮之间的间距 QButtonGroup *radioGroup = new QButtonGroup(rightWidget); QString currentValue = fieldConfig["value"].toString(); QJsonArray options = fieldConfig["options"].toArray(); for (const QJsonValue &option : options) { QRadioButton *radioButton = new QRadioButton(option.toString()); // 使用默认样式,无需自定义样式表 if (option.toString() == currentValue) { radioButton->setChecked(true); } radioGroup->addButton(radioButton); radioLayout->addWidget(radioButton); qDebug() << "添加单选按钮:" << option.toString(); } rightLayout->addLayout(radioLayout); } else if (fieldType == "checkbox") { // 创建 QCheckBox 复选框,并添加标签 QCheckBox *checkBox = new QCheckBox; checkBox->setChecked(fieldConfig["value"].toBool()); // 使用默认样式,无需自定义样式表 // 创建标签,基于字段名称 QLabel *checkBoxLabel = new QLabel(fieldName); checkBoxLabel->setAlignment(Qt::AlignVCenter | Qt::AlignLeft); checkBoxLabel->setStyleSheet("font-size: 14px;"); // 可选:调整字体大小 QHBoxLayout *checkboxLayout = new QHBoxLayout; checkboxLayout->setSpacing(3); // 减少复选框和标签之间的间距 checkboxLayout->setContentsMargins(0, 0, 0, 0); checkboxLayout->addWidget(checkBox); checkboxLayout->addWidget(checkBoxLabel); rightLayout->addLayout(checkboxLayout); qDebug() << "添加多选框和标签:" << fieldName; } else if (fieldType == "dropdown") { // 创建 QComboBox 下拉框 QComboBox *comboBox = new QComboBox; comboBox->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed); // 固定宽度 comboBox->setFixedSize(120, 28); // 减少宽度和高度 comboBox->setStyleSheet(R"( QComboBox { background: #FFFFFF; border: 1px solid #BABBDC; border-radius: 6px; padding: 2px 5px; } QComboBox::drop-down { width: 20px; } )"); QJsonArray options = fieldConfig["options"].toArray(); for (const QJsonValue &option : options) { comboBox->addItem(option.toString()); } comboBox->setCurrentText(fieldConfig["value"].toString()); rightLayout->addWidget(comboBox); qDebug() << "添加下拉框:" << fieldName; } else if (fieldType == "time") { // 创建 QTimeEdit 时间选择框 QTimeEdit *timeEdit = new QTimeEdit; timeEdit->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed); // 固定宽度 timeEdit->setFixedSize(120, 28); // 减少宽度和高度 timeEdit->setStyleSheet(R"( QTimeEdit { background: #FFFFFF; border: 1px solid #BABBDC; border-radius: 6px; padding: 2px 5px; } )"); timeEdit->setDisplayFormat("HH:mm:ss"); timeEdit->setTime(QTime::fromString(fieldConfig["value"].toString(), "HH:mm:ss")); rightLayout->addWidget(timeEdit); qDebug() << "添加时间选择框:" << fieldName; } else if (fieldType == "switch") { // 创建 QCheckBox 开关控件,并添加文字标签“开”和“关” QWidget *switchContainer = new QWidget; QHBoxLayout *switchLayout = new QHBoxLayout(switchContainer); switchLayout->setSpacing(5); // 减少开关和标签之间的间距 switchLayout->setContentsMargins(0, 0, 0, 0); QCheckBox *switchBox = new QCheckBox; switchBox->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed); switchBox->setFixedSize(30, 30); // 调整开关大小 switchBox->setStyleSheet(R"( QCheckBox::indicator { width: 30px; height: 30px; } QCheckBox::indicator:unchecked { background-color: #BABBDC; border-radius: 6px; } QCheckBox::indicator:checked { background-color: #4CAF50; border-radius: 6px; } )"); // 设置初始状态 QString switchValue = fieldConfig["value"].toString(); if (switchValue == "on") { switchBox->setChecked(true); } else { switchBox->setChecked(false); } // 添加文字标签 QLabel *switchLabel = new QLabel(switchBox->isChecked() ? "开" : "关"); switchLabel->setAlignment(Qt::AlignVCenter | Qt::AlignLeft); switchLabel->setStyleSheet("font-size: 14px;"); // 可选:调整字体大小 // 连接开关状态改变信号以更新标签文字 connect(switchBox, &QCheckBox::stateChanged, [switchLabel](int state){ if (state == Qt::Checked) { switchLabel->setText("开"); } else { switchLabel->setText("关"); } }); switchLayout->addWidget(switchBox); switchLayout->addWidget(switchLabel); rightLayout->addWidget(switchContainer); qDebug() << "添加开关控件和标签:" << fieldName; } else if (fieldType == "combined") { // 组合控件(包含 QLineEdit 和两个 QToolButton) QJsonObject combinedValue = fieldConfig["value"].toObject(); // 确保必要的字段存在 if (!combinedValue.contains("inputValue") || !combinedValue.contains("moduleButton") || !combinedValue.contains("axisButton")) { qWarning() << "组合控件的 value 字段不完整:" << fieldName; continue; } QLineEdit *comboInput = new QLineEdit(combinedValue["inputValue"].toString()); comboInput->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed); // 水平方向扩展 comboInput->setFixedHeight(28); // 减少高度 comboInput->setStyleSheet(R"( QLineEdit { background: #FFFFFF; border: 1px solid #BABBDC; border-radius: 5px; padding: 2px 5px; } )"); qDebug() << "添加组合控件的输入框:" << fieldName; // 创建一个容器 widget 来包含组合控件 QWidget *combinedWidget = new QWidget; QHBoxLayout *combinedLayout = new QHBoxLayout(combinedWidget); combinedLayout->setSpacing(5); // 减少控件之间的间距 combinedLayout->setContentsMargins(0, 0, 0, 0); // “模组” QToolButton QToolButton *moduleButton = new QToolButton(combinedWidget); // 设置父级 moduleButton->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed); moduleButton->setFixedSize(80, 28); // 调整按钮大小 moduleButton->setStyleSheet(R"( QToolButton { background: #FFFFFF; border: 1px solid #BABBDC; border-radius: 5px; padding: 0px; /* 移除默认内边距 */ text-align: center; /* 使文本居中 */ } QToolButton::menu-indicator { image: none; } QToolButton::checked { background: #4CAF50; /* 高亮颜色 */ } /* 强制文本居中 */ QToolButton::hover { qproperty-textAlignment: 'AlignCenter'; } )"); moduleButton->setText("模组"); moduleButton->setCheckable(true); moduleButton->setPopupMode(QToolButton::InstantPopup); // “轴向” QToolButton QToolButton *axisButton = new QToolButton(combinedWidget); // 设置父级 axisButton->setObjectName("axisButton"); // 为轴向按钮设置对象名以便查找 axisButton->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed); axisButton->setFixedSize(80, 28); // 调整按钮大小 axisButton->setStyleSheet(R"( QToolButton { background: #FFFFFF; border: 1px solid #BABBDC; border-radius: 5px; padding: 0px; /* 移除默认内边距 */ text-align: center; /* 使文本居中 */ } QToolButton::menu-indicator { image: none; } QToolButton::checked { background: #4CAF50; /* 高亮颜色 */ } /* 强制文本居中 */ QToolButton::hover { qproperty-textAlignment: 'AlignCenter'; } )"); axisButton->setText("轴向"); axisButton->setCheckable(true); axisButton->setPopupMode(QToolButton::InstantPopup); axisButton->setEnabled(false); // 初始时禁用轴向按钮 // 创建 QMenu 用于“轴向”按钮,并设置样式表 QMenu *axisMenu = new QMenu(axisButton); axisMenu->setStyleSheet(R"( QMenu { background-color: white; color: black; border: 1px solid #BABBDC; } QMenu::item:selected { background-color: #4CAF50; /* 选中时背景颜色 */ color: white; /* 选中时字体颜色 */ } )"); QJsonObject axisMap = fieldConfig["axisMap"].toObject(); // 初始化轴向菜单内容为空,等待选择模组后填充 axisButton->setMenu(axisMenu); qDebug() << "初始化轴向菜单为空:" << fieldName; // 连接“轴向”按钮的菜单触发事件来更新“轴向”菜单 connect(axisMenu, &QMenu::triggered, this, [axisButton](QAction *action){ axisButton->setText(action->text()); axisButton->setChecked(true); qDebug() << "轴向选择:" << action->text(); }); // “模组” QMenu QMenu *moduleMenu = new QMenu(moduleButton); moduleMenu->setStyleSheet(R"( QMenu { background-color: white; color: black; border: 1px solid #BABBDC; } QMenu::item:selected { background-color: #4CAF50; /* 选中时背景颜色 */ color: white; /* 选中时字体颜色 */ } )"); QJsonArray moduleOptions = fieldConfig["moduleOptions"].toArray(); for (const QJsonValue &mod : moduleOptions) { QAction *action = moduleMenu->addAction(mod.toString()); // 使用按值捕获,避免悬空指针 connect(action, &QAction::triggered, this, [moduleButton, action, fieldConfig, combinedWidget, comboInput, fieldName, axisButton, axisMenu, axisMap]() { moduleButton->setText(action->text()); moduleButton->setChecked(true); qDebug() << "模组选择:" << action->text(); // 更改背景颜色为高亮色 moduleButton->setStyleSheet("background: #4CAF50;"); axisButton->setStyleSheet("background: #4CAF50;"); qDebug() << "组合控件颜色已切换为高亮颜色"; // 启用轴向按钮 axisButton->setEnabled(true); // 动态填充轴向菜单 axisMenu->clear(); // 清空现有菜单项 if (axisMap.contains(action->text())) { QJsonArray axes = axisMap[action->text()].toArray(); for (const QJsonValue &axis : axes) { //QAction *axisAction = axisMenu->addAction(axis.toString()); axisMenu->addAction(axis.toString()); } qDebug() << "轴向菜单已根据模组选择动态填充"; } else { qDebug() << "没有找到对应模组的轴向选项"; } // 启动定时器 int timeoutSec = fieldConfig["timeout"].toInt(1); // 默认180秒(3分钟) QTimer *timer = new QTimer(combinedWidget); timer->setSingleShot(true); connect(timer, &QTimer::timeout, combinedWidget, [comboInput, moduleButton, axisButton]() { // 恢复背景颜色为默认 moduleButton->setStyleSheet("background: #FFFFFF;"); axisButton->setStyleSheet("background: #FFFFFF;"); qDebug() << "组合控件颜色已切换为默认(超时)"; }); timer->start(timeoutSec * 30); // 修正为 timeoutSec * 1000 毫秒 (3分钟) qDebug() << "启动定时器," << timeoutSec << "秒后更改组合控件颜色"; }); } moduleButton->setMenu(moduleMenu); qDebug() << "添加组合控件的模组按钮:" << fieldName; // 创建一个容器 widget 来包含组合控件 combinedLayout->addWidget(comboInput); combinedLayout->addWidget(moduleButton); combinedLayout->addWidget(axisButton); combinedLayout->addStretch(); // 保证组合控件紧凑排列 rightLayout->addWidget(combinedWidget); qDebug() << "组合控件已添加到布局:" << fieldName; } else { qWarning() << "未知字段类型:" << fieldType; } // 将 rightWidget 加到 fieldLayout 的右侧 fieldLayout->addWidget(rightWidget); qDebug() << "将 rightWidget 添加到 fieldLayout"; // 将 fieldLayout 添加到 scrollLayout scrollLayout->addLayout(fieldLayout); qDebug() << "添加字段布局:" << fieldName; } // 4. 补一个弹性伸缩,让底部也有一定空隙 scrollLayout->addStretch(); qDebug() << "添加弹性伸缩以填充底部空隙"; // 5. 将 scrollWidget 设置给 scrollArea scrollArea->setWidget(scrollWidget); qDebug() << "滚动容器已设置到 QScrollArea"; // 6. 最后将 scrollArea 放到 fieldWindow 的主布局中 QVBoxLayout *mainLayout = new QVBoxLayout(fieldWindow); mainLayout->setContentsMargins(0, 0, 0, 0); mainLayout->addWidget(scrollArea); qDebug() << "主布局已设置到 fieldWindow"; // 7. 显示窗口 fieldWindow->show(); qDebug() << "三级目录字段窗口已打开"; } void TreeViewManager::setupButton() { buttonOpenFile = new QPushButton(widget2); buttonUp = new QPushButton(widget2); buttonDown = new QPushButton(widget2); buttonLeft = new QPushButton(widget2); buttonRight = new QPushButton(widget2); // 设置 buttonOpenFile 的位置 buttonOpenFile->setParent(widget2); // 明确设置 widget2 为父级 buttonOpenFile->setMaximumSize(76, 30); buttonOpenFile->setIcon(QIcon(":/images/home_openFile.png")); buttonOpenFile->setText(""); buttonOpenFile->setGeometry(328, 16, 76, 30); // 设置按钮位置大小 buttonUp->setParent(widget2); buttonUp->setMaximumSize(36, 30); buttonUp->setIcon(QIcon(":/images/home_up.png")); buttonUp->setText(""); buttonUp->setGeometry(408, 16, 36, 30); // 位置示例 buttonDown->setParent(widget2); buttonDown->setMaximumSize(36, 30); buttonDown->setIcon(QIcon(":/images/home_down.png")); buttonDown->setText(""); buttonDown->setGeometry(408, 50, 36, 30); // 位置示例 buttonLeft->setParent(widget2); buttonLeft->setMaximumSize(36, 30); buttonLeft->setIcon(QIcon(":/images/home_left.png")); buttonLeft->setText(""); buttonLeft->setGeometry(328, 50, 36, 30); // 位置示例 buttonRight->setParent(widget2); buttonRight->setMaximumSize(36, 30); buttonRight->setIcon(QIcon(":/images/home_right.png")); buttonRight->setText(""); buttonRight->setGeometry(368, 50, 36, 30); // 位置示例 // 显示所有按钮 buttonOpenFile->show(); buttonUp->show(); buttonDown->show(); buttonLeft->show(); buttonRight->show(); } void TreeViewManager::onButtonOpenFileClicked() { foreach (QObject *child, widget2->children()) { QWidget *childWidget = qobject_cast(child); if (childWidget && childWidget->windowTitle() == "字段展示") { qDebug() << "关闭字段窗口:" << childWidget; childWidget->close(); } } treeViewDown->show(); // 显示 treeViewDown treeViewDown->collapseAll(); // 收起所有节点 treeViewDown->clearSelection(); // 展开一级目录 QStandardItem *rootItem = downModel->invisibleRootItem(); if (rootItem) { for (int i = 0; i < rootItem->rowCount(); ++i) { QStandardItem *childItem = rootItem->child(i); if (childItem) { treeViewDown->expand(downModel->indexFromItem(childItem)); qDebug() << "展开一级目录:" << childItem->text(); } } } // 重置导航栏 updateNavigationBar(QModelIndex()); qDebug() << "成功返回到一级菜单"; } void TreeViewManager::onButtonUpClicked() { qDebug() << "TreeViewManager: 向上遍历所有目录"; // 获取当前选中项索引 QModelIndex currentIndex = treeViewDown->currentIndex(); if (!currentIndex.isValid()) { qDebug() << "当前无有效索引,从最后一个根节点开始遍历"; // 从最后一个根节点开始 int lastRootRow = downModel->rowCount() - 1; if (lastRootRow >= 0) { currentIndex = downModel->index(lastRootRow, 0); treeViewDown->setCurrentIndex(currentIndex); updateNavigationBar(currentIndex); qDebug() << "当前目录:" << downModel->itemFromIndex(currentIndex)->text(); } return; } QStandardItem *currentItem = downModel->itemFromIndex(currentIndex); if (!currentItem) { qWarning() << "无法获取当前目录项"; return; } // 检查当前节点是否有上一个同级节点 QModelIndex previousSiblingIndex = currentIndex.siblingAtRow(currentIndex.row() - 1); if (previousSiblingIndex.isValid()) { // 如果有上一个同级节点,则进入该节点的最后一个子节点 qDebug() << "当前目录有上一个同级节点:" << downModel->itemFromIndex(previousSiblingIndex)->text(); QModelIndex lastChildIndex = getLastChildIndex(previousSiblingIndex); if (lastChildIndex.isValid()) { treeViewDown->setCurrentIndex(lastChildIndex); updateNavigationBar(lastChildIndex); qDebug() << "进入上一个同级节点的最后一个子节点:" << downModel->itemFromIndex(lastChildIndex)->text(); } else { treeViewDown->setCurrentIndex(previousSiblingIndex); updateNavigationBar(previousSiblingIndex); qDebug() << "进入上一个同级节点:" << downModel->itemFromIndex(previousSiblingIndex)->text(); } return; } // 如果没有上一个同级节点,返回到父节点 QModelIndex parentIndex = currentIndex.parent(); if (parentIndex.isValid()) { treeViewDown->setCurrentIndex(parentIndex); updateNavigationBar(parentIndex); qDebug() << "返回到父节点:" << downModel->itemFromIndex(parentIndex)->text(); return; } // 如果没有父节点,说明已经到达最顶部 qDebug() << "已经到达根目录顶部,无法继续向上遍历"; } // 获取最后一个子节点的索引 QModelIndex TreeViewManager::getLastChildIndex(const QModelIndex &parentIndex) { if (!parentIndex.isValid() || downModel->rowCount(parentIndex) == 0) { return QModelIndex(); // 无效索引 } // 获取最后一个子节点的索引 int lastRow = downModel->rowCount(parentIndex) - 1; QModelIndex lastChildIndex = downModel->index(lastRow, 0, parentIndex); // 如果最后一个子节点还有子节点,递归查找其最后一个子节点 QModelIndex lastGrandChildIndex = getLastChildIndex(lastChildIndex); return lastGrandChildIndex.isValid() ? lastGrandChildIndex : lastChildIndex; } void TreeViewManager::onButtonDownClicked() { qDebug() << "TreeViewManager: 向下遍历所有目录"; // 获取当前选中项索引 QModelIndex currentIndex = treeViewDown->currentIndex(); if (!currentIndex.isValid()) { qDebug() << "当前无有效索引,从第一个根节点开始遍历"; currentIndex = downModel->index(0, 0); // 从第一个根节点开始 treeViewDown->setCurrentIndex(currentIndex); updateNavigationBar(currentIndex); // 更新导航栏 qDebug() << "当前目录:" << downModel->itemFromIndex(currentIndex)->text(); return; } QStandardItem *currentItem = downModel->itemFromIndex(currentIndex); if (!currentItem) { qWarning() << "无法获取当前目录项"; return; } // 如果当前项有子节点,则进入子节点 if (currentItem->hasChildren()) { qDebug() << "当前目录有子目录,进入第一个子目录:" << currentItem->text(); treeViewDown->expand(currentIndex); // 展开当前目录 QModelIndex childIndex = downModel->index(0, 0, currentIndex); // 获取第一个子节点 if (childIndex.isValid()) { treeViewDown->setCurrentIndex(childIndex); // 进入第一个子节点 updateNavigationBar(childIndex); // 更新导航栏 qDebug() << "进入子目录:" << downModel->itemFromIndex(childIndex)->text(); return; } else { qWarning() << "当前目录有子节点但无法获取"; } } // 当前目录没有子节点,寻找同级的下一个节点 QModelIndex nextSiblingIndex = currentIndex.siblingAtRow(currentIndex.row() + 1); while (!nextSiblingIndex.isValid()) { // 如果没有下一个同级节点,向上查找父节点的下一个同级节点 QModelIndex parentIndex = currentIndex.parent(); if (!parentIndex.isValid()) { qDebug() << "已到达最底层目录,从第一个根节点重新开始遍历"; nextSiblingIndex = downModel->index(0, 0); // 回到根目录的第一个节点 break; } nextSiblingIndex = parentIndex.siblingAtRow(parentIndex.row() + 1); // 获取父节点的下一个同级节点 currentIndex = parentIndex; // 更新当前索引为父节点 } // 进入下一个节点(同级或回到根节点的第一个节点) if (nextSiblingIndex.isValid()) { treeViewDown->setCurrentIndex(nextSiblingIndex); updateNavigationBar(nextSiblingIndex); // 更新导航栏 qDebug() << "进入同级或上层同级目录:" << downModel->itemFromIndex(nextSiblingIndex)->text(); } else { qWarning() << "无法找到下一个目录节点"; } } // 获取下一个有效索引 QModelIndex TreeViewManager::getNextIndex(const QModelIndex ¤tIndex) { // 尝试获取当前项的下一个兄弟项 QModelIndex nextIndex = currentIndex.sibling(currentIndex.row() + 1, 0); if (nextIndex.isValid()) { return nextIndex; } // 如果没有兄弟项,向上找到父节点的下一个兄弟项 QModelIndex parentIndex = currentIndex.parent(); while (parentIndex.isValid()) { QModelIndex nextParentSibling = parentIndex.sibling(parentIndex.row() + 1, 0); if (nextParentSibling.isValid()) { return nextParentSibling; } parentIndex = parentIndex.parent(); // 再往上层找 } // 如果没有兄弟项或父节点兄弟项,返回无效索引 return QModelIndex(); } void TreeViewManager::onButtonLeftClicked() { qDebug() << "TreeViewManager: 返回上一级目录"; // 检查是否是三级目录字段展示窗口 bool isFieldWindowClosed = false; foreach (QObject *child, widget2->children()) { QWidget *childWidget = qobject_cast(child); if (childWidget && childWidget->windowTitle() == "字段展示") { qDebug() << "关闭三级目录窗口并返回到三级目录"; childWidget->close(); // 关闭字段展示窗口 isFieldWindowClosed = true; } } if (isFieldWindowClosed) { // 重新显示 treeViewDown 并恢复到对应的三级目录索引 treeViewDown->show(); QModelIndex currentIndex = treeViewDown->currentIndex(); if (currentIndex.isValid()) { updateNavigationBar(currentIndex); // 更新导航栏 qDebug() << "返回到三级目录索引:" << downModel->itemFromIndex(currentIndex)->text(); } else { qWarning() << "当前索引无效,无法更新导航栏"; } // **继续执行向上遍历的逻辑** QModelIndex parentIndex = currentIndex.parent(); if (parentIndex.isValid()) { treeViewDown->setCurrentIndex(parentIndex); treeViewDown->expand(parentIndex); // 确保父节点展开 updateNavigationBar(parentIndex); // 更新导航栏 QStandardItem *parentItem = downModel->itemFromIndex(parentIndex); if (parentItem) { qDebug() << "返回上一级目录:" << parentItem->text(); } else { qWarning() << "未找到父目录项"; } } else { qWarning() << "当前节点没有父节点"; } return; // 确保退出此方法,避免执行以下逻辑 } // 获取当前选中项的索引 QModelIndex currentIndex = treeViewDown->currentIndex(); if (!currentIndex.isValid()) { qDebug() << "当前无有效索引,无法返回"; return; } // 获取父节点索引 QModelIndex parentIndex = currentIndex.parent(); if (parentIndex.isValid()) { // 如果有父节点,返回到父节点 treeViewDown->setCurrentIndex(parentIndex); treeViewDown->expand(parentIndex); // 展开父节点 updateNavigationBar(parentIndex); // 更新导航栏 QStandardItem *parentItem = downModel->itemFromIndex(parentIndex); if (parentItem) { qDebug() << "返回上一级目录:" << parentItem->text(); } else { qWarning() << "未找到父目录项"; } } else { // 如果没有父节点,返回到一级目录的第一行 QModelIndex firstIndex = downModel->index(0, 0); if (firstIndex.isValid()) { treeViewDown->setCurrentIndex(firstIndex); treeViewDown->expand(firstIndex); // 展开一级目录 updateNavigationBar(firstIndex); // 更新导航栏 QStandardItem *firstItem = downModel->itemFromIndex(firstIndex); if (firstItem) { qDebug() << "返回到一级目录的第一行:" << firstItem->text(); } else { qWarning() << "未找到一级目录的第一行"; } } else { qWarning() << "无法找到任何一级目录"; } } } void TreeViewManager::onButtonRightClicked() { qDebug() << "TreeViewManager: 进入下一级目录"; // 获取当前选中项索引 QModelIndex currentIndex = treeViewDown->currentIndex(); if (!currentIndex.isValid()) { qDebug() << "当前无有效索引,自动从第一个根节点开始"; currentIndex = downModel->index(0, 0); // 从根节点第一个开始 } QStandardItem *currentItem = downModel->itemFromIndex(currentIndex); if (!currentItem) { qWarning() << "无法获取当前目录项"; return; } // 检查当前项是否有子节点 if (currentItem->hasChildren()) { qDebug() << "当前目录有子目录,展开并进入第一个子目录:" << currentItem->text(); // 展开当前项并进入第一个子项 treeViewDown->expand(currentIndex); QModelIndex childIndex = downModel->index(0, 0, currentIndex); // 使用 QAbstractItemModel::index() if (childIndex.isValid()) { treeViewDown->setCurrentIndex(childIndex); updateNavigationBar(childIndex); // 更新导航栏 qDebug() << "进入子目录:" << downModel->itemFromIndex(childIndex)->text(); return; } else { qWarning() << "展开失败:未找到子节点"; return; } } // 当前目录没有子节点,寻找同级的下一个节点 QModelIndex nextSiblingIndex = currentIndex.siblingAtRow(currentIndex.row() + 1); while (!nextSiblingIndex.isValid()) { // 如果没有下一个同级节点,向上查找父节点的下一个同级节点 QModelIndex parentIndex = currentIndex.parent(); if (!parentIndex.isValid()) { qDebug() << "已到达最底层目录,没有更多的下一级节点"; return; // 已经遍历完所有节点 } nextSiblingIndex = parentIndex.siblingAtRow(parentIndex.row() + 1); currentIndex = parentIndex; } // 进入下一个同级节点 treeViewDown->setCurrentIndex(nextSiblingIndex); updateNavigationBar(nextSiblingIndex); // 更新导航栏 qDebug() << "进入同级目录:" << downModel->itemFromIndex(nextSiblingIndex)->text(); }