#include "DbTreeViewManager.h" #include "OriginalWnd/OriginalWnd.h" #include "OriginalWnd/NonInteractiveCheckDelegate.h" #include #include #include // 构造函数 DbTreeViewManager::DbTreeViewManager(OriginalWnd* originalWnd, QWidget* widget2, QWidget* parent) : QWidget(parent), m_originalWnd(originalWnd), widget2(widget2), treeViewDown(new QTreeView(this)), model(new QStandardItemModel(this)), restoring(false), m_blockItemChanged(false) { if (!widget2) { // qWarning() << "DbTreeViewManager: widget2 未初始化"; return; } // 设置模型 treeViewDown->setModel(model); treeViewDown->setHeaderHidden(true); treeViewDown->setEditTriggers(QAbstractItemView::NoEditTriggers); // 设置树视图的几何位置 treeViewDown->setGeometry(16, 106, widget2->width() - 16, widget2->height() - 106); // 安装事件过滤器以自定义绘制虚线 treeViewDown->viewport()->installEventFilter(this); // 创建统一分隔线 lineFrame1 = createUnifiedSeparator(widget2, 2); lineFrame1->setGeometry(16, 100, 460, 2); // 创建按钮并设置布局 setupButton(); // 创建导航栏 navigationWidget = new QWidget(widget2); navigationWidget->setGeometry(15, 15, 300, 74); // 连接目录前的复选框信号与槽 connect(model, &QStandardItemModel::itemChanged, this, &DbTreeViewManager::onItemChanged); // 目录树连接点击信号 connect(treeViewDown, &QTreeView::clicked, this, &DbTreeViewManager::onTreeViewClicked); // 连接目录 expanded 和 collapsed 信号 connect(treeViewDown, &QTreeView::expanded, this, [=](const QModelIndex &index) { QStandardItem *item = model->itemFromIndex(index); if (!item) return; QStringList path = buildItemPath(item); expandedPaths.insert(path.join("/")); updateSeparatorLine(); // 保存展开路径 saveExpandedPaths(); }); connect(treeViewDown, &QTreeView::collapsed, this, [=](const QModelIndex &index) { QStandardItem *item = model->itemFromIndex(index); if (!item) return; QStringList path = buildItemPath(item); expandedPaths.remove(path.join("/")); updateSeparatorLine(); // 保存展开路径 saveExpandedPaths(); }); // 所有展开操作完成后更新分隔线 QTimer::singleShot(0, this, [=]() { QStandardItem *rootItem = model->invisibleRootItem(); QStandardItem *thirdItem = findFirstThirdLevelItemDFS(rootItem); if (thirdItem) { QJsonObject thirdLevelObj = thirdItem->data(Qt::UserRole + 2).toJsonObject(); if (thirdLevelObj.contains("IsThirdLevel") && thirdLevelObj["IsThirdLevel"].toBool()) { loadButtonConfigForThirdLevel(thirdLevelObj); } } }); // 应用自定义只读复选框委托 treeViewDown->setItemDelegate(new NonInteractiveCheckDelegate(treeViewDown)); menuArray[0] = {2, false,-1}; menuArray[1] = {5, false,-1}; menuArray[2] = {3, false,-1}; menuArray[3] = {4, false,-1}; menuArray[4] = {6, false,-1}; currentMenuId = -1; } DbTreeViewManager::~DbTreeViewManager() { } // 创建横线样式 QFrame* DbTreeViewManager::createUnifiedSeparator(QWidget *parent, int height) { QFrame *separator = new QFrame(parent); separator->setFrameShape(QFrame::NoFrame); // 移除默认框架 separator->setFixedHeight(height); // 设置固定高度 separator->setStyleSheet("background-color: #C7CAEB;"); separator->hide(); // 初始化为隐藏 return separator; } // 目录树样式 void DbTreeViewManager::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; } /* 设置项目选中的背景色 */ QTreeView::item:selected { background-color: #A9B4FF; } /* 设置项目的行间距 */ QTreeView::item { padding-top: 5px; /* 上边距 */ padding-bottom: 5px; /* 下边距 */ } )"); } // 检查权限 bool DbTreeViewManager::hasPrivilege(const int &UserGrade, const int &userPrivilege) { bool hasPriv; // UserGrade 是以逗号分隔的字符串,如 "1,2,3" if(UserGrade==userPrivilege){ hasPriv = true; }else{ hasPriv = false; } // qDebug() << "Checking privilege. UserGrade:" << UserGrade << "userPrivilege:" << userPrivilege << "result:" << hasPriv; return hasPriv; } void DbTreeViewManager::updateDb(const QString &TableName, const int &Id,const QString currentValue){ QSqlDatabase db = QSqlDatabase::database(); if (!db.isOpen()) { qWarning() << "数据库未打开"; } QString sql = QString("UPDATE %1 SET currentValue = :newValue WHERE id = :id").arg(TableName); QSqlQuery query; query.prepare(sql); query.bindValue(":newValue", currentValue); query.bindValue(":id", Id); // 执行更新操作 if (!query.exec()) { qWarning() << "Failed to update currentValue:" << query.lastError().text(); } else { qDebug() << "currentValue updated successfully."; } } void DbTreeViewManager::initializeTree(int configId, const int &userPrivilege) { qDebug() << "Initializing tree with configId:" << configId << "and userPrivilege:" << userPrivilege; m_currentConfigId = configId; // 设置当前配置ID // 先清空历史 clearHistory(); // 保存之前的选中/展开状态 m_blockItemChanged = true; restoring = true; // 清理当前的分隔线 clearAllSeparators(); // 清空已有模型数据和相关记录 model->clear(); firstLevelSeparators.clear(); expandedPaths.clear(); // 清理并隐藏三级目录窗口 clearThirdLevelMenu(); // **Home 界面逻辑** if (configId == 1) { // 隐藏目录树和分隔线 treeViewDown->hide(); for (auto separator : firstLevelSeparators) { if (separator) separator->hide(); } // 隐藏导航栏 navigationWidget->hide(); // 隐藏按钮 updateButtonsVisibility(); // 将按钮隐藏 // 隐藏特定的分隔线 lineFrame1 if (lineFrame1) { lineFrame1->hide(); } // 从 BondHead 和 Buttons 表中加载 DirectoryId = 1 的数据 QJsonObject data = fetchThirdLevelData(1, userPrivilege); displayThirdLevelFields(data, true); // 传递参数表示 Home 界面 // 把当前页面压到 m_backStack 里 PageState st; st.path << "Home"; st.isThirdLevel = true; st.directoryId = 1; m_backStack.append(st); if(m_backStack.size() >= 2){ buttonLeft->setIcon(QIcon(":/images/home_left.png")); } } else { // **其他配置逻辑** // 设置 treeViewDown 的几何位置 treeViewDown->setGeometry(16, 106, widget2->width() - 16, widget2->height() - 106); // 显示目录树和分隔线 treeViewDown->show(); for (auto separator : firstLevelSeparators) { if (separator) separator->show(); } // 应用自定义样式 applyCustomStyles(); // 显示导航栏 navigationWidget->show(); // 显示按钮 updateButtonsVisibility(); // 显示特定的分隔线 lineFrame1 if (lineFrame1) { lineFrame1->show(); } // 加载目录数据 并进行权限判断 loadDirectories(configId, userPrivilege); // 更新分隔线 updateSeparatorLine(); m_blockItemChanged = false; restoring = false; // qDebug() << "Tree initialization completed."; // 恢复展开路径 loadExpandedPaths(); // 恢复复选框状态 loadCheckedPaths(); // 自动选中第一个根目录项并更新导航栏 QStandardItem *rootItem = model->invisibleRootItem()->child(0); if (rootItem) { QModelIndex rootIndex = model->indexFromItem(rootItem); treeViewDown->setCurrentIndex(rootIndex); updateNavigationBar(rootIndex); // 如果当前根目录是三级目录,则加载其字段内容 QVariant dataVar = rootItem->data(Qt::UserRole + 2).toJsonObject(); bool isThirdLevel = false; int directoryId = -1; if (dataVar.canConvert()) { QJsonObject thirdLevelObj = dataVar.toJsonObject(); if (thirdLevelObj.contains("IsThirdLevel") && thirdLevelObj["IsThirdLevel"].toBool()) { isThirdLevel = true; if (thirdLevelObj.contains("Id")) { directoryId = thirdLevelObj["Id"].toInt(); } } } if (isThirdLevel) { if (directoryId == -1) { // qWarning() << "无效的 DirectoryId,无法加载第三层目录内容。"; return; } // userPrivilege 同样传递 QJsonObject data = fetchThirdLevelData(directoryId, userPrivilege); displayThirdLevelFields(data, false); // 传递参数表示非 Home 界面 // 把当前状态压入 m_backStack PageState st; st.path = buildItemPath(rootItem); st.isThirdLevel = true; st.directoryId = directoryId; m_backStack.append(st); if(m_backStack.size() >= 2){ buttonLeft->setIcon(QIcon(":/images/home_left.png")); } } } else { // qWarning() << "树形模型中没有根目录项。"; } // 自动找第一个三级目录 QStandardItem *rootItem1 = model->invisibleRootItem(); QStandardItem *firstThirdItem = findFirstThirdLevelItemDFS(rootItem1); if (!firstThirdItem) { // qDebug() << "[initializeTree] No third-level item found, do nothing."; return; } // QStandardItem 里获取它的目录信息 QVariant dataVar = firstThirdItem->data(Qt::UserRole + 2); if (!dataVar.canConvert()) { // qWarning() << "[initializeTree] firstThirdItem->data 无法转换为 QJsonObject"; return; } QJsonObject dirObj = dataVar.toJsonObject(); if (!dirObj.contains("Id")) { // qWarning() << "[initializeTree] 第一个三级目录无 Id 字段,无法加载"; return; } int directoryId = dirObj["Id"].toInt(); // 数据库BondHead/Buttons QJsonObject data = fetchThirdLevelData(directoryId, userPrivilege); if (!data.contains("buttons")) { // 第三层没有 buttons 字段 qWarning() << "[initializeTree] fetchThirdLevelData: no 'buttons', skip"; return; } // singleShot 在所有展开操作完成后更新分隔线 QTimer::singleShot(0, this, &DbTreeViewManager::updateSeparatorLine); // loadButtonConfigForThirdLevel 显示按钮 loadButtonConfigForThirdLevel(data); } } // 从数据库加载目录 包含权限判断 void DbTreeViewManager::loadDirectories(int configId, const int &userPrivilege) { // qDebug() << "Loading directories for configId:" << configId << "with userPrivilege:" << userPrivilege; QSqlDatabase db = QSqlDatabase::database(); if (!db.isOpen()) { qWarning() << "数据库未打开"; return; } QSqlQuery query(db); query.prepare(R"( SELECT Id, Name, ParentId, IsThirdLevel, Separator, UserGrade, Circle FROM Directories WHERE ConfigId = :configId )"); query.bindValue(":configId", configId); if (!query.exec()) { qWarning() << "查询 Directories 失败:" << query.lastError().text(); return; } // 以 QJsonObject 保存所有目录 QList directories; while (query.next()) { QJsonObject obj; int id = query.value("Id").toInt(); obj["Id"] = id; obj["Name"] = query.value("Name").toString(); obj["ParentId"] = query.value("ParentId").isNull() ? -1 : query.value("ParentId").toInt(); obj["IsThirdLevel"] = query.value("IsThirdLevel").toBool(); obj["Separator"] = query.value("Separator").toInt(); obj["UserGrade"] = query.value("UserGrade").toString(); obj["Circle"] = query.value("Circle").toInt(); qDebug() << "加载目录:"<< obj["Name"].toString() << " ParentId:" << obj["ParentId"].toInt()<< " Separator:" << obj["Separator"].toInt(); qDebug() << " Circle:" << obj["Circle"].toInt(); // 权限判断:只有当记录的 UserGrade 中包含当前用户权限时才加入 bool ok; if (hasPrivilege(obj["UserGrade"].toString().toInt(&ok,16), userPrivilege)) directories.append(obj); else qDebug() << "目录跳过(权限不足):" << obj["Name"].toString(); } // qDebug() << "Loaded directories count:" << directories.size(); // 根据目录列表构建树模型 buildTreeFromDirectories(directories); } void DbTreeViewManager::buildTreeFromDirectories(const QList &directories) { // 建立 Id->QStandardItem 的映射 QMap idItemMap; for (const QJsonObject &dir : directories) { QStandardItem *item = new QStandardItem(dir["Name"].toString()); item->setData(dir["Id"].toInt(), Qt::UserRole + 1); // 保存目录Id // 如果是三级目录,将整个 JSON 对象存到 UserRole+2 if (dir["IsThirdLevel"].toBool()) { item->setData(dir, Qt::UserRole + 2); } else { item->setData(false, Qt::UserRole + 2); // 标记为非三级目录 } item->setCheckable(true); // 复选框状态由程序逻辑设置 item->setCheckState(Qt::Unchecked); idItemMap.insert(dir["Id"].toInt(), item); } // 建立父子关系 for (const QJsonObject &dir : directories) { int parentId = dir["ParentId"].toInt(); int currentId = dir["Id"].toInt(); QStandardItem *childItem = idItemMap.value(currentId); if (parentId == -1) { // 说明这是一级目录 model->invisibleRootItem()->appendRow(childItem); // 如果一级目录的 "Separator" == 1,则为其创建一条分割线 if (dir["Separator"].toInt() == 1) { QFrame *sep = createUnifiedSeparator(widget2, 2); sep->hide(); firstLevelSeparators.insert(childItem, sep); } } else { // 非一级目录 => 子目录 QStandardItem *parentItem = idItemMap.value(parentId); if (parentItem) parentItem->appendRow(childItem); else qWarning() << "无法找到 ParentId:" << parentId << "的父目录项"; } } } // 查询三级目录下的 BondHead 和 Buttons 数据 均判断权限 QJsonObject DbTreeViewManager::fetchThirdLevelData(int directoryId, const int &userPrivilege) { QJsonObject data; QJsonArray fieldsArray; QJsonArray buttonsArray; QString temp; bool allChangeFlag = true; // 默认所有 ChangeFlag 为 true QSqlDatabase db = QSqlDatabase::database(); if (!db.isOpen()) { qWarning() << "数据库未打开"; return data; } // 查询 TableName 表 QSqlQuery queryBondtest(db); queryBondtest.prepare(R"( SELECT TableName FROM Directories WHERE Id = :dirId )"); queryBondtest.bindValue(":dirId",directoryId); if (queryBondtest.exec()) { while (queryBondtest.next()) { temp = queryBondtest.value("TableName").toString(); } } QStringList tableName = temp.split(","); QString currentTableName; for (const QString &item : tableName) { if (item.isEmpty()) { qDebug() << "Encountered an empty string, stopping traversal."; break; // 遇到空字符串时退出循环 }else{ currentTableName = item; QString sql = QString("SELECT Id, DirectoryId, Describe, Type, Value,CurrentValue,UpLimit,DownLimit,units, Groupld, UserGrade, ChangeFlag FROM %1 WHERE DirectoryId = :dirId").arg(currentTableName); // 查询 BondHead 表 QSqlQuery queryBond(db); queryBond.prepare(sql); queryBond.bindValue(":dirId", directoryId); if (queryBond.exec()) { while (queryBond.next()) { bool ok; int dbUserGrade = queryBond.value("UserGrade").toString().toInt(&ok, 16); // 只有当数据库记录的 UserGrade 包含当前用户权限时才加载该字段 if (!hasPrivilege(dbUserGrade, userPrivilege)) continue; QJsonObject field; field["Id"] = queryBond.value("Id").toInt(); field["DirectoryId"] = queryBond.value("DirectoryId").toInt(); field["Describe"] = queryBond.value("Describe").toString(); field["Type"] = queryBond.value("Type").toString(); field["Value"] = queryBond.value("Value").toString(); field["CurrentValue"] = queryBond.value("CurrentValue").toString(); field["UpLimit"] = queryBond.value("UpLimit").toString(); field["DownLimit"] = queryBond.value("DownLimit").toString(); field["units"] = queryBond.value("units").toString(); field["Groupld"] = queryBond.value("Groupld").toInt(); field["ChangeFlag"] = queryBond.value("ChangeFlag").toInt(); field["TableName"] = currentTableName; fieldsArray.append(field); // 如果有任一字段 ChangeFlag 为 0,则 allChangeFlag = false if (queryBond.value("ChangeFlag").toInt() == 0) allChangeFlag = false; } // qDebug() << "Fetched fields:" << fieldsArray; } else { qWarning() << "查询 BondHead 失败:" << queryBond.lastError().text(); } } } //QString sql = QString("SELECT Id, DirectoryId, Describe, Type, Value,units, Groupld, UserGrade, ChangeFlag FROM %1 WHERE DirectoryId = :dirId").arg(currentTableName); // // 查询 BondHead 表 // QSqlQuery queryBond(db); // queryBond.prepare(sql); // queryBond.bindValue(":dirId", directoryId); // if (queryBond.exec()) { // while (queryBond.next()) { // bool ok; // int dbUserGrade = queryBond.value("UserGrade").toString().toInt(&ok, 16); // // 只有当数据库记录的 UserGrade 包含当前用户权限时才加载该字段 // if (!hasPrivilege(dbUserGrade, userPrivilege)) // continue; // QJsonObject field; // field["Id"] = queryBond.value("Id").toInt(); // field["DirectoryId"] = queryBond.value("DirectoryId").toInt(); // field["Describe"] = queryBond.value("Describe").toString(); // field["Type"] = queryBond.value("Type").toString(); // field["Value"] = queryBond.value("Value").toString(); // field["units"] = queryBond.value("units").toString(); // field["Groupld"] = queryBond.value("Groupld").toInt(); // field["ChangeFlag"] = queryBond.value("ChangeFlag").toInt(); // fieldsArray.append(field); // // 如果有任一字段 ChangeFlag 为 0,则 allChangeFlag = false // if (queryBond.value("ChangeFlag").toInt() == 0) // allChangeFlag = false; // } // // qDebug() << "Fetched fields:" << fieldsArray; // } else { // qWarning() << "查询 BondHead 失败:" << queryBond.lastError().text(); // } // 查询 Buttons 表 QSqlQuery queryBtn(db); queryBtn.prepare(R"( SELECT ButtonId, Icon, Text, Enabled, UserGrade FROM Buttons WHERE DirectoryId = :dirId )"); queryBtn.bindValue(":dirId", directoryId); if (queryBtn.exec()) { while (queryBtn.next()) { bool ok; int btnUserGrade = queryBtn.value("UserGrade").toString().toInt(&ok, 16); if (!hasPrivilege(btnUserGrade, userPrivilege)) continue; QJsonObject button; button["id"] = queryBtn.value("ButtonId").toString(); button["icon"] = queryBtn.value("Icon").toString(); button["text"] = queryBtn.value("Text").toString(); button["enabled"] = queryBtn.value("Enabled").toBool(); buttonsArray.append(button); } // qDebug() << "Fetched buttons:" << buttonsArray; } else { qWarning() << "查询 Buttons 失败:" << queryBtn.lastError().text(); } data["fields"] = fieldsArray; data["buttons"] = buttonsArray; data["IsThirdLevel"] = true; data["allChangeFlag"] = allChangeFlag; return data; } // 事件过滤器,用于自定义绘制虚线 bool DbTreeViewManager::eventFilter(QObject *watched, QEvent *event) { // 拦截 Paint 事件 if (watched == treeViewDown->viewport() && event->type() == QEvent::Paint) { // 进行默认绘制 bool handled = QWidget::eventFilter(watched, event); // 使用 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(); return handled; } // 其余事件交给父类默认处理 return QWidget::eventFilter(watched, event); } // 递归绘制所有分支 void DbTreeViewManager::paintAllBranches(const QModelIndex &parentIndex, QPainter &painter) { int rowCount = model->rowCount(parentIndex); for(int i = 0; i < rowCount; ++i) { // 当前子节点 QModelIndex childIndex = model->index(i, 0, parentIndex); if (!childIndex.isValid()) continue; // 1) 父->子拐角线 drawParentChildLine(childIndex, painter); // 2) 兄弟延续竖线(如果本节点不是最后一个兄弟,就在拐点列画条向下的线) if (i < rowCount - 1) { drawSiblingLine(childIndex, painter); } // 3) 递归处理子节点 paintAllBranches(childIndex, painter); } } // 在“父节点 -> 子节点”间画一条“L”型拐角线,调整横向线段的长度 void DbTreeViewManager::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; // 绘制竖线 painter.drawLine(QPoint(branchX, rootY), QPoint(branchX, childRect.center().y())); // 计算新的横线终点 int newX = childRect.left() + hOffset; // 绘制横线 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; // 绘制竖线 painter.drawLine(QPoint(branchX, pMidY), QPoint(branchX, cMidY)); // 计算新的横线终点 int newX = childRect.left() + hOffset; // 绘制横线 painter.drawLine(QPoint(branchX, cMidY), QPoint(newX, cMidY)); } // 节点下面还有兄弟,则在拐点列那里继续往下画竖线 void DbTreeViewManager::drawSiblingLine(const QModelIndex &childIndex, QPainter &painter) { QModelIndex parentIndex = childIndex.parent(); if (!parentIndex.isValid()) { return; // 没有父节点 } // 下一个兄弟 int row = childIndex.row(); int lastRow = model->rowCount(parentIndex) - 1; if (row >= lastRow) { return; // 说明是最后一个兄弟,不用画延伸线 } QModelIndex nextSibling = model->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)); } // 递归查找第一个三级目录项 QStandardItem* DbTreeViewManager::findFirstThirdLevelItemDFS(QStandardItem *parentItem) { if (!parentItem) { return nullptr; } // 遍历当前 parentItem 的所有子 for (int i = 0; i < parentItem->rowCount(); ++i) { QStandardItem *child = parentItem->child(i); if (!child) continue; // 检查这个子节点是否是三级目录 QVariant data = child->data(Qt::UserRole + 2); if (data.canConvert()) { QJsonObject obj = data.toJsonObject(); if (obj.contains("IsThirdLevel") && obj["IsThirdLevel"].toBool()) { // 找到第一个 IsThirdLevel = true 的节点就返回 return child; } } // 如果不是 IsThirdLevel,继续往子节点里找 QStandardItem* deeperFound = findFirstThirdLevelItemDFS(child); if (deeperFound) { return deeperFound; } } return nullptr; } void DbTreeViewManager::onItemChanged(QStandardItem *item) { if (m_blockItemChanged || restoring) { return; // 防止递归和恢复期间触发 } m_blockItemChanged = true; Qt::CheckState state = item->checkState(); // 更新所有子项的复选框状态 for (int i = 0; i < item->rowCount(); ++i) { QStandardItem *child = item->child(i); if (child) { child->setCheckState(state); // 递归更新子项 onItemChanged(child); } } // 更新所有父项的复选框状态 QModelIndex parentIndex = item->index().parent(); while (parentIndex.isValid()) { QStandardItem *parentItem = model->itemFromIndex(parentIndex); if (!parentItem) break; int checkedCount = 0; int totalCount = parentItem->rowCount(); for (int i = 0; i < totalCount; ++i) { QStandardItem *child = parentItem->child(i); if (child && child->checkState() == Qt::Checked) { checkedCount++; } } if (checkedCount == totalCount) { parentItem->setCheckState(Qt::Checked); } else { parentItem->setCheckState(Qt::Unchecked); } parentIndex = parentIndex.parent(); } m_blockItemChanged = false; // 记录复选框状态 saveCheckedPaths(); } // 初始化和设置按钮 void DbTreeViewManager::setupButton() { // 创建按钮并设置属性 auto createButton = [&](QPushButton*& button, const QString& iconPath, const QRect& geometry) { button = new QPushButton(this); button->setIcon(QIcon(iconPath)); button->setGeometry(geometry); button->setStyleSheet(R"( QPushButton { position: absolute; border-radius: 6px; opacity: 1; background: #FFFFFF; border: 1px solid #BABBDC; } QPushButton:hover { background-color: #A9B4FF; /* 鼠标悬停效果 */ } )"); button->show(); }; // 根据原始代码调整按钮的位置和大小 createButton(ButtonBack, ":/images/home_openFile.png", QRect(328, 6, 76, 30)); createButton(buttonUp, ":/images/home_up.png", QRect(408, 6, 36, 30)); createButton(buttonDown, ":/images/home_down.png", QRect(408, 40, 36, 30)); createButton(buttonLeft, ":/images/home_left_hide.png", QRect(328, 40, 36, 30)); createButton(buttonRight, ":/images/home_right.png", QRect(368, 40, 36, 30)); // 连接按钮的点击信号到相应的槽函数 connect(ButtonBack, &QPushButton::clicked, this, &DbTreeViewManager::onButtonBackClicked); connect(buttonUp, &QPushButton::clicked, this, &DbTreeViewManager::onButtonUpClicked); connect(buttonDown, &QPushButton::clicked, this, &DbTreeViewManager::onButtonDownClicked); connect(buttonLeft, &QPushButton::clicked, this, &DbTreeViewManager::onButtonLeftClicked); connect(buttonRight, &QPushButton::clicked, this, &DbTreeViewManager::onButtonRightClicked); } void DbTreeViewManager::updateButtonsVisibility() { if (m_currentConfigId == 1) { // Home 界面,隐藏所有按钮 ButtonBack->hide(); buttonUp->hide(); buttonDown->hide(); buttonLeft->hide(); buttonRight->hide(); } else { // 其他配置,显示所有按钮 ButtonBack->show(); buttonUp->show(); buttonDown->show(); buttonLeft->show(); buttonRight->show(); } } QStandardItem* DbTreeViewManager::deepCopyItem(const QStandardItem *item){ if (!item) { return nullptr; } // 创建一个新的 QStandardItem QStandardItem *newItem = new QStandardItem(item->text()); newItem->setIcon(item->icon()); newItem->setToolTip(item->toolTip()); newItem->setEditable(item->isEditable()); newItem->setCheckable(item->isCheckable()); newItem->setCheckState(item->checkState()); // 递归复制子项 for (int i = 0; i < item->rowCount(); ++i) { QStandardItem *childItem = item->child(i); QStandardItem *newChildItem = deepCopyItem(childItem); newItem->appendRow(newChildItem); } return newItem; } void DbTreeViewManager::loadpage(const int &configId){ for(int i=0;i<5;i++){ if(configId == menuArray[i].menuId){ QJsonObject data = fetchThirdLevelData(menuArray[i].index, 0x1); displayThirdLevelFields(data, false); } } } void DbTreeViewManager::onTreeViewClicked(const QModelIndex &index) { QStandardItem *item = model->itemFromIndex(index); if (!item) return; // 是否第三层 bool isThird = false; int dirId = -1; QVariant dataVar = item->data(Qt::UserRole + 2); if (dataVar.canConvert()) { QJsonObject obj = dataVar.toJsonObject(); if (obj.contains("IsThirdLevel") && obj["IsThirdLevel"].toBool()) { isThird = true; if (obj.contains("Id")) { dirId = obj["Id"].toInt(); } } } updateNavigationBar(index); if (isThird) { int userPrivilege = 0x1; // 示例 if (dirId < 0) { qWarning() << "无效directoryId"; return; } QJsonObject data = fetchThirdLevelData(dirId, userPrivilege); displayThirdLevelFields(data, false); for(int i=0;i<5;i++){ if(currentMenuId == menuArray[i].menuId){ menuArray[i].isthird = true; menuArray[i].index = dirId; } } // 将“新页面”压入后退栈, 并清空前进栈 PageState st; st.path = buildItemPath(item); st.isThirdLevel = true; st.directoryId = dirId; m_backStack.append(st); if(m_backStack.size() >= 2){ buttonLeft->setIcon(QIcon(":/images/home_left.png")); } m_forwardStack.clear(); buttonRight->setIcon(QIcon(":/images/home_right.png")); } else { // 不是第三层,只是选中目录 // 清理第三层窗口 if (m_thirdLevelFieldWnd) { m_thirdLevelFieldWnd->close(); m_thirdLevelFieldWnd->deleteLater(); m_thirdLevelFieldWnd = nullptr; } // 同样更新历史 PageState st; st.path = buildItemPath(item); st.isThirdLevel = false; st.directoryId = -1; m_backStack.append(st); if(m_backStack.size() >= 2){ buttonLeft->setIcon(QIcon(":/images/home_left.png")); } m_forwardStack.clear(); buttonRight->setIcon(QIcon(":/images/home_right.png")); } } void DbTreeViewManager::onTreeViewClicked_updown(const QModelIndex &index){ QStandardItem *item = model->itemFromIndex(index); if (!item) return; // 是否第三层 bool isThird = false; int dirId = -1; QVariant dataVar = item->data(Qt::UserRole + 2); if (dataVar.canConvert()) { QJsonObject obj = dataVar.toJsonObject(); if (obj.contains("IsThirdLevel") && obj["IsThirdLevel"].toBool()) { isThird = true; if (obj.contains("Id")) { dirId = obj["Id"].toInt(); } } } updateNavigationBar(index); if (isThird) { int userPrivilege = 0x1; // 示例 if (dirId < 0) { qWarning() << "无效directoryId"; return; } QJsonObject data = fetchThirdLevelData(dirId, userPrivilege); displayThirdLevelFields(data, false); // 将“新页面”压入后退栈, 并清空前进栈 PageState st; st.path = buildItemPath(item); st.isThirdLevel = true; st.directoryId = dirId; m_backStack.append(st); if(m_backStack.size() >= 2){ buttonLeft->setIcon(QIcon(":/images/home_left.png")); } m_forwardStack.clear(); buttonRight->setIcon(QIcon(":/images/home_right.png")); } else { // 不是第三层,只是选中目录 // 清理第三层窗口 if (m_thirdLevelFieldWnd) { m_thirdLevelFieldWnd->close(); m_thirdLevelFieldWnd->deleteLater(); m_thirdLevelFieldWnd = nullptr; } // 同样更新历史 PageState st; st.path = buildItemPath(item); st.isThirdLevel = false; st.directoryId = -1; m_backStack.append(st); if(m_backStack.size() >= 2){ buttonLeft->setIcon(QIcon(":/images/home_left.png")); } m_forwardStack.clear(); buttonRight->setIcon(QIcon(":/images/home_right.png")); } } void DbTreeViewManager::updateNavigationBar(const QModelIndex &index) { QStandardItem *item = model->itemFromIndex(index); if (!item) { qWarning() << "导航栏更新失败:未找到对应项"; return; } // 清理现有布局 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) { path.prepend(temp); // 从根节点开始 temp = temp->parent(); } QVBoxLayout *newLayout = new QVBoxLayout; // 创建新的导航栏布局 newLayout->setContentsMargins(0, 0, 3, 3); 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(14); font.setFamily("思源黑体"); font.setBold(true); // 设置文字为粗体 font.setLetterSpacing(QFont::PercentageSpacing,105); // 设置字间距100%为默认 label->setFont(font); label->setFixedHeight(navigationWidget->height() / 3); newLayout->addWidget(label); } // 设置布局并更新导航栏 navigationWidget->setLayout(newLayout); navigationWidget->update(); } void DbTreeViewManager::clearAllSeparators() { // 遍历 firstLevelSeparators 中所有 QFrame, // 隐藏后调用 deleteLater() for (auto separator : firstLevelSeparators.values()) { if(separator) { separator->hide(); separator->deleteLater(); } } // 清空映射 firstLevelSeparators.clear(); } void DbTreeViewManager::updateSeparatorLine() { // 如果目录树被隐藏,就把分割线都藏起来 if (!treeViewDown->isVisible()) { for (auto it = firstLevelSeparators.begin(); it != firstLevelSeparators.end(); ++it) { QFrame *sep = it.value(); if (sep) sep->hide(); } return; } // 遍历所有“一级目录”与其分隔线 for (auto it = firstLevelSeparators.begin(); it != firstLevelSeparators.end(); ++it) { QStandardItem *firstLevelItem = it.key(); QFrame *separator = it.value(); if (!firstLevelItem || !separator) continue; // 拿到可视区域 QModelIndex firstLevelIndex = model->indexFromItem(firstLevelItem); QRect firstLevelRect = treeViewDown->visualRect(firstLevelIndex); // 如果这个一级目录滚动到看不见了,就把分割线也藏起来 if (!firstLevelRect.isValid()) { separator->hide(); continue; } // 如果展开并且它有子节点,就找“最后一个可见子项” if (treeViewDown->isExpanded(firstLevelIndex) && firstLevelItem->hasChildren()) { QModelIndex lastVisibleChild = findLastVisibleChild(firstLevelIndex); if (lastVisibleChild.isValid()) { QRect lastChildRect = treeViewDown->visualRect(lastVisibleChild); if (lastChildRect.isValid()) { // 将分割线放在最后一个子项下面 separator->setGeometry(16,lastChildRect.bottom() + 115,widget2->width() - 40,1); separator->show(); continue; } } } // 如果收起或找不到可见子项,就放在本一级目录下面 separator->setGeometry(16,firstLevelRect.bottom() + 115,widget2->width() - 40,1); separator->show(); } } QModelIndex DbTreeViewManager::findLastVisibleChild(const QModelIndex &parentIndex) { if (!parentIndex.isValid()) return QModelIndex(); int childCount = model->rowCount(parentIndex); QModelIndex lastVisible; for (int i = childCount - 1; i >= 0; --i) { QModelIndex childIndex = model->index(i, 0, parentIndex); if (!treeViewDown->isRowHidden(i, parentIndex)) { if (treeViewDown->isExpanded(childIndex) && model->rowCount(childIndex) > 0) { QModelIndex deeper = findLastVisibleChild(childIndex); if (deeper.isValid()) { return deeper; } } lastVisible = childIndex; break; } } return lastVisible; } void DbTreeViewManager::displayThirdLevelFields(const QJsonObject &data, bool isHome) { if (data.isEmpty()) { qWarning() << "字段数据为空,无法显示"; return; } if (!data.contains("IsThirdLevel") || !data["IsThirdLevel"].toBool()) { qWarning() << "不是三级目录,跳过按钮加载"; return; } bool allChangeFlag = false; if (data.contains("allChangeFlag") && data["allChangeFlag"].isBool()) { allChangeFlag = data["allChangeFlag"].toBool(); } else { qWarning() << "数据中缺少 'allChangeFlag' 字段或类型不正确"; } // 若已有第三层窗口,先关闭并释放 if (m_thirdLevelFieldWnd) { m_thirdLevelFieldWnd->close(); m_thirdLevelFieldWnd->deleteLater(); m_thirdLevelFieldWnd = nullptr; } // 获取当前选中的目录项,设置状态 QModelIndex currentIndex = treeViewDown->currentIndex(); if (currentIndex.isValid()) { QStandardItem* currentItem = model->itemFromIndex(currentIndex); if (currentItem) { currentItem->setCheckState(allChangeFlag ? Qt::Checked : Qt::Unchecked); qDebug() << "设置当前目录项复选框状态为:" << (allChangeFlag ? "Checked" : "Unchecked"); } } else { qWarning() << "当前没有选中的目录项"; } // 隐藏目录树及所有分隔线 treeViewDown->hide(); for (auto separator : firstLevelSeparators) { if (separator) separator->hide(); } // 显示按钮 loadButtonConfigForThirdLevel(data); // 清理之前的控件列表 m_fieldWidgets.clear(); // 创建新的 "字段展示" 窗口,并赋值给 m_thirdLevelFieldWnd m_thirdLevelFieldWnd = new QWidget(widget2); m_thirdLevelFieldWnd->setWindowTitle("字段展示"); m_thirdLevelFieldWnd->setStyleSheet("background-color: transparent;"); if (isHome) { // Home 界面,填满 widget2 m_thirdLevelFieldWnd->setGeometry(0, 0, widget2->width(), widget2->height()); } else { // 其他配置界面,设置与 treeViewDown 相同的几何位置 m_thirdLevelFieldWnd->setGeometry(treeViewDown->geometry()); } // 创建滚动区域 QScrollArea *scrollArea = new QScrollArea(m_thirdLevelFieldWnd); scrollArea->setWidgetResizable(true); scrollArea->setHorizontalScrollBarPolicy(Qt::ScrollBarAsNeeded); // 创建滚动容器并设置布局 QWidget *scrollWidget = new QWidget; scrollWidget->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred); QVBoxLayout *scrollLayout = new QVBoxLayout(scrollWidget); scrollLayout->setSpacing(10); scrollLayout->setContentsMargins(10, 10, 10, 10); int previousGroupId = -1; // 遍历字段数组 if (data.contains("fields") && data["fields"].isArray()) { QJsonArray fields = data["fields"].toArray(); for (const QJsonValue &val : fields) { QJsonObject field = val.toObject(); int fieldId = field["Id"].toInt(); QString fieldName = field["Describe"].toString(); QString fieldType = field["Type"].toString(); QString fieldValue = field["Value"].toString(); QString fieldCurrentValue = field["CurrentValue"].toString(); QString fieldTableName = field["TableName"].toString(); QString fieldUpLimit = field["UpLimit"].toString(); QString fieldDownLimit = field["DownLimit"].toString(); QString fieldUnits = field["units"].toString(); int groupId = field["Groupld"].toInt(); // 如果组变化,插入分隔线 if (previousGroupId != -1 && groupId != previousGroupId) { QFrame *separator = createUnifiedSeparator(scrollWidget, 2); QHBoxLayout *separatorLayout = new QHBoxLayout; separatorLayout->setContentsMargins(0, 5, 0, 5); separatorLayout->addWidget(separator); scrollLayout->addLayout(separatorLayout); separator->show(); } previousGroupId = groupId; // 每个字段一行 QHBoxLayout *fieldLayout = new QHBoxLayout; fieldLayout->setSpacing(5); QLabel *label = new QLabel(fieldName); label->setAlignment(Qt::AlignVCenter | Qt::AlignLeft); label->setFixedHeight(24); label->setMinimumWidth(120); fieldLayout->addWidget(label); fieldLayout->addStretch(1); QWidget *rightWidget = new QWidget; QHBoxLayout *rightLayout = new QHBoxLayout(rightWidget); rightLayout->setContentsMargins(0, 0, 20, 0); rightLayout->setSpacing(5); QWidget *createdWidget = nullptr; if (fieldType == "input") { // 检查 Value 中是否包含逗号分隔(比如 "请输入内容1,分钟") if (fieldUnits!= "") { // // 采用逗号分割,trim去除空白 // QStringList parts = fieldValue.split(",", Qt::SkipEmptyParts); // QString leftText = parts.at(0).trimmed(); // QString rightText = (parts.size() > 1 ? parts.at(1).trimmed() : QString()); // 创建 QLineEdit 显示左边文本 QLineEdit *lineEdit = new QLineEdit(); if((fieldUpLimit=="")&&(fieldDownLimit=="")){ lineEdit->setText(fieldCurrentValue); lineEdit->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed); lineEdit->setFixedSize(105, 28); lineEdit->setAlignment(Qt::AlignLeft); lineEdit->setStyleSheet(R"( QLineEdit { background: #FFFFFF; border: 1px solid #BABBDC; border-radius: 6px; padding: 2px 5px; } )"); }else{//上下限至少设置了一个值 if(fieldCurrentValue == ""){ lineEdit->setPlaceholderText("请输入数字"); }else{ lineEdit->setText(fieldCurrentValue); } lineEdit->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed); lineEdit->setFixedSize(105, 28); lineEdit->setAlignment(Qt::AlignLeft); lineEdit->setStyleSheet(R"( QLineEdit { background: #FFFFFF; border: 1px solid #BABBDC; border-radius: 6px; padding: 2px 5px; } )"); } // 创建 QLabel 显示右边文本(比如 "分钟") QLabel *unitLabel = new QLabel(fieldUnits); unitLabel->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed); unitLabel->setFixedHeight(28); unitLabel->setStyleSheet("QLabel { font-size: 14px; }"); // 把 QLineEdit 和 QLabel 水平排列,确保 Qlabel 显示在 QLineEdit 右侧 QHBoxLayout *inputLayout = new QHBoxLayout; inputLayout->setSpacing(10); inputLayout->setContentsMargins(0,0,0,0); inputLayout->addWidget(lineEdit); inputLayout->addWidget(unitLabel); // 用一个容器部件来装下这个布局 QWidget *inputWidget = new QWidget; inputWidget->setLayout(inputLayout); rightLayout->addWidget(inputWidget); // 保存控件指针到 m_fieldWidgets(可选) m_fieldWidgets.append(lineEdit); m_fieldWidgets.append(unitLabel); createdWidget = inputWidget; // // 连接 textChanged 信号到 lambda 函数 connect(lineEdit, &QLineEdit::textChanged, [this,lineEdit,fieldTableName,fieldId,fieldUpLimit,fieldDownLimit]() { if((fieldUpLimit!="")&&(fieldDownLimit!="")){ int uplimit = fieldUpLimit.toInt(); int downlimit = fieldDownLimit.toInt(); int inputvalue = (lineEdit->text()).toInt(); if((inputvalue<=uplimit)&&(inputvalue>=downlimit)){ updateDb(fieldTableName,fieldId,lineEdit->text()); }else{ lineEdit->setPlaceholderText("超出设定范围,请重新输入"); } }else if(fieldDownLimit!=""){ int downlimit = fieldDownLimit.toInt(); int inputvalue = (lineEdit->text()).toInt(); if(inputvalue>=downlimit){ updateDb(fieldTableName,fieldId,lineEdit->text()); }else{ lineEdit->setPlaceholderText("超出设定范围,请重新输入"); } }else if(fieldUpLimit!=""){ int uplimit = fieldUpLimit.toInt(); int inputvalue = (lineEdit->text()).toInt(); if(inputvalue<=uplimit){ updateDb(fieldTableName,fieldId,lineEdit->text()); }else{ lineEdit->setPlaceholderText("超出设定范围,请重新输入"); } }else{ updateDb(fieldTableName,fieldId,lineEdit->text()); } }); } else { // 如果不包含逗号,按原有逻辑只创建 QLineEdit QLineEdit *lineEdit1 = new QLineEdit(fieldCurrentValue); lineEdit1->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed); lineEdit1->setFixedSize(140, 28); lineEdit1->setAlignment(Qt::AlignLeft); lineEdit1->setStyleSheet(R"( QLineEdit { background: #FFFFFF; border: 1px solid #BABBDC; border-radius: 6px; padding: 2px 5px; } )"); rightLayout->addWidget(lineEdit1); createdWidget = lineEdit1; // // 连接 textChanged 信号到 lambda 函数 connect(lineEdit1, &QLineEdit::textChanged, [this,lineEdit1,fieldTableName,fieldId]() { updateDb(fieldTableName,fieldId,lineEdit1->text()); loginput(fieldTableName,fieldId,lineEdit1->text()); }); } } else if (fieldType == "radio") { // 用逗号分隔的选项 QStringList optionList = fieldValue.split(QRegExp("[,,]"), Qt::SkipEmptyParts); QHBoxLayout *radioLayout = new QHBoxLayout; radioLayout->setSpacing(5); QButtonGroup *radioGroup = new QButtonGroup(rightWidget); for (const QString &optionText : optionList) { QString trimmedOpt = optionText.trimmed(); if (trimmedOpt.isEmpty()) continue; QRadioButton *radioButton = new QRadioButton(trimmedOpt); radioGroup->addButton(radioButton); radioLayout->addWidget(radioButton); m_fieldWidgets.append(radioButton); if(fieldCurrentValue == trimmedOpt){ radioButton->setChecked(true); } } // 使用Lambda函数连接 buttonToggled 信号 connect(radioGroup, static_cast(&QButtonGroup::buttonToggled),[this,fieldTableName,fieldId](QAbstractButton *button,bool checked) { if (checked) { // qDebug() << "Button toggled:" << button->text(); // 在这里添加你想要执行的操作 updateDb(fieldTableName,fieldId,button->text()); } }); rightLayout->addLayout(radioLayout); } else if (fieldType == "checkbox") { bool isChecked; if(fieldCurrentValue == ""){ isChecked = (fieldValue == "1"); }else{ isChecked = (fieldCurrentValue == "1"); } QCheckBox *checkBox = new QCheckBox; checkBox->setChecked(isChecked); checkBox->setStyleSheet(R"( QCheckBox::indicator { width: 20px; height: 20px; } QCheckBox::indicator:unchecked { background-color: #FFFFFF; border: 1px solid #BABBDC; border-radius: 2px; } QCheckBox::indicator:checked { image: url(:/images/three_Selecte.png); } QCheckBox { spacing: 0px; } )"); rightLayout->addWidget(checkBox); createdWidget = checkBox; connect(checkBox, &QCheckBox::stateChanged, [this,fieldTableName,fieldId](int state) { if (state == Qt::Checked) { // qDebug() << "CheckBox is checked"<setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed); comboBox->setFixedSize(140, 28); comboBox->setStyleSheet(R"( QComboBox { background: #FFFFFF; border: 1px solid #BABBDC; border-radius: 6px; padding: 2px 5px; } QComboBox::drop-down { width: 20px; } )"); // int newIndex = -1; for (const QString &opt : optionList) { QString trimmedOpt = opt.trimmed(); if (!trimmedOpt.isEmpty()) comboBox->addItem(trimmedOpt); } if(fieldCurrentValue == ""){ comboBox->setCurrentIndex(0); }else{ comboBox->setCurrentIndex(fieldCurrentValue.toInt()); } rightLayout->addWidget(comboBox); createdWidget = comboBox; // 使用Lambda函数连接 currentIndexChanged 信号 connect(comboBox, QOverload::of(&QComboBox::currentIndexChanged), [this,comboBox,fieldTableName,fieldId](int index) { QString selectedText = comboBox->itemText(index); QString indexString = QString::number(index); // qDebug() << "ComboBox index changed to:" << index << "Text:" << selectedText; updateDb(fieldTableName,fieldId,indexString); // 在这里添加你想要执行的操作 }); } else if (fieldType == "time") { 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(fieldValue, "HH:mm:ss")); rightLayout->addWidget(timeEdit); createdWidget = timeEdit; } else if (fieldType == "switch") { 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; if(fieldCurrentValue==""){ switchValue = fieldValue.toLower(); }else{ switchValue = fieldCurrentValue.toLower(); } 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, [fieldTableName,fieldId,switchLabel, this](int state){ if (state == Qt::Checked){ switchLabel->setText("开"); updateDb(fieldTableName,fieldId,"on"); }else{ switchLabel->setText("关"); updateDb(fieldTableName,fieldId,"off"); } }); switchLayout->addWidget(switchBox); switchLayout->addWidget(switchLabel); rightLayout->addWidget(switchContainer); createdWidget = switchBox; } else if (fieldType == "combined") { // 用逗号分隔 QStringList parts = fieldValue.split(QRegExp("[,,]"), Qt::SkipEmptyParts); QString inputText = (parts.size() >= 1 ? parts.at(0).trimmed() : QString()); QString button1Text = (parts.size() >= 2 ? parts.at(1).trimmed() : QStringLiteral("获取")); QString button2Text = (parts.size() >= 3 ? parts.at(2).trimmed() : QStringLiteral("设置")); QLineEdit *comboInput = new QLineEdit(inputText); 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; } )"); m_fieldWidgets.append(comboInput); QWidget *combinedWidget = new QWidget; QHBoxLayout *combinedLayout = new QHBoxLayout(combinedWidget); combinedLayout->setSpacing(5); combinedLayout->setContentsMargins(0, 0, 0, 0); QPushButton *btnGet = new QPushButton(button1Text, combinedWidget); btnGet->setFixedSize(80, 28); btnGet->setStyleSheet(R"( QPushButton { background: #FFFFFF; border: 1px solid #BABBDC; border-radius: 5px; } QPushButton:hover { background-color: #F0F0F0; } )"); m_fieldWidgets.append(btnGet); QPushButton *btnSet = new QPushButton(button2Text, combinedWidget); btnSet->setFixedSize(80, 28); btnSet->setStyleSheet(R"( QPushButton { background: #FFFFFF; border: 1px solid #BABBDC; border-radius: 5px; } QPushButton:hover { background-color: #F0F0F0; } )"); m_fieldWidgets.append(btnSet); combinedLayout->addWidget(comboInput); combinedLayout->addWidget(btnGet); combinedLayout->addWidget(btnSet); combinedLayout->addStretch(); rightLayout->addWidget(combinedWidget); } else { qWarning() << "未知字段类型:" << fieldType; } if (createdWidget) m_fieldWidgets.append(createdWidget); fieldLayout->addWidget(rightWidget); scrollLayout->addLayout(fieldLayout); } } scrollLayout->addStretch(); scrollArea->setWidget(scrollWidget); QVBoxLayout *mainLayout = new QVBoxLayout(m_thirdLevelFieldWnd); mainLayout->setContentsMargins(0, 0, 0, 0); mainLayout->addWidget(scrollArea); m_thirdLevelFieldWnd->show(); } void DbTreeViewManager::updateParentCheckState(QStandardItem *item) { if (!item) return; QStandardItem *parentItem = item->parent(); if (!parentItem) return; bool allChecked = true; bool noneChecked = true; for (int i = 0; i < parentItem->rowCount(); ++i) { QStandardItem *child = parentItem->child(i); if (child->checkState() != Qt::Checked) { allChecked = false; } if (child->checkState() == Qt::Checked) { noneChecked = false; } } if (allChecked) { parentItem->setCheckState(Qt::Checked); } else { parentItem->setCheckState(Qt::Unchecked); } if (noneChecked) { qDebug() << "noneChecked状态为:" << noneChecked; } // 递归更新上一级 updateParentCheckState(parentItem); } void DbTreeViewManager::onButtonBackClicked() { if (m_thirdLevelFieldWnd) { // 当前在第三层目录,返回到上一层目录 qDebug() << "当前在第三层目录,准备返回上一层。"; for(int i=0;i<5;i++){ if(currentMenuId == menuArray[i].menuId){ menuArray[i].isthird = false; } } // 关闭并销毁字段展示窗口 m_thirdLevelFieldWnd->close(); m_thirdLevelFieldWnd->deleteLater(); m_thirdLevelFieldWnd = nullptr; // 显示目录树和分隔线 treeViewDown->show(); for (auto separator : firstLevelSeparators) { if (separator) separator->show(); } // 获取当前导航路径 QStringList path; QLayout* layout = navigationWidget->layout(); if (!layout) { qWarning() << "导航栏没有布局,无法获取路径。"; return; } for (int i = 0; i < layout->count(); ++i) { QLayoutItem* item = layout->itemAt(i); if (item && item->widget()) { QLabel* label = qobject_cast(item->widget()); if (label) { QString text = label->text().trimmed(); if (!text.isEmpty()) { path << text; } } } } if (path.isEmpty()) { qWarning() << "导航路径为空,无法返回上一层。"; return; } // 移除最后一个目录名称以返回上一层 path.removeLast(); if (path.isEmpty()) { qDebug() << "已经在根目录,无法返回。"; return; } // 根据新的路径查找对应的 QModelIndex QModelIndex parentIndex = findItemByPath(path); if (!parentIndex.isValid()) { qWarning() << "无法找到路径对应的目录项:" << path; return; } // 选中父目录项 treeViewDown->setCurrentIndex(parentIndex); treeViewDown->scrollTo(parentIndex); // 更新导航栏 updateNavigationBar(parentIndex); // 检查父目录是否为第三层目录 QStandardItem* parentItem = model->itemFromIndex(parentIndex); if (!parentItem) { qWarning() << "父目录项无效。"; return; } QVariant dataVar = parentItem->data(Qt::UserRole + 2); bool isThirdLevel = false; int directoryId = -1; if (dataVar.canConvert()) { QJsonObject dataObj = dataVar.toJsonObject(); if (dataObj.contains("IsThirdLevel") && dataObj["IsThirdLevel"].toBool()) { isThirdLevel = true; if (dataObj.contains("Id")) { directoryId = dataObj["Id"].toInt(); } } } if (isThirdLevel) { if (directoryId == -1) { qWarning() << "无效的 DirectoryId,无法加载第三层目录内容。"; return; } int userPrivilege = 0x1; // 当前用户的权限等级 // 获取第三层目录的数据 QJsonObject data = fetchThirdLevelData(directoryId, userPrivilege); // 显示字段展示窗口 displayThirdLevelFields(data, false); // 传递参数表示非 Home 界面 } else { // 父目录不是第三层目录,确保目录树和分隔线可见 treeViewDown->show(); for (auto separator : firstLevelSeparators) { if (separator) separator->show(); } } return; } // 如果不在第三层目录,则在目录树中返回上一层 qDebug() << "当前不在第三层目录,尝试在目录树中返回上一层。"; QModelIndex currentIndex = treeViewDown->currentIndex(); if (!currentIndex.isValid()) { qWarning() << "当前没有选中的目录项,无法返回。"; return; } QStandardItem* currentItem = model->itemFromIndex(currentIndex); if (!currentItem) { qWarning() << "当前选中的目录项无效。"; return; } QStandardItem* parentItem = currentItem->parent(); if (!parentItem) { qDebug() << "当前已经在根目录,无法返回。"; return; } QModelIndex parentIndex = model->indexFromItem(parentItem); if (!parentIndex.isValid()) { qWarning() << "父目录的 QModelIndex 无效。"; return; } // 选中父目录项 treeViewDown->setCurrentIndex(parentIndex); treeViewDown->scrollTo(parentIndex); // 更新导航栏 updateNavigationBar(parentIndex); // 检查父目录是否为第三层目录 QVariant dataVar = parentItem->data(Qt::UserRole + 2); bool isThirdLevel = false; int directoryId = -1; if (dataVar.canConvert()) { QJsonObject dataObj = dataVar.toJsonObject(); if (dataObj.contains("IsThirdLevel") && dataObj["IsThirdLevel"].toBool()) { isThirdLevel = true; if (dataObj.contains("Id")) { directoryId = dataObj["Id"].toInt(); } } } if (isThirdLevel) { if (directoryId == -1) { qWarning() << "无效的 DirectoryId,无法加载第三层目录内容。"; return; } int userPrivilege = 0x1; // 根据实际情况获取当前用户的权限等级 QJsonObject data = fetchThirdLevelData(directoryId, userPrivilege); displayThirdLevelFields(data, false); // 传递参数表示非 Home 界面 } } QList DbTreeViewManager::collectAllThirdLevelItems() { QList result; // 从根节点开始递归搜集 QStandardItem *root = model->invisibleRootItem(); if (!root) return result; std::function dfsCollectThirdLevel; dfsCollectThirdLevel = [&](QStandardItem* parentItem) { if (!parentItem) return; int rowCount = parentItem->rowCount(); for (int i = 0; i < rowCount; ++i) { QStandardItem *child = parentItem->child(i); if (!child) continue; // 判断是否是第三层 QVariant dataVar = child->data(Qt::UserRole + 2); if (dataVar.canConvert()) { QJsonObject obj = dataVar.toJsonObject(); if (obj.contains("IsThirdLevel") && obj["IsThirdLevel"].toBool()) { // 收集这个第三层节点 result.append(child); } } // 即使不是第三层,也要继续往下找子节点 dfsCollectThirdLevel(child); } }; dfsCollectThirdLevel(root); return result; } void DbTreeViewManager::onButtonDownClicked() { // 1) 收集所有 第三层 节点 QList thirdLevelList = collectAllThirdLevelItems(); if (thirdLevelList.isEmpty()) { qDebug() << "[onButtonDownClicked] 没有任何三级目录,无法遍历。"; return; } // 2) 找到 当前选中的节点 在 thirdLevelList 里的索引 QModelIndex curIndex = treeViewDown->currentIndex(); if (!curIndex.isValid()) { qDebug() << "[onButtonDownClicked] 当前没有选中节点,默认跳到第一个三级目录。"; // 如果想默认跳到第一个 QStandardItem *firstItem = thirdLevelList.first(); QModelIndex idx = model->indexFromItem(firstItem); treeViewDown->setCurrentIndex(idx); // 模拟点击一下 onTreeViewClicked_updown(idx); // 保存复选框状态 saveCheckedPaths(); // 保存展开路径 saveExpandedPaths(); return; } QStandardItem *curItem = model->itemFromIndex(curIndex); if (!curItem) { qWarning() << "[onButtonDownClicked] currentItem 无效。"; return; } // 若不是三级目录,就先找它最近的父级是不是三级目录,否则当做没找到。 int currentPos = -1; { // 在 thirdLevelList 里找到 curItem currentPos = thirdLevelList.indexOf(curItem); if (currentPos < 0) { qDebug() << "[onButtonDownClicked] 当前节点不是三级目录,尝试找父级是不是三级目录…"; // 向上找父节点是否在 thirdLevelList 里 QStandardItem *temp = curItem->parent(); while (temp) { int pos = thirdLevelList.indexOf(temp); if (pos >= 0) { currentPos = pos; break; } temp = temp->parent(); } if (currentPos < 0) { qDebug() << "还是找不到,说明当前目录不属于任何三级目录,直接跳到第一个"; QStandardItem *firstItem = thirdLevelList.first(); QModelIndex idx = model->indexFromItem(firstItem); treeViewDown->setCurrentIndex(idx); onTreeViewClicked_updown(idx); // 保存复选框状态 saveCheckedPaths(); // 保存展开路径 saveExpandedPaths(); return; } } } // 尝试下一个 int nextPos = currentPos + 1; if (nextPos >= thirdLevelList.size()) { qDebug() << "[onButtonDownClicked] 已经是最后一个三级目录了,无法再向下。"; return; } // 跳到下一个 QStandardItem *nextItem = thirdLevelList[nextPos]; QModelIndex nextIndex = model->indexFromItem(nextItem); treeViewDown->setCurrentIndex(nextIndex); // 相当于模拟点击 onTreeViewClicked_updown(nextIndex); // 保存复选框状态 saveCheckedPaths(); // 保存展开路径 saveExpandedPaths(); } void DbTreeViewManager::onButtonUpClicked() { // 1) 收集所有 第三层 节点 QList thirdLevelList = collectAllThirdLevelItems(); if (thirdLevelList.isEmpty()) { qDebug() << "[onButtonUpClicked] 没有任何三级目录,无法遍历。"; return; } // 2) 找到 当前选中的节点 QModelIndex curIndex = treeViewDown->currentIndex(); if (!curIndex.isValid()) { qDebug() << "[onButtonUpClicked] 当前无选中节点,默认跳到最后一个三级目录。"; // 跳到最后一个 QStandardItem *lastItem = thirdLevelList.last(); QModelIndex idx = model->indexFromItem(lastItem); treeViewDown->setCurrentIndex(idx); // 模拟点击 onTreeViewClicked_updown(idx); // 保存复选框状态 saveCheckedPaths(); // 保存展开路径 saveExpandedPaths(); return; } QStandardItem *curItem = model->itemFromIndex(curIndex); if (!curItem) { qWarning() << "[onButtonUpClicked] currentItem 无效。"; return; } // 如果当前节点不是三级目录, 向上查找 int currentPos = thirdLevelList.indexOf(curItem); if (currentPos < 0) { qDebug() << "[onButtonUpClicked] 当前节点不是三级目录,尝试找父级是不是三级目录。"; QStandardItem *temp = curItem->parent(); while (temp) { int pos = thirdLevelList.indexOf(temp); if (pos >= 0) { currentPos = pos; break; } temp = temp->parent(); } if (currentPos < 0) { qDebug() << "找不到任何三级目录,直接跳到最后一个。"; QStandardItem *lastItem = thirdLevelList.last(); QModelIndex idx = model->indexFromItem(lastItem); treeViewDown->setCurrentIndex(idx); onTreeViewClicked_updown(idx); // 保存复选框状态 saveCheckedPaths(); // 保存展开路径 saveExpandedPaths(); return; } } // 尝试上一个 int prevPos = currentPos - 1; if (prevPos < 0) { qDebug() << "[onButtonUpClicked] 已经是第一个三级目录了,无法再向上。"; return; } // 跳到上一个 QStandardItem *prevItem = thirdLevelList[prevPos]; QModelIndex prevIndex = model->indexFromItem(prevItem); treeViewDown->setCurrentIndex(prevIndex); // 模拟点击 onTreeViewClicked_updown(prevIndex); // 保存复选框状态 saveCheckedPaths(); // 保存展开路径 saveExpandedPaths(); } void DbTreeViewManager::onButtonRightClicked() { if (m_forwardStack.isEmpty()) { qDebug() << "[Forward] 已经没有可以前进的页面"; buttonRight->setIcon(QIcon(":/images/home_right.png")); return; } // 1. 弹出 forwardStack 的最后一个 PageState st = m_forwardStack.takeLast(); // 2. 把当前页面 push 到 backStack PageState cur = getCurrentPageState(); m_backStack.append(cur); if(m_backStack.size() >= 2){ buttonLeft->setIcon(QIcon(":/images/home_left.png")); } // 3. 加载 st loadPageState(st, true); } void DbTreeViewManager::onButtonLeftClicked() { if (m_backStack.size() < 2) { qDebug() << "[Back] 已经无法再后退"; buttonLeft->setIcon(QIcon(":/images/home_left_hide.png")); return; } // 1. 先把当前页面(相当于 m_backStack 最后一个)弹出,放到 forwardStack PageState cur = m_backStack.takeLast(); if(m_backStack.size() >= 2){ buttonLeft->setIcon(QIcon(":/images/home_left.png")); }else{ buttonLeft->setIcon(QIcon(":/images/home_left_hide.png")); } m_forwardStack.append(cur); buttonRight->setIcon(QIcon(":/images/home_right_show.png")); // 2. 拿到新的 m_backStack 末尾(即上一次看的页面) const PageState &prev = m_backStack.last(); // 3. 加载 prev loadPageState(prev, true ); } // 构建节点的完整路径 QStringList DbTreeViewManager::buildItemPath(QStandardItem *item) { QStringList path; QStandardItem *currentItem = item; while (currentItem) { path.prepend(currentItem->text()); currentItem = currentItem->parent(); } return path; } // 根据路径查找对应的节点 QModelIndex DbTreeViewManager::findItemByPath(const QStringList &path) { if (path.isEmpty()) return QModelIndex(); QStandardItem *currentItem = model->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 = model->indexFromItem(child); currentItem = child; found = true; qDebug() << "找到路径部分:" << part; break; } } if (!found) { qWarning() << "路径部分未找到:" << part; return QModelIndex(); } } return currentIndex; } void DbTreeViewManager::setCheckedPaths(const QStringList &checkedPathsList) { m_blockItemChanged = true; for (const QString &pathStr : checkedPathsList) { QStringList path = pathStr.split("/"); QModelIndex idx = findItemByPath(path); if (idx.isValid()) { QStandardItem *item = model->itemFromIndex(idx); if (item) { item->setCheckState(Qt::Checked); qDebug() << " Setting item:" << item->text() << "to Checked"; } } else { qDebug() << "Path not found:" << pathStr; } } m_blockItemChanged = false; } // 递归收集被选中的路径 QStringList DbTreeViewManager::collectCheckedPathsRecursive(QStandardItem *item, QStringList path) { QStringList checkedList; if (!item) { item = model->invisibleRootItem(); } for (int i = 0; i < item->rowCount(); ++i) { QStandardItem *child = item->child(i); if (child) { QStringList currentPath = path; currentPath << child->text(); if (child->checkState() == Qt::Checked) { checkedList << currentPath.join("/"); } // 递归收集子项 checkedList << collectCheckedPathsRecursive(child, currentPath); } } return checkedList; } // 收集所有被选中的复选框路径 QStringList DbTreeViewManager::collectCheckedPaths() { return collectCheckedPathsRecursive(model->invisibleRootItem(), QStringList()); } // 更新父项的复选框状态 void DbTreeViewManager::updateParentItems(QStandardItem *parentItem) { if (!parentItem) return; int checkedCount = 0; int totalCount = parentItem->rowCount(); qDebug() << "Updating child items of:" << parentItem->text(); for (int i = 0; i < totalCount; ++i) { QStandardItem *child = parentItem->child(i); if (child && child->checkState() == Qt::Checked) { checkedCount++; } } if (checkedCount == totalCount) { parentItem->setCheckState(Qt::Checked); } else { parentItem->setCheckState(Qt::Unchecked); } // 递归更新上层父项 updateParentItems(parentItem->parent()); } // 加载并显示三级目录对应按钮配置信息 void DbTreeViewManager::loadButtonConfigForThirdLevel(const QJsonObject &thirdLevelObj) { if (!m_originalWnd) { qWarning() << "OriginalWnd 指针为空,无法加载按钮配置"; return; } if (!thirdLevelObj.contains("buttons")) { qWarning() << "三级目录配置中不包含 'buttons' 字段"; return; } QJsonArray buttonsArray = thirdLevelObj.value("buttons").toArray(); // 获取 widget_left QWidget* widgetLeft = m_originalWnd->getWidgetLeft(); if (!widgetLeft) { qWarning() << "无法访问 widget_left"; return; } // 清空 widget_left 中由 loadButtonConfigForThirdLevel 创建的按钮 QList existingButtons = widgetLeft->findChildren(); for (QPushButton* button : existingButtons) { if (button->objectName().startsWith("thirdLevelBtn_")) { // 仅删除特定按钮 button->deleteLater(); } } // 使用绝对定位创建按钮 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("thirdLevelBtn_" + buttonId); // 设置带前缀的对象名称 // 设置按钮的样式,调整图标和文本的位置 button->setStyleSheet(R"( QPushButton { position: absolute; border-radius: 6px; opacity: 1; background: #CBD0FF; border: none; } QPushButton:hover { background-color: #A9B4FF; /* 鼠标悬停效果 */ } )"); // 设置按钮的位置和大小 int x = 16; int y = 245 + i * (48 + 13); // 第一个按钮 y=245,后续每个按钮间隔13px button->setGeometry(x, y, 158, 48); // 设置按钮的可见性,根据 "enabled" 字段显示或隐藏按钮 button->setVisible(isEnabled); // 创建图标标签 QLabel *iconLabel = new QLabel(button); iconLabel->setPixmap(QIcon(buttonIcon).pixmap(16, 16)); iconLabel->setGeometry(10, 16, 16, 16); // 图标距离左边10px,顶部16px iconLabel->setFixedSize(16, 16); iconLabel->setStyleSheet("background-color: transparent;"); iconLabel->setVisible(isEnabled); // 根据按钮的可见性设置图标的可见性 // 创建文本标签 QLabel *textLabel = new QLabel(buttonText, button); textLabel->setGeometry(34, 0, 90, 48); // 文本距离左边34px textLabel->setWordWrap(true); // 允许换行 textLabel->setAlignment(Qt::AlignLeft | Qt::AlignVCenter); textLabel->setStyleSheet(R"( QLabel { background: transparent; font-family: "思源黑体"; font-size: 14px; font-weight: 500; color: #4E51CE; } )"); textLabel->setVisible(isEnabled); // 根据按钮的可见性设置文本的可见性 // 创建 F1-F12 标签 QString fLabelText = QString("F%1").arg(i + 1); // F1, F2, ..., F12 QLabel *fLabel = new QLabel(fLabelText, button); fLabel->setFixedSize(21, 16); // 设置大小为21x16 fLabel->setAlignment(Qt::AlignCenter); fLabel->setStyleSheet(R"( QLabel { background-color: transparent; color: #2A7ED8; font-size: 12px; font-weight: bold; } )"); // 设置标签的位置 int fX = 134; int fY = 2; fLabel->setGeometry(fX, fY, 14, 16); fLabel->setVisible(isEnabled); // 根据按钮的可见性设置标签的可见性 // 将按钮、图标、文本和标签添加到控件列表 m_fieldWidgets.append(button); m_fieldWidgets.append(iconLabel); m_fieldWidgets.append(textLabel); m_fieldWidgets.append(fLabel); } } // 清理并隐藏三级目录菜单内容 void DbTreeViewManager::clearThirdLevelMenu() { // 遍历所有子控件,找到标题为 "字段展示" 的窗口并关闭 foreach (QObject *child, widget2->children()) { QWidget *childWidget = qobject_cast(child); if (childWidget && childWidget->windowTitle() == "字段展示") { qDebug() << "关闭现有的字段展示窗口"; childWidget->close(); } } // 显示主目录树和分隔线 treeViewDown->show(); for (auto separator : firstLevelSeparators) { separator->show(); } } // 保存选中路径 void DbTreeViewManager::saveCheckedPaths() { if (m_currentConfigId == -1) { qWarning() << "当前配置ID无效,无法保存复选框状态。"; return; } QSettings settings("RunCloudTech", "David"); QString configKey = QString::number(m_currentConfigId); settings.beginGroup("TreeViewCheckedState"); // 保存选中路径 QString keyChecked = QString("checkedPaths/%1").arg(configKey); QStringList checkedList = collectCheckedPaths(); settings.setValue(keyChecked, checkedList); settings.endGroup(); qDebug() << "保存复选框状态路径:" << checkedList; } // 加载选中路径 void DbTreeViewManager::loadCheckedPaths() { if (m_currentConfigId == -1) { qWarning() << "当前配置ID无效,无法加载复选框状态。"; return; } QSettings settings("RunCloudTech", "David"); QString configKey = QString::number(m_currentConfigId); settings.beginGroup("TreeViewCheckedState"); // 读取选中路径 QString keyChecked = QString("checkedPaths/%1").arg(configKey); QStringList loadedChecked = settings.value(keyChecked).toStringList(); settings.endGroup(); qDebug() << "加载复选框状态路径:" << loadedChecked; m_blockItemChanged = true; setCheckedPaths(loadedChecked); m_blockItemChanged = false; // 更新导航栏 if (!loadedChecked.isEmpty()) { QString lastPathStr = loadedChecked.last(); QStringList lastPath = lastPathStr.split("/"); QModelIndex lastIdx = findItemByPath(lastPath); if (lastIdx.isValid()) { treeViewDown->setCurrentIndex(lastIdx); updateNavigationBar(lastIdx); } } else { // 如果没有加载到任何路径,自动选择第一个目录 QStandardItem *rootItem = model->invisibleRootItem(); if (rootItem->rowCount() > 0) { QModelIndex firstIndex = model->index(0, 0, QModelIndex()); if (firstIndex.isValid()) { treeViewDown->setCurrentIndex(firstIndex); treeViewDown->expand(firstIndex); // 展开第一个目录 QStandardItem *firstItem = model->itemFromIndex(firstIndex); QVariant data = firstItem->data(Qt::UserRole + 2); if (data.canConvert()) { QJsonObject thirdLevelObj = data.toJsonObject(); if (thirdLevelObj.contains("IsThirdLevel") && thirdLevelObj["IsThirdLevel"].toBool()) { loadButtonConfigForThirdLevel(thirdLevelObj); } } } } } } // 保存展开路径 void DbTreeViewManager::saveExpandedPaths() { if (m_currentConfigId == -1) { qWarning() << "当前配置ID无效,无法保存展开路径。"; return; } QSettings settings("RunCloudTech", "David"); QString configKey = QString::number(m_currentConfigId); settings.beginGroup("TreeViewExpandedState"); // 保存展开路径 QString keyExpanded = QString("expandedPaths/%1").arg(configKey); QStringList expandedList = QStringList(expandedPaths.begin(), expandedPaths.end()); settings.setValue(keyExpanded, expandedList); settings.endGroup(); qDebug() << "保存展开路径:" << expandedList; } // 加载展开路径 void DbTreeViewManager::loadExpandedPaths() { if (m_currentConfigId == -1) { qWarning() << "当前配置ID无效,无法加载展开路径。"; return; } QSettings settings("RunCloudTech", "David"); QString configKey = QString::number(m_currentConfigId); settings.beginGroup("TreeViewExpandedState"); // 读取展开路径 QString keyExpanded = QString("expandedPaths/%1").arg(configKey); QStringList loadedExpanded = settings.value(keyExpanded).toStringList(); settings.endGroup(); qDebug() << "加载展开路径:" << loadedExpanded; m_blockItemChanged = true; // 恢复展开路径 for (const QString &p : loadedExpanded) { QStringList path = p.split("/"); QModelIndex idx = findItemByPath(path); if (idx.isValid()) { treeViewDown->expand(idx); expandedPaths.insert(p); qDebug() << "成功恢复展开路径:" << p; } else { qDebug() << "未找到展开路径部分: " << p; } } m_blockItemChanged = false; } // 清空历史 void DbTreeViewManager::clearHistory() { m_backStack.clear(); m_forwardStack.clear(); buttonLeft->setIcon(QIcon(":/images/home_left_hide.png")); buttonRight->setIcon(QIcon(":/images/home_right.png")); } // 获取当前页面的 PageState DbTreeViewManager::PageState DbTreeViewManager::getCurrentPageState() { PageState st; st.isThirdLevel = false; st.directoryId = -1; // 判断是否在第三层窗口中 if (m_thirdLevelFieldWnd && m_thirdLevelFieldWnd->isVisible()) { // 如果此时是在第三层界面,则用当前导航栏 or 目录树的 “选中项” 来获取路径 QModelIndex curIndex = treeViewDown->currentIndex(); if (!curIndex.isValid()) { st.path << "未知目录"; } else { QStandardItem* item = model->itemFromIndex(curIndex); st.path = buildItemPath(item); } // 如果能拿到 DirectoryId,则置为第三层 QVariant dataVar = model->itemFromIndex(treeViewDown->currentIndex())->data(Qt::UserRole + 2); if (dataVar.canConvert()) { QJsonObject obj = dataVar.toJsonObject(); if (obj.contains("IsThirdLevel") && obj["IsThirdLevel"].toBool()) { st.isThirdLevel = true; st.directoryId = obj.value("Id").toInt(-1); } } } else { // 当前是目录树界面,就看 treeView 选中项 QModelIndex curIndex = treeViewDown->currentIndex(); if (curIndex.isValid()) { QStandardItem* item = model->itemFromIndex(curIndex); st.path = buildItemPath(item); // 检查是否第三层 QVariant dataVar = item->data(Qt::UserRole + 2); if (dataVar.canConvert()) { QJsonObject obj = dataVar.toJsonObject(); if (obj.contains("IsThirdLevel") && obj["IsThirdLevel"].toBool()) { st.isThirdLevel = true; st.directoryId = obj.value("Id").toInt(-1); } } } } return st; } //加载指定的 PageState:相当于“回到该路径”或“跳转到这个第三层” void DbTreeViewManager::loadPageState(const PageState &st, bool isByHistoryNav) { // 先根据 st.path 找到对应的节点 QModelIndex idx = findItemByPath(st.path); if (!idx.isValid()) { qWarning() << "[loadPageState] 未找到路径" << st.path; return; } // 选中该节点 treeViewDown->setCurrentIndex(idx); treeViewDown->scrollTo(idx); // 更新导航栏 updateNavigationBar(idx); // 如果是第三层,就加载对应的数据窗口 if (st.isThirdLevel && st.directoryId != -1) { // 如果当前已在一个第三层窗口,先关闭它 if (m_thirdLevelFieldWnd) { m_thirdLevelFieldWnd->close(); m_thirdLevelFieldWnd->deleteLater(); m_thirdLevelFieldWnd = nullptr; } int userPrivilege = 0x1; QJsonObject data = fetchThirdLevelData(st.directoryId, userPrivilege); displayThirdLevelFields(data, (m_currentConfigId == 1)); } else { // 否则,显示目录树 if (m_thirdLevelFieldWnd) { m_thirdLevelFieldWnd->close(); m_thirdLevelFieldWnd->deleteLater(); m_thirdLevelFieldWnd = nullptr; } treeViewDown->show(); for (auto sep : firstLevelSeparators) { if (sep) sep->show(); } } if (!isByHistoryNav) { m_forwardStack.clear(); buttonRight->setIcon(QIcon(":/images/home_right.png")); // 把新状态压入后退栈 m_backStack.append(st); if(m_backStack.size() >= 2){ buttonLeft->setIcon(QIcon(":/images/home_left.png")); } } } void DbTreeViewManager::loginput(const QString& fieldTableName,const int& fieldId,const QString& modifies){ // 获取当前时间并格式化 QDateTime currentDateTime = QDateTime::currentDateTime(); QString timestamp = currentDateTime.toString("yyyy-MM-dd hh:mm:ss"); QString logMessage = QString("%1 :fieldTableName is %2 and fieldId is %3 ,currentvalue is modified %4" ).arg(timestamp).arg(fieldTableName).arg(fieldId).arg(modifies); QString pathoflog = "C:\\Users\\Administrator\\Desktop\\qt\\merge\\gujiangdong\\die-bonder-ui0218\\die-bonder-ui\\log/log.txt"; writeLogToFile(logMessage,pathoflog); } void DbTreeViewManager::writeLogToFile(const QString& logMessage, const QString& filePath) { QFile logFile(filePath); if (!logFile.open(QIODevice::Append | QIODevice::Text)) { qWarning() << "Cannot open file for writing:" << filePath; return; } QTextStream out(&logFile); out << logMessage << "\n"; logFile.close(); }